Advertisement
Guest User

Untitled

a guest
Aug 5th, 2017
216
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. /* =============================================================
  2.  * bootstrap-combobox.js v1.1.8
  3.  * =============================================================
  4.  * Copyright 2012 Daniel Farrell
  5.  *
  6.  * Licensed under the Apache License, Version 2.0 (the "License");
  7.  * you may not use this file except in compliance with the License.
  8.  * You may obtain a copy of the License at
  9.  *
  10.  * http://www.apache.org/licenses/LICENSE-2.0
  11.  *
  12.  * Unless required by applicable law or agreed to in writing, software
  13.  * distributed under the License is distributed on an "AS IS" BASIS,
  14.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  15.  * See the License for the specific language governing permissions and
  16.  * limitations under the License.
  17.  * ============================================================ */
  18.  
  19. (function( $ ) {
  20.  
  21.  "use strict";
  22.  
  23.  /* COMBOBOX PUBLIC CLASS DEFINITION
  24.   * ================================ */
  25.  
  26.   var Combobox = function ( element, options ) {
  27.     this.options = $.extend({}, $.fn.combobox.defaults, options);
  28.     this.template = this.options.template || this.template
  29.     this.$source = $(element);
  30.     this.$container = this.setup();
  31.     this.$element = this.$container.find('input[type=text]');
  32.     this.$target = this.$container.find('input[type=hidden]');
  33.     this.$button = this.$container.find('.dropdown-toggle');
  34.     this.$menu = $(this.options.menu).appendTo('body');
  35.     this.matcher = this.options.matcher || this.matcher;
  36.     this.sorter = this.options.sorter || this.sorter;
  37.     this.highlighter = this.options.highlighter || this.highlighter;
  38.     this.shown = false;
  39.     this.selected = false;
  40.     this.refresh();
  41.     this.transferAttributes();
  42.     this.listen();
  43.   };
  44.  
  45.   Combobox.prototype = {
  46.  
  47.     constructor: Combobox
  48.  
  49.   , setup: function () {
  50.       var combobox = $(this.template());
  51.       this.$source.before(combobox);
  52.       this.$source.hide();
  53.       return combobox;
  54.     }
  55.  
  56.   , disable: function() {
  57.       this.$element.prop('disabled', true);
  58.       this.$button.attr('disabled', true);
  59.       this.disabled = true;
  60.       this.$container.addClass('combobox-disabled');
  61.     }
  62.  
  63.   , enable: function() {
  64.       this.$element.prop('disabled', false);
  65.       this.$button.attr('disabled', false);
  66.       this.disabled = false;
  67.       this.$container.removeClass('combobox-disabled');
  68.     }
  69.   , parse: function () {
  70.       var that = this
  71.         , map = {}
  72.         , source = []
  73.         , selected = false
  74.         , selectedValue = '';
  75.       this.$source.find('option').each(function() {
  76.         var option = $(this);
  77.         if (option.val() === '') {
  78.           that.options.placeholder = option.text();
  79.           return;
  80.         }
  81.         map[option.text()] = option.val();
  82.         source.push(option.text());
  83.         if (option.prop('selected')) {
  84.           selected = option.text();
  85.           selectedValue = option.val();
  86.         }
  87.       })
  88.       this.map = map;
  89.       if (selected) {
  90.         this.$element.val(selected);
  91.         this.$target.val(selectedValue);
  92.         this.$container.addClass('combobox-selected');
  93.         this.selected = true;
  94.       }
  95.       return source;
  96.     }
  97.  
  98.   , transferAttributes: function() {
  99.     this.options.placeholder = this.$source.attr('data-placeholder') || this.options.placeholder
  100.     if(this.options.appendId !== "undefined") {
  101.         this.$element.attr('id', this.$source.attr('id') + this.options.appendId);
  102.     }
  103.     this.$element.attr('placeholder', this.options.placeholder)
  104.     this.$target.prop('name', this.$source.prop('name'))
  105.     this.$target.val(this.$source.val())
  106.     this.$source.removeAttr('name')  // Remove from source otherwise form will pass parameter twice.
  107.     this.$element.attr('required', this.$source.attr('required'))
  108.     this.$element.attr('rel', this.$source.attr('rel'))
  109.     this.$element.attr('title', this.$source.attr('title'))
  110.     this.$element.attr('class', this.$source.attr('class'))
  111.     this.$element.attr('tabindex', this.$source.attr('tabindex'))
  112.     this.$source.removeAttr('tabindex')
  113.     if (this.$source.attr('disabled')!==undefined)
  114.       this.disable();
  115.   }
  116.  
  117.   , select: function () {
  118.       var val = this.$menu.find('.active').attr('data-value');
  119.       this.$element.val(this.updater(val)).trigger('change');
  120.       this.$target.val(this.map[val]).trigger('change');
  121.       this.$source.val(this.map[val]).trigger('change');
  122.       this.$container.addClass('combobox-selected');
  123.       this.selected = true;
  124.       return this.hide();
  125.     }
  126.  
  127.   , updater: function (item) {
  128.       return item;
  129.     }
  130.  
  131.   , show: function () {
  132.       var pos = $.extend({}, this.$element.position(), {
  133.         height: this.$element[0].offsetHeight
  134.       });
  135.  
  136.       this.$menu
  137.         .insertAfter(this.$element)
  138.         .css({
  139.           top: pos.top + pos.height
  140.         , left: pos.left
  141.         })
  142.         .show();
  143.  
  144.       $('.dropdown-menu').on('mousedown', $.proxy(this.scrollSafety, this));
  145.  
  146.       this.shown = true;
  147.       return this;
  148.     }
  149.  
  150.   , hide: function () {
  151.       this.$menu.hide();
  152.       $('.dropdown-menu').off('mousedown', $.proxy(this.scrollSafety, this));
  153.       this.$element.on('blur', $.proxy(this.blur, this));
  154.       this.shown = false;
  155.       return this;
  156.     }
  157.  
  158.   , lookup: function (event) {
  159.       this.query = this.$element.val();
  160.       return this.process(this.source);
  161.     }
  162.  
  163.   , process: function (items) {
  164.       var that = this;
  165.  
  166.       items = $.grep(items, function (item) {
  167.         return that.matcher(item);
  168.       })
  169.  
  170.       items = this.sorter(items);
  171.  
  172.       if (!items.length) {
  173.         return this.shown ? this.hide() : this;
  174.       }
  175.  
  176.       return this.render(items.slice(0, this.options.items)).show();
  177.     }
  178.  
  179.   , template: function() {
  180.       if (this.options.bsVersion == '2') {
  181.         return '<div class="combobox-container"><input type="hidden" /> <div class="input-append"> <input type="text" autocomplete="off" /> <span class="add-on dropdown-toggle" data-dropdown="dropdown"> <span class="caret"/> <i class="icon-remove"/> </span> </div> </div>'
  182.       } else {
  183.         return '<div class="combobox-container"> <input type="hidden" /> <div class="input-group"> <input type="text" autocomplete="off" /> <span class="input-group-addon dropdown-toggle" data-dropdown="dropdown"> <span class="caret" /> <span class="glyphicon glyphicon-remove" /> </span> </div> </div>'
  184.       }
  185.     }
  186.  
  187.   , matcher: function (item) {
  188.       return ~item.toLowerCase().indexOf(this.query.toLowerCase());
  189.     }
  190.  
  191.   , sorter: function (items) {
  192.       var beginswith = []
  193.         , caseSensitive = []
  194.         , caseInsensitive = []
  195.         , item;
  196.  
  197.       while (item = items.shift()) {
  198.         if (!item.toLowerCase().indexOf(this.query.toLowerCase())) {beginswith.push(item);}
  199.         else if (~item.indexOf(this.query)) {caseSensitive.push(item);}
  200.         else {caseInsensitive.push(item);}
  201.       }
  202.  
  203.       return beginswith.concat(caseSensitive, caseInsensitive);
  204.     }
  205.  
  206.   , highlighter: function (item) {
  207.       var query = this.query.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, '\\$&');
  208.       return item.replace(new RegExp('(' + query + ')', 'ig'), function ($1, match) {
  209.         return '<strong>' + match + '</strong>';
  210.       })
  211.     }
  212.  
  213.   , render: function (items) {
  214.       var that = this;
  215.  
  216.       items = $(items).map(function (i, item) {
  217.         i = $(that.options.item).attr('data-value', item);
  218.         i.find('a').html(that.highlighter(item));
  219.         return i[0];
  220.       })
  221.  
  222.       items.first().addClass('active');
  223.       this.$menu.html(items);
  224.       return this;
  225.     }
  226.  
  227.   , next: function (event) {
  228.       var active = this.$menu.find('.active').removeClass('active')
  229.         , next = active.next();
  230.  
  231.       if (!next.length) {
  232.         next = $(this.$menu.find('li')[0]);
  233.       }
  234.  
  235.       next.addClass('active');
  236.     }
  237.  
  238.   , prev: function (event) {
  239.       var active = this.$menu.find('.active').removeClass('active')
  240.         , prev = active.prev();
  241.  
  242.       if (!prev.length) {
  243.         prev = this.$menu.find('li').last();
  244.       }
  245.  
  246.       prev.addClass('active');
  247.     }
  248.  
  249.   , toggle: function () {
  250.     if (!this.disabled) {
  251.       if (this.$container.hasClass('combobox-selected')) {
  252.         this.clearTarget();
  253.         this.triggerChange();
  254.         this.clearElement();
  255.       } else {
  256.         if (this.shown) {
  257.           this.hide();
  258.         } else {
  259.           this.clearElement();
  260.           this.lookup();
  261.         }
  262.       }
  263.     }
  264.   }
  265.  
  266.   , scrollSafety: function(e) {
  267.       if (e.target.tagName == 'UL') {
  268.           this.$element.off('blur');
  269.       }
  270.   }
  271.   , clearElement: function () {
  272.     this.$element.val('').focus();
  273.   }
  274.  
  275.   , clearTarget: function () {
  276.     this.$source.val('');
  277.     this.$target.val('');
  278.     this.$container.removeClass('combobox-selected');
  279.     this.selected = false;
  280.   }
  281.  
  282.   , triggerChange: function () {
  283.     this.$source.trigger('change');
  284.   }
  285.  
  286.   , refresh: function () {
  287.     this.source = this.parse();
  288.     this.options.items = this.source.length;
  289.   }
  290.  
  291.   , listen: function () {
  292.       this.$element
  293.         .on('focus',    $.proxy(this.focus, this))
  294.         .on('blur',     $.proxy(this.blur, this))
  295.         .on('keypress', $.proxy(this.keypress, this))
  296.         .on('keyup',    $.proxy(this.keyup, this));
  297.  
  298.       if (this.eventSupported('keydown')) {
  299.         this.$element.on('keydown', $.proxy(this.keydown, this));
  300.       }
  301.  
  302.       this.$menu
  303.         .on('click', $.proxy(this.click, this))
  304.         .on('mouseenter', 'li', $.proxy(this.mouseenter, this))
  305.         .on('mouseleave', 'li', $.proxy(this.mouseleave, this));
  306.  
  307.       this.$button
  308.         .on('click', $.proxy(this.toggle, this));
  309.     }
  310.  
  311.   , eventSupported: function(eventName) {
  312.       var isSupported = eventName in this.$element;
  313.       if (!isSupported) {
  314.         this.$element.setAttribute(eventName, 'return;');
  315.         isSupported = typeof this.$element[eventName] === 'function';
  316.       }
  317.       return isSupported;
  318.     }
  319.  
  320.   , move: function (e) {
  321.       if (!this.shown) {return;}
  322.  
  323.       switch(e.keyCode) {
  324.         case 9: // tab
  325.         case 13: // enter
  326.         case 27: // escape
  327.           e.preventDefault();
  328.           break;
  329.  
  330.         case 38: // up arrow
  331.           e.preventDefault();
  332.           this.prev();
  333.           this.fixMenuScroll();
  334.           break;
  335.  
  336.         case 40: // down arrow
  337.           e.preventDefault();
  338.           this.next();
  339.           this.fixMenuScroll();
  340.           break;
  341.       }
  342.  
  343.       e.stopPropagation();
  344.     }
  345.  
  346.   , fixMenuScroll: function(){
  347.       var active = this.$menu.find('.active');
  348.       if(active.length){
  349.           var top = active.position().top;
  350.           var bottom = top + active.height();
  351.           var scrollTop = this.$menu.scrollTop();
  352.           var menuHeight = this.$menu.height();
  353.           if(bottom > menuHeight){
  354.               this.$menu.scrollTop(scrollTop + bottom - menuHeight);
  355.           } else if(top < 0){
  356.               this.$menu.scrollTop(scrollTop + top);
  357.           }
  358.       }
  359.   }
  360.  
  361.   , keydown: function (e) {
  362.       this.suppressKeyPressRepeat = ~$.inArray(e.keyCode, [40,38,9,13,27]);
  363.       this.move(e);
  364.     }
  365.  
  366.   , keypress: function (e) {
  367.       if (this.suppressKeyPressRepeat) {return;}
  368.       this.move(e);
  369.     }
  370.  
  371.   , keyup: function (e) {
  372.       switch(e.keyCode) {
  373.         case 40: // down arrow
  374.          if (!this.shown){
  375.            this.toggle();
  376.          }
  377.          break;
  378.         case 39: // right arrow
  379.         case 38: // up arrow
  380.         case 37: // left arrow
  381.         case 36: // home
  382.         case 35: // end
  383.         case 16: // shift
  384.         case 17: // ctrl
  385.         case 18: // alt
  386.           break;
  387.  
  388.         case 9: // tab
  389.         case 13: // enter
  390.           if (!this.shown) {return;}
  391.           this.select();
  392.           break;
  393.  
  394.         case 27: // escape
  395.           if (!this.shown) {return;}
  396.           this.hide();
  397.           break;
  398.  
  399.         default:
  400.           this.clearTarget();
  401.           this.lookup();
  402.       }
  403.  
  404.       e.stopPropagation();
  405.       e.preventDefault();
  406.   }
  407.  
  408.   , focus: function (e) {
  409.       this.focused = true;
  410.     }
  411.  
  412.   , blur: function (e) {
  413.       var that = this;
  414.       this.focused = false;
  415.       var val = this.$element.val();
  416.       if (!this.selected && val !== '' ) {
  417.         this.$element.val('');
  418.         this.$source.val('').trigger('change');
  419.         this.$target.val('').trigger('change');
  420.       }
  421.       if (!this.mousedover && this.shown) {setTimeout(function () { that.hide(); }, 200);}
  422.     }
  423.  
  424.   , click: function (e) {
  425.       e.stopPropagation();
  426.       e.preventDefault();
  427.       this.select();
  428.       this.$element.focus();
  429.     }
  430.  
  431.   , mouseenter: function (e) {
  432.       this.mousedover = true;
  433.       this.$menu.find('.active').removeClass('active');
  434.       $(e.currentTarget).addClass('active');
  435.     }
  436.  
  437.   , mouseleave: function (e) {
  438.       this.mousedover = false;
  439.     }
  440.   };
  441.  
  442.   /* COMBOBOX PLUGIN DEFINITION
  443.    * =========================== */
  444.   $.fn.combobox = function ( option ) {
  445.     return this.each(function () {
  446.       var $this = $(this)
  447.         , data = $this.data('combobox')
  448.         , options = typeof option == 'object' && option;
  449.       if(!data) {$this.data('combobox', (data = new Combobox(this, options)));}
  450.       if (typeof option == 'string') {data[option]();}
  451.     });
  452.   };
  453.  
  454.   $.fn.combobox.defaults = {
  455.     bsVersion: '4'
  456.   , menu: '<ul class="typeahead typeahead-long dropdown-menu"></ul>'
  457.   , item: '<li><a href="#" class="dropdown-item"></a></li>'
  458.   };
  459.  
  460.   $.fn.combobox.Constructor = Combobox;
  461.  
  462. }( window.jQuery ));
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement