1
1
/*!
2
2
* ui-select
3
3
* http://github.com/angular-ui/ui-select
4
- * Version: 0.3.1 - 2014-07-12T16:26:10.166Z
4
+ * Version: 0.5.0 - 2014-07-30T04:47:33.132Z
5
5
* License: MIT
6
6
*/
7
7
51
51
* Original discussion about parsing "repeat" attribute instead of fully relying on ng-repeat:
52
52
* https://github.com/angular-ui/ui-select/commit/5dd63ad#commitcomment-5504697
53
53
*/
54
- . service ( 'RepeatParser' , [ 'uiSelectMinErr' , function ( uiSelectMinErr ) {
54
+ . service ( 'RepeatParser' , [ 'uiSelectMinErr' , '$parse' , function ( uiSelectMinErr , $parse ) {
55
55
var self = this ;
56
56
57
57
/**
58
58
* Example:
59
59
* expression = "address in addresses | filter: {street: $select.search} track by $index"
60
- * lhs = "address",
61
- * rhs = "addresses | filter: {street: $select.search}",
60
+ * itemName = "address",
61
+ * source = "addresses | filter: {street: $select.search}",
62
62
* trackByExp = "$index",
63
- * valueIdentifier = "address",
64
- * keyIdentifier = undefined
65
63
*/
66
64
self . parse = function ( expression ) {
67
- if ( ! expression ) {
68
- throw uiSelectMinErr ( 'repeat' , "Expected 'repeat' expression." ) ;
69
- }
70
65
71
- var match = expression . match ( / ^ \s * ( [ \s \S ] + ?) \s + i n \s + ( [ \s \S ] + ?) (?: \s + t r a c k \s + b y \s + ( [ \s \S ] + ?) ) ? \s * $ / ) ;
66
+ var match = expression . match ( / ^ \s * (?: ( [ \s \S ] + ? ) \s + a s \s + ) ? ( [ \s \S ] + ?) \s + i n \s + ( [ \s \S ] + ?) (?: \s + t r a c k \s + b y \s + ( [ \s \S ] + ?) ) ? \s * $ / ) ;
72
67
73
68
if ( ! match ) {
74
69
throw uiSelectMinErr ( 'iexp' , "Expected expression in form of '_item_ in _collection_[ track by _id_]' but got '{0}'." ,
75
- expression ) ;
76
- }
77
-
78
- var lhs = match [ 1 ] ; // Left-hand side
79
- var rhs = match [ 2 ] ; // Right-hand side
80
- var trackByExp = match [ 3 ] ;
81
-
82
- match = lhs . match ( / ^ (?: ( [ \$ \w ] + ) | \( ( [ \$ \w ] + ) \s * , \s * ( [ \$ \w ] + ) \) ) $ / ) ;
83
- if ( ! match ) {
84
- throw uiSelectMinErr ( 'iidexp' , "'_item_' in '_item_ in _collection_' should be an identifier or '(_key_, _value_)' expression, but got '{0}'." ,
85
- lhs ) ;
70
+ expression ) ;
86
71
}
87
72
88
- // Unused for now
89
- // var valueIdentifier = match[3] || match[1];
90
- // var keyIdentifier = match[2];
91
-
92
73
return {
93
- lhs : lhs ,
94
- rhs : rhs ,
95
- trackByExp : trackByExp
74
+ itemName : match [ 2 ] , // (lhs) Left-hand side,
75
+ source : match [ 3 ] , // (rhs) Right-hand side,
76
+ trackByExp : match [ 4 ] ,
77
+ modelMapper : $parse ( match [ 1 ] || match [ 2 ] )
96
78
} ;
79
+
97
80
} ;
98
81
99
82
self . getGroupNgRepeatExpression = function ( ) {
100
83
return '($group, $items) in $select.groups' ;
101
84
} ;
102
85
103
- self . getNgRepeatExpression = function ( lhs , rhs , trackByExp , grouped ) {
104
- var expression = lhs + ' in ' + ( grouped ? '$items' : rhs ) ;
86
+ self . getNgRepeatExpression = function ( itemName , source , trackByExp , grouped ) {
87
+ var expression = itemName + ' in ' + ( grouped ? '$items' : source ) ;
105
88
if ( trackByExp ) {
106
89
expression += ' track by ' + trackByExp ;
107
90
}
188
171
ctrl . items = items ;
189
172
}
190
173
191
- var repeat = RepeatParser . parse ( repeatAttr ) ,
192
- setItemsFn = groupByExp ? updateGroups : setPlainItems ;
174
+ var setItemsFn = groupByExp ? updateGroups : setPlainItems ;
175
+
176
+ ctrl . parserResult = RepeatParser . parse ( repeatAttr ) ;
193
177
194
178
ctrl . isGrouped = ! ! groupByExp ;
195
- ctrl . itemProperty = repeat . lhs ;
179
+ ctrl . itemProperty = ctrl . parserResult . itemName ;
196
180
197
181
// See https://github.com/angular/angular.js/blob/v1.2.15/src/ng/directive/ngRepeat.js#L259
198
- $scope . $watchCollection ( repeat . rhs , function ( items ) {
182
+ $scope . $watchCollection ( ctrl . parserResult . source , function ( items ) {
199
183
200
184
if ( items === undefined || items === null ) {
201
185
// If the user specifies undefined or null => reset the collection
212
196
}
213
197
214
198
} ) ;
199
+
215
200
} ;
216
201
217
202
var _refreshDelayPromise ;
299
284
300
285
$scope . $apply ( function ( ) {
301
286
var processed = _onKeydown ( key ) ;
302
- if ( processed ) {
287
+ if ( processed && key != Key . Tab ) {
303
288
e . preventDefault ( ) ;
304
289
e . stopPropagation ( ) ;
305
290
}
363
348
var $select = ctrls [ 0 ] ;
364
349
var ngModel = ctrls [ 1 ] ;
365
350
351
+ //From view --> model
352
+ ngModel . $parsers . unshift ( function ( inputValue ) {
353
+ var locals = { } ;
354
+ locals [ $select . parserResult . itemName ] = inputValue ;
355
+ var result = $select . parserResult . modelMapper ( scope , locals ) ;
356
+ return result ;
357
+ } ) ;
358
+
359
+ //From model --> view
360
+ ngModel . $formatters . unshift ( function ( inputValue ) {
361
+ var match = $select . parserResult . source . match ( / ^ \s * ( [ \S ] + ) .* $ / ) ;
362
+ var data = scope [ match [ 1 ] ] ;
363
+ if ( data ) {
364
+ for ( var i = data . length - 1 ; i >= 0 ; i -- ) {
365
+ var locals = { } ;
366
+ locals [ $select . parserResult . itemName ] = data [ i ] ;
367
+ var result = $select . parserResult . modelMapper ( scope , locals ) ;
368
+ if ( result == inputValue ) {
369
+ return data [ i ] ;
370
+ }
371
+ }
372
+ }
373
+ return inputValue ;
374
+ } ) ;
375
+
376
+
366
377
//Idea from: https://github.com/ivaynberg/select2/blob/79b5bf6db918d7560bdd959109b7bcfb47edaf43/select2.js#L1954
367
378
var focusser = angular . element ( "<input ng-disabled='$select.disabled' class='ui-select-focusser ui-select-offscreen' type='text' aria-haspopup='true' role='button' />" ) ;
368
379
$compile ( focusser ) ( scope ) ;
381
392
} ) ;
382
393
focusser . bind ( "keydown" , function ( e ) {
383
394
395
+ if ( e . which === KEY . BACKSPACE ) {
396
+ e . preventDefault ( ) ;
397
+ e . stopPropagation ( ) ;
398
+ $select . select ( undefined ) ;
399
+ scope . $digest ( ) ;
400
+ return ;
401
+ }
402
+
384
403
if ( e . which === KEY . TAB || KEY . isControl ( e ) || KEY . isFunctionKey ( e ) || e . which === KEY . ESC ) {
385
404
return ;
386
405
}
396
415
397
416
focusser . bind ( "keyup input" , function ( e ) {
398
417
399
- if ( e . which === KEY . TAB || KEY . isControl ( e ) || KEY . isFunctionKey ( e ) || e . which === KEY . ESC || e . which == KEY . ENTER ) {
418
+ if ( e . which === KEY . TAB || KEY . isControl ( e ) || KEY . isFunctionKey ( e ) || e . which === KEY . ESC || e . which == KEY . ENTER || e . which === KEY . BACKSPACE ) {
400
419
return ;
401
420
}
402
421
510
529
var transcluded = angular . element ( '<div>' ) . append ( clone ) ;
511
530
512
531
var transcludedMatch = transcluded . querySelectorAll ( '.ui-select-match' ) ;
532
+ transcludedMatch . removeAttr ( 'ui-select-match' ) ; //To avoid loop in case directive as attr
513
533
if ( transcludedMatch . length !== 1 ) {
514
534
throw uiSelectMinErr ( 'transcluded' , "Expected 1 .ui-select-match but got '{0}'." , transcludedMatch . length ) ;
515
535
}
516
536
element . querySelectorAll ( '.ui-select-match' ) . replaceWith ( transcludedMatch ) ;
517
537
518
538
var transcludedChoices = transcluded . querySelectorAll ( '.ui-select-choices' ) ;
539
+ transcludedChoices . removeAttr ( 'ui-select-choices' ) ; //To avoid loop in case directive as attr
519
540
if ( transcludedChoices . length !== 1 ) {
520
541
throw uiSelectMinErr ( 'transcluded' , "Expected 1 .ui-select-choices but got '{0}'." , transcludedChoices . length ) ;
521
542
}
541
562
} ,
542
563
543
564
compile : function ( tElement , tAttrs ) {
544
- var repeat = RepeatParser . parse ( tAttrs . repeat ) ;
545
- var groupByExp = tAttrs . groupBy ;
565
+
566
+ if ( ! tAttrs . repeat ) throw uiSelectMinErr ( 'repeat' , "Expected 'repeat' expression." ) ;
567
+
546
568
return function link ( scope , element , attrs , $select , transcludeFn ) {
569
+
570
+ // var repeat = RepeatParser.parse(attrs.repeat);
571
+ var groupByExp = attrs . groupBy ;
572
+
573
+ $select . parseRepeatAttr ( attrs . repeat , groupByExp ) ; //Result ready at $select.parserResult
547
574
548
575
if ( groupByExp ) {
549
576
var groups = element . querySelectorAll ( '.ui-select-choices-group' ) ;
556
583
throw uiSelectMinErr ( 'rows' , "Expected 1 .ui-select-choices-row but got '{0}'." , choices . length ) ;
557
584
}
558
585
559
- choices . attr ( 'ng-repeat' , RepeatParser . getNgRepeatExpression ( repeat . lhs , '$select.items' , repeat . trackByExp , groupByExp ) )
560
- . attr ( 'ng-mouseenter' , '$select.setActiveItem(' + repeat . lhs + ')' )
561
- . attr ( 'ng-click' , '$select.select(' + repeat . lhs + ')' ) ;
562
-
586
+ choices . attr ( 'ng-repeat' , RepeatParser . getNgRepeatExpression ( $select . parserResult . itemName , '$select.items' , $select . parserResult . trackByExp , groupByExp ) )
587
+ . attr ( 'ng-mouseenter' , '$select.setActiveItem(' + $select . parserResult . itemName + ')' )
588
+ . attr ( 'ng-click' , '$select.select(' + $select . parserResult . itemName + ')' ) ;
563
589
564
590
transcludeFn ( function ( clone ) {
565
591
var rowsInner = element . querySelectorAll ( '.ui-select-choices-row-inner' ) ;
570
596
$compile ( element ) ( scope ) ;
571
597
} ) ;
572
598
573
- $select . parseRepeatAttr ( attrs . repeat , groupByExp ) ;
574
-
575
599
scope . $watch ( '$select.search' , function ( ) {
576
600
$select . activeIndex = 0 ;
577
601
$select . refresh ( attrs . refresh ) ;
626
650
angular . module ( "ui.select" ) . run ( [ "$templateCache" , function ( $templateCache ) { $templateCache . put ( "bootstrap/choices.tpl.html" , "<ul class=\"ui-select-choices ui-select-choices-content dropdown-menu\" role=\"menu\" aria-labelledby=\"dLabel\" ng-show=\"$select.items.length > 0\"><li class=\"ui-select-choices-group\"><div class=\"divider\" ng-show=\"$index > 0\"></div><div ng-show=\"$select.isGrouped\" class=\"ui-select-choices-group-label dropdown-header\">{{$group}}</div><div class=\"ui-select-choices-row\" ng-class=\"{active: $select.isActive(this)}\"><a href=\"javascript:void(0)\" class=\"ui-select-choices-row-inner\"></a></div></li></ul>" ) ;
627
651
$templateCache . put ( "bootstrap/match.tpl.html" , "<button type=\"button\" class=\"btn btn-default form-control ui-select-match\" tabindex=\"-1\" ng-hide=\"$select.open\" ng-disabled=\"$select.disabled\" ng-class=\"{\'btn-default-focus\':$select.focus}\" ;=\"\" ng-click=\"$select.activate()\"><span ng-hide=\"$select.selected !== undefined\" class=\"text-muted\">{{$select.placeholder}}</span> <span ng-show=\"$select.selected !== undefined\" ng-transclude=\"\"></span> <span class=\"caret\"></span></button>" ) ;
628
652
$templateCache . put ( "bootstrap/select.tpl.html" , "<div class=\"ui-select-bootstrap dropdown\" ng-class=\"{open: $select.open}\"><div class=\"ui-select-match\"></div><input type=\"text\" autocomplete=\"off\" tabindex=\"-1\" class=\"form-control ui-select-search\" placeholder=\"{{$select.placeholder}}\" ng-model=\"$select.search\" ng-show=\"$select.open\"><div class=\"ui-select-choices\"></div></div>" ) ;
629
- $templateCache . put ( "select2/choices.tpl.html" , "<ul class=\"ui-select-choices ui-select-choices-content select2-results\"><li class=\"ui-select-choices-group\" ng-class=\"{\'select2-result-with-children\': $select.isGrouped}\"><div ng-show=\"$select.isGrouped\" class=\"ui-select-choices-group-label select2-result-label\">{{$group}}</div><ul class=\"select2-result-sub\"><li class=\"ui-select-choices-row\" ng-class=\"{\'select2-highlighted\': $select.isActive(this)}\"><div class=\"select2-result-label ui-select-choices-row-inner\"></div></li></ul></li></ul>" ) ;
630
- $templateCache . put ( "select2/match.tpl.html" , "<a class=\"select2-choice ui-select-match\" ng-class=\"{\'select2-default\': $select.selected === undefined}\" ng-click=\"$select.activate()\"><span ng-hide=\"$select.selected !== undefined\" class=\"select2-chosen\">{{$select.placeholder}}</span> <span ng-show=\"$select.selected !== undefined\" class=\"select2-chosen\" ng-transclude=\"\"></span> <span class=\"select2-arrow\"><b></b></span></a>" ) ;
631
- $templateCache . put ( "select2/select.tpl.html" , "<div class=\"select2 select2-container\" ng-class=\"{\'select2-container-active select2-dropdown-open\': $select.open,\n \'select2-container-disabled\': $select.disabled,\n \'select2-container-active\': $select.focus }\"><div class=\"ui-select-match\"></div><div class=\"select2-drop select2-with-searchbox select2-drop-active\" ng-class=\"{\'select2-display-none\': !$select.open}\"><div class=\"select2-search\"><input type=\"text\" autocomplete=\"off\" autocorrect=\"off\" autocapitalize=\"off\" spellcheck=\"false\" class=\"ui-select-search select2-input\" ng-model=\"$select.search\"></div><div class=\"ui-select-choices\"></div></div></div>" ) ;
632
653
$templateCache . put ( "selectize/choices.tpl.html" , "<div ng-show=\"$select.open\" class=\"ui-select-choices selectize-dropdown single\"><div class=\"ui-select-choices-content selectize-dropdown-content\"><div class=\"ui-select-choices-group optgroup\"><div ng-show=\"$select.isGrouped\" class=\"ui-select-choices-group-label optgroup-header\">{{$group}}</div><div class=\"ui-select-choices-row\" ng-class=\"{active: $select.isActive(this)}\"><div class=\"option ui-select-choices-row-inner\" data-selectable=\"\"></div></div></div></div></div>" ) ;
633
654
$templateCache . put ( "selectize/match.tpl.html" , "<div ng-hide=\"$select.open || $select.selected === undefined\" class=\"ui-select-match\" ng-transclude=\"\"></div>" ) ;
634
- $templateCache . put ( "selectize/select.tpl.html" , "<div class=\"selectize-control single\"><div class=\"selectize-input\" ng-class=\"{\'focus\': $select.open, \'disabled\': $select.disabled, \'selectize-focus\' : $select.focus}\" ng-click=\"$select.activate()\"><div class=\"ui-select-match\"></div><input type=\"text\" autocomplete=\"off\" tabindex=\"-1\" class=\"ui-select-search\" placeholder=\"{{$select.placeholder}}\" ng-model=\"$select.search\" ng-hide=\"$select.selected && !$select.open\" ng-disabled=\"$select.disabled\"></div><div class=\"ui-select-choices\"></div></div>" ) ; } ] ) ;
655
+ $templateCache . put ( "selectize/select.tpl.html" , "<div class=\"selectize-control single\"><div class=\"selectize-input\" ng-class=\"{\'focus\': $select.open, \'disabled\': $select.disabled, \'selectize-focus\' : $select.focus}\" ng-click=\"$select.activate()\"><div class=\"ui-select-match\"></div><input type=\"text\" autocomplete=\"off\" tabindex=\"-1\" class=\"ui-select-search\" placeholder=\"{{$select.placeholder}}\" ng-model=\"$select.search\" ng-hide=\"$select.selected && !$select.open\" ng-disabled=\"$select.disabled\"></div><div class=\"ui-select-choices\"></div></div>" ) ;
656
+ $templateCache . put ( "select2/choices.tpl.html" , "<ul class=\"ui-select-choices ui-select-choices-content select2-results\"><li class=\"ui-select-choices-group\" ng-class=\"{\'select2-result-with-children\': $select.isGrouped}\"><div ng-show=\"$select.isGrouped\" class=\"ui-select-choices-group-label select2-result-label\">{{$group}}</div><ul ng-class=\"{\'select2-result-sub\': $select.isGrouped, \'select2-result-single\': !$select.isGrouped}\"><li class=\"ui-select-choices-row\" ng-class=\"{\'select2-highlighted\': $select.isActive(this)}\"><div class=\"select2-result-label ui-select-choices-row-inner\"></div></li></ul></li></ul>" ) ;
657
+ $templateCache . put ( "select2/match.tpl.html" , "<a class=\"select2-choice ui-select-match\" ng-class=\"{\'select2-default\': $select.selected === undefined}\" ng-click=\"$select.activate()\"><span ng-hide=\"$select.selected !== undefined\" class=\"select2-chosen\">{{$select.placeholder}}</span> <span ng-show=\"$select.selected !== undefined\" class=\"select2-chosen\" ng-transclude=\"\"></span> <span class=\"select2-arrow\"><b></b></span></a>" ) ;
658
+ $templateCache . put ( "select2/select.tpl.html" , "<div class=\"select2 select2-container\" ng-class=\"{\'select2-container-active select2-dropdown-open\': $select.open,\n \'select2-container-disabled\': $select.disabled,\n \'select2-container-active\': $select.focus }\"><div class=\"ui-select-match\"></div><div class=\"select2-drop select2-with-searchbox select2-drop-active\" ng-class=\"{\'select2-display-none\': !$select.open}\"><div class=\"select2-search\"><input type=\"text\" autocomplete=\"off\" autocorrect=\"off\" autocapitalize=\"off\" spellcheck=\"false\" class=\"ui-select-search select2-input\" ng-model=\"$select.search\"></div><div class=\"ui-select-choices\"></div></div></div>" ) ; } ] ) ;
0 commit comments