1(function($) { 2 $.fn.amyuiFancySelect = function(opts) { 3 var isiOS, settings; 4 if (opts == null) { 5 opts = {}; 6 } 7 settings = $.extend({ 8 forceiOS: false, 9 includeBlank: false, 10 optionTemplate: function(optionEl) { 11 return optionEl.text(); 12 }, 13 optgroupTemplate: function(optgroupEl) { 14 return optgroupEl.attr('label'); 15 }, 16 triggerTemplate: function(optionEl) { 17 return optionEl.text(); 18 } 19 }, opts); 20 isiOS = !!navigator.userAgent.match(/iP(hone|od|ad)/i); 21 return this.each(function() { 22 var copyOptionsToList, disabled, nextElement, options, prevElement, sel, selClass, trigger, updateTriggerText, wrapper; 23 sel = $(this); 24 if (sel.hasClass('amyui-fancified') || sel.prop('tagName').toLowerCase() !== 'select') { 25 return; 26 } 27 selClass = sel.attr('class'); 28 sel.addClass('amyui-fancified'); 29 sel.css({ 30 width: 1, 31 height: 1, 32 display: 'block', 33 position: 'absolute', 34 top: 0, 35 left: 0, 36 padding: 0, 37 margin: 0, 38 opacity: 0 39 }); 40 sel.wrap('<div class="amyui-fancy-select">'); 41 wrapper = sel.parent(); 42 if (sel.data('class')) { 43 wrapper.addClass(sel.data('class')); 44 } 45 wrapper.append($('<div class="fs-trigger">').addClass(selClass)); 46 if (!(isiOS && !settings.forceiOS)) { 47 wrapper.append('<ul class="fs-options">'); 48 } 49 trigger = wrapper.find('.fs-trigger'); 50 options = wrapper.find('.fs-options'); 51 disabled = sel.prop('disabled'); 52 if (disabled) { 53 wrapper.addClass('fs-disabled'); 54 } 55 updateTriggerText = function() { 56 var triggerHtml; 57 triggerHtml = settings.triggerTemplate(sel.find(':selected')); 58 return trigger.html(triggerHtml); 59 }; 60 nextElement = function(el, $els) { 61 var index; 62 index = $els.index(el); 63 if (index === $els.length - 1) { 64 index = -1; 65 } 66 return $($els.get(index + 1)); 67 }; 68 prevElement = function(el, $els) { 69 var index; 70 index = $els.index(el); 71 if (index === 0) { 72 index = $els.length; 73 } 74 return $($els.get(index - 1)); 75 }; 76 sel.on('blur.fs', function() { 77 if (trigger.hasClass('fs-open')) { 78 setTimeout(function() { 79 return trigger.trigger('close.fs'); 80 }, 120); 81 } 82 }); 83 trigger.on('close.fs', function() { 84 trigger.removeClass('fs-open'); 85 options.removeClass('fs-open'); 86 }); 87 trigger.on('click.fs', function() { 88 var offParent, parent; 89 if (!disabled) { 90 trigger.toggleClass('fs-open'); 91 if (trigger.hasClass('fs-open')) { 92 options.find('li.fs-selected').addClass('fs-hover'); 93 } 94 if (isiOS && !settings.forceiOS) { 95 if (trigger.hasClass('fs-open')) { 96 sel.focus(); 97 } 98 } else { 99 if (trigger.hasClass('fs-open')) { 100 parent = trigger.parent(); 101 offParent = parent.offsetParent(); 102 if ((parent.offset().top + parent.outerHeight() + options.outerHeight() + 20) > $(window).height() + $(window).scrollTop()) { 103 options.addClass('fs-overflowing'); 104 } else { 105 options.removeClass('fs-overflowing'); 106 } 107 } 108 options.toggleClass('fs-open'); 109 if (!isiOS) { 110 sel.focus(); 111 } 112 } 113 } 114 }); 115 sel.on('enable', function() { 116 sel.prop('disabled', false); 117 wrapper.removeClass('fs-disabled'); 118 disabled = false; 119 copyOptionsToList(); 120 }); 121 sel.on('disable', function() { 122 sel.prop('disabled', true); 123 wrapper.addClass('fs-disabled'); 124 disabled = true; 125 }); 126 sel.on('change.fs', function(e) { 127 if (e.originalEvent && e.originalEvent.isTrusted) { 128 e.stopPropagation(); 129 } else { 130 updateTriggerText(); 131 } 132 }); 133 sel.on('update.fs', function() { 134 wrapper.find('.fs-options').empty(); 135 copyOptionsToList(); 136 }); 137 sel.on('keydown', function(e) { 138 var hovered, newHovered, w; 139 w = e.which; 140 hovered = options.find('.fs-hover'); 141 hovered.removeClass('fs-hover'); 142 if (!options.hasClass('fs-open')) { 143 if (w === 13 || w === 32 || w === 38 || w === 40) { 144 e.preventDefault(); 145 trigger.trigger('click.fs'); 146 } 147 } else { 148 if (w === 38) { 149 e.preventDefault(); 150 if (hovered.length) { 151 prevElement(hovered, options.find('li.fs-option')).addClass('fs-hover'); 152 } else { 153 options.find('li.fs-option').last().addClass('fs-hover'); 154 } 155 } else if (w === 40) { 156 e.preventDefault(); 157 if (hovered.length) { 158 nextElement(hovered, options.find('li.fs-option')).addClass('fs-hover'); 159 } else { 160 options.find('li.fs-option').first().addClass('fs-hover'); 161 } 162 } else if (w === 27) { 163 e.preventDefault(); 164 trigger.trigger('click.fs'); 165 } else if (w === 13 || w === 32) { 166 e.preventDefault(); 167 hovered.trigger('mousedown.fs'); 168 } else if (w === 9) { 169 if (trigger.hasClass('fs-open')) { 170 trigger.trigger('close.fs'); 171 } 172 } 173 newHovered = options.find('.fs-hover'); 174 if (newHovered.lenth) { 175 options.scrollTop(0); 176 options.scrollTop(newHovered.position().top - 12); 177 } 178 } 179 }); 180 options.on('mousedown.fs', 'li.fs-option', function(e) { 181 var clicked; 182 clicked = $(this); 183 options.find('.fs-selected').removeClass('fs-selected'); 184 clicked.addClass('fs-selected'); 185 trigger.addClass('fs-selected'); 186 sel.val(clicked.data('raw-value')).trigger('change').trigger('change.fs').trigger('blur.fs').trigger('focus.fs'); 187 setTimeout(function() { 188 return sel.focus(); 189 }, 5); 190 }); 191 options.on('mousedown.fs', 'li.fs-optgroup > span', function(e) { 192 e.preventDefault(); 193 e.stopPropagation(); 194 }); 195 options.on('mouseenter.fs', 'li.fs-option', function() { 196 var hovered, nowHovered; 197 nowHovered = $(this); 198 hovered = options.find('.fs-hover'); 199 hovered.removeClass('fs-hover'); 200 nowHovered.addClass('fs-hover'); 201 }); 202 options.on('mouseleave.fs', 'li.fs-option', function() { 203 options.find('.fs-hover').removeClass('fs-hover'); 204 }); 205 copyOptionsToList = function() { 206 var generateChildren, selOpts; 207 updateTriggerText();
208 if (isiOS && !settings.forceiOS) { 209 return; 210 } 211 selOpts = sel.find('option'); 212 generateChildren = function(el, $options) { 213 el.children().each(function(i, child) { 214 var $child, $li, $optGroups, optHtml; 215 $child = $(child); 216 if ($child.prop('tagName').toLowerCase() === 'optgroup') { 217 optHtml = settings.optgroupTemplate($child); 218 $optGroups = $('<ul class="fs-optgroup"></ul>'); 219 $li = $("<li class=\"fs-optgroup\"><span>" + optHtml + "</span></li>"); 220 $li.append($optGroups); 221 $options.append($li); 222 generateChildren($child, $optGroups); 223 } else if ($child.prop('tagName').toLowerCase() === 'option') { 224 optHtml = settings.optionTemplate($child); 225 if ($child.prop('selected')) { 226 $options.append("<li data-raw-value=\"" + ($child.val()) + "\" class=\"fs-option fs-selected\">" + optHtml + "</li>"); 227 } else { 228 $options.append("<li data-raw-value=\"" + ($child.val()) + "\" class=\"fs-option\">" + optHtml + "</li>"); 229 } 230 } 231 }); 232 }; 233 generateChildren(sel, options); 234 }; 235 copyOptionsToList(); 236 }); 237 }; 238})(jQuery);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.