diff options
Diffstat (limited to 'chimere/static/bsmSelect/js/jquery.bsmselect.js')
| -rw-r--r-- | chimere/static/bsmSelect/js/jquery.bsmselect.js | 386 | 
1 files changed, 386 insertions, 0 deletions
| diff --git a/chimere/static/bsmSelect/js/jquery.bsmselect.js b/chimere/static/bsmSelect/js/jquery.bsmselect.js new file mode 100644 index 0000000..7751418 --- /dev/null +++ b/chimere/static/bsmSelect/js/jquery.bsmselect.js @@ -0,0 +1,386 @@ +/* + * Better Select Multiple - jQuery Plugin + * + * based on Alternate Select Multiple (asmSelect) 1.0.4a beta (http://www.ryancramer.com/projects/asmselect/) + * + * Copyright (c) 2009 by Ryan Cramer - http://www.ryancramer.com + * Copyright (c) 2010-2013 by Victor Berchet - http://www.github.com/vicb + * + * Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses. + * + * bsmSelect version: v1.4.7 - 2013-12-19 + */ + +(function($) { + +  function BsmSelect(target, options) +  { +    this.$original = $(target);             // the original select multiple +    this.buildingSelect = false;            // is the new select being constructed right now? +    this.ieClick = false;                   // in IE, has a click event occurred? ignore if not +    this.ignoreOriginalChangeEvent = false; // originalChangeEvent bypassed when this is true +    this.options = options; +    this.buildDom(); +  } + +  BsmSelect.prototype = { +    /** +     * Generate an UID +     */ +    generateUid: function(index) { +      return (this.uid = this.options.containerClass + index); +    }, + +    /** +     * Build the DOM for bsmSelect +     */ +    buildDom: function() { +      var self = this, o = this.options; + +      if (o.addItemTarget === 'original') { +        $('option', this.$original).each(function(i, o) { +          if ($(o).data('bsm-order') === undefined) { $(o).data('bsm-order', i); } +        }); +      } + +      for (var index = 0; $('#' + this.generateUid(index)).size(); index++) {} + +      this.$select = $('<select>', { +        'class': o.selectClass, +        id: o.selectClass + this.uid, +        change: $.proxy(this.selectChangeEvent, this), +        click: $.proxy(this.selectClickEvent, this) +      }); + +      this.$list = $.isFunction(o.listType) +        ? o.listType(this.$original) +        : $('<' + o.listType + '>', { id: o.listClass + this.uid }); + +      this.$list.addClass(o.listClass); + +      this.$container = $('<div>', { 'class':  o.containerClass, id: this.uid }); + +      this.buildSelect(); + +      this.$original.change($.proxy(this.originalChangeEvent, this)).wrap(this.$container).before(this.$select); + +      // if the list isn't already in the document, add it (it might be inserted by a custom callback) +      if (!this.$list.parent().length) { this.$original.before(this.$list); } + +      if (this.$original.attr('id')) { +        $("label[for='" + this.$original.attr('id') + "']").attr('for', this.$select.attr('id')); +      } + +      // set up remove event (may be a link, or the list item itself) +      this.$list.delegate('.' + o.removeClass, 'click', function() { +        self.dropListItem($(this).closest('li')); +        return false; +      }); + +      $.each(o.plugins, function() { this.init(self); }); +    }, + +    /** +     * Triggered when an item has been selected +     * Check to make sure it's not an IE screwup, and add it to the list +     */ +    selectChangeEvent: function() { +      if ($.browser && $.browser.msie && $.browser.version < 7 && !this.ieClick) { return; } +      var bsmOpt = $('option:selected:eq(0)', this.$select); +      if (bsmOpt.data('orig-option')) { +        if (this.triggerOriginalChange(bsmOpt.data('orig-option'), 'add') == false) { +          this.addListItem(bsmOpt); +        } +      } +      this.ieClick = false; +    }, + +    /** +     * IE6 lets you scroll around in a select without it being pulled down +     * making sure a click preceded the change() event reduces the chance +     * if unintended items being added. there may be a better solution? +     */ +    selectClickEvent: function() { +      this.ieClick = true; +    }, + +    /** +     * Rebuild bsmSelect when the 'change' event is triggered on the original select +     */ +    originalChangeEvent: function() { +      if (this.ignoreOriginalChangeEvent) { +        // We don't want to rebuild everything when an item is added / droped +        this.ignoreOriginalChangeEvent = false; +      } else { +        this.buildSelect(); +        // opera has an issue where it needs a force redraw, otherwise +        // the items won't appear until something else forces a redraw +        if ($.browser && $.browser.opera) { this.$list.hide().show(); } +      } +    }, + +    /** +     * Build the DOM for the new select +     */ +    buildSelect: function() { +      var self = this; + +      this.buildingSelect = true; + +      // add a first option to be the home option / default selectLabel +      this.$select.empty().prepend($('<option value=""></option>').text(this.$original.attr('title') || this.options.title)); +      this.$list.empty(); + +      this.$original.children().each(function() { +        if ($(this).is('option')) { +          self.addSelectOption(self.$select, $(this)); +        } else if ($(this).is('optgroup')) { +          self.addSelectOptionGroup(self.$select, $(this)); +        } +      }); + +      if (!this.options.debugMode) { this.$original.hide(); } +      this.selectFirstItem(); +      this.buildingSelect = false; +    }, + +    /** +     * Append an option to the new select +     * +     * @param {jQuery} $parent Where to append the option +     * @param {jQuery} $origOpt Option from the original select +     */ +     addSelectOption: function ($parent, $origOpt) { +     var $bsmOpt = $('<option>', { +        text: $origOpt.text(), +        val: $origOpt.val() }).appendTo($parent).data('orig-option', $origOpt), +      isSelected = $origOpt.is(':selected'), +      isDisabled = $origOpt.is(':disabled'); +      $origOpt.data('bsm-option', $bsmOpt); +      if (isSelected && !isDisabled) { +        this.addListItem($bsmOpt); +        this.disableSelectOption($bsmOpt); +      } else if (!isSelected && isDisabled) { +        this.disableSelectOption($bsmOpt); +      } +    }, + +    /** +     * Append an option group to the new select +     * +     * @param {jQuery} $parent Where to append the group +     * @param {jQuery} $group  Model group from the original select +     */ +    addSelectOptionGroup: function($parent, $group) +    { +      var self = this, +        $G = $('<optgroup>', { label: $group.attr('label')} ).appendTo($parent); +      if ($group.is(':disabled')) { $G.attr('disabled', 'disabled'); } +      $('option', $group).each(function() { self.addSelectOption($G, $(this)); }); +    }, + +    /** +     * Select the first item of the new select +     */ +    selectFirstItem: function() { +      $('option:eq(0)', this.$select).attr('selected', 'selected'); +    }, + +    /** +     * Make an option disabled, indicating that it's already been selected +     * because safari is the only browser that makes disabled items look 'disabled' +     * we apply a class that reproduces the disabled look in other browsers +     * +     * @param {jQuery} $bsmOpt Option from the new select +     */ +    disableSelectOption: function($bsmOpt) { +      $bsmOpt.addClass(this.options.optionDisabledClass) +        .removeAttr('selected') +        .attr('disabled', 'disabled') +        .toggle(!this.options.hideWhenAdded); +      if ($.browser && $.browser.msie && $.browser.version < 8) { this.$select.hide().show(); } // this forces IE to update display +    }, + +    /** +     * Enable a select option +     * +     * @param {jQuery} $bsmOpt Option from the new select +     */ +    enableSelectOption: function($bsmOpt) { +      $bsmOpt.removeClass(this.options.optionDisabledClass) +        .removeAttr('disabled') +        .toggle(!this.options.hideWhenAdded); +      if ($.browser && $.browser.msie && $.browser.version < 8) { this.$select.hide().show(); } // this forces IE to update display +    }, + +    /** +     * Append an item corresponding to the option to the list +     * +     * @param {jQuery} $bsmOpt Option from the new select +     */ +    addListItem: function($bsmOpt) { +      var $item, +        $origOpt = $bsmOpt.data('orig-option'), +        o = this.options; + +      if (!$origOpt) { return; } // this is the first item, selectLabel + +      if (!this.buildingSelect) { +        if ($origOpt.is(':selected')) { return; } // already have it +        $origOpt.attr('selected', 'selected'); +      } + +      $item = $('<li>', { 'class': o.listItemClass }) +        .append($('<span>', { 'class': o.listItemLabelClass, html: o.extractLabel($bsmOpt, o)})) +        .append($('<a>', { href: '#', 'class': o.removeClass, html: o.removeLabel })) +        .data('bsm-option', $bsmOpt); + +      this.disableSelectOption($bsmOpt.data('item', $item)); + +      switch (o.addItemTarget) { +        case 'bottom': +          this.$list.append($item.hide()); +          break; +        case 'original': +          var order = $origOpt.data('bsm-order'), inserted = false; +          this.$list.children().each(function() { +            if (order < $(this).data('bsm-option').data('orig-option').data('bsm-order')) { +              $item.hide().insertBefore(this); +              inserted = true; +              return false; +            } +          }); +          if (!inserted) { this.$list.append($item.hide()); } +          break; +        default: +          this.$list.prepend($item.hide()); +      } + +      if (this.buildingSelect) { +        $.bsmSelect.effects.show($item); +      } else { +        o.showEffect($item); +        o.highlightEffect(this.$select, $item, o.highlightAddedLabel, this.options); +        this.selectFirstItem(); +      } +    }, + +    /** +     * Remove an item from the list of selection +     * +     * @param {jQuery} $item A list item +     */ +    dropListItem: function($item) { +      var $bsmOpt = $item.data('bsm-option'), o = this.options; +      if (this.triggerOriginalChange($bsmOpt.data('orig-option'), 'drop') == false) { +        $bsmOpt.removeData('item').data('orig-option').removeAttr('selected'); +        (this.buildingSelect ? $.bsmSelect.effects.remove : o.hideEffect)($item); +        this.enableSelectOption($bsmOpt); +        o.highlightEffect(this.$select, $item, o.highlightRemovedLabel, o); +      } +    }, + +    /** +     * Trigger a change event on the original select multiple +     * so that other scripts can pick them up +     * +     * @param {jQuery} $origOpt The option from the original select +     * @param {String} type     Event type +     * +     * @return Whether the event default is prevented +     */ +    triggerOriginalChange: function($origOpt, type) { +      var event = $.Event('change'); +      this.ignoreOriginalChangeEvent = true; +      this.$original.trigger(event, [{ +        option: $origOpt, +        value: $origOpt.val(), +        item: $origOpt.data('bsm-option').data('item'), +        type: type +      }]); +      return event.isDefaultPrevented(); +    } +  }; + +  $.fn.bsmSelect = function(customOptions) { +    var options = $.extend({}, $.bsmSelect.conf, customOptions); +    return this.each(function() { +      var bsm = $(this).data("bsmSelect"); +      if (!bsm) { +        bsm = new BsmSelect($(this), options); +        $(this).data("bsmSelect", bsm); +      } +    }); +  }; + +  $.bsmSelect = {}; +  $.extend($.bsmSelect, { +    effects: { +      show: function($el) { $el.show(); }, + +      remove: function($el) { $el.remove(); }, + +      highlight: function ($select, $item, label, conf) { +        var $highlight, +          id = $select.attr('id') + conf.highlightClass; +        $('#' + id).remove(); +        $highlight = $('<span>', { +          'class': conf.highlightClass, +          id: id, +          html: label + $item.children('.' + conf.listItemLabelClass).first().text() +        }).hide(); +        $select.after($highlight.fadeIn('fast').delay(50).fadeOut('slow', function() { $(this).remove(); })); +      }, + +      verticalListAdd: function ($el) { +        $el.animate({ opacity: 'show', height: 'show' }, 100, function() { +          $(this).animate({ height: '+=2px' }, 100, function() { +            $(this).animate({ height: '-=2px' }, 100); +          }); +        }); +      }, + +      verticalListRemove: function($el) { +        $el.animate({ opacity: 'hide', height: 'hide' }, 100, function() { +          $(this).prev('li').animate({ height: '-=2px' }, 100, function() { +            $(this).animate({ height: '+=2px' }, 100); +          }); +          $(this).remove(); +        }); +      } +    }, +    plugins: { +    } +  }); + +  // Default configuration +  $.bsmSelect.conf = { +    listType: 'ol',                             // Ordered list 'ol', or unordered list 'ul' + +    showEffect: $.bsmSelect.effects.show, +    hideEffect: $.bsmSelect.effects.remove, +    highlightEffect: $.noop, + +    addItemTarget: 'bottom',                    // Where to place new selected items in list: top or bottom +    hideWhenAdded: false,                       // Hide the option when added to the list? works only in FF +    debugMode: false,                           // Debug mode keeps original select visible + +    title: 'Select...',                         // Text used for the default select label +    removeLabel: 'remove',                      // HTML used for the 'remove' link +    highlightAddedLabel: 'Added: ',             // Text that precedes highlight of added item +    highlightRemovedLabel: 'Removed: ',         // Text that precedes highlight of removed item +    extractLabel: function($o) { return $o.html(); }, + +    plugins: [],                                // An array of plugin objects to enable + +    containerClass: 'bsmContainer',             // Class for container that wraps this widget +    selectClass: 'bsmSelect',                   // Class for the newly created <select> +    optionDisabledClass: 'bsmOptionDisabled',   // Class for items that are already selected / disabled +    listClass: 'bsmList',                       // Class for the list ($list) +    listItemClass: 'bsmListItem',               // Class for the <li> list items +    listItemLabelClass: 'bsmListItemLabel',     // Class for the label text that appears in list items +    removeClass: 'bsmListItemRemove',           // Class given to the 'remove' link +    highlightClass: 'bsmHighlight'              // Class given to the highlight <span> +  }; + +})(jQuery); | 
