summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README.md18
-rw-r--r--angular-multi-select.css4
-rw-r--r--angular-multi-select.js125
-rw-r--r--multiselect.htm120
4 files changed, 195 insertions, 72 deletions
diff --git a/README.md b/README.md
index 0d692c2..aee14df 100644
--- a/README.md
+++ b/README.md
@@ -21,7 +21,7 @@ Usage
multi-select
input-model="input_list"
item-label="firstName lastName"
- item-ticker="selected"
+ tick-property="selected"
output-model="output_list"
orientation="vertical"
max-labels="4"
@@ -50,7 +50,7 @@ $scope variable. Array of objects.
<br />&nbsp;&nbsp;&nbsp;&nbsp;{ id: 3, firstName: "Bruce", lastName: "Wayne", selected: true },
<br />&nbsp;&nbsp;&nbsp;&nbsp;{ id: 4, firstName: "David", lastName: "Banner", selected: false },
<br />&nbsp;&nbsp;&nbsp;&nbsp;{ id: 5, firstName: "Natalia", lastName: "Romanova", selected: false },
-<br />&nbsp;&nbsp;&nbsp;&nbsp;{ id: 6, firstName: "Clark", lastName: "Kent", selected: true },
+<br />&nbsp;&nbsp;&nbsp;&nbsp;{ id: 6, firstName: "Clark", lastName: "Kent", selected: true }
<br />];
- #### item-label (REQUIRED)
@@ -59,7 +59,7 @@ input-model property that you want to display on the button & checkboxes. Separa
item-label="firstName lastName"
-- #### item-ticker (IMPORTANT):
+- #### 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,8 +69,6 @@ input-model property with a boolean value that represent the state of a checkbox
- if isOn === true, checkbox will be ticked.
<br />If isOn === false, checkbox will not be ticked.
-
-&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;If not specified, the default will be "selected"
- #### output-model:
A $scope variable. If specified, will list all the selected checkboxes model.
@@ -96,6 +94,16 @@ Example
--
Download all the files into a same folder and open multiselect.htm
+Requirements
+--
+AngularJS v1.2.15 is used in the script
+
+Browser Support
+--
+Tested on:
+- IE8
+- Firefox 27
+
Licence
--
Released under the MIT license.
diff --git a/angular-multi-select.css b/angular-multi-select.css
index 3fddf58..521604e 100644
--- a/angular-multi-select.css
+++ b/angular-multi-select.css
@@ -122,3 +122,7 @@
.multiSelect .line {
margin-bottom: 15px;
}
+
+.multiSelect .helperButton + .helperButton {
+ margin-left: 5px;
+}
diff --git a/angular-multi-select.js b/angular-multi-select.js
index 7dd1470..29fa87c 100644
--- a/angular-multi-select.js
+++ b/angular-multi-select.js
@@ -41,14 +41,14 @@ angular.module( 'multi-select', ['ng'] ).directive( 'multiSelect' , [ '$timeout'
scope:
{
- inputModel : '=',
- outputModel : '=',
- itemLabel : '@',
- itemTicker : '@',
- orientation : '@',
- maxLabels : '@',
- maxHeight : '@',
- isDisabled : '='
+ inputModel : '=',
+ outputModel : '=',
+ itemLabel : '@',
+ tickProperty : '@',
+ orientation : '@',
+ maxLabels : '@',
+ maxHeight : '@',
+ isDisabled : '='
},
template:
@@ -72,8 +72,8 @@ angular.module( 'multi-select', ['ng'] ).directive( 'multiSelect' , [ '$timeout'
'<button type="button" class="multiSelect helperButton" ng-click="labelFilter=\'\'">Clear</button>' +
'</div>' +
'<div ng-repeat="item in inputModel | filter:labelFilter" ng-class="orientation" class="multiSelect multiSelectItem">' +
- '<label class="multiSelect" ng-class="{checkboxSelected:item[ itemSelector ]}">' +
- '<input class="multiSelect" type="checkbox" ng-disabled="isDisabled" ng-checked="item[ itemSelector ]" ng-click="syncItems( item )" />' +
+ '<label class="multiSelect" ng-class="{checkboxSelected:item[ tickProperty ]}">' +
+ '<input class="multiSelect" type="checkbox" ng-disabled="isDisabled" ng-checked="item[ tickProperty ]" ng-click="syncItems( item )" />' +
'{{writeLabel( item )}}' +
'</label>&nbsp;&nbsp;' +
'</div>' +
@@ -88,20 +88,24 @@ angular.module( 'multi-select', ['ng'] ).directive( 'multiSelect' , [ '$timeout'
$scope.varMaxLabels = 0;
// Checkbox is ticked
- $scope.syncItems = function( item ) {
- item[ $scope.itemSelector ] = !item[ $scope.itemSelector ];
+ $scope.syncItems = function( item ) {
+ index = $scope.inputModel.indexOf( item );
+ $scope.inputModel[ index ][ $scope.tickProperty ] = !$scope.inputModel[ index ][ $scope.tickProperty ];
$scope.refreshSelectedItems();
}
// Refresh the button to display the selected items and push into output model if specified
$scope.refreshSelectedItems = function() {
+
$scope.selectedItems = [];
angular.forEach( $scope.inputModel, function( value, key ) {
- if ( value[ $scope.itemSelector ] === true || value[ $scope.itemSelector ] === 'true' ) {
- $scope.selectedItems.push( value );
+ if ( typeof value !== 'undefined' ) {
+ if ( value[ $scope.tickProperty ] === true || value[ $scope.tickProperty ] === 'true' ) {
+ $scope.selectedItems.push( value );
+ }
}
});
-
+
// Push into output model
if ( typeof attrs.outputModel !== 'undefined' ) {
$scope.outputModel = angular.copy( $scope.selectedItems );
@@ -119,7 +123,7 @@ angular.module( 'multi-select', ['ng'] ).directive( 'multiSelect' , [ '$timeout'
}
else {
$scope.varMaxLabels = $scope.maxLabels;
- }
+ }
}
// UI operations to show/hide checkboxes
@@ -158,12 +162,16 @@ angular.module( 'multi-select', ['ng'] ).directive( 'multiSelect' , [ '$timeout'
switch( type.toUpperCase() ) {
case 'ALL':
angular.forEach( $scope.inputModel, function( value, key ) {
- value[ $scope.itemSelector ] = true;
+ if ( typeof value !== 'undefined' ) {
+ value[ $scope.tickProperty ] = true;
+ }
});
break;
case 'NONE':
angular.forEach( $scope.inputModel, function( value, key ) {
- value[ $scope.itemSelector ] = false;
+ if ( typeof value !== 'undefined' ) {
+ value[ $scope.tickProperty ] = false;
+ }
});
break;
case 'RESET':
@@ -175,29 +183,76 @@ angular.module( 'multi-select', ['ng'] ).directive( 'multiSelect' , [ '$timeout'
}
// What's written on the button
- $scope.writeLabel= function( item ) {
+ $scope.writeLabel = function( item ) {
var label = '';
var temp = $scope.itemLabel.split( ' ' );
angular.forEach( temp, function( value2, key2 ) {
- angular.forEach( item, function( value1, key1 ) {
- if ( key1 == value2 ) {
- label += ' ' + value1;
- }
- });
+ if ( typeof value2 !== 'undefined' ) {
+ angular.forEach( item, function( value1, key1 ) {
+ if ( key1 == value2 ) {
+ label += ' ' + value1;
+ }
+ });
+ }
});
return label;
}
+ validateProperties = function( arrProperties, arrObject ) {
+ var notThere = false;
+ var missingProperty = '';
+ angular.forEach( arrProperties, function( value1, key1 ) {
+ if ( typeof value1 !== 'undefined' ) {
+ var keepGoing = true;
+ angular.forEach( arrObject, function( value2, key2 ) {
+ if ( typeof value2 !== 'undefined' && keepGoing ) {
+ if (!( value1 in value2 )) {
+ notThere = true;
+ keepGoing = false;
+ missingLabel = value1;
+ }
+ }
+ });
+ }
+ });
+ if ( notThere === true ) {
+ alert( 'multi-select ERROR:\n\nProperty "' + missingLabel + '" is not available in the input model.' );
+ }
+
+ }
+
/////////////////////
// Logic starts here
/////////////////////
- $scope.itemSelector = ( typeof $scope.itemTicker === 'string' ? $scope.itemTicker : 'selected' );
+
+
+ // 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();
// Watch for changes in input model (allow dynamic input)
- $scope.$watch( 'inputModel' , function( newVal ) {
- $scope.refreshSelectedItems();
- $scope.backUp = angular.copy( $scope.inputModel );
+ $scope.$watch( 'inputModel' , function( oldVal, newVal ) {
+ validate();
+ $scope.backUp = angular.copy( $scope.inputModel );
+ $scope.refreshSelectedItems();
});
// Watch for changes in directive state (disabled or enabled)
@@ -220,7 +275,19 @@ angular.module( 'multi-select', ['ng'] ).directive( 'multiSelect' , [ '$timeout'
$scope.$apply();
e.stopPropagation();
}
- });
+ });
+
+ if ( !Array.prototype.indexOf ) {
+ Array.prototype.indexOf = function(what, i) {
+ i = i || 0;
+ var L = this.length;
+ while (i < L) {
+ if(this[i] === what) return i;
+ ++i;
+ }
+ return -1;
+ };
+ }
}
}
}]);
diff --git a/multiselect.htm b/multiselect.htm
index 23e00f3..385772e 100644
--- a/multiselect.htm
+++ b/multiselect.htm
@@ -6,8 +6,10 @@
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js"></script>
<!-- multi select directive -->
<script src="angular-multi-select.js"></script>
+ <script src="debug.js"></script>
<!-- css -->
<link rel="stylesheet" href="angular-multi-select.css">
+ <meta http-equiv="X-UA-Compatible" content="IE=Edge">
</head>
<body ng-controller="main">
@@ -18,6 +20,7 @@
multi-select
input-model="minData"
item-label="firstName"
+ tick-property="selected"
>
</div>
@@ -25,23 +28,38 @@
Full:
<br />
- <button type="button" ng-click="fullDisabled = !fullDisabled" >Enable / Disable</button>
- <br />
<div
multi-select
input-model="fullData"
+ output-model="resultData"
item-label="firstName lastName"
- item-ticker="checked"
- output-model="resultData"
+ tick-property="checked"
orientation="vertical"
- max-height="800"
- max-labels="3"
- is-disabled="fullDisabled"
+ max-labels="3"
>
</div>
<br /><br />
- <button type="button" ng-click="switchSource()" >Dynamically switch data source</button>
+
+ Dynamic input model and checkbox state
+ <br />
+ <div
+ multi-select
+ input-model="dynamicData"
+ item-label="car"
+ tick-property="ticked"
+ is-disabled="dinDisabled"
+ >
+ </div>
+
+ <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>
</body>
@@ -52,71 +70,97 @@ var myApp = angular.module('myApp', [ 'multi-select' ]);
// Controller
myApp.controller( 'main' , [ '$scope' , function ($scope) {
-
- $scope.switchSource = function() {
- var temp = angular.copy( $scope.minData );
- $scope.minData = angular.copy( $scope.fullData );
- $scope.fullData = angular.copy( temp );
- alert( 'You have switched the data source. If you don\'t see the pre-selected items, maybe you need to change the "item-ticker" from \'selected\' <=> \'checked\' in your directive tag :) ');
- }
/////////////
// Minimal
/////////////
$scope.minData = [
- { id: 1, firstName: "Peter", lastName: "Parker", selected: false },
- { id: 2, firstName: "Mary", lastName: "Jane", selected: false },
- { id: 3, firstName: "Bruce", lastName: "Wayne", selected: true },
- { id: 4, firstName: "David", lastName: "Banner", selected: false },
- { id: 5, firstName: "Natalia", lastName: "Romanova", selected: false },
- { id: 6, firstName: "Clark", lastName: "Kent", selected: true },
+ { id: 1, firstName: "Peter", lastName: "Parker", selected: false, hoho:'hoho' },
+ { id: 2, firstName: "Mary", lastName: "Jane", selected: false, hoho:'hoho' },
+ { id: 3, firstName: "Bruce", lastName: "Wayne", selected: true, hoho:'hoho' },
+ { id: 4, firstName: "David", lastName: "Banner", selected: false, hoho:'hoho' },
+ { id: 5, firstName: "Natalia", lastName: "Romanova", selected: false, hoho:'hoho' },
+ { id: 6, firstName: "Clark", lastName: "Kent", selected: true, hoho:'hoho' },
];
- // Watch minData changed
- $scope.$watch( "minData" , function( newVal ) {
+ // Open your console and watch minData changes
+ $scope.$watch( "minData" , function( newVal ) {
angular.forEach( newVal , function( value, key ) {
if ( value.selected === true ) {
- console.log( '.selected === true: ' + value.firstName + ' ' + value.lastName );
+ console.log( 'minData .selected === true: ' + value.firstName + ' ' + value.lastName );
}
});
- }, true );
+ }, true );
/////////////
// Full
/////////////
- // You can try to disable/enable the checkboxes here
- $scope.fullDisabled = false;
$scope.resultData = [];
// Data. For the sake of testing, this time around we try to use 'checked' to hold checkbox state.
$scope.fullData = [
- { id: 1, firstName: "Tom", lastName: "Cruise", checked: true },
- { id: 2, firstName: "Brad", lastName: "Pitt", checked: false },
- { id: 3, firstName: "Angelina", lastName: "Jolie", checked: false },
- { id: 4, firstName: "Scarlett", lastName: "Johansson", checked: false },
- { id: 5, firstName: "Gerard", lastName: "Buttler", checked: true },
- { id: 6, firstName: "Leonardo", lastName: "DiCaprio", checked: false },
+ { id: 1, firstName: "Tom", lastName: "Cruise", checked: true, yeye:'yeye' },
+ { id: 2, firstName: "Brad", lastName: "Pitt", checked: false, yeye:'yeye' },
+ { id: 3, firstName: "Angelina", lastName: "Jolie", checked: false, yeye:'yeye' },
+ { id: 4, firstName: "Scarlett", lastName: "Johansson", checked: false, yeye:'yeye' },
+ { id: 5, firstName: "Gerard", lastName: "Buttler", checked: true, yeye:'yeye' },
+ { id: 6, firstName: "Leonardo", lastName: "DiCaprio", checked: false, yeye:'yeye' },
];
- // Watch fullData changed
+ // Open your console and watch fullData changes
$scope.$watch( "fullData" , function( newVal ) {
angular.forEach( newVal , function( value, key ) {
if ( value.checked === true ) {
- console.log( '.checked === true: ' + value.firstName + ' ' + value.lastName );
+ console.log( 'fullData .checked === true: ' + value.firstName + ' ' + value.lastName );
}
});
}, true );
- // Watch resultData changed
+ // Open your console and watch resultData changes
$scope.$watch( "resultData" , function( newVal ) {
angular.forEach( newVal , function( value, key ) {
if ( value.checked === true ) {
- console.log( '.checked === true: ' + value.firstName + ' ' + value.lastName );
+ console.log( 'resultData .checked === true: ' + value.firstName + ' ' + value.lastName );
}
});
- }, true );
+ }, true );
+
+/////////////
+// Dynamic
+/////////////
+
+
+ $scope.dynamicData = [];
+ $scope.dinDisabled = false;
+
+ $scope.switchSource = function( data ) {
+ $scope.dynamicData = $scope[ data ];
+ }
+
+ // Japan cars
+ $scope.data1 = [
+ { car: 'Toyota' , ticked: true },
+ { car: 'Mazda' , ticked: false },
+ { car: 'Nissan' , ticked: true },
+ { car: 'Honda' , ticked: false }
+ ];
+
+ // German cars
+ $scope.data2 = [
+ { car: 'Audi' , ticked: false },
+ { car: 'BMW' , ticked: false },
+ { car: 'Mercedes' , ticked: true },
+ ];
+
+ // Italian cars
+ $scope.data3 = [
+ { car: 'Porsche' , ticked: false },
+ { car: 'Ferrari' , ticked: false },
+ { car: 'Fiat' , ticked: true },
+ { car: 'Lamborgini' , ticked: true },
+ ];
}]);