Skip to content

Commit 1ec7806

Browse files
committed
v1.1.0. Callbacks and helper elements config
1 parent 32820f9 commit 1ec7806

File tree

4 files changed

+102
-47
lines changed

4 files changed

+102
-47
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
Angular Multi Select
2-
====================
1+
Angular MultiSelect
2+
==
33
An AngularJS directive which creates a dropdown button with multiple or single selections.
44
Allows you to customize your labels and use some HTML tags in the data. Fully configurable through element attributes and CSS.
55
Doesn't require jQuery and works well with other Javascript libraries.

angular-multi-select.css

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@
7474
border-top: 4px solid #333;
7575
border-right: 4px solid transparent;
7676
border-left: 4px solid transparent;
77-
border-bottom: 0 dotted;
77+
border-bottom: 0 dotted;
7878
}
7979

8080
.multiSelect.multiSelectItem {
@@ -110,11 +110,6 @@ label.multiSelect span {
110110
user-select: none;
111111
}
112112

113-
label.multiSelect span:hover{
114-
cursor: pointer;
115-
color: #333;
116-
}
117-
118113
/* hide the checkbox away */
119114
.multiSelect .checkbox {
120115
position: absolute;
@@ -138,6 +133,22 @@ label.multiSelect span:hover{
138133
margin-left: 1px;
139134
}
140135

136+
/* On mouse over and focus */
137+
label.multiSelect input:focus ~ span::after,
138+
label.multiSelect span:focus::after,
139+
label.multiSelect span:hover::after {
140+
/* Enable this if you want some arrow pointer */
141+
/* content: ' \00AB'; */
142+
}
143+
144+
label.multiSelect input:focus ~ span,
145+
label.multiSelect span:hover {
146+
color: #333;
147+
cursor: pointer;
148+
/* Enable this if you want some arrow pointer */
149+
/* content: ' \00AB'; */
150+
}
151+
141152
/* for checkboxes currently selected */
142153
.multiSelect .checkboxSelected {
143154
color: #000;

angular-multi-select.js

Lines changed: 82 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
* --------------------------------------------------------------------------------
3232
*/
3333

34-
angular.module( 'multi-select', ['ng'] ).directive( 'multiSelect' , [ '$sce', function ( $sce ) {
34+
angular.module( 'multi-select', ['ng'] ).directive( 'multiSelect' , [ '$sce', '$filter', function ( $sce, $filter ) {
3535
return {
3636
restrict:
3737
'AE',
@@ -52,47 +52,93 @@ angular.module( 'multi-select', ['ng'] ).directive( 'multiSelect' , [ '$sce', fu
5252
maxLabels : '@',
5353
isDisabled : '=',
5454
directiveId : '@',
55-
// JH DotComIt Added 5/8/2014
56-
onPopupopen: '&onPopupopen',
57-
onPopupclose: '&onPopupclose'
55+
helperElements : '@',
56+
onOpen : '&',
57+
onClose : '&',
58+
onBlur : '&',
59+
onFocus : '&'
5860
},
5961

6062
template:
61-
'<span class="multiSelect inlineBlock">' +
62-
'<button type="button" class="multiSelect button multiSelectButton" ng-click="toggleCheckboxes( $event ); refreshSelectedItems();" ng-bind-html="varButtonLabel">' +
63+
'<span class="multiSelect inlineBlock" >' +
64+
'<button type="button" class="multiSelect button multiSelectButton" ng-click="toggleCheckboxes( $event ); refreshSelectedItems();" ng-bind-html="varButtonLabel" ng-focus="onFocus()" ng-blur="onBlur()">' +
6365
'</button>' +
6466
'<div class="multiSelect checkboxLayer hide">' +
6567
'<div class="multiSelect line">' +
66-
'<span ng-if="!isDisabled">Select: &nbsp;</span>' +
67-
'<button type="button" ng-click="select( \'all\' )" class="multiSelect helperButton" ng-if="!isDisabled && selectionMode.toUpperCase() != \'SINGLE\'">All</button> ' +
68-
'<button type="button" ng-click="select( \'none\' )" class="multiSelect helperButton" ng-if="!isDisabled && selectionMode.toUpperCase() != \'SINGLE\'">None</button> ' +
69-
'<button type="button" ng-click="select( \'reset\' )" class="multiSelect helperButton" ng-if="!isDisabled">Reset</button>' +
68+
'<span ng-if="!isDisabled && ( displayHelper( \'all\' ) || displayHelper( \'none\' ) || displayHelper( \'reset\' ))">Select: &nbsp;</span>' +
69+
'<button type="button" ng-click="select( \'all\' )" class="multiSelect helperButton" ng-if="!isDisabled && displayHelper( \'all\' )">All</button> ' +
70+
'<button type="button" ng-click="select( \'none\' )" class="multiSelect helperButton" ng-if="!isDisabled && displayHelper( \'none\' )">None</button> ' +
71+
'<button type="button" ng-click="select( \'reset\' )" class="multiSelect helperButton" ng-if="!isDisabled && displayHelper( \'reset\' )">Reset</button>' +
7072
'</div>' +
71-
'<div class="multiSelect line">' +
73+
'<div class="multiSelect line" ng-show="displayHelper( \'filter\' )">' +
7274
'Filter: <input class="multiSelect" type="text" ng-model="labelFilter" />' +
7375
'&nbsp;<button type="button" class="multiSelect helperButton" ng-click="labelFilter=\'\'">Clear</button>' +
7476
'</div>' +
75-
'<div ng-repeat="item in inputModel | filter:labelFilter" ng-class="orientation" class="multiSelect multiSelectItem">' +
77+
'<div ng-repeat="item in (filteredModel = (inputModel | filter:labelFilter ))" ng-class="orientation" class="multiSelect multiSelectItem">' +
7678
'<div class="multiSelect acol">' +
7779
'<div class="multiSelect" ng-show="item[ tickProperty ]">&#10004;</div>' +
7880
'</div>' +
7981
'<div class="multiSelect acol">' +
8082
'<label class="multiSelect" ng-class="{checkboxSelected:item[ tickProperty ]}">' +
81-
'<input class="multiSelect checkbox" type="checkbox" ng-disabled="itemIsDisabled( item )" ng-checked="item[ tickProperty ]" ng-click="syncItems( item, $event )" />' +
82-
'<span class="multiSelect" ng-class="{disabled:itemIsDisabled( item )}" ng-bind-html="writeLabel( item, \'itemLabel\' )"></span>' +
83+
'<input class="multiSelect checkbox" type="checkbox" ng-disabled="itemIsDisabled( item )" ng-checked="item[ tickProperty ]" ng-click="syncItems( item, $event )"/>' +
84+
'<span class="multiSelect" ng-class="{disabled:itemIsDisabled( item )}" ng-bind-html="writeLabel( item, \'itemLabel\' )"></span>' +
8385
'</label>&nbsp;&nbsp;' +
8486
'</div>' +
8587
'</div>' +
8688
'</div>' +
8789
'</span>',
8890

89-
link: function ( $scope, element, attrs ) {
91+
link: function ( $scope, element, attrs ) {
9092

9193
$scope.selectedItems = [];
9294
$scope.backUp = [];
93-
$scope.varButtonLabel = '';
95+
$scope.varButtonLabel = '';
96+
$scope.tabIndex = 0;
97+
$scope.tabables = null;
98+
$scope.currentButton = null;
99+
100+
// Show or hide a helper element
101+
$scope.displayHelper = function( elementString ) {
102+
if ( typeof attrs.helperElements === 'undefined' ) {
103+
return true;
104+
}
105+
switch( elementString.toUpperCase() ) {
106+
case 'ALL':
107+
if ( attrs.selectionMode && $scope.selectionMode.toUpperCase() === 'SINGLE' ) {
108+
return false;
109+
}
110+
else {
111+
if ( attrs.helperElements && $scope.helperElements.toUpperCase().indexOf( 'ALL' ) >= 0 ) {
112+
return true;
113+
}
114+
}
115+
break;
116+
case 'NONE':
117+
if ( attrs.selectionMode && $scope.selectionMode.toUpperCase() === 'SINGLE' ) {
118+
return false;
119+
}
120+
else {
121+
if ( attrs.helperElements && $scope.helperElements.toUpperCase().indexOf( 'NONE' ) >= 0 ) {
122+
return true;
123+
}
124+
}
125+
break;
126+
case 'RESET':
127+
if ( attrs.helperElements && $scope.helperElements.toUpperCase().indexOf( 'RESET' ) >= 0 ) {
128+
return true;
129+
}
130+
break;
131+
case 'FILTER':
132+
if ( attrs.helperElements && $scope.helperElements.toUpperCase().indexOf( 'FILTER' ) >= 0 ) {
133+
return true;
134+
}
135+
break;
136+
default:
137+
break;
138+
}
139+
}
94140

95-
// Checkbox is ticked
141+
// Call this function when a checkbox is ticked...
96142
$scope.syncItems = function( item, e ) {
97143
index = $scope.inputModel.indexOf( item );
98144
$scope.inputModel[ index ][ $scope.tickProperty ] = !$scope.inputModel[ index ][ $scope.tickProperty ];
@@ -107,8 +153,9 @@ angular.module( 'multi-select', ['ng'] ).directive( 'multiSelect' , [ '$sce', fu
107153
}
108154
$scope.toggleCheckboxes( e );
109155
}
110-
111-
$scope.refreshSelectedItems();
156+
157+
$scope.refreshSelectedItems();
158+
e.target.focus();
112159
}
113160

114161
// Refresh the button to display the selected items and push into output model if specified
@@ -199,7 +246,7 @@ angular.module( 'multi-select', ['ng'] ).directive( 'multiSelect' , [ '$sce', fu
199246
return $sce.trustAsHtml( label );
200247
}
201248

202-
// UI operations to show/hide checkboxes
249+
// UI operations to show/hide checkboxes based on click event..
203250
$scope.toggleCheckboxes = function( e ) {
204251

205252
if ( e.target ) {
@@ -238,20 +285,19 @@ angular.module( 'multi-select', ['ng'] ).directive( 'multiSelect' , [ '$sce', fu
238285
for( i=0; i < checkboxes.length; i++ ) {
239286
if ( i != multiSelectIndex ) {
240287
checkboxes[i].className = 'multiSelect checkboxLayer hide';
241-
// JH DotComIt 5/8/2014 Added method handler for closing the popup
242-
$scope.onPopupclose();
243288
}
244289
}
245290

246291
if ( checkboxes[ multiSelectIndex ].className == 'multiSelect checkboxLayer hide' ) {
292+
$scope.currentButton = multiSelectButtons[ multiSelectIndex ];
247293
checkboxes[ multiSelectIndex ].className = 'multiSelect checkboxLayer show';
248-
// JH DotComIt 5/8/2014 Added method handler for opening the popup
249-
$scope.onPopupopen();
294+
// https://github.com/isteven/angular-multi-select/pull/5 - On open callback
295+
$scope.onOpen();
250296
}
251297
else if ( checkboxes[ multiSelectIndex ].className == 'multiSelect checkboxLayer show' ) {
252298
checkboxes[ multiSelectIndex ].className = 'multiSelect checkboxLayer hide';
253-
// JH DotComIt 5/8/2014 Added method handler for closing the popup
254-
$scope.onPopupclose();
299+
// https://github.com/isteven/angular-multi-select/pull/5 - On close callback
300+
$scope.onClose();
255301
}
256302
}
257303
}
@@ -289,8 +335,8 @@ angular.module( 'multi-select', ['ng'] ).directive( 'multiSelect' , [ '$sce', fu
289335
}
290336
});
291337
break;
292-
case 'RESET':
293-
$scope.inputModel = angular.copy( $scope.backUp );
338+
case 'RESET':
339+
$scope.inputModel = angular.copy( $scope.backUp );
294340
break;
295341
default:
296342
}
@@ -299,6 +345,7 @@ angular.module( 'multi-select', ['ng'] ).directive( 'multiSelect' , [ '$sce', fu
299345

300346

301347
// Generic validation for required attributes
348+
// Might give false positives so just ignore if everything's alright.
302349
validate = function() {
303350
if ( !( 'inputModel' in attrs )) {
304351
console.log( 'Multi-select error: input-model is not defined! (ID: ' + $scope.directiveId + ')' );
@@ -337,17 +384,16 @@ angular.module( 'multi-select', ['ng'] ).directive( 'multiSelect' , [ '$sce', fu
337384
});
338385
if ( notThere === true ) {
339386
console.log( 'Multi-select error: property "' + missingLabel + '" is not available in the input model. (Name: ' + $scope.directiveId + ')' );
340-
}
341-
342-
}
387+
}
388+
}
343389

344390
///////////////////////
345391
// Logic starts here
346392
///////////////////////
347393

348394
validate();
349-
$scope.refreshSelectedItems();
350-
395+
$scope.refreshSelectedItems();
396+
351397
// Watch for changes in input model (allow dynamic input)
352398
$scope.$watch( 'inputModel' , function( oldVal, newVal ) {
353399
if ( $scope.inputModel !== 'undefined' ) {
@@ -368,14 +414,12 @@ angular.module( 'multi-select', ['ng'] ).directive( 'multiSelect' , [ '$sce', fu
368414
var checkboxes = document.querySelectorAll( '.checkboxLayer' );
369415
if ( e.target.className.indexOf( 'multiSelect' ) === -1 ) {
370416
for( i=0; i < checkboxes.length; i++ ) {
371-
checkboxes[i].className = 'multiSelect checkboxLayer hide';
372-
// JH DotComIt 5/8/2014 Added method handler for closing the popup
373-
$scope.onPopupclose();
417+
checkboxes[i].className = 'multiSelect checkboxLayer hide';
374418
}
375419
e.stopPropagation();
376420
}
377-
});
378-
421+
});
422+
379423
// For IE8, perhaps. Not sure if this is really executed.
380424
if ( !Array.prototype.indexOf ) {
381425
Array.prototype.indexOf = function(what, i) {

0 commit comments

Comments
 (0)