diff --git a/dist/select.css b/dist/select.css index 43216a153..e98302d0c 100644 --- a/dist/select.css +++ b/dist/select.css @@ -1,7 +1,7 @@ /*! * ui-select * http://github.com/angular-ui/ui-select - * Version: 0.7.0 - 2014-09-09T01:02:43.612Z + * Version: 0.7.0 - 2014-10-06T12:29:59.832Z * License: MIT */ @@ -144,6 +144,13 @@ background-color: #428bca; } +.ui-select-bootstrap .ui-select-choices-row.disabled>a, +.ui-select-bootstrap .ui-select-choices-row.active.disabled>a { + color: #777; + cursor: not-allowed; + background-color: #fff; +} + /* fix hide/show angular animation */ .ui-select-match.ng-hide-add, .ui-select-search.ng-hide-add { diff --git a/dist/select.min.css b/dist/select.css.min.css similarity index 84% rename from dist/select.min.css rename to dist/select.css.min.css index 8b0c793e2..181465e97 100644 --- a/dist/select.min.css +++ b/dist/select.css.min.css @@ -1,6 +1,6 @@ /*! * ui-select * http://github.com/angular-ui/ui-select - * Version: 0.7.0 - 2014-09-09T01:02:43.612Z + * Version: 0.7.0 - 2014-10-06T12:29:59.832Z * License: MIT - */.ui-select-highlight{font-weight:700}.ui-select-offscreen{clip:rect(0 0 0 0)!important;width:1px!important;height:1px!important;border:0!important;margin:0!important;padding:0!important;overflow:hidden!important;position:absolute!important;outline:0!important;left:0!important;top:0!important}.ng-dirty.ng-invalid>a.select2-choice{border-color:#D44950}.select2-result-single{padding-left:0}.selectize-input.selectize-focus{border-color:#007FBB!important}.selectize-control>.selectize-dropdown,.selectize-control>.selectize-input>input{width:100%}.ng-dirty.ng-invalid>div.selectize-input{border-color:#D44950}.btn-default-focus{color:#333;background-color:#EBEBEB;border-color:#ADADAD;text-decoration:none;outline:-webkit-focus-ring-color auto 5px;outline-offset:-2px;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.input-group>.ui-select-bootstrap.dropdown{position:static}.input-group>.ui-select-bootstrap>input.ui-select-search.form-control{border-radius:4px 0 0 4px}.ui-select-bootstrap>.ui-select-match{text-align:left}.ui-select-bootstrap>.ui-select-match>.caret{position:absolute;top:45%;right:15px}.ui-select-bootstrap>.ui-select-choices{width:100%;height:auto;max-height:200px;overflow-x:hidden}.ui-select-multiple.ui-select-bootstrap{height:auto;padding:.3em}.ui-select-multiple.ui-select-bootstrap input.ui-select-search{background-color:transparent!important;border:none;outline:0;height:1.666666em}.ui-select-multiple.ui-select-bootstrap .ui-select-match .close{font-size:1.6em;line-height:.75}.ui-select-bootstrap .ui-select-choices-row>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.42857143;color:#333;white-space:nowrap}.ui-select-bootstrap .ui-select-choices-row>a:focus,.ui-select-bootstrap .ui-select-choices-row>a:hover{text-decoration:none;color:#262626;background-color:#f5f5f5}.ui-select-bootstrap .ui-select-choices-row.active>a{color:#fff;text-decoration:none;outline:0;background-color:#428bca}.ui-select-match.ng-hide-add,.ui-select-search.ng-hide-add{display:none!important}.ui-select-bootstrap.ng-dirty.ng-invalid>button.btn.ui-select-match{border-color:#D44950} \ No newline at end of file + */.ui-select-highlight{font-weight:700}.ui-select-offscreen{clip:rect(0 0 0 0)!important;width:1px!important;height:1px!important;border:0!important;margin:0!important;padding:0!important;overflow:hidden!important;position:absolute!important;outline:0!important;left:0!important;top:0!important}.ng-dirty.ng-invalid>a.select2-choice{border-color:#D44950}.select2-result-single{padding-left:0}.selectize-input.selectize-focus{border-color:#007FBB!important}.selectize-control>.selectize-dropdown,.selectize-control>.selectize-input>input{width:100%}.ng-dirty.ng-invalid>div.selectize-input{border-color:#D44950}.btn-default-focus{color:#333;background-color:#EBEBEB;border-color:#ADADAD;text-decoration:none;outline:-webkit-focus-ring-color auto 5px;outline-offset:-2px;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.input-group>.ui-select-bootstrap.dropdown{position:static}.input-group>.ui-select-bootstrap>input.ui-select-search.form-control{border-radius:4px 0 0 4px}.ui-select-bootstrap>.ui-select-match{text-align:left}.ui-select-bootstrap>.ui-select-match>.caret{position:absolute;top:45%;right:15px}.ui-select-bootstrap>.ui-select-choices{width:100%;height:auto;max-height:200px;overflow-x:hidden}.ui-select-multiple.ui-select-bootstrap{height:auto;padding:.3em}.ui-select-multiple.ui-select-bootstrap input.ui-select-search{background-color:transparent!important;border:none;outline:0;height:1.666666em}.ui-select-multiple.ui-select-bootstrap .ui-select-match .close{font-size:1.6em;line-height:.75}.ui-select-bootstrap .ui-select-choices-row>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.42857143;color:#333;white-space:nowrap}.ui-select-bootstrap .ui-select-choices-row>a:focus,.ui-select-bootstrap .ui-select-choices-row>a:hover{text-decoration:none;color:#262626;background-color:#f5f5f5}.ui-select-bootstrap .ui-select-choices-row.active>a{color:#fff;text-decoration:none;outline:0;background-color:#428bca}.ui-select-bootstrap .ui-select-choices-row.active.disabled>a,.ui-select-bootstrap .ui-select-choices-row.disabled>a{color:#777;cursor:not-allowed;background-color:#fff}.ui-select-match.ng-hide-add,.ui-select-search.ng-hide-add{display:none!important}.ui-select-bootstrap.ng-dirty.ng-invalid>button.btn.ui-select-match{border-color:#D44950} \ No newline at end of file diff --git a/dist/select.js b/dist/select.js index ad1611186..8b9f1c3ab 100755 --- a/dist/select.js +++ b/dist/select.js @@ -1,7 +1,7 @@ /*! * ui-select * http://github.com/angular-ui/ui-select - * Version: 0.7.0 - 2014-09-09T01:02:43.608Z + * Version: 0.7.0 - 2014-10-06T12:29:59.829Z * License: MIT */ @@ -164,6 +164,7 @@ ctrl.resetSearchInput = undefined; // Initialized inside uiSelect directive link function ctrl.refreshDelay = undefined; // Initialized inside uiSelectChoices directive link function ctrl.multiple = false; // Initialized inside uiSelect directive link function + ctrl.disableChoiceExpression = undefined; // Initialized inside uiSelect directive link function ctrl.isEmpty = function() { return angular.isUndefined(ctrl.selected) || ctrl.selected === null || ctrl.selected === ''; @@ -307,24 +308,45 @@ return ctrl.items.indexOf(itemScope[ctrl.itemProperty]) === ctrl.activeIndex; }; + ctrl.isDisabled = function(itemScope) { + var itemIndex = ctrl.items.indexOf(itemScope[ctrl.itemProperty]); + var isDisabled = false; + var item; + + if (itemIndex >= 0 && !angular.isUndefined(ctrl.disableChoiceExpression)) { + item = ctrl.items[itemIndex]; + isDisabled = !!(itemScope.$eval(ctrl.disableChoiceExpression)); // force the boolean value + item._uiSelectChoiceDisabled = isDisabled; // store this for later reference + } + + return isDisabled; + }; + // When the user clicks on an item inside the dropdown ctrl.select = function(item) { - var locals = {}; - locals[ctrl.parserResult.itemName] = item; + if (!item || !item._uiSelectChoiceDisabled) { + if(ctrl.tagging.isActivated && !item && ctrl.search.length > 0) { + // create new item on the fly + item = ctrl.tagging.fct !== undefined ? ctrl.tagging.fct(ctrl.search) : ctrl.search; + } - ctrl.onSelectCallback($scope, { - $item: item, - $model: ctrl.parserResult.modelMapper($scope, locals) - }); + var locals = {}; + locals[ctrl.parserResult.itemName] = item; - if(ctrl.multiple){ - ctrl.selected.push(item); - ctrl.sizeSearchInput(); - } else { - ctrl.selected = item; + ctrl.onSelectCallback($scope, { + $item: item, + $model: ctrl.parserResult.modelMapper($scope, locals) + }); + + if(ctrl.multiple){ + ctrl.selected.push(item); + ctrl.sizeSearchInput(); + } else { + ctrl.selected = item; + } + ctrl.close(); } - ctrl.close(); }; // Closes the dropdown @@ -338,6 +360,13 @@ } }; + // Toggle dropdown + ctrl.toggle = function(e) { + if (ctrl.open) ctrl.close(); else ctrl.activate(); + e.preventDefault(); + e.stopPropagation(); + }; + // Remove item from multiple select ctrl.removeChoice = function(index){ ctrl.selected.splice(index, 1); @@ -371,7 +400,7 @@ break; case KEY.UP: if (!ctrl.open && ctrl.multiple) ctrl.activate(false, true); //In case its the search input in 'multiple' mode - else if (ctrl.activeIndex > 0) { ctrl.activeIndex--; } + else if (ctrl.activeIndex > 0 || (ctrl.search.length === 0 && ctrl.tagging.isActivated)) { ctrl.activeIndex--; } break; case KEY.TAB: //TODO: Que hacemos en modo multiple? @@ -470,7 +499,7 @@ processed = _handleMatchSelection(key); } - if (!processed && ctrl.items.length > 0) { + if (!processed && (ctrl.items.length > 0 || ctrl.tagging.isActivated)) { processed = _handleDropDownSelection(key); } @@ -550,6 +579,8 @@ var $select = ctrls[0]; var ngModel = ctrls[1]; + var searchInput = element.querySelectorAll('input.ui-select-search'); + $select.multiple = angular.isDefined(attrs.multiple); $select.onSelectCallback = $parse(attrs.onSelect); @@ -625,6 +656,21 @@ //Idea from: https://github.com/ivaynberg/select2/blob/79b5bf6db918d7560bdd959109b7bcfb47edaf43/select2.js#L1954 var focusser = angular.element(""); + + if(attrs.tabindex){ + //tabindex might be an expression, wait until it contains the actual value before we set the focusser tabindex + attrs.$observe('tabindex', function(value) { + //If we are using multiple, add tabindex to the search input + if($select.multiple){ + searchInput.attr("tabindex", value); + } else { + focusser.attr("tabindex", value); + } + //Remove the tabindex on the parent so that it is not focusable + element.removeAttr("tabindex"); + }); + } + $compile(focusser)(scope); $select.focusser = focusser; @@ -695,6 +741,19 @@ $select.resetSearchInput = resetSearchInput !== undefined ? resetSearchInput : true; }); + attrs.$observe('tagging', function() { + if(attrs.tagging !== undefined) + { + // $eval() is needed otherwise we get a string instead of a function or a boolean + var taggingEval = scope.$eval(attrs.tagging); + $select.tagging = {isActivated: true, fct: taggingEval !== true ? taggingEval : undefined}; + } + else + { + $select.tagging = {isActivated: false, fct: undefined}; + } + }); + if ($select.multiple){ scope.$watchCollection('$select.selected', function(newValue) { //On v1.2.19 the 2nd and 3rd parameteres are ignored @@ -802,6 +861,8 @@ $select.parseRepeatAttr(attrs.repeat, groupByExp); //Result ready at $select.parserResult + $select.disableChoiceExpression = attrs.uiDisableChoice; + if(groupByExp) { var groups = element.querySelectorAll('.ui-select-choices-group'); if (groups.length !== 1) throw uiSelectMinErr('rows', "Expected 1 .ui-select-choices-group but got '{0}'.", groups.length); @@ -825,7 +886,7 @@ scope.$watch('$select.search', function(newValue) { if(newValue && !$select.open && $select.multiple) $select.activate(false, true); - $select.activeIndex = 0; + $select.activeIndex = $select.tagging.isActivated ? -1 : 0; $select.refresh(attrs.refresh); }); @@ -890,16 +951,16 @@ }); }()); -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",""); +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",""); $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/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","
    {{$group.name}}
    "); +$templateCache.put("selectize/choices.tpl.html","
    {{$group.name}}
    "); $templateCache.put("selectize/match.tpl.html","
    "); -$templateCache.put("selectize/select.tpl.html","
    ");}]); \ No newline at end of file +$templateCache.put("selectize/select.tpl.html","
    ");}]); \ No newline at end of file diff --git a/dist/select.js.min.js b/dist/select.js.min.js new file mode 100755 index 000000000..e99b45e53 --- /dev/null +++ b/dist/select.js.min.js @@ -0,0 +1,7 @@ +/*! + * ui-select + * http://github.com/angular-ui/ui-select + * Version: 0.7.0 - 2014-10-06T12:29:59.829Z + * License: MIT + */ +!function(){"use strict";var e={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,isControl:function(t){var c=t.which;switch(c){case e.SHIFT:case e.CTRL:case e.ALT:return!0}return t.metaKey?!0:!1},isFunctionKey:function(e){return e=e.which?e.which:e,e>=112&&123>=e},isVerticalMovement:function(t){return~[e.UP,e.DOWN].indexOf(t)},isHorizontalMovement:function(t){return~[e.LEFT,e.RIGHT,e.BACKSPACE,e.DELETE].indexOf(t)}};void 0===angular.element.prototype.querySelectorAll&&(angular.element.prototype.querySelectorAll=function(e){return angular.element(this[0].querySelectorAll(e))}),angular.module("ui.select",[]).constant("uiSelectConfig",{theme:"bootstrap",searchEnabled:!0,placeholder:"",refreshDelay:1e3}).service("uiSelectMinErr",function(){var e=angular.$$minErr("ui.select");return function(){var t=e.apply(this,arguments),c=t.message.replace(new RegExp("\nhttp://errors.angularjs.org/.*"),"");return new Error(c)}}).service("RepeatParser",["uiSelectMinErr","$parse",function(e,t){var c=this;c.parse=function(c){var s=c.match(/^\s*(?:([\s\S]+?)\s+as\s+)?([\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/);if(!s)throw e("iexp","Expected expression in form of '_item_ in _collection_[ track by _id_]' but got '{0}'.",c);return{itemName:s[2],source:t(s[3]),trackByExp:s[4],modelMapper:t(s[1]||s[2])}},c.getGroupNgRepeatExpression=function(){return"$group in $select.groups"},c.getNgRepeatExpression=function(e,t,c,s){var l=e+" in "+(s?"$group.items":t);return c&&(l+=" track by "+c),l}}]).controller("uiSelectCtrl",["$scope","$element","$timeout","RepeatParser","uiSelectMinErr",function(t,c,s,l,i){function n(){d.resetSearchInput&&(d.search=p,d.selected&&d.items.length&&!d.multiple&&(d.activeIndex=d.items.indexOf(d.selected)))}function a(t){var c=!0;switch(t){case e.DOWN:!d.open&&d.multiple?d.activate(!1,!0):d.activeIndex0||0===d.search.length&&d.tagging.isActivated)&&d.activeIndex--;break;case e.TAB:d.multiple||d.select(d.items[d.activeIndex]);break;case e.ENTER:d.open?d.select(d.items[d.activeIndex]):d.activate(!1,!0);break;case e.ESC:d.close();break;default:c=!1}return c}function r(t){function c(){switch(t){case e.LEFT:return~d.activeMatchIndex?u:n;case e.RIGHT:return~d.activeMatchIndex&&a!==n?r:(d.activate(),!1);case e.BACKSPACE:return~d.activeMatchIndex?(d.removeChoice(a),u):n;case e.DELETE:return~d.activeMatchIndex?(d.removeChoice(d.activeMatchIndex),a):!1}}var s=o(h[0]),l=d.selected.length,i=0,n=l-1,a=d.activeMatchIndex,r=d.activeMatchIndex+1,u=d.activeMatchIndex-1,p=a;return s>0||d.search.length&&t==e.RIGHT?!1:(d.close(),p=c(),d.activeMatchIndex=d.selected.length&&p!==!1?Math.min(n,Math.max(i,p)):-1,!0)}function o(e){return angular.isNumber(e.selectionStart)?e.selectionStart:e.value.length}function u(){var e=c.querySelectorAll(".ui-select-choices-content"),t=e.querySelectorAll(".ui-select-choices-row");if(t.length<1)throw i("choices","Expected multiple .ui-select-choices-row but got '{0}'.",t.length);var s=t[d.activeIndex],l=s.offsetTop+s.clientHeight-e[0].scrollTop,n=e[0].offsetHeight;l>n?e[0].scrollTop+=l-n:l=d.items.length?0:d.activeIndex,s(function(){d.search=e||d.search,h[0].focus()}))},d.findGroupByName=function(e){return d.groups&&d.groups.filter(function(t){return t.name===e})[0]},d.parseRepeatAttr=function(e,c){function s(e){d.groups=[],angular.forEach(e,function(e){var s=t.$eval(c),l=angular.isFunction(s)?s(e):e[s],i=d.findGroupByName(l);i?i.items.push(e):d.groups.push({name:l,items:[e]})}),d.items=[],d.groups.forEach(function(e){d.items=d.items.concat(e.items)})}function n(e){d.items=e}var a=c?s:n;d.parserResult=l.parse(e),d.isGrouped=!!c,d.itemProperty=d.parserResult.itemName,t.$watchCollection(d.parserResult.source,function(e){if(void 0===e||null===e)d.items=[];else{if(!angular.isArray(e))throw i("items","Expected an array but got '{0}'.",e);if(d.multiple){var t=e.filter(function(e){return d.selected.indexOf(e)<0});a(t)}else a(e);d.ngModel.$modelValue=null}}),d.multiple&&t.$watchCollection("$select.selected",function(e){if(e){var c=d.parserResult.source(t),s=c.filter(function(t){return e.indexOf(t)<0});a(s)}})};var v;d.refresh=function(e){void 0!==e&&(v&&s.cancel(v),v=s(function(){t.$eval(e)},d.refreshDelay))},d.setActiveItem=function(e){d.activeIndex=d.items.indexOf(e)},d.isActive=function(e){return d.items.indexOf(e[d.itemProperty])===d.activeIndex},d.isDisabled=function(e){var t,c=d.items.indexOf(e[d.itemProperty]),s=!1;return c>=0&&!angular.isUndefined(d.disableChoiceExpression)&&(t=d.items[c],s=!!e.$eval(d.disableChoiceExpression),t._uiSelectChoiceDisabled=s),s},d.select=function(e){if(!e||!e._uiSelectChoiceDisabled){d.tagging.isActivated&&!e&&d.search.length>0&&(e=void 0!==d.tagging.fct?d.tagging.fct(d.search):d.search);var c={};c[d.parserResult.itemName]=e,d.onSelectCallback(t,{$item:e,$model:d.parserResult.modelMapper(t,c)}),d.multiple?(d.selected.push(e),d.sizeSearchInput()):d.selected=e,d.close()}},d.close=function(){d.open&&(n(),d.open=!1,s(function(){d.focusser[0].focus()},0,!1))},d.toggle=function(e){d.open?d.close():d.activate(),e.preventDefault(),e.stopPropagation()},d.removeChoice=function(e){d.selected.splice(e,1),d.activeMatchIndex=-1,d.sizeSearchInput()},d.getPlaceholder=function(){return d.multiple&&d.selected.length?void 0:d.placeholder},d.sizeSearchInput=function(){var e=h[0],t=h.parent().parent()[0];h.css("width","10px"),s(function(){var c=t.clientWidth-e.offsetLeft-10;50>c&&(c=t.clientWidth),h.css("width",c+"px")},0,!1)},h.on("keydown",function(c){var s=c.which;t.$apply(function(){var t=!1;d.multiple&&e.isHorizontalMovement(s)&&(t=r(s)),!t&&(d.items.length>0||d.tagging.isActivated)&&(t=a(s)),t&&s!=e.TAB&&(c.preventDefault(),c.stopPropagation())}),e.isVerticalMovement(s)&&d.items.length>0&&u()}),h.on("blur",function(){s(function(){d.activeMatchIndex=-1,d.activeIndex=0})}),t.$on("$destroy",function(){h.off("keydown blur")})}]).directive("uiSelect",["$document","uiSelectConfig","uiSelectMinErr","$compile","$parse",function(t,c,s,l,i){return{restrict:"EA",templateUrl:function(e,t){var s=t.theme||c.theme;return s+(angular.isDefined(t.multiple)?"/select-multiple.tpl.html":"/select.tpl.html")},replace:!0,transclude:!0,require:["uiSelect","ngModel"],scope:!0,controller:"uiSelectCtrl",controllerAs:"$select",link:function(c,n,a,r,o){function u(e){var t=!1;t=window.jQuery?window.jQuery.contains(n[0],e.target):n[0].contains(e.target),t||(d.close(),c.$digest())}var d=r[0],p=r[1],h=n.querySelectorAll("input.ui-select-search");d.multiple=angular.isDefined(a.multiple),d.onSelectCallback=i(a.onSelect),p.$parsers.unshift(function(e){var t,s={};if(d.multiple){for(var l=[],i=e.length-1;i>=0;i--)s={},s[d.parserResult.itemName]=e[i],t=d.parserResult.modelMapper(c,s),l.unshift(t);return l}return s={},s[d.parserResult.itemName]=e,t=d.parserResult.modelMapper(c,s)}),p.$formatters.unshift(function(e){var t,s=d.parserResult.source(c,{$select:{search:""}}),l={};if(s){if(d.multiple){var i=[],n=function(e,s){if(e&&e.length){for(var n=e.length-1;n>=0;n--)if(l[d.parserResult.itemName]=e[n],t=d.parserResult.modelMapper(c,l),t==s)return i.unshift(e[n]),!0;return!1}};if(!e)return i;for(var a=e.length-1;a>=0;a--)n(d.selected,e[a])||n(s,e[a]);return i}var r=function(s){return l[d.parserResult.itemName]=s,t=d.parserResult.modelMapper(c,l),t==e};if(d.selected&&r(d.selected))return d.selected;for(var o=s.length-1;o>=0;o--)if(r(s[o]))return s[o]}return e}),d.ngModel=p;var v=angular.element("");a.tabindex&&a.$observe("tabindex",function(e){d.multiple?h.attr("tabindex",e):v.attr("tabindex",e),n.removeAttr("tabindex")}),l(v)(c),d.focusser=v,d.multiple||(n.append(v),v.bind("focus",function(){c.$evalAsync(function(){d.focus=!0})}),v.bind("blur",function(){c.$evalAsync(function(){d.focus=!1})}),v.bind("keydown",function(t){return t.which===e.BACKSPACE?(t.preventDefault(),t.stopPropagation(),d.select(void 0),c.$digest(),void 0):(t.which===e.TAB||e.isControl(t)||e.isFunctionKey(t)||t.which===e.ESC||((t.which==e.DOWN||t.which==e.UP||t.which==e.ENTER||t.which==e.SPACE)&&(t.preventDefault(),t.stopPropagation(),d.activate()),c.$digest()),void 0)}),v.bind("keyup input",function(t){t.which===e.TAB||e.isControl(t)||e.isFunctionKey(t)||t.which===e.ESC||t.which==e.ENTER||t.which===e.BACKSPACE||(d.activate(v.val()),v.val(""),c.$digest())})),c.$watch("searchEnabled",function(){var e=c.$eval(a.searchEnabled);d.searchEnabled=void 0!==e?e:!0}),a.$observe("disabled",function(){d.disabled=void 0!==a.disabled?a.disabled:!1}),a.$observe("resetSearchInput",function(){var e=c.$eval(a.resetSearchInput);d.resetSearchInput=void 0!==e?e:!0}),a.$observe("tagging",function(){if(void 0!==a.tagging){var e=c.$eval(a.tagging);d.tagging={isActivated:!0,fct:e!==!0?e:void 0}}else d.tagging={isActivated:!1,fct:void 0}}),d.multiple?(c.$watchCollection("$select.selected",function(e){p.$setViewValue(e,null,!0)}),v.prop("disabled",!0)):c.$watch("$select.selected",function(e){p.$viewValue!==e&&p.$setViewValue(e)}),p.$render=function(){if(d.multiple&&!angular.isArray(p.$viewValue)){if(!angular.isUndefined(p.$viewValue)&&null!==p.$viewValue)throw s("multiarr","Expected model value to be array but got '{0}'",p.$viewValue);d.selected=[]}d.selected=p.$viewValue},t.on("click",u),c.$on("$destroy",function(){t.off("click",u)}),o(c,function(e){var t=angular.element("
    ").append(e),c=t.querySelectorAll(".ui-select-match");if(c.removeAttr("ui-select-match"),1!==c.length)throw s("transcluded","Expected 1 .ui-select-match but got '{0}'.",c.length);n.querySelectorAll(".ui-select-match").replaceWith(c);var l=t.querySelectorAll(".ui-select-choices");if(l.removeAttr("ui-select-choices"),1!==l.length)throw s("transcluded","Expected 1 .ui-select-choices but got '{0}'.",l.length);n.querySelectorAll(".ui-select-choices").replaceWith(l)})}}}]).directive("uiSelectChoices",["uiSelectConfig","RepeatParser","uiSelectMinErr","$compile",function(e,t,c,s){return{restrict:"EA",require:"^uiSelect",replace:!0,transclude:!0,templateUrl:function(t){var c=t.parent().attr("theme")||e.theme;return c+"/choices.tpl.html"},compile:function(l,i){if(!i.repeat)throw c("repeat","Expected 'repeat' expression.");return function(l,i,n,a,r){var o=n.groupBy;if(a.parseRepeatAttr(n.repeat,o),a.disableChoiceExpression=n.uiDisableChoice,o){var u=i.querySelectorAll(".ui-select-choices-group");if(1!==u.length)throw c("rows","Expected 1 .ui-select-choices-group but got '{0}'.",u.length);u.attr("ng-repeat",t.getGroupNgRepeatExpression())}var d=i.querySelectorAll(".ui-select-choices-row");if(1!==d.length)throw c("rows","Expected 1 .ui-select-choices-row but got '{0}'.",d.length);d.attr("ng-repeat",t.getNgRepeatExpression(a.parserResult.itemName,"$select.items",a.parserResult.trackByExp,o)).attr("ng-mouseenter","$select.setActiveItem("+a.parserResult.itemName+")").attr("ng-click","$select.select("+a.parserResult.itemName+")");var p=i.querySelectorAll(".ui-select-choices-row-inner");if(1!==p.length)throw c("rows","Expected 1 .ui-select-choices-row-inner but got '{0}'.",p.length);p.attr("uis-transclude-append",""),s(i,r)(l),l.$watch("$select.search",function(e){e&&!a.open&&a.multiple&&a.activate(!1,!0),a.activeIndex=a.tagging.isActivated?-1:0,a.refresh(n.refresh)}),n.$observe("refreshDelay",function(){var t=l.$eval(n.refreshDelay);a.refreshDelay=void 0!==t?t:e.refreshDelay})}}}}]).directive("uisTranscludeAppend",function(){return{link:function(e,t,c,s,l){l(e,function(e){t.append(e)})}}}).directive("uiSelectMatch",["uiSelectConfig",function(e){return{restrict:"EA",require:"^uiSelect",replace:!0,transclude:!0,templateUrl:function(t){var c=t.parent().attr("theme")||e.theme,s=t.parent().attr("multiple");return c+(s?"/match-multiple.tpl.html":"/match.tpl.html")},link:function(t,c,s,l){s.$observe("placeholder",function(t){l.placeholder=void 0!==t?t:e.placeholder}),l.multiple&&l.sizeSearchInput()}}}]).filter("highlight",function(){function e(e){return e.replace(/([.?*+^$[\]\\(){}|-])/g,"\\$1")}return function(t,c){return c&&t?t.replace(new RegExp(e(c),"gi"),'$&'):t}})}(),angular.module("ui.select").run(["$templateCache",function(e){e.put("bootstrap/choices.tpl.html",''),e.put("bootstrap/match-multiple.tpl.html",''),e.put("bootstrap/match.tpl.html",''),e.put("bootstrap/select-multiple.tpl.html",''),e.put("bootstrap/select.tpl.html",''),e.put("select2/choices.tpl.html",'
    • {{$group.name}}
    '),e.put("select2/match-multiple.tpl.html",'
  • '),e.put("select2/match.tpl.html",'{{$select.placeholder}} '),e.put("select2/select-multiple.tpl.html",'
    '),e.put("select2/select.tpl.html",'
    '),e.put("selectize/choices.tpl.html",'
    {{$group.name}}
    '),e.put("selectize/match.tpl.html",'
    '),e.put("selectize/select.tpl.html",'
    ')}]); \ No newline at end of file diff --git a/dist/select.min.js b/dist/select.min.js deleted file mode 100755 index 18691097b..000000000 --- a/dist/select.min.js +++ /dev/null @@ -1,7 +0,0 @@ -/*! - * ui-select - * http://github.com/angular-ui/ui-select - * Version: 0.7.0 - 2014-09-09T01:02:43.608Z - * License: MIT - */ -!function(){"use strict";var e={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,isControl:function(t){var c=t.which;switch(c){case e.SHIFT:case e.CTRL:case e.ALT:return!0}return t.metaKey?!0:!1},isFunctionKey:function(e){return e=e.which?e.which:e,e>=112&&123>=e},isVerticalMovement:function(t){return~[e.UP,e.DOWN].indexOf(t)},isHorizontalMovement:function(t){return~[e.LEFT,e.RIGHT,e.BACKSPACE,e.DELETE].indexOf(t)}};void 0===angular.element.prototype.querySelectorAll&&(angular.element.prototype.querySelectorAll=function(e){return angular.element(this[0].querySelectorAll(e))}),angular.module("ui.select",[]).constant("uiSelectConfig",{theme:"bootstrap",searchEnabled:!0,placeholder:"",refreshDelay:1e3}).service("uiSelectMinErr",function(){var e=angular.$$minErr("ui.select");return function(){var t=e.apply(this,arguments),c=t.message.replace(new RegExp("\nhttp://errors.angularjs.org/.*"),"");return new Error(c)}}).service("RepeatParser",["uiSelectMinErr","$parse",function(e,t){var c=this;c.parse=function(c){var s=c.match(/^\s*(?:([\s\S]+?)\s+as\s+)?([\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/);if(!s)throw e("iexp","Expected expression in form of '_item_ in _collection_[ track by _id_]' but got '{0}'.",c);return{itemName:s[2],source:t(s[3]),trackByExp:s[4],modelMapper:t(s[1]||s[2])}},c.getGroupNgRepeatExpression=function(){return"$group in $select.groups"},c.getNgRepeatExpression=function(e,t,c,s){var l=e+" in "+(s?"$group.items":t);return c&&(l+=" track by "+c),l}}]).controller("uiSelectCtrl",["$scope","$element","$timeout","RepeatParser","uiSelectMinErr",function(t,c,s,l,i){function n(){p.resetSearchInput&&(p.search=d,p.selected&&p.items.length&&!p.multiple&&(p.activeIndex=p.items.indexOf(p.selected)))}function a(t){var c=!0;switch(t){case e.DOWN:!p.open&&p.multiple?p.activate(!1,!0):p.activeIndex0&&p.activeIndex--;break;case e.TAB:p.multiple||p.select(p.items[p.activeIndex]);break;case e.ENTER:p.open?p.select(p.items[p.activeIndex]):p.activate(!1,!0);break;case e.ESC:p.close();break;default:c=!1}return c}function r(t){function c(){switch(t){case e.LEFT:return~p.activeMatchIndex?u:n;case e.RIGHT:return~p.activeMatchIndex&&a!==n?r:(p.activate(),!1);case e.BACKSPACE:return~p.activeMatchIndex?(p.removeChoice(a),u):n;case e.DELETE:return~p.activeMatchIndex?(p.removeChoice(p.activeMatchIndex),a):!1}}var s=o(h[0]),l=p.selected.length,i=0,n=l-1,a=p.activeMatchIndex,r=p.activeMatchIndex+1,u=p.activeMatchIndex-1,d=a;return s>0||p.search.length&&t==e.RIGHT?!1:(p.close(),d=c(),p.activeMatchIndex=p.selected.length&&d!==!1?Math.min(n,Math.max(i,d)):-1,!0)}function o(e){return angular.isNumber(e.selectionStart)?e.selectionStart:e.value.length}function u(){var e=c.querySelectorAll(".ui-select-choices-content"),t=e.querySelectorAll(".ui-select-choices-row");if(t.length<1)throw i("choices","Expected multiple .ui-select-choices-row but got '{0}'.",t.length);var s=t[p.activeIndex],l=s.offsetTop+s.clientHeight-e[0].scrollTop,n=e[0].offsetHeight;l>n?e[0].scrollTop+=l-n:l=p.items.length?0:p.activeIndex,s(function(){p.search=e||p.search,h[0].focus()}))},p.findGroupByName=function(e){return p.groups&&p.groups.filter(function(t){return t.name===e})[0]},p.parseRepeatAttr=function(e,c){function s(e){p.groups=[],angular.forEach(e,function(e){var s=t.$eval(c),l=angular.isFunction(s)?s(e):e[s],i=p.findGroupByName(l);i?i.items.push(e):p.groups.push({name:l,items:[e]})}),p.items=[],p.groups.forEach(function(e){p.items=p.items.concat(e.items)})}function n(e){p.items=e}var a=c?s:n;p.parserResult=l.parse(e),p.isGrouped=!!c,p.itemProperty=p.parserResult.itemName,t.$watchCollection(p.parserResult.source,function(e){if(void 0===e||null===e)p.items=[];else{if(!angular.isArray(e))throw i("items","Expected an array but got '{0}'.",e);if(p.multiple){var t=e.filter(function(e){return p.selected.indexOf(e)<0});a(t)}else a(e);p.ngModel.$modelValue=null}}),p.multiple&&t.$watchCollection("$select.selected",function(e){if(e){var c=p.parserResult.source(t),s=c.filter(function(t){return e.indexOf(t)<0});a(s)}})};var v;p.refresh=function(e){void 0!==e&&(v&&s.cancel(v),v=s(function(){t.$eval(e)},p.refreshDelay))},p.setActiveItem=function(e){p.activeIndex=p.items.indexOf(e)},p.isActive=function(e){return p.items.indexOf(e[p.itemProperty])===p.activeIndex},p.select=function(e){var c={};c[p.parserResult.itemName]=e,p.onSelectCallback(t,{$item:e,$model:p.parserResult.modelMapper(t,c)}),p.multiple?(p.selected.push(e),p.sizeSearchInput()):p.selected=e,p.close()},p.close=function(){p.open&&(n(),p.open=!1,s(function(){p.focusser[0].focus()},0,!1))},p.removeChoice=function(e){p.selected.splice(e,1),p.activeMatchIndex=-1,p.sizeSearchInput()},p.getPlaceholder=function(){return p.multiple&&p.selected.length?void 0:p.placeholder},p.sizeSearchInput=function(){var e=h[0],t=h.parent().parent()[0];h.css("width","10px"),s(function(){var c=t.clientWidth-e.offsetLeft-10;50>c&&(c=t.clientWidth),h.css("width",c+"px")},0,!1)},h.on("keydown",function(c){var s=c.which;t.$apply(function(){var t=!1;p.multiple&&e.isHorizontalMovement(s)&&(t=r(s)),!t&&p.items.length>0&&(t=a(s)),t&&s!=e.TAB&&(c.preventDefault(),c.stopPropagation())}),e.isVerticalMovement(s)&&p.items.length>0&&u()}),h.on("blur",function(){s(function(){p.activeMatchIndex=-1,p.activeIndex=0})}),t.$on("$destroy",function(){h.off("keydown blur")})}]).directive("uiSelect",["$document","uiSelectConfig","uiSelectMinErr","$compile","$parse",function(t,c,s,l,i){return{restrict:"EA",templateUrl:function(e,t){var s=t.theme||c.theme;return s+(angular.isDefined(t.multiple)?"/select-multiple.tpl.html":"/select.tpl.html")},replace:!0,transclude:!0,require:["uiSelect","ngModel"],scope:!0,controller:"uiSelectCtrl",controllerAs:"$select",link:function(c,n,a,r,o){function u(e){var t=!1;t=window.jQuery?window.jQuery.contains(n[0],e.target):n[0].contains(e.target),t||(p.close(),c.$digest())}var p=r[0],d=r[1];p.multiple=angular.isDefined(a.multiple),p.onSelectCallback=i(a.onSelect),d.$parsers.unshift(function(e){var t,s={};if(p.multiple){for(var l=[],i=e.length-1;i>=0;i--)s={},s[p.parserResult.itemName]=e[i],t=p.parserResult.modelMapper(c,s),l.unshift(t);return l}return s={},s[p.parserResult.itemName]=e,t=p.parserResult.modelMapper(c,s)}),d.$formatters.unshift(function(e){var t,s=p.parserResult.source(c,{$select:{search:""}}),l={};if(s){if(p.multiple){var i=[],n=function(e,s){if(e&&e.length){for(var n=e.length-1;n>=0;n--)if(l[p.parserResult.itemName]=e[n],t=p.parserResult.modelMapper(c,l),t==s)return i.unshift(e[n]),!0;return!1}};if(!e)return i;for(var a=e.length-1;a>=0;a--)n(p.selected,e[a])||n(s,e[a]);return i}var r=function(s){return l[p.parserResult.itemName]=s,t=p.parserResult.modelMapper(c,l),t==e};if(p.selected&&r(p.selected))return p.selected;for(var o=s.length-1;o>=0;o--)if(r(s[o]))return s[o]}return e}),p.ngModel=d;var h=angular.element("");l(h)(c),p.focusser=h,p.multiple||(n.append(h),h.bind("focus",function(){c.$evalAsync(function(){p.focus=!0})}),h.bind("blur",function(){c.$evalAsync(function(){p.focus=!1})}),h.bind("keydown",function(t){return t.which===e.BACKSPACE?(t.preventDefault(),t.stopPropagation(),p.select(void 0),void c.$digest()):void(t.which===e.TAB||e.isControl(t)||e.isFunctionKey(t)||t.which===e.ESC||((t.which==e.DOWN||t.which==e.UP||t.which==e.ENTER||t.which==e.SPACE)&&(t.preventDefault(),t.stopPropagation(),p.activate()),c.$digest()))}),h.bind("keyup input",function(t){t.which===e.TAB||e.isControl(t)||e.isFunctionKey(t)||t.which===e.ESC||t.which==e.ENTER||t.which===e.BACKSPACE||(p.activate(h.val()),h.val(""),c.$digest())})),c.$watch("searchEnabled",function(){var e=c.$eval(a.searchEnabled);p.searchEnabled=void 0!==e?e:!0}),a.$observe("disabled",function(){p.disabled=void 0!==a.disabled?a.disabled:!1}),a.$observe("resetSearchInput",function(){var e=c.$eval(a.resetSearchInput);p.resetSearchInput=void 0!==e?e:!0}),p.multiple?(c.$watchCollection("$select.selected",function(e){d.$setViewValue(e,null,!0)}),h.prop("disabled",!0)):c.$watch("$select.selected",function(e){d.$viewValue!==e&&d.$setViewValue(e)}),d.$render=function(){if(p.multiple&&!angular.isArray(d.$viewValue)){if(!angular.isUndefined(d.$viewValue)&&null!==d.$viewValue)throw s("multiarr","Expected model value to be array but got '{0}'",d.$viewValue);p.selected=[]}p.selected=d.$viewValue},t.on("click",u),c.$on("$destroy",function(){t.off("click",u)}),o(c,function(e){var t=angular.element("
    ").append(e),c=t.querySelectorAll(".ui-select-match");if(c.removeAttr("ui-select-match"),1!==c.length)throw s("transcluded","Expected 1 .ui-select-match but got '{0}'.",c.length);n.querySelectorAll(".ui-select-match").replaceWith(c);var l=t.querySelectorAll(".ui-select-choices");if(l.removeAttr("ui-select-choices"),1!==l.length)throw s("transcluded","Expected 1 .ui-select-choices but got '{0}'.",l.length);n.querySelectorAll(".ui-select-choices").replaceWith(l)})}}}]).directive("uiSelectChoices",["uiSelectConfig","RepeatParser","uiSelectMinErr","$compile",function(e,t,c,s){return{restrict:"EA",require:"^uiSelect",replace:!0,transclude:!0,templateUrl:function(t){var c=t.parent().attr("theme")||e.theme;return c+"/choices.tpl.html"},compile:function(l,i){if(!i.repeat)throw c("repeat","Expected 'repeat' expression.");return function(l,i,n,a,r){var o=n.groupBy;if(a.parseRepeatAttr(n.repeat,o),o){var u=i.querySelectorAll(".ui-select-choices-group");if(1!==u.length)throw c("rows","Expected 1 .ui-select-choices-group but got '{0}'.",u.length);u.attr("ng-repeat",t.getGroupNgRepeatExpression())}var p=i.querySelectorAll(".ui-select-choices-row");if(1!==p.length)throw c("rows","Expected 1 .ui-select-choices-row but got '{0}'.",p.length);p.attr("ng-repeat",t.getNgRepeatExpression(a.parserResult.itemName,"$select.items",a.parserResult.trackByExp,o)).attr("ng-mouseenter","$select.setActiveItem("+a.parserResult.itemName+")").attr("ng-click","$select.select("+a.parserResult.itemName+")");var d=i.querySelectorAll(".ui-select-choices-row-inner");if(1!==d.length)throw c("rows","Expected 1 .ui-select-choices-row-inner but got '{0}'.",d.length);d.attr("uis-transclude-append",""),s(i,r)(l),l.$watch("$select.search",function(e){e&&!a.open&&a.multiple&&a.activate(!1,!0),a.activeIndex=0,a.refresh(n.refresh)}),n.$observe("refreshDelay",function(){var t=l.$eval(n.refreshDelay);a.refreshDelay=void 0!==t?t:e.refreshDelay})}}}}]).directive("uisTranscludeAppend",function(){return{link:function(e,t,c,s,l){l(e,function(e){t.append(e)})}}}).directive("uiSelectMatch",["uiSelectConfig",function(e){return{restrict:"EA",require:"^uiSelect",replace:!0,transclude:!0,templateUrl:function(t){var c=t.parent().attr("theme")||e.theme,s=t.parent().attr("multiple");return c+(s?"/match-multiple.tpl.html":"/match.tpl.html")},link:function(t,c,s,l){s.$observe("placeholder",function(t){l.placeholder=void 0!==t?t:e.placeholder}),l.multiple&&l.sizeSearchInput()}}}]).filter("highlight",function(){function e(e){return e.replace(/([.?*+^$[\]\\(){}|-])/g,"\\$1")}return function(t,c){return c&&t?t.replace(new RegExp(e(c),"gi"),'$&'):t}})}(),angular.module("ui.select").run(["$templateCache",function(e){e.put("bootstrap/choices.tpl.html",''),e.put("bootstrap/match-multiple.tpl.html",''),e.put("bootstrap/match.tpl.html",''),e.put("bootstrap/select-multiple.tpl.html",''),e.put("bootstrap/select.tpl.html",''),e.put("select2/choices.tpl.html",'
    • {{$group.name}}
    '),e.put("select2/match-multiple.tpl.html",'
  • '),e.put("select2/match.tpl.html",'{{$select.placeholder}} '),e.put("select2/select-multiple.tpl.html",'
    '),e.put("select2/select.tpl.html",'
    '),e.put("selectize/choices.tpl.html",'
    {{$group.name}}
    '),e.put("selectize/match.tpl.html",'
    '),e.put("selectize/select.tpl.html",'
    ')}]); \ No newline at end of file diff --git a/src/select.js b/src/select.js index abbdf8e22..e16d1f7dc 100644 --- a/src/select.js +++ b/src/select.js @@ -317,7 +317,12 @@ // When the user clicks on an item inside the dropdown ctrl.select = function(item) { - if (!item._uiSelectChoiceDisabled) { + if (!item || !item._uiSelectChoiceDisabled) { + if(ctrl.tagging.isActivated && !item && ctrl.search.length > 0) { + // create new item on the fly + item = ctrl.tagging.fct !== undefined ? ctrl.tagging.fct(ctrl.search) : ctrl.search; + } + var locals = {}; locals[ctrl.parserResult.itemName] = item; @@ -387,7 +392,7 @@ break; case KEY.UP: if (!ctrl.open && ctrl.multiple) ctrl.activate(false, true); //In case its the search input in 'multiple' mode - else if (ctrl.activeIndex > 0) { ctrl.activeIndex--; } + else if (ctrl.activeIndex > 0 || (ctrl.search.length === 0 && ctrl.tagging.isActivated)) { ctrl.activeIndex--; } break; case KEY.TAB: //TODO: Que hacemos en modo multiple? @@ -486,7 +491,7 @@ processed = _handleMatchSelection(key); } - if (!processed && ctrl.items.length > 0) { + if (!processed && (ctrl.items.length > 0 || ctrl.tagging.isActivated)) { processed = _handleDropDownSelection(key); } @@ -728,6 +733,19 @@ $select.resetSearchInput = resetSearchInput !== undefined ? resetSearchInput : true; }); + attrs.$observe('tagging', function() { + if(attrs.tagging !== undefined) + { + // $eval() is needed otherwise we get a string instead of a function or a boolean + var taggingEval = scope.$eval(attrs.tagging); + $select.tagging = {isActivated: true, fct: taggingEval !== true ? taggingEval : undefined}; + } + else + { + $select.tagging = {isActivated: false, fct: undefined}; + } + }); + if ($select.multiple){ scope.$watchCollection('$select.selected', function(newValue) { //On v1.2.19 the 2nd and 3rd parameteres are ignored @@ -860,7 +878,7 @@ scope.$watch('$select.search', function(newValue) { if(newValue && !$select.open && $select.multiple) $select.activate(false, true); - $select.activeIndex = 0; + $select.activeIndex = $select.tagging.isActivated ? -1 : 0; $select.refresh(attrs.refresh); }); diff --git a/src/select2/match-multiple.tpl.html b/src/select2/match-multiple.tpl.html index d4a2217e7..53c8f21ae 100644 --- a/src/select2/match-multiple.tpl.html +++ b/src/select2/match-multiple.tpl.html @@ -7,6 +7,6 @@
  • - +
  • - \ No newline at end of file + diff --git a/test/select.spec.js b/test/select.spec.js index f2f4f2690..17f404d72 100644 --- a/test/select.spec.js +++ b/test/select.spec.js @@ -67,6 +67,7 @@ describe('ui-select tests', function() { if (attrs.required !== undefined) { attrsHtml += ' ng-required="' + attrs.required + '"'; } if (attrs.theme !== undefined) { attrsHtml += ' theme="' + attrs.theme + '"'; } if (attrs.tabindex !== undefined) { attrsHtml += ' tabindex="' + attrs.tabindex + '"'; } + if (attrs.tagging !== undefined) { attrsHtml += ' tagging="' + attrs.tagging + '"'; } } return compileTemplate( @@ -246,6 +247,39 @@ describe('ui-select tests', function() { expect(isDropdownOpened(el3)).toEqual(true); }); + it('should allow tagging if the attribute says so', function() { + var el = createUiSelect({tagging: true}); + clickMatch(el); + + $(el).scope().$select.select("I don't exist"); + + expect($(el).scope().$select.selected).toEqual("I don't exist"); + }); + + it('should format new items using the tagging function when the attribute is a function', function() { + scope.taggingFunc = function (name) { + return { + name: name, + email: name + '@email.com', + group: 'Foo', + age: 12 + }; + }; + + var el = createUiSelect({tagging: 'taggingFunc'}); + clickMatch(el); + + $(el).scope().$select.search = 'idontexist'; + $(el).scope().$select.select(); + + expect($(el).scope().$select.selected).toEqual({ + name: 'idontexist', + email: 'idontexist@email.com', + group: 'Foo', + age: 12 + }); + }); + // See when an item that evaluates to false (such as "false" or "no") is selected, the placeholder is shown https://github.com/angular-ui/ui-select/pull/32 it('should not display the placeholder when item evaluates to false', function() { scope.items = ['false'];