/*! * ui-select * http://github.com/angular-ui/ui-select * Version: 0.16.0 - 2016-03-23T20:51:56.609Z * License: MIT */ (function () { "use strict"; var KEY = { TAB: 9, ENTER: 13, ESC: 27, SPACE: 32, LEFT: 37, UP: 38, RIGHT: 39, DOWN: 40, SHIFT: 16, CTRL: 17, ALT: 18, PAGE_UP: 33, PAGE_DOWN: 34, HOME: 36, END: 35, BACKSPACE: 8, DELETE: 46, COMMAND: 91, MAP: { 91 : "COMMAND", 8 : "BACKSPACE" , 9 : "TAB" , 13 : "ENTER" , 16 : "SHIFT" , 17 : "CTRL" , 18 : "ALT" , 19 : "PAUSEBREAK" , 20 : "CAPSLOCK" , 27 : "ESC" , 32 : "SPACE" , 33 : "PAGE_UP", 34 : "PAGE_DOWN" , 35 : "END" , 36 : "HOME" , 37 : "LEFT" , 38 : "UP" , 39 : "RIGHT" , 40 : "DOWN" , 43 : "+" , 44 : "PRINTSCREEN" , 45 : "INSERT" , 46 : "DELETE", 48 : "0" , 49 : "1" , 50 : "2" , 51 : "3" , 52 : "4" , 53 : "5" , 54 : "6" , 55 : "7" , 56 : "8" , 57 : "9" , 59 : ";", 61 : "=" , 65 : "A" , 66 : "B" , 67 : "C" , 68 : "D" , 69 : "E" , 70 : "F" , 71 : "G" , 72 : "H" , 73 : "I" , 74 : "J" , 75 : "K" , 76 : "L", 77 : "M" , 78 : "N" , 79 : "O" , 80 : "P" , 81 : "Q" , 82 : "R" , 83 : "S" , 84 : "T" , 85 : "U" , 86 : "V" , 87 : "W" , 88 : "X" , 89 : "Y" , 90 : "Z", 96 : "0" , 97 : "1" , 98 : "2" , 99 : "3" , 100 : "4" , 101 : "5" , 102 : "6" , 103 : "7" , 104 : "8" , 105 : "9", 106 : "*" , 107 : "+" , 109 : "-" , 110 : "." , 111 : "/", 112 : "F1" , 113 : "F2" , 114 : "F3" , 115 : "F4" , 116 : "F5" , 117 : "F6" , 118 : "F7" , 119 : "F8" , 120 : "F9" , 121 : "F10" , 122 : "F11" , 123 : "F12", 144 : "NUMLOCK" , 145 : "SCROLLLOCK" , 186 : ";" , 187 : "=" , 188 : "," , 189 : "-" , 190 : "." , 191 : "/" , 192 : "`" , 219 : "[" , 220 : "\\" , 221 : "]" , 222 : "'" }, isControl: function (e) { var k = e.which; switch (k) { case KEY.COMMAND: case KEY.SHIFT: case KEY.CTRL: case KEY.ALT: return true; } if (e.metaKey) return true; return false; }, isFunctionKey: function (k) { k = k.which ? k.which : k; return k >= 112 && k <= 123; }, isVerticalMovement: function (k){ return ~[KEY.UP, KEY.DOWN].indexOf(k); }, isHorizontalMovement: function (k){ return ~[KEY.LEFT,KEY.RIGHT,KEY.BACKSPACE,KEY.DELETE].indexOf(k); }, toSeparator: function (k) { var sep = {ENTER:"\n",TAB:"\t",SPACE:" "}[k]; if (sep) return sep; // return undefined for special keys other than enter, tab or space. // no way to use them to cut strings. return KEY[k] ? undefined : k; } }; /** * Add querySelectorAll() to jqLite. * * jqLite find() is limited to lookups by tag name. * TODO This will change with future versions of AngularJS, to be removed when this happens * * See jqLite.find - why not use querySelectorAll? https://github.com/angular/angular.js/issues/3586 * See feat(jqLite): use querySelectorAll instead of getElementsByTagName in jqLite.find https://github.com/angular/angular.js/pull/3598 */ if (angular.element.prototype.querySelectorAll === undefined) { angular.element.prototype.querySelectorAll = function(selector) { return angular.element(this[0].querySelectorAll(selector)); }; } /** * Add closest() to jqLite. */ if (angular.element.prototype.closest === undefined) { angular.element.prototype.closest = function( selector) { var elem = this[0]; var matchesSelector = elem.matches || elem.webkitMatchesSelector || elem.mozMatchesSelector || elem.msMatchesSelector; while (elem) { if (matchesSelector.bind(elem)(selector)) { return elem; } else { elem = elem.parentElement; } } return false; }; } var latestId = 0; var uis = angular.module('ui.select', []) .constant('uiSelectConfig', { theme: 'bootstrap', searchEnabled: true, sortable: false, placeholder: '', // Empty by default, like HTML tag "); $compile(focusser)(scope); $select.focusser = focusser; //Input that will handle focus $select.focusInput = focusser; element.parent().append(focusser); focusser.bind("focus", function(){ scope.$evalAsync(function(){ $select.focus = true; }); }); focusser.bind("blur", function(){ scope.$evalAsync(function(){ $select.focus = false; }); }); focusser.bind("keydown", function(e){ if (e.which === KEY.BACKSPACE) { e.preventDefault(); e.stopPropagation(); $select.select(undefined); scope.$apply(); return; } if (e.which === KEY.TAB || KEY.isControl(e) || KEY.isFunctionKey(e) || e.which === KEY.ESC) { return; } if (e.which == KEY.DOWN || e.which == KEY.UP || e.which == KEY.ENTER || e.which == KEY.SPACE){ e.preventDefault(); e.stopPropagation(); $select.activate(); } scope.$digest(); }); focusser.bind("keyup input", function(e){ if (e.which === KEY.TAB || KEY.isControl(e) || KEY.isFunctionKey(e) || e.which === KEY.ESC || e.which == KEY.ENTER || e.which === KEY.BACKSPACE) { return; } $select.activate(focusser.val()); //User pressed some regular key, so we pass it to the search input focusser.val(''); scope.$digest(); }); $select.searchInput.on('keyup', function(e) { if ( ! KEY.isVerticalMovement(e.which) ) { scope.$evalAsync( function () { $select.activeIndex = $select.taggingLabel === false ? -1 : 0; }); } // Push a "create new" item into array if there is a search string if ( $select.tagging.isActivated && $select.search.length > 0 ) { // return early with these keys if (e.which === KEY.TAB || KEY.isControl(e) || KEY.isFunctionKey(e) || e.which === KEY.ESC || KEY.isVerticalMovement(e.which) ) { return; } // always reset the activeIndex to the first item when tagging $select.activeIndex = $select.taggingLabel === false ? -1 : 0; // taggingLabel === false bypasses all of this if ($select.taggingLabel === false) return; var items = angular.copy( $select.items ); var stashArr = angular.copy( $select.items ); var newItem; var item; var hasTag = false; var dupeIndex = -1; var tagItems; var tagItem; // case for object tagging via transform `$select.tagging.fct` function if ( $select.tagging.fct !== undefined) { tagItems = $select.$filter('filter')(items,{'isTag': true}); if ( tagItems.length > 0 ) { tagItem = tagItems[0]; } // remove the first element, if it has the `isTag` prop we generate a new one with each keyup, shaving the previous if ( items.length > 0 && tagItem ) { hasTag = true; items = items.slice(1,items.length); stashArr = stashArr.slice(1,stashArr.length); } newItem = $select.tagging.fct($select.search); // verify the new tag doesn't match the value of a possible selection choice or an already selected item. if ( angular.equals($select.selected, newItem) ) { scope.$evalAsync(function () { $select.activeIndex = 0; $select.items = items; }); return; } newItem.isTag = true; // handle newItem string and stripping dupes in tagging string context } else { // find any tagging items already in the $select.items array and store them tagItems = $select.$filter('filter')(items,function (item) { return item.match($select.taggingLabel); }); if ( tagItems.length > 0 ) { tagItem = tagItems[0]; } item = items[0]; // remove existing tag item if found (should only ever be one tag item) if ( item !== undefined && items.length > 0 && tagItem ) { hasTag = true; items = items.slice(1,items.length); stashArr = stashArr.slice(1,stashArr.length); } newItem = $select.search+' '+$select.taggingLabel; if ( _findApproxDupe($select.selected, $select.search) > -1 ) { return; } // verify the the tag doesn't match the value of an existing item from // the searched data set or the items already selected if ( _findCaseInsensitiveDupe(stashArr.concat($select.selected)) ) { // if there is a tag from prev iteration, strip it / queue the change // and return early if ( hasTag ) { items = stashArr; scope.$evalAsync( function () { $select.activeIndex = 0; $select.items = items; }); } return; } if ( _findCaseInsensitiveDupe(stashArr) ) { // if there is a tag from prev iteration, strip it if ( hasTag ) { $select.items = stashArr.slice(1,stashArr.length); } return; } } if ( hasTag ) dupeIndex = _findApproxDupe($select.selected, newItem); // dupe found, shave the first item if ( dupeIndex > -1 ) { items = items.slice(dupeIndex+1,items.length-1); } else { items = []; items.push(newItem); items = items.concat(stashArr); } scope.$evalAsync( function () { $select.activeIndex = 0; $select.items = items; }); } }); function _findCaseInsensitiveDupe(arr) { if ( arr === undefined || $select.search === undefined ) { return false; } var hasDupe = arr.filter( function (origItem) { if ( $select.search.toUpperCase() === undefined || origItem === undefined ) { return false; } return origItem.toUpperCase() === $select.search.toUpperCase(); }).length > 0; return hasDupe; } function _findApproxDupe(haystack, needle) { var dupeIndex = -1; if(angular.isArray(haystack)) { var tempArr = angular.copy(haystack); for (var i = 0; i
  • 0\">
  • "); $templateCache.put("bootstrap/match-multiple.tpl.html"," × "); $templateCache.put("bootstrap/match.tpl.html","
    {{$select.placeholder}}
    "); $templateCache.put("bootstrap/select-multiple.tpl.html","
    "); $templateCache.put("bootstrap/select.tpl.html","
    "); $templateCache.put("select2/choices.tpl.html",""); $templateCache.put("select2/match-multiple.tpl.html","
  • "); $templateCache.put("select2/match.tpl.html","{{$select.placeholder}} "); $templateCache.put("select2/select-multiple.tpl.html","
    "); $templateCache.put("select2/select.tpl.html","
    "); $templateCache.put("selectize/choices.tpl.html","
    "); $templateCache.put("selectize/match.tpl.html","
    "); $templateCache.put("selectize/select.tpl.html","
    ");}]);