123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317 |
- /**
- * angular-strap
- * @version v2.3.9 - 2016-06-10
- * @link http://mgcrea.github.io/angular-strap
- * @author Olivier Louvignes <olivier@mg-crea.com> (https://github.com/mgcrea)
- * @license MIT License, http://www.opensource.org/licenses/MIT
- */
- 'use strict';
- angular.module('mgcrea.ngStrap.select', [ 'mgcrea.ngStrap.tooltip', 'mgcrea.ngStrap.helpers.parseOptions' ]).provider('$select', function() {
- var defaults = this.defaults = {
- animation: 'am-fade',
- prefixClass: 'select',
- prefixEvent: '$select',
- placement: 'bottom-left',
- templateUrl: 'select/select.tpl.html',
- trigger: 'focus',
- container: false,
- keyboard: true,
- html: false,
- delay: 0,
- multiple: false,
- allNoneButtons: false,
- sort: true,
- caretHtml: ' <span class="caret"></span>',
- placeholder: 'Choose among the following...',
- allText: 'All',
- noneText: 'None',
- maxLength: 3,
- maxLengthHtml: 'selected',
- iconCheckmark: 'glyphicon glyphicon-ok',
- toggle: false
- };
- this.$get = [ '$window', '$document', '$rootScope', '$tooltip', '$timeout', function($window, $document, $rootScope, $tooltip, $timeout) {
- var isNative = /(ip[ao]d|iphone|android)/gi.test($window.navigator.userAgent);
- var isTouch = 'createTouch' in $window.document && isNative;
- function SelectFactory(element, controller, config) {
- var $select = {};
- var options = angular.extend({}, defaults, config);
- $select = $tooltip(element, options);
- var scope = $select.$scope;
- scope.$matches = [];
- if (options.multiple) {
- scope.$activeIndex = [];
- } else {
- scope.$activeIndex = -1;
- }
- scope.$isMultiple = options.multiple;
- scope.$showAllNoneButtons = options.allNoneButtons && options.multiple;
- scope.$iconCheckmark = options.iconCheckmark;
- scope.$allText = options.allText;
- scope.$noneText = options.noneText;
- scope.$activate = function(index) {
- scope.$$postDigest(function() {
- $select.activate(index);
- });
- };
- scope.$select = function(index, evt) {
- scope.$$postDigest(function() {
- $select.select(index);
- });
- };
- scope.$isVisible = function() {
- return $select.$isVisible();
- };
- scope.$isActive = function(index) {
- return $select.$isActive(index);
- };
- scope.$selectAll = function() {
- for (var i = 0; i < scope.$matches.length; i++) {
- if (!scope.$isActive(i)) {
- scope.$select(i);
- }
- }
- };
- scope.$selectNone = function() {
- for (var i = 0; i < scope.$matches.length; i++) {
- if (scope.$isActive(i)) {
- scope.$select(i);
- }
- }
- };
- $select.update = function(matches) {
- scope.$matches = matches;
- $select.$updateActiveIndex();
- };
- $select.activate = function(index) {
- if (options.multiple) {
- if ($select.$isActive(index)) {
- scope.$activeIndex.splice(scope.$activeIndex.indexOf(index), 1);
- } else {
- scope.$activeIndex.push(index);
- }
- if (options.sort) scope.$activeIndex.sort(function(a, b) {
- return a - b;
- });
- } else {
- scope.$activeIndex = index;
- }
- return scope.$activeIndex;
- };
- $select.select = function(index) {
- if (angular.isUndefined(index) || index < 0 || index >= scope.$matches.length) {
- return;
- }
- var value = scope.$matches[index].value;
- scope.$apply(function() {
- $select.activate(index);
- if (options.multiple) {
- controller.$setViewValue(scope.$activeIndex.map(function(index) {
- if (angular.isUndefined(scope.$matches[index])) {
- return null;
- }
- return scope.$matches[index].value;
- }));
- } else {
- if (options.toggle) {
- controller.$setViewValue(value === controller.$modelValue ? undefined : value);
- } else {
- controller.$setViewValue(value);
- }
- $select.hide();
- }
- });
- scope.$emit(options.prefixEvent + '.select', value, index, $select);
- if (angular.isDefined(options.onSelect) && angular.isFunction(options.onSelect)) {
- options.onSelect(value, index, $select);
- }
- };
- $select.$updateActiveIndex = function() {
- if (options.multiple) {
- if (angular.isArray(controller.$modelValue)) {
- scope.$activeIndex = controller.$modelValue.map(function(value) {
- return $select.$getIndex(value);
- });
- } else {
- scope.$activeIndex = [];
- }
- } else {
- if (angular.isDefined(controller.$modelValue) && scope.$matches.length) {
- scope.$activeIndex = $select.$getIndex(controller.$modelValue);
- } else {
- scope.$activeIndex = -1;
- }
- }
- };
- $select.$isVisible = function() {
- if (!options.minLength || !controller) {
- return scope.$matches.length;
- }
- return scope.$matches.length && controller.$viewValue.length >= options.minLength;
- };
- $select.$isActive = function(index) {
- if (options.multiple) {
- return scope.$activeIndex.indexOf(index) !== -1;
- }
- return scope.$activeIndex === index;
- };
- $select.$getIndex = function(value) {
- var index;
- for (index = scope.$matches.length; index--; ) {
- if (angular.equals(scope.$matches[index].value, value)) break;
- }
- return index;
- };
- $select.$onMouseDown = function(evt) {
- evt.preventDefault();
- evt.stopPropagation();
- if (isTouch) {
- var targetEl = angular.element(evt.target);
- targetEl.triggerHandler('click');
- }
- };
- $select.$onKeyDown = function(evt) {
- if (!/(9|13|38|40)/.test(evt.keyCode)) return;
- if (evt.keyCode !== 9) {
- evt.preventDefault();
- evt.stopPropagation();
- }
- if (options.multiple && evt.keyCode === 9) {
- return $select.hide();
- }
- if (!options.multiple && (evt.keyCode === 13 || evt.keyCode === 9)) {
- return $select.select(scope.$activeIndex);
- }
- if (!options.multiple) {
- if (evt.keyCode === 38 && scope.$activeIndex > 0) scope.$activeIndex--; else if (evt.keyCode === 38 && scope.$activeIndex < 0) scope.$activeIndex = scope.$matches.length - 1; else if (evt.keyCode === 40 && scope.$activeIndex < scope.$matches.length - 1) scope.$activeIndex++; else if (angular.isUndefined(scope.$activeIndex)) scope.$activeIndex = 0;
- scope.$digest();
- }
- };
- $select.$isIE = function() {
- var ua = $window.navigator.userAgent;
- return ua.indexOf('MSIE ') > 0 || ua.indexOf('Trident/') > 0 || ua.indexOf('Edge/') > 0;
- };
- $select.$selectScrollFix = function(e) {
- if ($document[0].activeElement.tagName === 'UL') {
- e.preventDefault();
- e.stopImmediatePropagation();
- e.target.focus();
- }
- };
- var _show = $select.show;
- $select.show = function() {
- _show();
- if (options.multiple) {
- $select.$element.addClass('select-multiple');
- }
- $timeout(function() {
- $select.$element.on(isTouch ? 'touchstart' : 'mousedown', $select.$onMouseDown);
- if (options.keyboard) {
- element.on('keydown', $select.$onKeyDown);
- }
- }, 0, false);
- };
- var _hide = $select.hide;
- $select.hide = function() {
- if (!options.multiple && angular.isUndefined(controller.$modelValue)) {
- scope.$activeIndex = -1;
- }
- $select.$element.off(isTouch ? 'touchstart' : 'mousedown', $select.$onMouseDown);
- if (options.keyboard) {
- element.off('keydown', $select.$onKeyDown);
- }
- _hide(true);
- };
- return $select;
- }
- SelectFactory.defaults = defaults;
- return SelectFactory;
- } ];
- }).directive('bsSelect', [ '$window', '$parse', '$q', '$select', '$parseOptions', function($window, $parse, $q, $select, $parseOptions) {
- var defaults = $select.defaults;
- return {
- restrict: 'EAC',
- require: 'ngModel',
- link: function postLink(scope, element, attr, controller) {
- var options = {
- scope: scope,
- placeholder: defaults.placeholder
- };
- angular.forEach([ 'template', 'templateUrl', 'controller', 'controllerAs', 'placement', 'container', 'delay', 'trigger', 'keyboard', 'html', 'animation', 'placeholder', 'allNoneButtons', 'maxLength', 'maxLengthHtml', 'allText', 'noneText', 'iconCheckmark', 'autoClose', 'id', 'sort', 'caretHtml', 'prefixClass', 'prefixEvent', 'toggle' ], function(key) {
- if (angular.isDefined(attr[key])) options[key] = attr[key];
- });
- var falseValueRegExp = /^(false|0|)$/i;
- angular.forEach([ 'html', 'container', 'allNoneButtons', 'sort' ], function(key) {
- if (angular.isDefined(attr[key]) && falseValueRegExp.test(attr[key])) {
- options[key] = false;
- }
- });
- angular.forEach([ 'onBeforeShow', 'onShow', 'onBeforeHide', 'onHide', 'onSelect' ], function(key) {
- var bsKey = 'bs' + key.charAt(0).toUpperCase() + key.slice(1);
- if (angular.isDefined(attr[bsKey])) {
- options[key] = scope.$eval(attr[bsKey]);
- }
- });
- var dataMultiple = element.attr('data-multiple');
- if (angular.isDefined(dataMultiple)) {
- if (falseValueRegExp.test(dataMultiple)) {
- options.multiple = false;
- } else {
- options.multiple = dataMultiple;
- }
- }
- if (element[0].nodeName.toLowerCase() === 'select') {
- var inputEl = element;
- inputEl.css('display', 'none');
- element = angular.element('<button type="button" class="btn btn-default"></button>');
- inputEl.after(element);
- }
- var parsedOptions = $parseOptions(attr.bsOptions);
- var select = $select(element, controller, options);
- if (select.$isIE()) {
- element[0].addEventListener('blur', select.$selectScrollFix);
- }
- var watchedOptions = parsedOptions.$match[7].replace(/\|.+/, '').trim();
- scope.$watch(watchedOptions, function(newValue, oldValue) {
- parsedOptions.valuesFn(scope, controller).then(function(values) {
- select.update(values);
- controller.$render();
- });
- }, true);
- scope.$watch(attr.ngModel, function(newValue, oldValue) {
- select.$updateActiveIndex();
- controller.$render();
- }, true);
- controller.$render = function() {
- var selected;
- var index;
- if (options.multiple && angular.isArray(controller.$modelValue)) {
- selected = controller.$modelValue.map(function(value) {
- index = select.$getIndex(value);
- return index !== -1 ? select.$scope.$matches[index].label : false;
- }).filter(angular.isDefined);
- if (selected.length > (options.maxLength || defaults.maxLength)) {
- selected = selected.length + ' ' + (options.maxLengthHtml || defaults.maxLengthHtml);
- } else {
- selected = selected.join(', ');
- }
- } else {
- index = select.$getIndex(controller.$modelValue);
- selected = index !== -1 ? select.$scope.$matches[index].label : false;
- }
- element.html((selected || options.placeholder) + (options.caretHtml || defaults.caretHtml));
- };
- if (options.multiple) {
- controller.$isEmpty = function(value) {
- return !value || value.length === 0;
- };
- }
- scope.$on('$destroy', function() {
- if (select) select.destroy();
- options = null;
- select = null;
- });
- }
- };
- } ]);
|