diff options
author | isteven <isteven@server.fake> | 2014-03-28 17:53:21 +0800 |
---|---|---|
committer | isteven <isteven@server.fake> | 2014-03-28 17:53:21 +0800 |
commit | 2f283f174c1d8b521f74b7eff4b67dbe171b18e7 (patch) | |
tree | 3c2bd217bf11f043e85d8596b282630e96f704a1 | |
parent | 9ded8a2d388383deff8f056d979de974061f04d1 (diff) | |
download | angular-multi-select-2f283f174c1d8b521f74b7eff4b67dbe171b18e7.zip angular-multi-select-2f283f174c1d8b521f74b7eff4b67dbe171b18e7.tar.gz angular-multi-select-2f283f174c1d8b521f74b7eff4b67dbe171b18e7.tar.bz2 |
Removed divs inside button tag
Changed button into div and make it responsive
Removed no-wrap from CSS
Used 9662 HTML char as the caret. Caret class is still available.
-rw-r--r-- | README.md | 19 | ||||
-rw-r--r-- | angular-multi-select.css | 15 | ||||
-rw-r--r-- | angular-multi-select.js | 156 | ||||
-rw-r--r-- | multiselect.htm | 19 | ||||
-rw-r--r-- | screenshot.jpg | bin | 20586 -> 20551 bytes |
5 files changed, 109 insertions, 100 deletions
@@ -13,7 +13,6 @@ Features - Set orientation of checkboxes - Enable / disable checkboxes - Set maximum number of items to be displayed on the button label - - Maximum height of checkbox layer in pixels (will show scrollbar on overflow) - Utilizes AngularJS filter - Responsive to some extent @@ -27,7 +26,6 @@ Usage output-model="output_list" orientation="vertical" max-labels="4" - max-height="500" is-disabled="multi_select_state" > </div> @@ -35,7 +33,7 @@ Usage <multi-select ... - ... + ... > </multi-select> Attributes / Options @@ -59,7 +57,7 @@ input-model property that you want to display on the button & checkboxes. Separa <br />Example: item-label="firstName lastName" -##### tick-property (REQUIRED): +##### tick-property (REQUIRED) input-model property with a boolean value that represent the state of a checkbox. <br />For example: - item-ticker is "selected" @@ -69,7 +67,7 @@ input-model property with a boolean value that represent the state of a checkbox - if isOn === true, checkbox will be ticked. - If isOn === false, checkbox will not be ticked. -##### output-model: +##### output-model A $scope variable. If specified, will list all the selected checkboxes model. ##### orientation ( "vertical" | "horizontal" ) @@ -78,11 +76,7 @@ Orientation of the list of checkboxes. If not specified, the default will be "ve ##### max-labels Maximum number of items that will be displayed in the dropdown button. If not specified, will display all selected items. <br />Example: "1" -<br />- Using the input-model above, then button will display: "Bruce Wayne, ... [ Selected: 2 ]" - -##### max-height -Maximum height of the list of checkboxes in pixels. Will show scrollbar on overflow. -<br />Example: "100". +<br />- Using the input-model above, then button will display: "Bruce Wayne, ... [ Total: 2 ]" ##### is-disabled Expression to be evaluated. Will disable or enable the checkboxes. @@ -93,7 +87,10 @@ Example -- Download all the files into a same folder and open multiselect.htm. <br />Or, if you prefer JSfiddle: http://jsfiddle.net/s47RE/ -<br />_I don't know why but JSfiddle requires you to click on the caret icon (the small triangle button) to toggle the dropdown. However, the multiselect.htm sample works OK in all browsers I tested._ + +Note +-- +I use HTML entity 9662 for the caret (downward pointing arrow). If you want a better looking arrow, you can use the .caret class in the CSS file. Just create a span using that .caret. Do note that this span won't toggle the dropdown. You need to click outside the span. Requirements -- diff --git a/angular-multi-select.css b/angular-multi-select.css index 8031a0c..6a48c6b 100644 --- a/angular-multi-select.css +++ b/angular-multi-select.css @@ -1,4 +1,8 @@ -.multiSelect { +body { + font-family: "Verdana"; + font-size: 14px; +} +.multiSelect { } .multiSelect.inlineBlock { @@ -7,14 +11,14 @@ .multiSelect .button { display: block; - margin-bottom: 0; + position: relative; + margin:0 auto; font-weight: normal; text-align: center; vertical-align: middle; cursor: pointer; - background-image: none; + background-image: none; border: 1px solid transparent; - white-space: nowrap; padding: 6px 12px; font-size: 14px; line-height: 1.428571429; @@ -26,7 +30,7 @@ user-select: none; background-color: #5CB85C; border-color: #4CAE4C; - color: #fff; + color: #fff; } .multiSelect .helperButton { @@ -38,7 +42,6 @@ cursor: pointer; background-image: none; border: 1px solid #ccc; - white-space: nowrap; padding: 2px 2px; font-size: 14px; line-height: 1; diff --git a/angular-multi-select.js b/angular-multi-select.js index 29fa87c..72dae75 100644 --- a/angular-multi-select.js +++ b/angular-multi-select.js @@ -1,11 +1,10 @@ /* - * Ignatius Steven * Created: Tue, 14 Jan 2014 - 5:18:02 PM - * Last update: Wed, 26 Mar 2014 - 11:12:29 AM * * Angular JS Multi Select * Creates a dropdown-like button with checkboxes. * + * Released under MIT License * -------------------------------------------------------------------------------- * MIT License * @@ -47,19 +46,15 @@ angular.module( 'multi-select', ['ng'] ).directive( 'multiSelect' , [ '$timeout' tickProperty : '@', orientation : '@', maxLabels : '@', - maxHeight : '@', isDisabled : '=' }, template: '<span class="multiSelect inlineBlock">' + - '<button type="button" class="multiSelect button multiSelectButton" ng-click="toggleCheckboxes( $event ); refreshSelectedItems();">' + - '<div ng-if="selectedItems.length <= 0">None selected</div>' + - '<div ng-if="selectedItems.length > 0" ng-repeat="item in selectedItems | limitTo: varMaxLabels">' + - '<span ng-if="$index > 0">, </span>{{writeLabel( item )}}' + - '</div>' + - '<div ng-if="more">, ... [ Selected: {{selectedItems.length}} ]</div><span class="caret"></span>' + - '</button>' + + '<div class="multiSelect button multiSelectButton" ng-click="toggleCheckboxes( $event ); refreshSelectedItems();">' + + '{{buttonLabel}}' + + ' ▾' + + '</div>' + '<div class="multiSelect checkboxLayer hide" style="{{layerStyle}}">' + '<div class="multiSelect line">' + '<span ng-if="!isDisabled">Select: </span>' + @@ -85,7 +80,7 @@ angular.module( 'multi-select', ['ng'] ).directive( 'multiSelect' , [ '$timeout' $scope.selectedItems = []; $scope.backUp = []; $scope.layerStyle = ''; - $scope.varMaxLabels = 0; + $scope.buttonLabel = ''; // Checkbox is ticked $scope.syncItems = function( item ) { @@ -97,39 +92,71 @@ angular.module( 'multi-select', ['ng'] ).directive( 'multiSelect' , [ '$timeout' // Refresh the button to display the selected items and push into output model if specified $scope.refreshSelectedItems = function() { - $scope.selectedItems = []; + $scope.buttonLabel = ''; + $scope.selectedItems = []; + ctr = 0; + angular.forEach( $scope.inputModel, function( value, key ) { if ( typeof value !== 'undefined' ) { if ( value[ $scope.tickProperty ] === true || value[ $scope.tickProperty ] === 'true' ) { - $scope.selectedItems.push( value ); + $scope.selectedItems.push( value ); } } }); - + // Push into output model if ( typeof attrs.outputModel !== 'undefined' ) { $scope.outputModel = angular.copy( $scope.selectedItems ); } + var tempMaxLabels = $scope.selectedItems.length; + if ( typeof $scope.maxLabels !== 'undefined' && $scope.maxLabels !== '' && $scope.maxLabels !== "0" ) { + tempMaxLabels = $scope.maxLabels; + } + // If max amount of labels displayed.. - if ( $scope.selectedItems.length > $scope.maxLabels ) { + if ( $scope.selectedItems.length > tempMaxLabels ) { $scope.more = true; } else { $scope.more = false; } - if ( typeof $scope.maxLabels === 'undefined' ) { - $scope.varMaxLabels = $scope.selectedItems.length; + + // Write label... + angular.forEach( $scope.selectedItems, function( value, key ) { + if ( typeof value !== 'undefined' ) { + if ( ctr < tempMaxLabels ) { + $scope.buttonLabel += ( $scope.buttonLabel.length > 0 ? ', ' : '') + $scope.writeLabel( value ); + } + ctr++; + } + }); + + if ( $scope.more === true ) { + $scope.buttonLabel += ', ... (Total: ' + $scope.selectedItems.length + ')'; } - else { - $scope.varMaxLabels = $scope.maxLabels; - } + } + + // A simple function to parse the item label settings + $scope.writeLabel = function( item ) { + var label = ''; + var temp = $scope.itemLabel.split( ' ' ); + angular.forEach( temp, function( value2, key2 ) { + if ( typeof value2 !== 'undefined' ) { + angular.forEach( item, function( value1, key1 ) { + if ( key1 == value2 ) { + label += ' ' + value1; + } + }); + } + }); + return label; } // UI operations to show/hide checkboxes $scope.toggleCheckboxes = function( e ) { - $scope.labelFilter = ''; + $scope.labelFilter = ''; // We search them based on the class names var multiSelectIndex = -1; @@ -137,24 +164,26 @@ angular.module( 'multi-select', ['ng'] ).directive( 'multiSelect' , [ '$timeout' var multiSelectButtons = document.querySelectorAll( '.multiSelectButton' ); for( i=0; i < multiSelectButtons.length; i++ ) { - if ( e.target == multiSelectButtons[ i ] ) { + if ( e.target === multiSelectButtons[ i ] ) { multiSelectIndex = i; break; } - } + } - for( i=0; i < checkboxes.length; i++ ) { - if ( i != multiSelectIndex ) { - checkboxes[i].className = 'multiSelect checkboxLayer hide'; - } - } + if ( multiSelectIndex > -1 ) { + for( i=0; i < checkboxes.length; i++ ) { + if ( i != multiSelectIndex ) { + checkboxes[i].className = 'multiSelect checkboxLayer hide'; + } + } - if ( checkboxes[ multiSelectIndex ].className == 'multiSelect checkboxLayer hide' ) { - checkboxes[ multiSelectIndex ].className = 'multiSelect checkboxLayer show'; + if ( checkboxes[ multiSelectIndex ].className == 'multiSelect checkboxLayer hide' ) { + checkboxes[ multiSelectIndex ].className = 'multiSelect checkboxLayer show'; + } + else if ( checkboxes[ multiSelectIndex ].className == 'multiSelect checkboxLayer show' ) { + checkboxes[ multiSelectIndex ].className = 'multiSelect checkboxLayer hide'; + } } - else if ( checkboxes[ multiSelectIndex ].className == 'multiSelect checkboxLayer show' ) { - checkboxes[ multiSelectIndex ].className = 'multiSelect checkboxLayer hide'; - } } // Select All / None / Reset @@ -180,24 +209,28 @@ angular.module( 'multi-select', ['ng'] ).directive( 'multiSelect' , [ '$timeout' default: } $scope.refreshSelectedItems(); - } + } - // What's written on the button - $scope.writeLabel = function( item ) { - var label = ''; - var temp = $scope.itemLabel.split( ' ' ); - angular.forEach( temp, function( value2, key2 ) { - if ( typeof value2 !== 'undefined' ) { - angular.forEach( item, function( value1, key1 ) { - if ( key1 == value2 ) { - label += ' ' + value1; - } - }); - } - }); - return label; + + // Generic validation for required attributes + validate = function() { + if ( typeof $scope.inputModel === 'undefined' ) { + alert( 'multi-select ERROR - input model is not defined!' ); + } + + if ( typeof $scope.itemLabel === 'undefined' ) { + alert( 'multi-select ERROR - item label is not defined!' ); + } + + if ( typeof $scope.tickProperty === 'undefined' ) { + alert( 'multi-select ERROR - tick property is not defined!' ); + } + + validateProperties( $scope.itemLabel.split( ' ' ), $scope.inputModel ); + validateProperties( new Array( $scope.tickProperty ), $scope.inputModel ); } + // Validate whether the properties specified in the directive attributes are present in the input model validateProperties = function( arrProperties, arrObject ) { var notThere = false; var missingProperty = ''; @@ -224,26 +257,7 @@ angular.module( 'multi-select', ['ng'] ).directive( 'multiSelect' , [ '$timeout' ///////////////////// // Logic starts here ///////////////////// - - - // Validations.. - validate = function() { - if ( typeof $scope.inputModel === 'undefined' ) { - alert( 'multi-select ERROR - input model is not defined!' ); - } - - if ( typeof $scope.itemLabel === 'undefined' ) { - alert( 'multi-select ERROR - item label is not defined!' ); - } - - if ( typeof $scope.tickProperty === 'undefined' ) { - alert( 'multi-select ERROR - tick property is not defined!' ); - } - - validateProperties( $scope.itemLabel.split( ' ' ), $scope.inputModel ); - validateProperties( new Array( $scope.tickProperty ), $scope.inputModel ); - } - + validate(); $scope.refreshSelectedItems(); @@ -260,11 +274,6 @@ angular.module( 'multi-select', ['ng'] ).directive( 'multiSelect' , [ '$timeout' $scope.isDisabled = newVal; }); - // Checkbox height - if ( typeof $scope.maxHeight !== 'undefined' ) { - $scope.layerStyle = 'max-height:' + $scope.maxHeight + 'px; overflow: auto; min-width: auto'; - } - // Monitor for clicks outside the button element to hide the checkboxes angular.element( document ).bind( 'click' , function( e ) { var checkboxes = document.querySelectorAll( '.checkboxLayer' ); @@ -277,6 +286,7 @@ angular.module( 'multi-select', ['ng'] ).directive( 'multiSelect' , [ '$timeout' } }); + // For IE8, perhaps. Not sure if this is really executed. if ( !Array.prototype.indexOf ) { Array.prototype.indexOf = function(what, i) { i = i || 0; diff --git a/multiselect.htm b/multiselect.htm index a05f684..6495f9e 100644 --- a/multiselect.htm +++ b/multiselect.htm @@ -15,7 +15,7 @@ Minimal: <br /> - <div + <div multi-select input-model="minData" item-label="firstName" @@ -33,33 +33,32 @@ output-model="resultData" item-label="firstName lastName" tick-property="checked" - orientation="vertical" + orientation="horizontal" max-labels="3" > </div> <br /><br /> - Dynamic input model and checkbox state + Use element instead of attribute, update input model on the fly, and toggle checkbox state <br /> - <div - multi-select + <multi-select input-model="dynamicData" item-label="car" tick-property="ticked" is-disabled="dinDisabled" > - </div> + </multi-select> <br /><br /> - <button type="button" ng-click="dinDisabled = !dinDisabled" >Enable / Disable</button> - Is disabled: {{dinDisabled}} - - <br /><br /> <button type="button" ng-click="switchSource( 'data1' )" >Load data 1</button> <button type="button" ng-click="switchSource( 'data2' )" >Load data 2</button> <button type="button" ng-click="switchSource( 'data3' )" >Load data 3</button> + <br /><br /> + <button type="button" ng-click="dinDisabled = !dinDisabled" >Enable / Disable</button> + Is disabled: {{dinDisabled}} + </body> <script> diff --git a/screenshot.jpg b/screenshot.jpg Binary files differindex dff59b0..9c229d7 100644 --- a/screenshot.jpg +++ b/screenshot.jpg |