/* * Alternate Select Multiple (asmSelect) 1.0.4a beta - jQuery Plugin * http://www.ryancramer.com/projects/asmselect/ * * Copyright (c) 2009 by Ryan Cramer - http://www.ryancramer.com * * Dual licensed under the MIT (MIT-LICENSE.txt) * and GPL (GPL-LICENSE.txt) licenses. * */ // The references to $.browser where commented out because it // breaks with newer version of jQuery. (function($) { $.fn.asmSelect = function(customOptions) { var options = { listType: 'ol', // Ordered list 'ol', or unordered list 'ul' sortable: false, // Should the list be sortable? highlight: false, // Use the highlight feature? animate: false, // Animate the the adding/removing of items in the list? 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 removeLabel: 'remove', // Text used in the "remove" link highlightAddedLabel: 'Added: ', // Text that precedes highlight of added item highlightRemovedLabel: 'Removed: ', // Text that precedes highlight of removed item containerClass: 'asmContainer', // Class for container that wraps this widget selectClass: 'asmSelect', // Class for the newly created ") .addClass(options.selectClass) .attr('name', options.selectClass + index) .attr('id', options.selectClass + index); $selectRemoved = $(""); $ol = $("<" + options.listType + ">") .addClass(options.listClass) .attr('id', options.listClass + index); $container = $("
") .addClass(options.containerClass) .attr('id', options.containerClass + index); buildSelect(); $select.change(selectChangeEvent) .click(selectClickEvent); $original.change(originalChangeEvent) .wrap($container).before($select).before($ol); if(options.sortable) makeSortable(); // if($.browser.msie && $.browser.version < 8) $ol.css('display', 'inline-block'); // Thanks Matthew Hutton } function makeSortable() { // make any items in the selected list sortable // requires jQuery UI sortables, draggables, droppables $ol.sortable({ items: 'li.' + options.listItemClass, handle: '.' + options.listItemLabelClass, axis: 'y', update: function(e, data) { var updatedOptionId; $(this).children("li").each(function(n) { $option = $('#' + $(this).attr('rel')); if($(this).is(".ui-sortable-helper")) { updatedOptionId = $option.attr('id'); return; } $original.append($option); }); if(updatedOptionId) triggerOriginalChange(updatedOptionId, 'sort'); } }).addClass(options.listSortableClass); } function selectChangeEvent(e) { // an item has been selected on the regular select we created // check to make sure it's not an IE screwup, and add it to the list // if($.browser.msie && $.browser.version < 7 && !ieClick) return; var id = $(this).children("option:selected").slice(0,1).attr('rel'); addListItem(id); ieClick = false; triggerOriginalChange(id, 'add'); // for use by user-defined callbacks } function selectClickEvent() { // 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? ieClick = true; } function originalChangeEvent(e) { // select or option change event manually triggered // on the original // used only by buildSelect() if(disabled == undefined) var disabled = false; var $O = $('#' + optionId); var $option = $("") .val($O.val()) .attr('rel', optionId); if(disabled) disableSelectOption($option); $select.append($option); } function selectFirstItem() { // select the firm item from the regular select that we created $select.children(":eq(0)").attr("selected", true); } function disableSelectOption($option) { // 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 $option.addClass(options.optionDisabledClass) .attr("selected", false) .attr("disabled", true); if(options.hideWhenAdded) $option.hide(); // if($.browser.msie) $select.hide().show(); // this forces IE to update display if(true) $select.hide().show(); // this forces IE to update display } function enableSelectOption($option) { // given an already disabled select option, enable it $option.removeClass(options.optionDisabledClass) .attr("disabled", false); if(options.hideWhenAdded) $option.show(); // if($.browser.msie) $select.hide().show(); // this forces IE to update display if(true) $select.hide().show(); // this forces IE to update display } function addListItem(optionId) { // add a new item to the html list var $O = $('#' + optionId); if(!$O) return; // this is the first item, selectLabel var $removeLink = $("") .attr("href", "#") .addClass(options.removeClass) .prepend(options.removeLabel) .click(function() { dropListItem($(this).parent('li').attr('rel')); return false; }); var $itemLabel = $("") .addClass(options.listItemLabelClass) .html($O.html()); var $item = $("
  • ") .attr('rel', optionId) .addClass(options.listItemClass) .append($itemLabel) .append($removeLink) .hide(); if(!buildingSelect) { if($O.is(":selected")) return; // already have it $O.attr('selected', true); } if(options.addItemTarget == 'top' && !buildingSelect) { $ol.prepend($item); if(options.sortable) $original.prepend($O); } else { $ol.append($item); if(options.sortable) $original.append($O); } addListItemShow($item); disableSelectOption($("[rel=" + optionId + "]", $select)); if(!buildingSelect) { setHighlight($item, options.highlightAddedLabel); selectFirstItem(); if(options.sortable) $ol.sortable("refresh"); } } function addListItemShow($item) { // reveal the currently hidden item with optional animation // used only by addListItem() if(options.animate && !buildingSelect) { $item.animate({ opacity: "show", height: "show" }, 100, "swing", function() { $item.animate({ height: "+=2px" }, 50, "swing", function() { $item.animate({ height: "-=2px" }, 25, "swing"); }); }); } else { $item.show(); } } function dropListItem(optionId, highlightItem) { // remove an item from the html list if(highlightItem == undefined) var highlightItem = true; var $O = $('#' + optionId); $O.attr('selected', false); $item = $ol.children("li[rel=" + optionId + "]"); dropListItemHide($item); enableSelectOption($("[rel=" + optionId + "]", options.removeWhenAdded ? $selectRemoved : $select)); if(highlightItem) setHighlight($item, options.highlightRemovedLabel); triggerOriginalChange(optionId, 'drop'); } function dropListItemHide($item) { // remove the currently visible item with optional animation // used only by dropListItem() if(options.animate && !buildingSelect) { $prevItem = $item.prev("li"); $item.animate({ opacity: "hide", height: "hide" }, 100, "linear", function() { $prevItem.animate({ height: "-=2px" }, 50, "swing", function() { $prevItem.animate({ height: "+=2px" }, 100, "swing"); }); $item.remove(); }); } else { $item.remove(); } } function setHighlight($item, label) { // set the contents of the highlight area that appears // directly after the