1
1
/*!
2
2
* ui-select
3
3
* http://github.com/angular-ui/ui-select
4
- * Version: 0.8.0 - 2014-10-07T13:45:31.563Z
4
+ * Version: 0.8.3 - 2014-10-14T18:22:05.432Z
5
5
* License: MIT
6
6
*/
7
7
27
27
END : 35 ,
28
28
BACKSPACE : 8 ,
29
29
DELETE : 46 ,
30
+ COMMAND : 91 ,
30
31
isControl : function ( e ) {
31
32
var k = e . which ;
32
33
switch ( k ) {
34
+ case KEY . COMMAND :
33
35
case KEY . SHIFT :
34
36
case KEY . CTRL :
35
37
case KEY . ALT :
158
160
ctrl . selected = undefined ;
159
161
ctrl . open = false ;
160
162
ctrl . focus = false ;
161
- ctrl . focusser = undefined ; //Reference to input element used to handle focus events
163
+ ctrl . focusser = undefined ; //Reference to input element used to handle focus events
162
164
ctrl . disabled = undefined ; // Initialized inside uiSelect directive link function
163
165
ctrl . searchEnabled = undefined ; // Initialized inside uiSelect directive link function
164
166
ctrl . resetSearchInput = undefined ; // Initialized inside uiSelect directive link function
190
192
ctrl . activate = function ( initSearchValue , avoidReset ) {
191
193
if ( ! ctrl . disabled && ! ctrl . open ) {
192
194
if ( ! avoidReset ) _resetSearchInput ( ) ;
195
+ ctrl . focusser . prop ( 'disabled' , true ) ; //Will reactivate it on .close()
193
196
ctrl . open = true ;
194
197
ctrl . activeMatchIndex = - 1 ;
195
198
257
260
var filteredItems = items . filter ( function ( i ) { return ctrl . selected . indexOf ( i ) < 0 ; } ) ;
258
261
setItemsFn ( filteredItems ) ;
259
262
} else {
260
- setItemsFn ( items ) ;
263
+ setItemsFn ( items ) ;
261
264
}
262
265
ctrl . ngModel . $modelValue = null ; //Force scope model value and ngModel value to be out of sync to re-run formatters
263
266
267
270
} ) ;
268
271
269
272
if ( ctrl . multiple ) {
270
- //Remove already selected items
273
+ //Remove already selected items
271
274
$scope . $watchCollection ( '$select.selected' , function ( selectedItems ) {
272
- if ( ! selectedItems . length ) return ;
273
275
var data = ctrl . parserResult . source ( $scope ) ;
274
- if ( ! data ) return ;
275
- var filteredItems = data . filter ( function ( i ) { return selectedItems . indexOf ( i ) < 0 ; } ) ;
276
- setItemsFn ( filteredItems ) ;
276
+ if ( ! selectedItems . length ) {
277
+ setItemsFn ( data ) ;
278
+ } else {
279
+ var filteredItems = data . filter ( function ( i ) { return selectedItems . indexOf ( i ) < 0 ; } ) ;
280
+ setItemsFn ( filteredItems ) ;
281
+ }
277
282
ctrl . sizeSearchInput ( ) ;
278
283
} ) ;
279
284
}
307
312
} ;
308
313
309
314
ctrl . isActive = function ( itemScope ) {
310
- if ( typeof itemScope [ ctrl . itemProperty ] === 'undefined' ) {
311
- return false ;
312
- }
315
+ return ctrl . open && ctrl . items . indexOf ( itemScope [ ctrl . itemProperty ] ) === ctrl . activeIndex ;
313
316
} ;
314
317
315
318
ctrl . isDisabled = function ( itemScope ) {
319
+
320
+ if ( ! ctrl . open ) return ;
321
+
316
322
var itemIndex = ctrl . items . indexOf ( itemScope [ ctrl . itemProperty ] ) ;
317
323
var isDisabled = false ;
318
324
var item ;
327
333
} ;
328
334
329
335
// When the user clicks on an item inside the dropdown
330
- ctrl . select = function ( item ) {
331
-
332
- if ( ! item || ! item . _uiSelectChoiceDisabled ) {
333
- if ( ctrl . tagging . isActivated && ! item && ctrl . search . length > 0 ) {
334
- // create new item on the fly
335
- item = ctrl . tagging . fct !== undefined ? ctrl . tagging . fct ( ctrl . search ) : ctrl . search ;
336
- }
336
+ ctrl . select = function ( item , skipFocusser ) {
337
337
338
+ if ( item === undefined || ! item . _uiSelectChoiceDisabled ) {
338
339
var locals = { } ;
339
340
locals [ ctrl . parserResult . itemName ] = item ;
340
341
349
350
} else {
350
351
ctrl . selected = item ;
351
352
}
352
- ctrl . close ( ) ;
353
+ ctrl . close ( skipFocusser ) ;
353
354
}
354
355
} ;
355
356
356
357
// Closes the dropdown
357
- ctrl . close = function ( ) {
358
- if ( ctrl . open ) {
359
- _resetSearchInput ( ) ;
360
- ctrl . open = false ;
358
+ ctrl . close = function ( skipFocusser ) {
359
+ if ( ! ctrl . open ) return ;
360
+ _resetSearchInput ( ) ;
361
+ ctrl . open = false ;
362
+ if ( ! ctrl . multiple ) {
361
363
$timeout ( function ( ) {
362
- ctrl . focusser [ 0 ] . focus ( ) ;
364
+ ctrl . focusser . prop ( 'disabled' , false ) ;
365
+ if ( ! skipFocusser ) ctrl . focusser [ 0 ] . focus ( ) ;
363
366
} , 0 , false ) ;
364
367
}
365
368
} ;
373
376
374
377
// Remove item from multiple select
375
378
ctrl . removeChoice = function ( index ) {
379
+ var removedChoice = ctrl . selected [ index ] ;
380
+ var locals = { } ;
381
+ locals [ ctrl . parserResult . itemName ] = removedChoice ;
382
+
376
383
ctrl . selected . splice ( index , 1 ) ;
377
384
ctrl . activeMatchIndex = - 1 ;
378
385
ctrl . sizeSearchInput ( ) ;
386
+
387
+ ctrl . onRemoveCallback ( $scope , {
388
+ $item : removedChoice ,
389
+ $model : ctrl . parserResult . modelMapper ( $scope , locals )
390
+ } ) ;
379
391
} ;
380
392
381
393
ctrl . getPlaceholder = function ( ) {
382
394
//Refactor single?
383
- if ( ctrl . multiple && ( ctrl . selected === undefined || ctrl . selected . length ) ) return ;
395
+ if ( ctrl . multiple && ctrl . selected . length ) return ;
384
396
return ctrl . placeholder ;
385
397
} ;
386
398
399
+ var containerSizeWatch ;
387
400
ctrl . sizeSearchInput = function ( ) {
388
401
var input = _searchInput [ 0 ] ,
389
402
container = _searchInput . parent ( ) . parent ( ) [ 0 ] ;
390
403
_searchInput . css ( 'width' , '10px' ) ;
391
- $timeout ( function ( ) {
404
+ var calculate = function ( ) {
392
405
var newWidth = container . clientWidth - input . offsetLeft - 10 ;
393
406
if ( newWidth < 50 ) newWidth = container . clientWidth ;
394
407
_searchInput . css ( 'width' , newWidth + 'px' ) ;
408
+ } ;
409
+ $timeout ( function ( ) { //Give tags time to render correctly
410
+ if ( container . clientWidth === 0 && ! containerSizeWatch ) {
411
+ containerSizeWatch = $scope . $watch ( function ( ) { return container . clientWidth ; } , function ( newValue ) {
412
+ if ( newValue !== 0 ) {
413
+ calculate ( ) ;
414
+ containerSizeWatch ( ) ;
415
+ containerSizeWatch = null ;
416
+ }
417
+ } ) ;
418
+ } else if ( ! containerSizeWatch ) {
419
+ calculate ( ) ;
420
+ }
395
421
} , 0 , false ) ;
396
422
} ;
397
423
404
430
break ;
405
431
case KEY . UP :
406
432
if ( ! ctrl . open && ctrl . multiple ) ctrl . activate ( false , true ) ; //In case its the search input in 'multiple' mode
407
- else if ( ctrl . activeIndex > 0 || ( ctrl . search . length === 0 && ctrl . tagging . isActivated ) ) { ctrl . activeIndex -- ; }
433
+ else if ( ctrl . activeIndex > 0 ) { ctrl . activeIndex -- ; }
408
434
break ;
409
435
case KEY . TAB :
410
- //TODO: Que hacemos en modo multiple?
411
- if ( ! ctrl . multiple ) ctrl . select ( ctrl . items [ ctrl . activeIndex ] ) ;
436
+ if ( ! ctrl . multiple || ctrl . open ) ctrl . select ( ctrl . items [ ctrl . activeIndex ] , true ) ;
412
437
break ;
413
438
case KEY . ENTER :
414
439
if ( ctrl . open ) {
429
454
// Handles selected options in "multiple" mode
430
455
function _handleMatchSelection ( key ) {
431
456
var caretPosition = _getCaretPosition ( _searchInput [ 0 ] ) ,
432
- length = ctrl . selected . length ,
457
+ length = ctrl . selected . length ,
433
458
// none = -1,
434
459
first = 0 ,
435
460
last = length - 1 ,
452
477
break ;
453
478
case KEY . RIGHT :
454
479
// Open drop-down
455
- if ( ! ~ ctrl . activeMatchIndex || curr === last ) {
480
+ if ( ! ~ ctrl . activeMatchIndex || curr === last ) {
456
481
ctrl . activate ( ) ;
457
482
return false ;
458
483
}
475
500
return curr ;
476
501
}
477
502
else return false ;
478
- }
503
+ }
479
504
}
480
505
481
506
newIndex = getNewActiveMatchIndex ( ) ;
503
528
processed = _handleMatchSelection ( key ) ;
504
529
}
505
530
506
- if ( ! processed && ( ctrl . items . length > 0 || ctrl . tagging . isActivated ) ) {
531
+ if ( ! processed && ctrl . items . length > 0 ) {
507
532
processed = _handleDropDownSelection ( key ) ;
508
533
}
509
-
534
+
510
535
if ( processed && key != KEY . TAB ) {
511
536
//TODO Check si el tab selecciona aun correctamente
512
537
//Crear test
524
549
_searchInput . on ( 'blur' , function ( ) {
525
550
$timeout ( function ( ) {
526
551
ctrl . activeMatchIndex = - 1 ;
527
- ctrl . activeIndex = 0 ;
528
552
} ) ;
529
553
} ) ;
530
554
585
609
586
610
var searchInput = element . querySelectorAll ( 'input.ui-select-search' ) ;
587
611
588
- $select . multiple = angular . isDefined ( attrs . multiple ) ;
612
+ $select . multiple = ( angular . isDefined ( attrs . multiple ) ) ? ( attrs . multiple === '' ) ? true : ( attrs . multiple . toLowerCase ( ) === 'true' ) : false ;
589
613
590
614
$select . onSelectCallback = $parse ( attrs . onSelect ) ;
591
-
592
- $select . tagging = { isActivated : false , fct : undefined } ;
615
+ $select . onRemoveCallback = $parse ( attrs . onRemove ) ;
593
616
594
617
//From view --> model
595
618
ngModel . $parsers . unshift ( function ( inputValue ) {
614
637
615
638
//From model --> view
616
639
ngModel . $formatters . unshift ( function ( inputValue ) {
617
- var data = $select . parserResult . source ( scope , { $select : { search :'' } } ) , //Overwrite $search
640
+ var data = $select . parserResult . source ( scope , { $select : { search :'' } } ) , //Overwrite $search
618
641
locals = { } ,
619
642
result ;
620
643
if ( data ) {
666
689
if ( attrs . tabindex ) {
667
690
//tabindex might be an expression, wait until it contains the actual value before we set the focusser tabindex
668
691
attrs . $observe ( 'tabindex' , function ( value ) {
669
- //If we are using multiple, add tabindex to the search input
692
+ //If we are using multiple, add tabindex to the search input
670
693
if ( $select . multiple ) {
671
694
searchInput . attr ( "tabindex" , value ) ;
672
695
} else {
699
722
e . preventDefault ( ) ;
700
723
e . stopPropagation ( ) ;
701
724
$select . select ( undefined ) ;
702
- scope . $digest ( ) ;
725
+ scope . $apply ( ) ;
703
726
return ;
704
727
}
705
728
721
744
if ( e . which === KEY . TAB || KEY . isControl ( e ) || KEY . isFunctionKey ( e ) || e . which === KEY . ESC || e . which == KEY . ENTER || e . which === KEY . BACKSPACE ) {
722
745
return ;
723
746
}
724
-
747
+
725
748
$select . activate ( focusser . val ( ) ) ; //User pressed some regular key, so we pass it to the search input
726
749
focusser . val ( '' ) ;
727
750
scope . $digest ( ) ;
747
770
$select . resetSearchInput = resetSearchInput !== undefined ? resetSearchInput : true ;
748
771
} ) ;
749
772
750
- attrs . $observe ( 'tagging' , function ( ) {
751
- if ( attrs . tagging !== undefined )
752
- {
753
- // $eval() is needed otherwise we get a string instead of a function or a boolean
754
- var taggingEval = scope . $eval ( attrs . tagging ) ;
755
- $select . tagging = { isActivated : true , fct : taggingEval !== true ? taggingEval : undefined } ;
756
- }
757
- else
758
- {
759
- $select . tagging = { isActivated : false , fct : undefined } ;
760
- }
761
- } ) ;
762
-
763
773
if ( $select . multiple ) {
774
+ scope . $watchCollection ( function ( ) { return ngModel . $modelValue ; } , function ( newValue , oldValue ) {
775
+ if ( oldValue != newValue )
776
+ ngModel . $modelValue = null ; //Force scope model value and ngModel value to be out of sync to re-run formatters
777
+ } ) ;
764
778
scope . $watchCollection ( '$select.selected' , function ( ) {
765
779
ngModel . $setViewValue ( Date . now ( ) ) ; //Set timestamp as a unique string to force changes
766
780
} ) ;
859
873
if ( ! tAttrs . repeat ) throw uiSelectMinErr ( 'repeat' , "Expected 'repeat' expression." ) ;
860
874
861
875
return function link ( scope , element , attrs , $select , transcludeFn ) {
862
-
876
+
863
877
// var repeat = RepeatParser.parse(attrs.repeat);
864
878
var groupByExp = attrs . groupBy ;
865
879
890
904
891
905
scope . $watch ( '$select.search' , function ( newValue ) {
892
906
if ( newValue && ! $select . open && $select . multiple ) $select . activate ( false , true ) ;
893
- $select . activeIndex = $select . tagging . isActivated ? - 1 : 0 ;
907
+ $select . activeIndex = 0 ;
894
908
$select . refresh ( attrs . refresh ) ;
895
909
} ) ;
896
910
931
945
} ) ;
932
946
933
947
if ( $select . multiple ) {
934
- $select . sizeSearchInput ( ) ;
948
+ $select . sizeSearchInput ( ) ;
935
949
}
936
950
937
951
}
@@ -967,4 +981,4 @@ $templateCache.put("select2/select-multiple.tpl.html","<div class=\"ui-select-mu
967
981
$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\" ng-show=\"$select.searchEnabled\"><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>" ) ;
968
982
$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.name}}</div><div class=\"ui-select-choices-row\" ng-class=\"{active: $select.isActive(this), disabled: $select.isDisabled(this)}\"><div class=\"option ui-select-choices-row-inner\" data-selectable=\"\"></div></div></div></div></div>" ) ;
969
983
$templateCache . put ( "selectize/match.tpl.html" , "<div ng-hide=\"$select.searchEnabled && ($select.open || $select.isEmpty())\" class=\"ui-select-match\" ng-transclude=\"\"></div>" ) ;
970
- $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 ui-select-toggle\" ng-click=\"$select.toggle($event)\" placeholder=\"{{$select.placeholder}}\" ng-model=\"$select.search\" ng-hide=\"!$select.searchEnabled || ($select.selected && !$select.open)\" ng-disabled=\"$select.disabled\"></div><div class=\"ui-select-choices\"></div></div>" ) ; } ] ) ;
984
+ $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 ui-select-toggle\" ng-click=\"$select.toggle($event)\" placeholder=\"{{$select.placeholder}}\" ng-model=\"$select.search\" ng-hide=\"!$select.searchEnabled || ($select.selected && !$select.open)\" ng-disabled=\"$select.disabled\"></div><div class=\"ui-select-choices\"></div></div>" ) ; } ] ) ;
0 commit comments