webshims.register('form-datalist-lazy', function($, webshims, window, document, undefined, options){ var listidIndex = 0; var formsCFG = $.webshims.cfg.forms; var globStoredOptions = {}; var getStoredOptions = function(name){ if(!name){return [];} if(globStoredOptions[name]){ return globStoredOptions[name]; } var data; try { data = JSON.parse(localStorage.getItem('storedDatalistOptions'+name)); } catch(e){} globStoredOptions[name] = data || []; return data || []; }; var storeOptions = function(name, val){ if(!name){return;} val = val || []; try { localStorage.setItem( 'storedDatalistOptions'+name, JSON.stringify(val) ); } catch(e){} }; var lReg = //g; var splitReg = /\s*,\s*/g; $.extend(options.shadowListProto, { _lazyCreate: function(opts){ var that = this; this.hideList = $.proxy(that, 'hideList'); this.index = -1; this.input = opts.input; this.arrayOptions = []; this._updateOptions(); this.popover = webshims.objectCreate(webshims.wsPopover, {}, this.options.popover); this.shadowList = this.popover.element.addClass('datalist-polyfill'); this.shadowList .on('mouseenter.datalistWidget mousedown.datalistWidget click.datalistWidget', 'li', function(e){ if(that._stopMouseOver && e && e.type == 'mouseenter'){return;} var items = $('li:not(.hidden-item)', that.shadowList); var select = (e.type == 'mousedown' || e.type == 'click'); that.markItem(items.index(e.currentTarget), select, items); if(e.type == 'click'){ that.hideList(); if(formsCFG.customDatalist){ $(opts.input).getNativeElement().trigger('datalistselect'); } } return (e.type != 'mousedown'); }) ; opts.input.setAttribute('autocomplete', 'off'); this.lastCompletedValue = ""; $(opts.input) .attr({ //role: 'combobox', 'aria-haspopup': 'true' }) .on({ 'input.datalistWidget': function(){ if(!that.triggeredByDatalist){ that.changedValue = false; that.showHideOptions(); } }, 'keydown.datalistWidget': function(e){ var keyCode = e.keyCode; var activeItem; var items; if(keyCode == 40 && !that.showList()){ that.markItem(that.index + 1, true); return false; } if(!that.popover.isVisible){return;} if(keyCode == 38){ that.markItem(that.index - 1, true); return false; } if(!e.shiftKey && (keyCode == 33 || keyCode == 36)){ that.markItem(0, true); return false; } if(!e.shiftKey && (keyCode == 34 || keyCode == 35)){ items = $('li:not(.hidden-item)', that.shadowList); that.markItem(items.length - 1, true, items); return false; } if(keyCode == 13 || keyCode == 27){ if (keyCode == 13){ activeItem = $('li.active-item:not(.hidden-item)', that.shadowList); that.changeValue( $('li.active-item:not(.hidden-item)', that.shadowList) ); } that.hideList(); if(formsCFG.customDatalist && activeItem && activeItem[0]){ $(opts.input).getNativeElement().trigger('datalistselect'); } if(e.keyCode != 13 || (activeItem && activeItem[0])){ return false; } } }, 'focus.datalistWidget': function(){ that.lastCompletedValue = ""; if(that.options.focus){ that.showList(); } }, 'mousedown.datalistWidget': function(){ if($(this).is(':focus')){ that.showList(); } } }) ; $(this.datalist) .off('updateDatalist.datalistWidget') .on('updateDatalist.datalistWidget', $.proxy(this, '_resetListCached')) .on('remove', function(e){ if(!e.originalEvent){ that.destroy(); } }) ; this._resetListCached(); if(opts.input.form && (opts.input.name || opts.input.id)){ $(opts.input.form).on('submit.datalistWidget'+opts.input.id, function(){ if(!$(opts.input).hasClass('no-datalist-cache') && that._autocomplete != 'off'){ var val = $.prop(opts.input, 'value'); var name = (opts.input.name || opts.input.id) + $.prop(opts.input, 'type'); if(!that.storedOptions){ that.storedOptions = getStoredOptions( name ); } if(val && that.storedOptions.indexOf(val) == -1){ that.storedOptions.push(val); storeOptions(name, that.storedOptions ); } } }); } $(window).on('unload.datalist'+this.id +' beforeunload.datalist'+this.id, function(e){ that.destroy(e); }); }, _resetListCached: function(e){ var that = this; var forceShow; this.needsUpdate = true; this.lastUpdatedValue = false; this.lastUnfoundValue = ''; if(!this.updateTimer){ if(window.QUnit || (forceShow = ($(that.input).is(':focus') && ($(that.input).hasClass('list-focus') || $.prop(that.input, 'value'))) )){ that.updateListOptions(forceShow); } else { that.updateTimer = setTimeout(function(){ that.updateListOptions(); that = null; listidIndex = 1; }, 200 + (100 * listidIndex)); } } }, _updateOptions: function(){ this.options = webshims.getOptions(this.input, 'list', options.list); if($(this.input).prop('multiple') && $(this.input).prop('type') == 'email'){ this.options.multiple = true; } if( this.options.getOptionContent && !$.isFunction(this.options.getOptionContent) ){ this.options.getOptionContent = false; } //depreacated option settings: if(options.getOptionContent){ webshims.error('getOptionContent is depreacated use $(input).on("getoptioncontent")'); } if($(this.input).hasClass('list-focus')){ webshims.error(".list-focus is depreacated. Use focus option."); } if(options.datalistPopover && !this.options.popover){ this.options.popover = options.datalistPopover; webshims.error("datalistPopover is depreacated. Use popover option."); } if($(this.input).hasClass('mark-option-text')){ this.options.highlight = true; webshims.error(".mark-option-text is depreacated. Use highlight option."); } if($(this.input).hasClass('list-multiple')){ this.options.multiple = true; webshims.error(".list-multiple is depreacated. Use multiple option."); } if($(this.input).hasClass('value-completion')){ this.options.valueCompletion = true; webshims.error(".value-completion is depreacated. Use valueCompletion option."); } if(this.options.valueCompletion && this.options.multiple){ webshims.warn("valueCompletion and multiple shouldn't be set together"); } }, updateListOptions: function(_forceShow){ this.needsUpdate = false; clearTimeout(this.updateTimer); this.updateTimer = false; this.lastCompletedValue = ""; var list = []; var values = []; var allOptions = []; var rElem, rItem, rOptions, rI, rLen, item, value; for(rOptions = $.prop(this.datalist, 'options'), rI = 0, rLen = rOptions.length; rI < rLen; rI++){ rElem = rOptions[rI]; if(!rElem.disabled && (value = $(rElem).val())){ rItem = { value: this.options.noHtmlEscape ? value : value.replace(lReg, '<').replace(gReg, '>'), label: $.trim($.attr(rElem, 'label')) || '', className: rElem.className || '', elem: options.getOptionContent ? rElem : null }; if(rItem.label){ rItem.className += ' has-option-label'; } values.push(rItem.value); allOptions.push(rItem); } } if(!this.storedOptions){ this.storedOptions = ($(this.input).hasClass('no-datalist-cache') || this._autocomplete == 'off') ? [] : getStoredOptions((this.input.name || this.input.id) + $.prop(this.input, 'type')); } this.storedOptions.forEach(function(val, i){ if(values.indexOf(val) == -1){ allOptions.push({value: val, label: '', className: 'stored-suggest', style: ''}); } }); for(rI = 0, rLen = allOptions.length; rI < rLen; rI++){ item = allOptions[rI]; list[rI] = '