├── LICENSE ├── README.md └── dist ├── dual-list-box.min.js └── dual-list-box.js /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2014 Geodan B.V. (Alex van den Hoogen) 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Bootstrap Dual List Box 2 | 3 | ## Synopsis 4 | 5 | Bootstrap Dual List Box is a dual list box implementation especially designed for Bootstrap and jQuery. This control is 6 | quite easy for users to understand and use. Also it is possible to work with very large multi-selects without confusing 7 | the user. 8 | 9 | ## Usage 10 | 11 | First off you should create a simple `'+(options.horizontal==false?"":createHorizontalButtons(1,options.moveAllBtn))+' '+" "+(options.horizontal==false?createVerticalButtons(options.moveAllBtn):"")+(options.horizontal==false?'
':'
')+'

- showing

'+' '+(options.horizontal==false?"":createHorizontalButtons(2,options.moveAllBtn))+' '+"
");$(options.parentElement+" .selected").prop("name",$(options.element).prop("name"));$(options.parentElement+" .unselected-title").text("Available "+options.title);$(options.parentElement+" .selected-title").text("Selected "+options.title)}function createHorizontalButtons(number,copyAllBtn){if(number==1){return(copyAllBtn?' ':"")+' '}else{return' '+(copyAllBtn?' ':"")}}function createVerticalButtons(copyAllBtn){return'
'+(copyAllBtn?' ':"")+' '+' '+(copyAllBtn?' ':"")+"
"}function handleMovement(options){$(options.parentElement+" .unselected").find("option:selected").prop("selected",false);$(options.parentElement+" .selected").find("option:selected").prop("selected",false);$(options.parentElement+" .filter").val("");$(options.parentElement+" select").find("option").each(function(){$(this).show()});countElements(options.parentElement)}function parseStubListBox(options){var textIsTooLong=false;$(options.element).find("option").text(function(i,text){$(this).data("title",text);if(text.length>options.textLength){textIsTooLong=true;return text.substr(0,options.textLength)+"..."}}).each(function(){if(textIsTooLong){$(this).prop("title",$(this).data("title"))}if($(this).is(":selected")){$(this).appendTo(options.parentElement+" .selected")}else{$(this).appendTo(options.parentElement+" .unselected")}});$(options.element).remove();handleMovement(options)}function toggleButtons(parentElement){$(parentElement+" .unselected").change(function(){$(parentElement+" .str").prop("disabled",false)});$(parentElement+" .selected").change(function(){$(parentElement+" .stl").prop("disabled",false)});if($(parentElement+" .unselected").has("option").length==0){$(parentElement+" .atr").prop("disabled",true);$(parentElement+" .str").prop("disabled",true)}else{$(parentElement+" .atr").prop("disabled",false)}if($(parentElement+" .selected").has("option").length==0){$(parentElement+" .atl").prop("disabled",true);$(parentElement+" .stl").prop("disabled",true)}else{$(parentElement+" .atl").prop("disabled",false)}}$.fn.filterByText=function(textBox,timeout,parentElement){return this.each(function(){var select=this;var options=[];$(select).find("option").each(function(){options.push({value:$(this).val(),text:$(this).text()})});$(select).data("options",options);$(textBox).bind("change keyup",function(){delay(function(){var options=$(select).data("options");var search=$.trim($(textBox).val());var regex=new RegExp(search,"gi");$.each(options,function(i){if(options[i].text.match(regex)===null){$(select).find($('option[value="'+options[i].value+'"]')).hide()}else{$(select).find($('option[value="'+options[i].value+'"]')).show()}});countElements(parentElement)},timeout)})})};$.fn.isVisible=function(){return!($(this).css("visibility")=="hidden"||$(this).css("display")=="none")};$.fn.sortOptions=function(){return this.each(function(){$(this).append($(this).find("option").remove().sort(function(a,b){var at=$(a).text(),bt=$(b).text();return at>bt?1:at and apply this script to that select via jQuery like so: 10 | * $('select').DualListBox(); - the DualListBox will than be created for you. 11 | * 12 | * Options and parameters can be provided through html5 data-* attributes or 13 | * via a provided JavaScript object. Optionally already selected items can 14 | * also be provided and this script can download the JSON to fill the 15 | * DualListBox when a valid URI is provided. 16 | * 17 | * See the default parameters (below) for a complete list of options. 18 | */ 19 | 20 | (function($) { 21 | /** Initializes the DualListBox code as jQuery plugin. */ 22 | $.fn.DualListBox = function(paramOptions, selected) { 23 | return this.each(function () { 24 | var defaults = { 25 | element: $(this).context, // Select element which creates this dual list box. 26 | uri: 'local.json', // JSON file that can be opened for the data. 27 | value: 'id', // Value that is assigned to the value field in the option. 28 | text: 'name', // Text that is assigned to the option field. 29 | title: 'Example', // Title of the dual list box. 30 | json: true, // Whether to retrieve the data through JSON. 31 | timeout: 500, // Timeout for when a filter search is started. 32 | horizontal: false, // Whether to layout the dual list box as horizontal or vertical. 33 | textLength: 45, // Maximum text length that is displayed in the select. 34 | moveAllBtn: true, // Whether the append all button is available. 35 | maxAllBtn: 500, // Maximum size of list in which the all button works without warning. See below. 36 | selectClass:'form-control', 37 | warning: 'Are you sure you want to move this many items? Doing so can cause your browser to become unresponsive.' 38 | }; 39 | 40 | var htmlOptions = { 41 | element: $(this).context, 42 | uri: $(this).data('source'), 43 | value: $(this).data('value'), 44 | text: $(this).data('text'), 45 | title: $(this).data('title'), 46 | json: $(this).data('json'), 47 | timeout: $(this).data('timeout'), 48 | horizontal: $(this).data('horizontal'), 49 | textLength: $(this).data('textLength'), 50 | moveAllBtn: $(this).data('moveAllBtn'), 51 | maxAllBtn: $(this).data('maxAllBtn'), 52 | selectClass:$(this).data('selectClass') 53 | }; 54 | 55 | var options = $.extend({}, defaults, htmlOptions, paramOptions); 56 | 57 | $.each(options, function(i, item) { 58 | if (item === undefined || item === null) { throw 'DualListBox: ' + i + ' is undefined.'; } 59 | }); 60 | 61 | options['parent'] = 'dual-list-box-' + options.title; 62 | options['parentElement'] = '#' + options.parent; 63 | 64 | selected = $.extend([{}], selected); 65 | 66 | if (options.json) { 67 | addElementsViaJSON(options, selected); 68 | } else { 69 | construct(options); 70 | } 71 | }) 72 | }; 73 | 74 | /** Retrieves all the option elements through a JSON request. */ 75 | function addElementsViaJSON(options, selected) { 76 | var multipleTextFields = false; 77 | 78 | if (options.text.indexOf(':') > -1) { 79 | var textToUse = options.text.split(':'); 80 | 81 | if (textToUse.length > 1) { 82 | multipleTextFields = true; 83 | } 84 | } 85 | 86 | $.getJSON(options.uri, function(json) { 87 | $.each(json, function(key, item) { 88 | var text = ''; 89 | 90 | if (multipleTextFields) { 91 | textToUse.forEach(function (entry) { text += item[entry] + ' '; }); 92 | } else { 93 | text = item[options.text]; 94 | } 95 | 96 | $('