/** * Inputosaurus Text * * Must be instantiated on an element * Allows multiple input items. Each item is represented with a removable tag that appears to be inside the input area. * * @requires: * * jQuery 3.5+ * jQueryUI 1.12+ Core * * @version 0.1.6 * @author Dan Kielp * @created October 3,2012 * * @modified by RainLoop Team * @modified by DJMaze */ ($ => { const fakeSpan = $(''); $('body').append(fakeSpan); $.widget("ui.inputosaurus", { options: { // bindable events // // 'change' - triggered whenever a tag is added or removed (should be similar to binding the the change event of the instantiated input // 'keyup' - keyup event on the newly created input // while typing, the user can separate values using these delimiters // the value tags are created on the fly when an inputDelimiter is detected inputDelimiters : [',', ';'], allowDragAndDrop : true, focusCallback : null, parseOnBlur : false, // simply passing an autoComplete source (array, string or function) will instantiate autocomplete functionality autoCompleteSource : '', // When forcing users to select from the autocomplete list, allow them to press 'Enter' to select an item if it's the only option left. activateFinalResult : false, // manipulate and return the input value after parseInput() parsing // the array of tag names is passed and expected to be returned as an array after manipulation parseHook : null, splitHook : null }, _create: function() { var widget = this, els = {}, o = widget.options, placeholder = this.element.attr('placeholder') || null; this._chosenValues = []; // Create the elements els.ul = $(''); if (this.options.allowDragAndDrop) { els.ul.droppable({ 'drop': (event, ui) => { ui.draggable.addClass('inputosaurus-dropped'); els.input.val(ui.draggable.data('inputosaurus-value')); if (ui.draggable.__widget) { ui.draggable.__widget._removeDraggedTag(ui.draggable); } widget.parseInput(); } }); } els.input = $(''); // els.input = $(''); els.inputCont = $('
  • '); els.origInputCont = $('
  • '); els.lastEdit = ''; els.input.on('focus', () => { widget._focusTrigger(true); }).on('blur', () => { widget._focusTrigger(false); }); // define starting placeholder if (placeholder) { o.placeholder = placeholder; els.input.attr('placeholder', o.placeholder); } this.element.replaceWith(els.ul); els.origInputCont.append(this.element).hide(); els.inputCont.append(els.input); els.ul.append(els.inputCont); els.ul.append(els.origInputCont); this.elements = els; widget._attachEvents(); // if instantiated input already contains a value, parse that junk if($.trim(this.element.val())){ els.input.val( this.element.val() ); this.parseInput(); } this._instAutocomplete(); }, _focusTriggerTimer : 0, _focusTrigger : function (bValue) { var widget = this; clearTimeout(this._focusTriggerTimer); this._focusTriggerTimer = setTimeout(() => { widget.elements.ul[!bValue ? 'removeClass' : 'addClass']('inputosaurus-focused'); widget.options.focusCallback(bValue); }, 10); }, _instAutocomplete : function() { if(this.options.autoCompleteSource){ var widget = this; this.elements.input.autocomplete({ position : { of : this.elements.ul }, source : this.options.autoCompleteSource, minLength : 1, autoFocus : true, select : (ev, ui) => { ev.preventDefault(); widget.elements.input.val(ui.item.value); widget.parseInput(); }, open : function() { var menu = $(this).data('ui-autocomplete').menu, $menuItems; menu.element.width(widget.elements.ul.outerWidth() - 6); // auto-activate the result if it's the only one if(widget.options.activateFinalResult){ $menuItems = menu.element.find('li'); // activate single item to allow selection upon pressing 'Enter' if($menuItems.length === 1){ menu[menu.activate ? 'activate' : 'focus']($.Event('click'), $menuItems); } } }, focus: () => false }); } }, _autoCompleteMenuPosition : function() { var widget; if(this.options.autoCompleteSource){ widget = this.elements.input.data('ui-autocomplete'); widget && widget.menu.element.position({ of: this.elements.ul, my: 'left top', at: 'left bottom', collision: 'none' }); } }, parseInput : function(ev) { var widget = (ev && ev.data.widget) || this, val, hook, delimiterFound = false, values = []; val = widget.elements.input.val(); if (val) { hook = widget.options.splitHook(val); } if (hook) { values = hook; } else if(delimiterFound !== false){ values = val.split(delimiterFound); } else if(!ev || ev.which === $.ui.keyCode.ENTER && !$('.ui-menu-item .ui-state-focus').length && !$('#ui-active-menuitem').length){ values.push(val); ev && ev.preventDefault(); // prevent autoComplete menu click from causing a false 'blur' } else if(ev.type === 'blur' && !$('#ui-active-menuitem').length){ values.push(val); } values = widget.options.parseHook(values); if(values.length){ widget._setChosen(values); widget.elements.input.val(''); widget._resizeInput(); } }, _inputFocus : function(ev) { var widget = ev.data.widget || this; widget.elements.input.value || (widget.options.autoCompleteSource.length && widget.elements.input.autocomplete('search', '')); }, _inputKeypress : function(ev) { var widget = ev.data.widget || this; ev.type === 'keyup' && widget._trigger('keyup', ev, widget); switch(ev.which){ case $.ui.keyCode.BACKSPACE: ev.type === 'keydown' && widget._inputBackspace(ev); break; case $.ui.keyCode.LEFT: ev.type === 'keydown' && widget._inputBackspace(ev); break; default : widget.parseInput(ev); widget._resizeInput(ev); } // reposition autoComplete menu as