/*! * ui-select * http://github.com/angular-ui/ui-select * Version: 0.11.2 - 2015-03-17T04:08:46.474Z * 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); } }; /** * 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(); }); } }; }]); // Make multiple matches sortable uis.directive('uiSelectSort', ['$timeout', 'uiSelectConfig', 'uiSelectMinErr', function($timeout, uiSelectConfig, uiSelectMinErr) { return { require: '^uiSelect', link: function(scope, element, attrs, $select) { if (scope[attrs.uiSelectSort] === null) { throw uiSelectMinErr('sort', "Expected a list to sort"); } var options = angular.extend({ axis: 'horizontal' }, scope.$eval(attrs.uiSelectSortOptions)); var axis = options.axis, draggingClassName = 'dragging', droppingClassName = 'dropping', droppingBeforeClassName = 'dropping-before', droppingAfterClassName = 'dropping-after'; scope.$watch(function() { return $select.sortable; }, function(n) { if (n) { element.attr('draggable', true); } else { element.removeAttr('draggable'); } }); element.on('dragstart', function(e) { element.addClass(draggingClassName); (e.dataTransfer || e.originalEvent.dataTransfer).setData('text/plain', scope.$index); }); element.on('dragend', function() { element.removeClass(draggingClassName); }); var move = function(from, to) { /*jshint validthis: true */ this.splice(to, 0, this.splice(from, 1)[0]); }; var dragOverHandler = function(e) { e.preventDefault(); var offset = axis === 'vertical' ? e.offsetY || e.layerY || (e.originalEvent ? e.originalEvent.offsetY : 0) : e.offsetX || e.layerX || (e.originalEvent ? e.originalEvent.offsetX : 0); if (offset < (this[axis === 'vertical' ? 'offsetHeight' : 'offsetWidth'] / 2)) { element.removeClass(droppingAfterClassName); element.addClass(droppingBeforeClassName); } else { element.removeClass(droppingBeforeClassName); element.addClass(droppingAfterClassName); } }; var dropTimeout; var dropHandler = function(e) { e.preventDefault(); var droppedItemIndex = parseInt((e.dataTransfer || e.originalEvent.dataTransfer).getData('text/plain'), 10); // prevent event firing multiple times in firefox $timeout.cancel(dropTimeout); dropTimeout = $timeout(function() { _dropHandler(droppedItemIndex); }, 20); }; var _dropHandler = function(droppedItemIndex) { var theList = scope.$eval(attrs.uiSelectSort), itemToMove = theList[droppedItemIndex], newIndex = null; if (element.hasClass(droppingBeforeClassName)) { if (droppedItemIndex < scope.$index) { newIndex = scope.$index - 1; } else { newIndex = scope.$index; } } else { if (droppedItemIndex < scope.$index) { newIndex = scope.$index; } else { newIndex = scope.$index + 1; } } move.apply(theList, [droppedItemIndex, newIndex]); scope.$apply(function() { scope.$emit('uiSelectSort:change', { array: theList, item: itemToMove, from: droppedItemIndex, to: newIndex }); }); element.removeClass(droppingClassName); element.removeClass(droppingBeforeClassName); element.removeClass(droppingAfterClassName); element.off('drop', dropHandler); }; element.on('dragenter', function() { if (element.hasClass(draggingClassName)) { return; } element.addClass(droppingClassName); element.on('dragover', dragOverHandler); element.on('drop', dropHandler); }); element.on('dragleave', function(e) { if (e.target != element) { return; } element.removeClass(droppingClassName); element.removeClass(droppingBeforeClassName); element.removeClass(droppingAfterClassName); element.off('dragover', dragOverHandler); element.off('drop', dropHandler); }); } }; }]); /** * Parses "repeat" attribute. * * Taken from AngularJS ngRepeat source code * See https://github.com/angular/angular.js/blob/v1.2.15/src/ng/directive/ngRepeat.js#L211 * * Original discussion about parsing "repeat" attribute instead of fully relying on ng-repeat: * https://github.com/angular-ui/ui-select/commit/5dd63ad#commitcomment-5504697 */ uis.service('uisRepeatParser', ['uiSelectMinErr', '$parse', function(uiSelectMinErr, $parse) { var self = this; /** * Example: * expression = "address in addresses | filter: {street: $select.search} track by $index" * itemName = "address", * source = "addresses | filter: {street: $select.search}", * trackByExp = "$index", */ self.parse = function(expression) { var match = expression.match(/^\s*(?:([\s\S]+?)\s+as\s+)?([\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/); if (!match) { throw uiSelectMinErr('iexp', "Expected expression in form of '_item_ in _collection_[ track by _id_]' but got '{0}'.", expression); } return { itemName: match[2], // (lhs) Left-hand side, source: $parse(match[3]), trackByExp: match[4], modelMapper: $parse(match[1] || match[2]) }; }; self.getGroupNgRepeatExpression = function() { return '$group in $select.groups'; }; self.getNgRepeatExpression = function(itemName, source, trackByExp, grouped) { var expression = itemName + ' in ' + (grouped ? '$group.items' : source); if (trackByExp) { expression += ' track by ' + trackByExp; } return expression; }; }]); }()); angular.module("ui.select").run(["$templateCache", function($templateCache) { $templateCache.put("bootstrap/choices.tpl.html", ""); $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", "
    "); }]);