1/** 2 * jQuery CoreUISelect 3 * Special thanks to Artem Terekhin, Yuriy Khabarov, Alexsey Shein 4 * 5 * @author Gennadiy Ukhanov 6 * @version 0.0.3 7 */ 8(function ($) { 9 10 var defaultOption = { 11 appendToBody : false, 12 jScrollPane : null, 13 onInit : null, 14 onFocus : null, 15 onBlur : null, 16 onOpen : null, 17 onClose : null, 18 onChange : null, 19 onDestroy : null 20 } 21 22 var allSelects = []; 23 24 //$.browser.mobile = (/iphone|ipad|ipod|android/i.test(navigator.userAgent.toLowerCase())); 25 $.browser.mobile = (/iphone|ipod|android/i.test(navigator.userAgent.toLowerCase())); 26 27 //custom tsudoi 28 function getBranch(){ 29 30 //TB 31 if( 32 (navigator.userAgent.indexOf('Android') > 0 && navigator.userAgent.indexOf('Mobile') == -1) 33 || navigator.userAgent.indexOf('iPad') > 0 34 ){ 35 return 'TB' 36 } 37 38 //SP 39 else if( 40 (navigator.userAgent.indexOf('iPhone') > 0 && navigator.userAgent.indexOf('iPad') == -1) 41 || navigator.userAgent.indexOf('iPod') > 0 42 || (navigator.userAgent.indexOf('Android') > 0 && navigator.userAgent.indexOf('Mobile') > 0) 43 || navigator.userAgent.indexOf('Windows Phone') > 0 44 ){ 45 return 'SP' 46 } 47 48 //PC 49 else{ 50 return 'PC' 51 } 52 } 53 54 //custom tsudoi 55 if( getBranch() == 'SP' ){ 56 $.browser.mobile = true; 57 } 58 else{ 59 $.browser.mobile = false; 60 } 61 62 var isAndroid = (/android/i.test(navigator.userAgent.toLowerCase())); 63 64 $.browser.operamini = Object.prototype.toString.call(window.operamini) === "[object OperaMini]"; 65 66 /** 67 * CoreUISelect - stylized standard select 68 * @constructor 69 */ 70 function CoreUISelect(__elem, __options, __templates) { 71 72 this.domSelect = __elem; 73 this.settings = __options || defaultOption; 74 this.isSelectShow = false; 75 this.isSelectFocus = false; 76 this.isJScrollPane = this.isJScrollPane(); 77 78 // templates 79 this.templates = __templates || 80 { 81 select : { 82 container : '<div class="b-core-ui-select"></div>', 83 value : '<span class="b-core-ui-select__value"></span>', 84 button : '<span class="b-core-ui-select__button"></span>' 85 }, 86 dropdown : { 87 container : '<div class="b-core-ui-select__dropdown"></div>', 88 wrapper : '<div class="b-core-ui-select__dropdown__wrap"></div>', 89 list : '<ul class="b-core-ui-select__dropdown__list"></ul>', 90 optionLabel : '<li class="b-core-ui-select__dropdown__label"></li>', 91 item : '<li class="b-core-ui-select__dropdown__item"></li>' 92 } 93 } 94 95 this.init(this.settings); 96 } 97 98 CoreUISelect.prototype.init = function() { 99 100 if($.browser.operamini) return this; 101 102 this.buildUI(); 103 104 this.hideDomSelect(); 105 106 if(this.domSelect.is(':disabled')) { 107 this.select.addClass('disabled'); 108 return this; 109 } 110 if(this.isJScrollPane) this.buildJScrollPane(); 111 this.bindUIEvents(); 112 this.settings.onInit && this.settings.onInit.apply(this, [this.domSelect, 'init']); 113 114 } 115 116 CoreUISelect.prototype.buildUI = function() { 117 118 // Build select container 119 if(!$.browser.mobile){ 120 this.select = $(this.templates.select.container).insertBefore(this.domSelect); 121 this.selectValue = $(this.templates.select.value).appendTo(this.select); 122 } 123 124 // TODO Add custom states for button 125 this.selectButton = $(this.templates.select.button) 126 .appendTo(this.select); 127 128 // Build dropdown container 129 this.dropdown = $(this.templates.dropdown.container); 130 this.dropdownWrapper = $(this.templates.dropdown.wrapper).appendTo(this.dropdown); 131 132 this.settings.appendToBody ? this.dropdown.appendTo($('body')) : this.dropdown.insertBefore(this.domSelect); 133 134 // Build dropdown 135 this.dropdownList = $(this.templates.dropdown.list).appendTo(this.dropdownWrapper); 136 this.domSelect.find('option').each($.proxy(this, 'addItems')); 137 138 // Build dropdown 139 this.dropdownItem = this.dropdown.find('.'+$(this.templates.dropdown.item).attr('class')); 140 141 // Add classes for dropdown 142 this.dropdownItem.filter(':first-child').addClass('first'); 143 this.dropdownItem.filter(':last-child').addClass('last'); 144 145 this.addOptionGroup(); 146 147 // Add placeholder value by selected option
148 this.setSelectValue( this.getSelectedItem().text() ); 149 150 this.updateDropdownPosition(); 151 152 // Set current item form option:selected 153 this.currentItemOfDomSelect = this.currentItemOfDomSelect || this.domSelect.find('option:selected'); 154 155 } 156 157 CoreUISelect.prototype.hideDomSelect = function() { 158 159 this.domSelect.addClass('b-core-ui-select__select_state_hide'); 160 this.domSelect.css({ 161 'top' : this.select.position().top, 162 'left' : this.select.position().left 163 }); 164 165 166 167 } 168 169 CoreUISelect.prototype.showDomSelect = function() { 170 this.domSelect.css({ 171 'top' : 'auto', 172 'left' : 'auto' 173 }) 174 this.domSelect.removeClass('b-core-ui-select__select_state_hide') ; 175 176 } 177 178 CoreUISelect.prototype.bindUIEvents = function() { 179 180 // Bind plugin elements 181 this.domSelect.bind('focus', $.proxy(this, 'onFocus')); 182 this.domSelect.bind('blur', $.proxy(this, 'onBlur')); 183 this.domSelect.bind('change', $.proxy(this, 'onChange')); 184 185 if( $.browser.mobile) this.domSelect.bind('change', $.proxy(this, 'changeDropdownData')); 186 187 this.select.bind('click', $.proxy(this, 'onSelectClick')); 188 this.dropdownItem.bind('click', $.proxy(this, 'onDropdownItemClick')); 189 190 } 191 192 CoreUISelect.prototype.getCurrentIndexOfItem = function(__item) { 193 return this.domSelect.find('option').index($(this.domSelect).find('option:selected')); 194 } 195 196 CoreUISelect.prototype.scrollToCurrentDropdownItem = function(__item) { 197 if(this.dropdownWrapper.data('jsp')) { 198 this.dropdownWrapper.data('jsp').scrollToElement(__item); 199 return this; 200 } 201 // Alternative scroll to element 202 $(this.dropdownWrapper) 203 .scrollTop($(this.dropdownWrapper) 204 .scrollTop() + __item.position().top - $(this.dropdownWrapper).height()/2 + __item.height()/2); 205 } 206 207 CoreUISelect.prototype.buildJScrollPane = function() { 208 this.dropdownWrapper.wrap($('<div class="j-scroll-pane"></div>')); 209 } 210 211 CoreUISelect.prototype.isJScrollPane = function() { 212 if(this.settings.jScrollPane) { 213 if($.fn.jScrollPane) return true; 214 else throw new Error('jScrollPane no found'); 215 } 216 } 217 218 CoreUISelect.prototype.initJScrollPane = function () { 219 this.dropdownWrapper.jScrollPane(this.settings.jScrollPane); 220 } 221 222 CoreUISelect.prototype.showDropdown = function() { 223 224 if( $.browser.mobile ){ 225 this.domSelect.focus(); 226 } 227 else{ 228 } 229 230 this.settings.onOpen && this.settings.onOpen.apply(this, [this.domSelect, 'open']); 231 232 if($.browser.mobile) return this; 233 234 if(!this.isSelectShow) { 235 this.isSelectShow = true; 236 this.select.addClass('open'); 237 this.dropdown.addClass('show').removeClass('hide'); 238 if(this.isJScrollPane) this.initJScrollPane(); 239 this.scrollToCurrentDropdownItem(this.dropdownItem.eq(this.getCurrentIndexOfItem(
239))); 240 this.updateDropdownPosition(); 241 } 242 243 } 244 245 CoreUISelect.prototype.hideDropdown = function() { 246 if(this.isSelectShow) { 247 this.isSelectShow = false; 248 this.select.removeClass('open'); 249 this.dropdown.removeClass('show').addClass('hide'); 250 this.settings.onClose && this.settings.onClose.apply(this, [this.domSelect, 'close']); 251 } 252 if(this.isSelectFocus) this.domSelect.focus(); 253 254 } 255 256 CoreUISelect.prototype.hideAllDropdown = function() { 257 for(var i in allSelects) { 258 if(allSelects[i].hasOwnProperty(i)) { 259 allSelects.dropdown.isSelectShow = false; 260 allSelects.dropdown.domSelect.blur(); 261 allSelects.dropdown.addClass('hide').removeClass('show'); 262 } 263 } 264 } 265 266 CoreUISelect.prototype.changeDropdownData = function(event) { 267 268 if((this.isSelectShow || this.isSelectFocus)) { 269 this.currentItemOfDomSelect = this.domSelect.find('option:selected'); 270 this.dropdownItem.removeClass("selected");
271 this.dropdownItem.eq(this.getCurrentIndexOfItem()).addClass("selected"); 272 this.scrollToCurrentDropdownItem(this.dropdownItem.eq(this.getCurrentIndexOfItem())); 273 this.setSelectValue(this.currentItemOfDomSelect.text()); 274 275 } 276 277 if($.browser.mobile) this.settings.onChange && this.settings.onChange.apply(this, [this.domSelect, 'change']); 278 } 279 280 CoreUISelect.prototype.onDomSelectChange = function(_is) { 281 this.domSelect.bind('change', $.proxy(this, 'onChange')); 282 dispatchEvent(this.domSelect.get(0), 'change'); 283 if(!_is) this.settings.onChange && this.settings.onChange.apply(this, [this.domSelect, 'change']); 284 } 285 286 CoreUISelect.prototype.addListenerByServicesKey = function(event) { 287 if(this.isSelectShow) { 288 switch (event.which) { 289 case 9: // TAB 290 case 13: // ESQ 291 case 27: // ENTER 292 this.hideDropdown(); 293 break; 294 } 295 } 296 } 297 298 CoreUISelect.prototype.onSelectClick = function() { 299 //alert('onSelectClick'); 300 if(!this.isSelectShow) this.showDropdown(); 301 else this.hideDropdown(); 302 return false; 303 } 304 305 CoreUISelect.prototype.onFocus = function () { 306 this.isDocumentMouseDown = false; 307 this.isSelectFocus = true; 308 this.select.addClass('focus'); 309 this.settings.onFocus && this.settings.onFocus.apply(this, [this.domSelect, 'focus']); 310 } 311 312 CoreUISelect.prototype.onBlur = function() { 313 if(!this.isDocumentMouseDown) { 314 this.isSelectFocus = false; 315 this.select.removeClass('focus'); 316 this.settings.onBlur && this.settings.onBlur.apply(this, [this.domSelect, 'blur']); 317 //this.hideDropdown(); 318 } 319 } 320 321 CoreUISelect.prototype.onChange = function () { 322 this.settings.onChange && this.settings.onChange.apply(this, [this.domSelect, 'change']); 323 } 324 325 CoreUISelect.prototype.onDropdownItemClick = function(event) { 326 var item = $(event.currentTarget); 327 if(!(item.hasClass('disabled') || item.hasClass('selected'))) { 328 this.domSelect.unbind('change', $.proxy(this, 'onChange')); 329 var index = this.dropdown.find('.'+$(this.templates.dropdown.item).attr('class')).index(item) 330 this.dropdownItem.removeClass('selected'); 331 this.dropdownItem.eq(index).addClass('selected'); 332 this.domSelect.find('option').removeAttr('selected'); 333 this.domSelect.find('option').eq(index).attr('selected', true); 334 this.setSelectValue(this.getSelectedItem().text()); 335 this.onDomSelectChange(true); 336 337 } 338 this.hideDropdown(); 339 return false; 340 } 341 342 CoreUISelect.prototype.onDocumentMouseDown = function(event) { 343 344 this.isDocumentMouseDown = true; 345 346 //alert('onDocumentMouseDown'); 347 348 if( 349 $(event.target).closest(this.select).length == 0 350 && $(event.target).closest(this.dropdown).length== 0 351 ){ 352 353 if($(event.target).closest('option').length==0) { // Hack for Opera 354 355 //alert('a'); 356 357 this.isDocumentMouseDown = false; 358 this.hideDropdown(); 359 360 } 361 } 362 363 return false; 364 365 } 366 367 CoreUISelect.prototype.updateDropdownPosition = function() { 368 if(this.isSelectShow) { 369 if(this.settings.appendToBody) { 370 this.dropdown.css({ 371 'position' : 'absolute', 372 'top' : this.select.offset().top+this.select.outerHeight(true), 373 'left' : this.select.offset().left, 374 'z-index' : '9999' 375 }); 376 } else { 377 this.dropdown.css({ 378 'position' : 'absolute', 379 'top' : this.select.position().top+this.select.outerHeight(true), 380 'left' : this.select.position().left, 381 'z-index' : '9999' 382 }); 383 } 384 385 var marginDifferenceBySelect = this.select.outerWidth() - this.select.width(); 386 var marginDifferenceByDropdown = this.dropdown.outerWidth() - this.dropdown.width(); 387 388 this.dropdown.width(this.select.outerWidth(true)); 389 390 if(this.dropdown.width() == this.select.outerWidth()) { 391 this.dropdown.width((this.select.width()+marginDifferenceBySelect)-marginDifferenceByDropdown); 392 } 393 394 if(this.isJScrollPane) this.initJScrollPane(); 395 } 396 } 397 398 CoreUISelect.prototype.setSelectValue = function(_text) { 399 this.selectValue.text(_text); 400 } 401 402 CoreUISelect.prototype.isOptionGroup = function() { 403 return this.domSelect.find('optgroup').length>0; 404 } 405 406 CoreUISelect.prototype.addOptionGroup = function() { 407 var optionGroup = this.domSelect.find('optgroup'); 408 for(var i=0; i<optionGroup.length; i++) { 409 var index = this.domSelect.find("option").index($(optionGroup[i]).find('option:first-child')) 410 $(this.templates.dropdown.optionLabel) 411 .text($(optionGroup[i]).attr('label')) 412 .insertBefore(this.dropdownItem.eq(index)); 413 } 414 } 415 416 CoreUISelect.prototype.addItems = function(index, el) { 417 var el = $(el); 418 var item = $(this.templates.dropdown.item).text(el.text()); 419 if(el.attr("disabled")) item.addClass('disabled'); 420 if(el.attr("selected")) { 421 this.domSelect.find('option').removeAttr('selected'); 422 item.addClass('selected'); 423 el.attr('selected', 'selected'); 424 } 425 426 item.addClass('cell'+index%2); 427 428 item.appendTo(this.dropdownList); 429 } 430 431 CoreUISelect.prototype.getSelectedItem = function() { 432 return this.dropdown.find('.selected').eq(0); 433 } 434 435 CoreUISelect.prototype.update = function() { 436 this.destroy(); 437 this.init(); 438 } 439 440 CoreUISelect.prototype.destroy = function() { 441 // Unbind plugin elements 442 this.domSelect.unbind('focus', $.proxy(this, 'onFocus')); 443 this.domSelect.unbind('blur', $.proxy(this, 'onBlur')); 444 this.domSelect.unbind('change', $.proxy(this, 'onChange'));
445 this.select.unbind('click', $.proxy(this, 'onSelectClick')); 446 this.dropdownItem.unbind('click', $.proxy(this, 'onDropdownItemClick')); 447 // Remove select container 448 this.select.remove(); 449 this.dropdown.remove(); 450 this.showDomSelect(); 451 this.settings.onDestroy && this.settings.onDestroy.apply(this, [this.domSelect, 'destroy']); 452 } 453 454 455 $.fn.coreUISelect = function(__options, __templates) { 456 return this.each(function () { 457 var select = $(this).data('coreUISelect'); 458 if(__options == 'destroy' && !select) return; 459 if(select){ 460 __options = (typeof __options == "string" && select[__options]) ? __options : 'update'; 461 select[__options].apply(select); 462 if(__options == 'destroy') { 463 $(this).removeData('coreUISelect'); 464 for(var i=0; i<allSelects.length; i++) { 465 if(allSelects[i] == select) { 466 allSelects.splice(i, 1); 467 break; 468 } 469 } 470 } 471 } else { 472 select = new CoreUISelect($(this), __options, __templates); 473 allSelects.push(select); 474 $(this).data('coreUISelect', select); 475 476 } 477 478 }); 479 }; 480 481 function dispatchEvent(obj, evt, doc) { 482 var doc = doc || document; 483 if(obj!==undefined || obj!==null) { 484 if (doc.createEvent) { 485 var evObj = doc.createEvent('MouseEvents'); 486 evObj.initEvent(evt, true, false); 487 obj.dispatchEvent(evObj); 488 } else if (doc.createEventObject) { 489 var evObj = doc.createEventObject(); 490 obj.fireEvent('on' + evt, evObj); 491 } 492 } 493 } 494 495 $(document).bind('mousedown', function(event){ 496 497 /* 498 for(var i=0; i<allSelects.length; i++){ 499 allSelects[i].onDocumentMouseDown(event); 500 } 501 */ 502 503 //custom tsudoi 504 //if( $.browser.mobile ){ 505 for(var i=0; i<allSelects.length; i++){ 506 allSelects[i].onDocumentMouseDown(event); 507 } 508 //} 509 //else{ 510 //CoreUISelect.prototype.onSelectClick(); 511 //alert('s'); 512 //return false; 513 //} 514 515 }); 516 517 $(document).bind('keyup', function(event){ 518 519 for(var i=0; i<allSelects.length; i++){ 520 if($.browser.safari || $.browser.msie || $.browser.opera) allSelects[i].changeDropdownData(event); // Hack for Safari 521 allSelects[i].addListenerByServicesKey(event); 522 } 523 524 }); 525 526 $(document).bind($.browser.safari ? 'keydown' : 'keypress', function(event){ 527 for(var i=0; i<allSelects.length; i++){ 528 allSelects[i].changeDropdownData(event); 529 } 530 }); 531 532 $(window).bind('resize', function(event){ 533 for(var i=0; i<allSelects.length; i++){ 534 allSelects[i].updateDropdownPosition(event); 535 } 536 }); 537 538 539 540})(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.