From 99b3e550470278beabf5162c00fb25301ca54235 Mon Sep 17 00:00:00 2001 From: tamtakoe Date: Tue, 10 May 2016 03:01:55 +0300 Subject: [PATCH 01/11] in progress --- CHANGELOG.md | 6 ++ README.md | 2 +- bower.json | 2 +- docs/examples/multiple/controller.js | 31 ++++++---- docs/examples/multiple/template.html | 4 +- docs/examples/single/controller.js | 4 +- docs/examples/single/template.html | 4 +- package.json | 4 +- src/directives.js | 40 ++++++++++--- src/filters.js | 8 +-- src/services.js | 86 ++++++++++++++++++++++------ 11 files changed, 140 insertions(+), 51 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 44cdd55..c3ad89d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,9 @@ +## 0.2.21 + +#### Bug Fixes + +- **oiSelectAscSort** works correct with different locales (f.e. Turkish) + ## 0.2.20 #### Features diff --git a/README.md b/README.md index be068ca..ee80b57 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ #oi.select — AngularJS directive of select element -**[Download 0.2.20](https://github.com/tamtakoe/oi.select/tree/master/dist)** +**[Download 0.2.21](https://github.com/tamtakoe/oi.select/tree/master/dist)** ## Features diff --git a/bower.json b/bower.json index db59773..01abc12 100644 --- a/bower.json +++ b/bower.json @@ -3,7 +3,7 @@ "name": "https://github.com/tamtakoe" }, "name": "oi.select", - "version": "0.2.20", + "version": "0.2.21", "main": ["./dist/select-tpls.min.js", "./dist/select.min.css"], "dependencies": { "angular": ">=1.2", diff --git a/docs/examples/multiple/controller.js b/docs/examples/multiple/controller.js index 922db81..4fad671 100644 --- a/docs/examples/multiple/controller.js +++ b/docs/examples/multiple/controller.js @@ -1,17 +1,28 @@ angular.module('selectDemo') .controller('selectMultipleController', function ($scope, ShopArr) { - $scope.shopArr = ShopArr.query(); + $scope.shopObj = { + 5: "shirts", + '1': "sneakers", + 2: "shoes", + 3: "foobar" + }; - $scope.bundle = [{ - "id": 5, - "name": "shirt", - "category": "clothes" - },{ - "id": 2, - "name": "shoes", - "category": "shoes" - }]; + // $scope.shopArr = ["shirts", "sneakers", "shoes", "foobar"]; + + $scope.bundle = ['1']; + + // $scope.shopArr = ShopArr.query(); + + // $scope.bundle = [{ + // "id": 5, + // "name": "shirt", + // "category": "clothes" + // },{ + // "id": 2, + // "name": "shoes", + // "category": "shoes" + // }]; $scope.bundle2 = []; $scope.bundle3 = []; diff --git a/docs/examples/multiple/template.html b/docs/examples/multiple/template.html index bd80d7e..f113d50 100644 --- a/docs/examples/multiple/template.html +++ b/docs/examples/multiple/template.html @@ -4,7 +4,7 @@

Multiple

Multiple
-oi-options="item.name for item in shopArr track by item.id" +oi-options="key as value for (key, value) in shopObj" ng-model="bundle" multiple
diff --git a/docs/examples/single/controller.js b/docs/examples/single/controller.js index 4a3e314..d60f079 100644 --- a/docs/examples/single/controller.js +++ b/docs/examples/single/controller.js @@ -1,9 +1,9 @@ angular.module('selectDemo') .controller('selectSingleController', function ($scope, ShopObj) { - $scope.shopObjShort = ShopObj.get(); + $scope.shopObj = ShopObj.get(); - $scope.shopObjShort.$promise.then(function(data) { + $scope.shopObj.$promise.then(function(data) { $scope.bundle = {a:1}; //data[3]; }) }); \ No newline at end of file diff --git a/docs/examples/single/template.html b/docs/examples/single/template.html index f291bd3..5ecf1c4 100644 --- a/docs/examples/single/template.html +++ b/docs/examples/single/template.html @@ -4,7 +4,7 @@

Single

@@ -13,7 +13,7 @@

Single

-oi-options="item for (key, item) in shopObjShort" +oi-options="item for (key, item) in shopObj" ng-model="bundle"
diff --git a/package.json b/package.json
index d95a361..35ac54b 100644
--- a/package.json
+++ b/package.json
@@ -1,13 +1,13 @@
 {
     "name":    "oi.select",
     "license": "MIT",
-    "version": "0.2.20",
+    "version": "0.2.21",
     "repository": {
         "type": "git",
         "url": "git://github.com/tamtakoe/oi.select.git"
     },
     "devDependencies": {
-        "gulp": "3.9.0",
+        "gulp": "3.9.1",
         "gulp-watch": "4.2.4",
         "gulp-webserver": "0.8.7",
         "gulp-stylus": "2.0.1",
diff --git a/src/directives.js b/src/directives.js
index a410eb2..819569c 100644
--- a/src/directives.js
+++ b/src/directives.js
@@ -19,7 +19,8 @@ angular.module('oi.select')
 
             var selectAsName          = / as /.test(match[0]) && match[1],    //item.modelValue
                 displayName           = match[2] || match[1],                 //item.label
-                valueName             = match[5] || match[7],                 //item
+                valueName             = match[5] || match[7],                 //item (value)
+                keyName               = match[6],                             //(key)
                 groupByName           = match[3] || '',                       //item.groupName
                 disableWhenName       = match[4] || '',                       //item.disableWhenName
                 trackByName           = match[9] || displayName,              //item.id
@@ -233,6 +234,10 @@ angular.module('oi.select')
                 });
 
                 scope.addItem = function addItem(option) {
+
+                    // var key = Object.keys(obj).filter(function(key) {return obj[key] === value})[0];
+
+                    console.log(option);
                     lastQuery = scope.query;
 
                     //duplicate
@@ -248,6 +253,9 @@ angular.module('oi.select')
                     var optionGroup = scope.groups[getGroupName(option)] = scope.groups[getGroupName(option)] || [];
                     var modelOption = selectAsFn ? selectAs(option) : option;
 
+                    // selectAsFn = $parse('key'),
+                    // console.log(selectAsFn(option));
+
                     optionGroup.splice(optionGroup.indexOf(option), 1);
 
                     if (multiple) {
@@ -283,6 +291,7 @@ angular.module('oi.select')
                             if (!multiple && !scope.inputHide) return;
 
                             if (multiple) {
+                                ctrl.$modelValue = [].concat(ctrl.$modelValue);
                                 ctrl.$modelValue.splice(position, 1);
                                 ctrl.$setViewValue([].concat(ctrl.$modelValue));
 
@@ -533,27 +542,42 @@ angular.module('oi.select')
                 }
 
                 function trackBy(item) {
-                    return oiUtils.getValue(valueName, item, scope.$parent, trackByFn);
+                    return oiUtils.getValue(valueName, item, scope.$parent, trackByFn, keyName);
                 }
 
                 function selectAs(item) {
-                    return oiUtils.getValue(valueName, item, scope.$parent, selectAsFn);
+                    // console.log(keyName);
+                    // function getValue(valueName, item, scope, getter, keyName) {
+                    //     console.log(valueName, item, scope, getter, keyName);
+                    //     var locals = {};
+                    //
+                    //     locals[valueName] = item;
+                    //     locals[keyName] = item;
+                    //
+                    //     //'name.subname' -> {name: {subname: item}}'
+                    //     // valueName.split('.').reduce(function (previousValue, currentItem, index, arr) {
+                    //     //     return previousValue[currentItem] = index < arr.length - 1 ? {} : item;
+                    //     // }, locals);
+                    //
+                    //     return getter(scope, locals);
+                    // }
+                    return oiUtils.getValue(valueName, item, scope.$parent, selectAsFn, keyName);
                 }
 
                 function getLabel(item) {
-                    return oiUtils.getValue(valueName, item, scope.$parent, displayFn);
+                    return oiUtils.getValue(valueName, item, scope.$parent, displayFn, keyName);
                 }
 
                 function getDisableWhen(item) {
-                    return oiUtils.getValue(valueName, item, scope.$parent, disableWhenFn);
+                    return oiUtils.getValue(valueName, item, scope.$parent, disableWhenFn, keyName);
                 }
 
                 function getGroupName(option) {
-                    return oiUtils.getValue(valueName, option, scope.$parent, groupByFn) || '';
+                    return oiUtils.getValue(valueName, option, scope.$parent, groupByFn, keyName) || '';
                 }
 
                 function filter(list) {
-                    return oiUtils.getValue(valuesName, list, scope.$parent, filteredValuesFn);
+                    return oiUtils.getValue(valuesName, list, scope.$parent, filteredValuesFn, keyName);
                 }
 
                 function compact(value) {
@@ -594,7 +618,7 @@ angular.module('oi.select')
 
                                 if (values && !selectedAs) {
                                     var outputValues = multiple ? scope.output : [];
-                                    var filteredList = listFilter(oiUtils.objToArr(values), query, getLabel, listFilterOptionsFn(scope.$parent), element);
+                                    var filteredList = listFilter(oiUtils.objToArr(values, !!keyName), query, getLabel, listFilterOptionsFn(scope.$parent), element);
                                     var withoutIntersection = oiUtils.intersection(filteredList, outputValues, trackBy, trackBy, true);
                                     var filteredOutput = filter(withoutIntersection);
 
diff --git a/src/filters.js b/src/filters.js
index adae0e4..58247a0 100644
--- a/src/filters.js
+++ b/src/filters.js
@@ -36,16 +36,16 @@ angular.module('oi.select')
         var i, j, isFound, output, output1 = [], output2 = [], output3 = [], output4 = [];
 
         if (query) {
-            query = oiSelectEscape(String(query));
+            query = oiSelectEscape(String(query)).toLocaleLowerCase();
 
             for (i = 0, isFound = false; i < input.length; i++) {
-                isFound = getLabel(input[i]).match(new RegExp(query, "i"));
+                isFound = getLabel(input[i]).toLocaleLowerCase().match(new RegExp(query));
 
                 if (!isFound && options && (options.length || options.fields)) {
                     for (j = 0; j < options.length; j++) {
                         if (isFound) break;
 
-                        isFound = String(input[i][options[j]]).match(new RegExp(query, "i"));
+                        isFound = String(input[i][options[j]]).toLocaleLowerCase().match(new RegExp(query));
                     }
                 }
 
@@ -54,7 +54,7 @@ angular.module('oi.select')
                 }
             }
             for (i = 0; i < output1.length; i++) {
-                if (getLabel(output1[i]).match(new RegExp('^' + query, "i"))) {
+                if (getLabel(output1[i]).toLocaleLowerCase().match(new RegExp('^' + query))) {
                     output2.push(output1[i]);
                 } else {
                     output3.push(output1[i]);
diff --git a/src/services.js b/src/services.js
index 76f3920..5df3f33 100644
--- a/src/services.js
+++ b/src/services.js
@@ -14,10 +14,10 @@ angular.module('oi.select')
             saveTrigger:    'enter tab blur'
         },
         version: {
-            full: '0.2.20',
+            full: '0.2.21',
             major: 0,
             minor: 2,
-            dot: 20
+            dot: 21
         },
         $get: function() {
             return {
@@ -291,18 +291,6 @@ angular.module('oi.select')
         return true;
     }
 
-    function objToArr(obj) {
-        var arr = [];
-
-        angular.forEach(obj, function (value, key) {
-            if (key.toString().charAt(0) !== '$') {
-                arr.push(value);
-            }
-        });
-
-        return arr;
-    }
-
     //lodash _.intersection + filter + invert
     function intersection(xArr, yArr, xFilter, yFilter, invert) {
         var i, j, n, filteredX, filteredY, out = invert ? [].concat(xArr) : [];
@@ -322,17 +310,77 @@ angular.module('oi.select')
         return out;
     }
 
-    function getValue(valueName, item, scope, getter) {
+    var keysMap = Map();
+
+    function getValue(valueName, item, scope, getter, keyName) {
+        // console.log(keysMap.get(keyName));
+        console.log(scope);
         var locals = {};
 
-        //'name.subname' -> {name: {subname: list}}'
-        valueName.split('.').reduce(function (previousValue, currentItem, index, arr) {
-            return previousValue[currentItem] = index < arr.length - 1 ? {} : item;
-        }, locals);
+        locals[valueName] = item;
+
+        if (keyName !== undefined) {
+            locals[keyName] = keysMap.get(keyName);
+        }
+
+        // var key = Object.keys(obj).filter(function(key) {return obj[key] === value})[0];
+
+        //'name.subname' -> {name: {subname: item}} -> locals'
+        // valueName.split('.').reduce(function (previousValue, currentItem, index, arr) {
+        //     return previousValue[currentItem] = index < arr.length - 1 ? {} : item;
+        // }, locals);
 
         return getter(scope, locals);
     }
 
+    function objToArr(obj, saveKeysMap) {
+        var arr = [];
+
+        angular.forEach(obj, function (value, key) {
+            if (key.toString().charAt(0) !== '$') {
+                arr.push(value);
+
+                if (saveKeysMap) {
+                    keysMap.clear().set(value, key);
+                }
+            }
+        });
+
+        return arr;
+    }
+
+    function Map() {
+        var i;
+
+        function SimpleMap(){
+            this._keys = [];
+            this._values = [];
+        }
+
+        SimpleMap.prototype.has = function(key) {
+            var list = this._keys;
+            if (key != key || key === 0) for (i = list.length; i-- && list[i] !== key;){}
+            else i = list.indexOf(key);
+            return -1 < i;
+        };
+
+        SimpleMap.prototype.get = function(key) {
+            return this.has(key) ? this._values[i] : undefined;
+        };
+
+        SimpleMap.prototype.set = function(key, value) {
+            this.has(key) ? this._values[i] = value : this._values[this._keys.push(key) - 1] = value;
+            return this;
+        };
+
+        SimpleMap.prototype.clear = function() {
+            (this._keys || 0).length = this._values.length = 0;
+            return this;
+        };
+
+        return new SimpleMap();
+    }
+
     return {
         contains: contains,
         bindFocusBlur: bindFocusBlur,

From c18d88d9766bd5a5c8b2df4a3212e650c0b30729 Mon Sep 17 00:00:00 2001
From: tamtakoe 
Date: Tue, 10 May 2016 03:08:41 +0300
Subject: [PATCH 02/11] in progress

---
 src/directives.js | 37 +++++------------------
 src/services.js   | 77 ++++++++---------------------------------------
 2 files changed, 20 insertions(+), 94 deletions(-)

diff --git a/src/directives.js b/src/directives.js
index 819569c..4beebcd 100644
--- a/src/directives.js
+++ b/src/directives.js
@@ -234,10 +234,6 @@ angular.module('oi.select')
                 });
 
                 scope.addItem = function addItem(option) {
-
-                    // var key = Object.keys(obj).filter(function(key) {return obj[key] === value})[0];
-
-                    console.log(option);
                     lastQuery = scope.query;
 
                     //duplicate
@@ -253,9 +249,6 @@ angular.module('oi.select')
                     var optionGroup = scope.groups[getGroupName(option)] = scope.groups[getGroupName(option)] || [];
                     var modelOption = selectAsFn ? selectAs(option) : option;
 
-                    // selectAsFn = $parse('key'),
-                    // console.log(selectAsFn(option));
-
                     optionGroup.splice(optionGroup.indexOf(option), 1);
 
                     if (multiple) {
@@ -291,7 +284,6 @@ angular.module('oi.select')
                             if (!multiple && !scope.inputHide) return;
 
                             if (multiple) {
-                                ctrl.$modelValue = [].concat(ctrl.$modelValue);
                                 ctrl.$modelValue.splice(position, 1);
                                 ctrl.$setViewValue([].concat(ctrl.$modelValue));
 
@@ -542,42 +534,27 @@ angular.module('oi.select')
                 }
 
                 function trackBy(item) {
-                    return oiUtils.getValue(valueName, item, scope.$parent, trackByFn, keyName);
+                    return oiUtils.getValue(valueName, item, scope.$parent, trackByFn);
                 }
 
                 function selectAs(item) {
-                    // console.log(keyName);
-                    // function getValue(valueName, item, scope, getter, keyName) {
-                    //     console.log(valueName, item, scope, getter, keyName);
-                    //     var locals = {};
-                    //
-                    //     locals[valueName] = item;
-                    //     locals[keyName] = item;
-                    //
-                    //     //'name.subname' -> {name: {subname: item}}'
-                    //     // valueName.split('.').reduce(function (previousValue, currentItem, index, arr) {
-                    //     //     return previousValue[currentItem] = index < arr.length - 1 ? {} : item;
-                    //     // }, locals);
-                    //
-                    //     return getter(scope, locals);
-                    // }
-                    return oiUtils.getValue(valueName, item, scope.$parent, selectAsFn, keyName);
+                    return oiUtils.getValue(valueName, item, scope.$parent, selectAsFn);
                 }
 
                 function getLabel(item) {
-                    return oiUtils.getValue(valueName, item, scope.$parent, displayFn, keyName);
+                    return oiUtils.getValue(valueName, item, scope.$parent, displayFn);
                 }
 
                 function getDisableWhen(item) {
-                    return oiUtils.getValue(valueName, item, scope.$parent, disableWhenFn, keyName);
+                    return oiUtils.getValue(valueName, item, scope.$parent, disableWhenFn);
                 }
 
                 function getGroupName(option) {
-                    return oiUtils.getValue(valueName, option, scope.$parent, groupByFn, keyName) || '';
+                    return oiUtils.getValue(valueName, option, scope.$parent, groupByFn) || '';
                 }
 
                 function filter(list) {
-                    return oiUtils.getValue(valuesName, list, scope.$parent, filteredValuesFn, keyName);
+                    return oiUtils.getValue(valuesName, list, scope.$parent, filteredValuesFn);
                 }
 
                 function compact(value) {
@@ -618,7 +595,7 @@ angular.module('oi.select')
 
                                 if (values && !selectedAs) {
                                     var outputValues = multiple ? scope.output : [];
-                                    var filteredList = listFilter(oiUtils.objToArr(values, !!keyName), query, getLabel, listFilterOptionsFn(scope.$parent), element);
+                                    var filteredList = listFilter(oiUtils.objToArr(values), query, getLabel, listFilterOptionsFn(scope.$parent), element);
                                     var withoutIntersection = oiUtils.intersection(filteredList, outputValues, trackBy, trackBy, true);
                                     var filteredOutput = filter(withoutIntersection);
 
diff --git a/src/services.js b/src/services.js
index 5df3f33..cb55299 100644
--- a/src/services.js
+++ b/src/services.js
@@ -291,6 +291,18 @@ angular.module('oi.select')
         return true;
     }
 
+    function objToArr(obj) {
+        var arr = [];
+
+        angular.forEach(obj, function (value, key) {
+            if (key.toString().charAt(0) !== '$') {
+                arr.push(value);
+            }
+        });
+
+        return arr;
+    }
+
     //lodash _.intersection + filter + invert
     function intersection(xArr, yArr, xFilter, yFilter, invert) {
         var i, j, n, filteredX, filteredY, out = invert ? [].concat(xArr) : [];
@@ -310,77 +322,14 @@ angular.module('oi.select')
         return out;
     }
 
-    var keysMap = Map();
-
-    function getValue(valueName, item, scope, getter, keyName) {
-        // console.log(keysMap.get(keyName));
-        console.log(scope);
+    function getValue(valueName, item, scope, getter) {
         var locals = {};
 
         locals[valueName] = item;
 
-        if (keyName !== undefined) {
-            locals[keyName] = keysMap.get(keyName);
-        }
-
-        // var key = Object.keys(obj).filter(function(key) {return obj[key] === value})[0];
-
-        //'name.subname' -> {name: {subname: item}} -> locals'
-        // valueName.split('.').reduce(function (previousValue, currentItem, index, arr) {
-        //     return previousValue[currentItem] = index < arr.length - 1 ? {} : item;
-        // }, locals);
-
         return getter(scope, locals);
     }
 
-    function objToArr(obj, saveKeysMap) {
-        var arr = [];
-
-        angular.forEach(obj, function (value, key) {
-            if (key.toString().charAt(0) !== '$') {
-                arr.push(value);
-
-                if (saveKeysMap) {
-                    keysMap.clear().set(value, key);
-                }
-            }
-        });
-
-        return arr;
-    }
-
-    function Map() {
-        var i;
-
-        function SimpleMap(){
-            this._keys = [];
-            this._values = [];
-        }
-
-        SimpleMap.prototype.has = function(key) {
-            var list = this._keys;
-            if (key != key || key === 0) for (i = list.length; i-- && list[i] !== key;){}
-            else i = list.indexOf(key);
-            return -1 < i;
-        };
-
-        SimpleMap.prototype.get = function(key) {
-            return this.has(key) ? this._values[i] : undefined;
-        };
-
-        SimpleMap.prototype.set = function(key, value) {
-            this.has(key) ? this._values[i] = value : this._values[this._keys.push(key) - 1] = value;
-            return this;
-        };
-
-        SimpleMap.prototype.clear = function() {
-            (this._keys || 0).length = this._values.length = 0;
-            return this;
-        };
-
-        return new SimpleMap();
-    }
-
     return {
         contains: contains,
         bindFocusBlur: bindFocusBlur,

From 3a827c83136174df822847ab727ed59968d2bc74 Mon Sep 17 00:00:00 2001
From: tamtakoe 
Date: Tue, 10 May 2016 18:37:57 +0300
Subject: [PATCH 03/11] fix select_as with object data source

---
 CHANGELOG.md                         |  2 ++
 docs/examples/multiple/controller.js | 39 ++++++++++------------------
 docs/examples/multiple/template.html |  2 +-
 src/directives.js                    | 34 ++++++++++++++++++++++--
 src/filters.js                       |  4 +--
 src/services.js                      | 18 +++----------
 6 files changed, 55 insertions(+), 44 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index c3ad89d..17032c6 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,8 @@
 
 #### Bug Fixes
 
+- **oi-select:** `select as`  works correct with object data source
+
 - **oiSelectAscSort** works correct with different locales (f.e. Turkish)
 
 ## 0.2.20
diff --git a/docs/examples/multiple/controller.js b/docs/examples/multiple/controller.js
index 4fad671..3bde30a 100644
--- a/docs/examples/multiple/controller.js
+++ b/docs/examples/multiple/controller.js
@@ -1,29 +1,18 @@
 angular.module('selectDemo')
-    .controller('selectMultipleController', function ($scope, ShopArr) {
+    .controller('selectMultipleController', function ($scope, ShopArr, ShopObjShort) {
+        
+        $scope.shopArr = ShopArr.query();
+        $scope.shopObjShort = ShopObjShort.get();
 
-        $scope.shopObj = {
-            5: "shirts",
-            '1': "sneakers",
-            2: "shoes",
-            3: "foobar"
-        };
-
-        // $scope.shopArr = ["shirts", "sneakers", "shoes", "foobar"];
-
-        $scope.bundle = ['1'];
-
-        // $scope.shopArr = ShopArr.query();
-
-        // $scope.bundle = [{
-        //     "id": 5,
-        //     "name": "shirt",
-        //     "category": "clothes"
-        // },{
-        //     "id": 2,
-        //     "name": "shoes",
-        //     "category": "shoes"
-        // }];
-
-        $scope.bundle2 = [];
+        $scope.bundle = ["1"];
+        $scope.bundle2 = [{
+            "id": 5,
+            "name": "shirt",
+            "category": "clothes"
+        },{
+            "id": 2,
+            "name": "shoes",
+            "category": "shoes"
+        }];
         $scope.bundle3 = [];
     });
diff --git a/docs/examples/multiple/template.html b/docs/examples/multiple/template.html
index f113d50..2c680ac 100644
--- a/docs/examples/multiple/template.html
+++ b/docs/examples/multiple/template.html
@@ -4,7 +4,7 @@ 

Multiple

0 || angular.isNumber(query)) { label = label.toString(); - query = oiSelectEscape(query.toString()); + query = oiSelectEscape(query); html = label.replace(new RegExp(query, 'gi'), '$&'); } else { @@ -36,7 +36,7 @@ angular.module('oi.select') var i, j, isFound, output, output1 = [], output2 = [], output3 = [], output4 = []; if (query) { - query = oiSelectEscape(String(query)).toLocaleLowerCase(); + query = oiSelectEscape(query).toLocaleLowerCase(); for (i = 0, isFound = false; i < input.length; i++) { isFound = getLabel(input[i]).toLocaleLowerCase().match(new RegExp(query)); diff --git a/src/services.js b/src/services.js index cb55299..cbe39f6 100644 --- a/src/services.js +++ b/src/services.js @@ -291,18 +291,6 @@ angular.module('oi.select') return true; } - function objToArr(obj) { - var arr = []; - - angular.forEach(obj, function (value, key) { - if (key.toString().charAt(0) !== '$') { - arr.push(value); - } - }); - - return arr; - } - //lodash _.intersection + filter + invert function intersection(xArr, yArr, xFilter, yFilter, invert) { var i, j, n, filteredX, filteredY, out = invert ? [].concat(xArr) : []; @@ -325,7 +313,10 @@ angular.module('oi.select') function getValue(valueName, item, scope, getter) { var locals = {}; - locals[valueName] = item; + //'name.subname' -> {name: {subname: item}} -> locals' + valueName.split('.').reduce(function (previousValue, currentItem, index, arr) { + return previousValue[currentItem] = index < arr.length - 1 ? {} : item; + }, locals); return getter(scope, locals); } @@ -335,7 +326,6 @@ angular.module('oi.select') bindFocusBlur: bindFocusBlur, scrollActiveOption: scrollActiveOption, groupsIsEmpty: groupsIsEmpty, - objToArr: objToArr, getValue: getValue, intersection: intersection } From 4a121b52672c142475fff52bfbb127e7dd3f4e7f Mon Sep 17 00:00:00 2001 From: tamtakoe Date: Tue, 10 May 2016 19:50:54 +0300 Subject: [PATCH 04/11] add empty list placeholder --- CHANGELOG.md | 2 + README.md | 3 + dist/select-tpls.js | 90 ++++++++++++++++++++-------- dist/select-tpls.min.js | 2 +- dist/select.css | 3 + dist/select.js | 90 ++++++++++++++++++++-------- dist/select.min.css | 2 +- dist/select.min.js | 2 +- docs/examples/multiple/template.html | 3 + src/directives.js | 24 +++++++- src/style.styl | 7 ++- 11 files changed, 173 insertions(+), 55 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 17032c6..d281b60 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,6 +4,8 @@ - **oi-select:** `select as` works correct with object data source +- **list-placeholder:** placeholder for dropdown list if no items found + - **oiSelectAscSort** works correct with different locales (f.e. Turkish) ## 0.2.20 diff --git a/README.md b/README.md index ee80b57..d9beb69 100644 --- a/README.md +++ b/README.md @@ -87,6 +87,9 @@ Use `oi-select` directive: * `ng-disabled` — specifies that a drop-down list should be disabled * `multiple` — specifies that multiple options can be selected at once * `multiple-limit` — maximum number of options that can be selected at once +* `placeholder` — native placeholder +* `multiple-placeholder` — placeholder which is shown in multiple mode near chosen options +* `list-placeholder` — placeholder which is shown in list if no elements found * `readonly` — specifies that an input field is read-only * `autofocus` — specifies that an input field should automatically get focus when the page loads * `oi-select-options` — object with options. You can override them in `oiSelectProvider.options` diff --git a/dist/select-tpls.js b/dist/select-tpls.js index 0b994be..f126fb3 100644 --- a/dist/select-tpls.js +++ b/dist/select-tpls.js @@ -15,10 +15,10 @@ angular.module('oi.select') saveTrigger: 'enter tab blur' }, version: { - full: '0.2.20', + full: '0.2.21', major: 0, minor: 2, - dot: 20 + dot: 21 }, $get: function() { return { @@ -292,18 +292,6 @@ angular.module('oi.select') return true; } - function objToArr(obj) { - var arr = []; - - angular.forEach(obj, function (value, key) { - if (key.toString().charAt(0) !== '$') { - arr.push(value); - } - }); - - return arr; - } - //lodash _.intersection + filter + invert function intersection(xArr, yArr, xFilter, yFilter, invert) { var i, j, n, filteredX, filteredY, out = invert ? [].concat(xArr) : []; @@ -326,7 +314,7 @@ angular.module('oi.select') function getValue(valueName, item, scope, getter) { var locals = {}; - //'name.subname' -> {name: {subname: list}}' + //'name.subname' -> {name: {subname: item}} -> locals' valueName.split('.').reduce(function (previousValue, currentItem, index, arr) { return previousValue[currentItem] = index < arr.length - 1 ? {} : item; }, locals); @@ -339,7 +327,6 @@ angular.module('oi.select') bindFocusBlur: bindFocusBlur, scrollActiveOption: scrollActiveOption, groupsIsEmpty: groupsIsEmpty, - objToArr: objToArr, getValue: getValue, intersection: intersection } @@ -365,11 +352,24 @@ angular.module('oi.select') var selectAsName = / as /.test(match[0]) && match[1], //item.modelValue displayName = match[2] || match[1], //item.label - valueName = match[5] || match[7], //item + valueName = match[5] || match[7], //item (value) + keyName = match[6], //(key) groupByName = match[3] || '', //item.groupName disableWhenName = match[4] || '', //item.disableWhenName trackByName = match[9] || displayName, //item.id - valueMatches = match[8].match(VALUES_REGEXP); //collection + valueMatches = match[8].match(VALUES_REGEXP), //collection + valueTitle = valueName, + keyTitle = keyName; + + if (keyName) { //convert object data sources format to array data sources format + valueName = 'i'; + selectAsName = valueName + '.' + (selectAsName || valueTitle); + trackByName = valueName + '.' + keyName; + displayName = valueName + '.' + displayName; + keyName = valueName + '.' + keyName; + groupByName = groupByName ? valueName + '.' + groupByName: undefined; + disableWhenName = disableWhenName ? valueName + '.' + disableWhenName: undefined; + } var valuesName = valueMatches[1], //collection filteredValuesName = valuesName + (valueMatches[3] || ''), //collection | filter @@ -384,6 +384,7 @@ angular.module('oi.select') trackByFn = $parse(trackByName); var multiplePlaceholderFn = $interpolate(attrs.multiplePlaceholder || ''), + listPlaceholderFn = $interpolate(attrs.listPlaceholder || ''), placeholderFn = $interpolate(attrs.placeholder || ''), optionsFn = $parse(attrs.oiSelectOptions), isOldAngular = angular.version.major <= 1 && angular.version.minor <= 3; @@ -405,6 +406,7 @@ angular.module('oi.select') listElement = angular.element(element[0].querySelector('.select-dropdown')), placeholder = placeholderFn(scope), multiplePlaceholder = multiplePlaceholderFn(scope), + listPlaceholder = listPlaceholderFn(scope), elementOptions = optionsFn(scope.$parent) || {}, options = angular.extend({cleanModel: elementOptions.newItem === 'prompt'}, oiSelect.options, elementOptions), editItem = options.editItem, @@ -572,6 +574,12 @@ angular.module('oi.select') }); }); + scope.$watch('isEmptyList', function(isEmptyList) { + $animate[isEmptyList ? 'addClass' : 'removeClass'](element, 'emptyList', !isOldAngular && { + tempClasses: 'emptyList-animate' + }); + }); + scope.$watch('showLoader', function(isLoading) { $animate[isLoading ? 'addClass' : 'removeClass'](element, 'loading', !isOldAngular && { tempClasses: 'loading-animate' @@ -891,7 +899,7 @@ angular.module('oi.select') } function getDisableWhen(item) { - return oiUtils.getValue(valueName, item, scope.$parent, disableWhenFn); + return scope.isEmptyList || oiUtils.getValue(valueName, item, scope.$parent, disableWhenFn); } function getGroupName(option) { @@ -915,6 +923,8 @@ angular.module('oi.select') } function getMatches(query, selectedAs) { + scope.isEmptyList = false; + if (timeoutPromise && waitTime) { $timeout.cancel(timeoutPromise); //cancel previous timeout } @@ -936,14 +946,44 @@ angular.module('oi.select') return $q.when(values.$promise || values) .then(function(values) { + scope.groups = {}; + if (values && keyName) { + //convert object data sources format to array data sources format + var arr = []; + + angular.forEach(values, function (value, key) { + if (key.toString().charAt(0) !== '$') { + var item = {}; + + item[keyTitle] = key; + item[valueTitle] = value; + arr.push(item); + } + }); + + values = arr; + } + if (values && !selectedAs) { var outputValues = multiple ? scope.output : []; - var filteredList = listFilter(oiUtils.objToArr(values), query, getLabel, listFilterOptionsFn(scope.$parent), element); + var filteredList = listFilter(values, query, getLabel, listFilterOptionsFn(scope.$parent), element); var withoutIntersection = oiUtils.intersection(filteredList, outputValues, trackBy, trackBy, true); var filteredOutput = filter(withoutIntersection); + //add element with placeholder to empty list + if (!filteredOutput.length) { + scope.isEmptyList = true; + + if (listPlaceholder) { + var context = {}; + + displayFn.assign(context, listPlaceholder); + filteredOutput = [context[valueName]] + } + } + scope.groups = group(filteredOutput); } updateGroupPos(); @@ -1058,7 +1098,7 @@ angular.module('oi.select') if (query.length > 0 || angular.isNumber(query)) { label = label.toString(); - query = oiSelectEscape(query.toString()); + query = oiSelectEscape(query); html = label.replace(new RegExp(query, 'gi'), '$&'); } else { @@ -1074,16 +1114,16 @@ angular.module('oi.select') var i, j, isFound, output, output1 = [], output2 = [], output3 = [], output4 = []; if (query) { - query = oiSelectEscape(String(query)); + query = oiSelectEscape(query).toLocaleLowerCase(); for (i = 0, isFound = false; i < input.length; i++) { - isFound = getLabel(input[i]).match(new RegExp(query, "i")); + isFound = getLabel(input[i]).toLocaleLowerCase().match(new RegExp(query)); if (!isFound && options && (options.length || options.fields)) { for (j = 0; j < options.length; j++) { if (isFound) break; - isFound = String(input[i][options[j]]).match(new RegExp(query, "i")); + isFound = String(input[i][options[j]]).toLocaleLowerCase().match(new RegExp(query)); } } @@ -1092,7 +1132,7 @@ angular.module('oi.select') } } for (i = 0; i < output1.length; i++) { - if (getLabel(output1[i]).match(new RegExp('^' + query, "i"))) { + if (getLabel(output1[i]).toLocaleLowerCase().match(new RegExp('^' + query))) { output2.push(output1[i]); } else { output3.push(output1[i]); diff --git a/dist/select-tpls.min.js b/dist/select-tpls.min.js index a19cc65..2c6c1ee 100644 --- a/dist/select-tpls.min.js +++ b/dist/select-tpls.min.js @@ -1 +1 @@ -angular.module("oi.select",[]),angular.module("oi.select").provider("oiSelect",function(){return{options:{debounce:500,searchFilter:"oiSelectCloseIcon",dropdownFilter:"oiSelectHighlight",listFilter:"oiSelectAscSort",groupFilter:"oiSelectGroup",editItem:!1,newItem:!1,closeList:!0,saveTrigger:"enter tab blur"},version:{full:"0.2.20",major:0,minor:2,dot:20},$get:function(){return{options:this.options,version:this.version}}}}).factory("oiSelectEscape",function(){var e=/[-\/\\^$*+?.()|[\]{}]/g,t="\\$&";return function(n){return String(n).replace(e,t)}}).factory("oiSelectEditItem",function(){return function(e,t,n,o){return o?"":n(e)}}).factory("oiUtils",["$document","$timeout",function(e,t){function n(e,t,n){for(var o=t;o&&o.ownerDocument&&11!==o.nodeType;){if(n){if(o===e)return!1;if(o.className.indexOf(n)>=0)return!0}else if(o===e)return!0;o=o.parentNode}return!1}function o(o,r){function i(e){return e&&"INPUT"!==e.target.nodeName?void 0:(d=!1,c?void(d=!0):void t(function(){o.triggerHandler("blur")}))}function s(){a||(a=!0,t(function(){o.triggerHandler("focus")}))}function l(){c=!0}function u(e){c=!1;var s=e.target,l=n(o[0],s);d&&!l&&i(),l&&"INPUT"!==s.nodeName&&t(function(){r[0].focus()}),!l&&a&&(a=!1)}var a,c,d;return e[0].addEventListener("click",u,!0),o[0].addEventListener("mousedown",l,!0),o[0].addEventListener("blur",i,!0),r.on("focus",s),function(){e[0].removeEventListener("click",u),o[0].removeEventListener("mousedown",l,!0),o[0].removeEventListener("blur",i,!0),r.off("focus",s)}}function r(e,t){var n,o,r,i,l,a;t&&(o=e.offsetHeight,r=u(t,"height","margin"),i=e.scrollTop||0,n=s(t).top-s(e).top+i,l=n,a=n-o+r,n+r>o+i?e.scrollTop=a:i>n&&(e.scrollTop=l))}function i(e,t,n,o,r){function i(e){return parseFloat(r[e])}for(var s=n===(o?"border":"content")?4:"width"===t?1:0,l=0,u=["Top","Right","Bottom","Left"];4>s;s+=2)"margin"===n&&(l+=i(n+u[s])),o?("content"===n&&(l-=i("padding"+u[s])),"margin"!==n&&(l-=i("border"+u[s]+"Width"))):(l+=i("padding"+u[s]),"padding"!==n&&(l+=i("border"+u[s]+"Width")));return l}function s(e){var t,n,o=e.getBoundingClientRect(),r=e&&e.ownerDocument;if(r)return t=r.documentElement,n=l(r),{top:o.top+n.pageYOffset-t.clientTop,left:o.left+n.pageXOffset-t.clientLeft}}function l(e){return null!=e&&e===e.window?e:9===e.nodeType&&e.defaultView}function u(e,t,n){var o=!0,r="width"===t?e.offsetWidth:e.offsetHeight,s=window.getComputedStyle(e,null),l=!1;if(0>=r||null==r){if(r=s[t],(0>r||null==r)&&(r=e.style[t]),g.test(r))return r;r=parseFloat(r)||0}return r+i(e,t,n||(l?"border":"content"),o,s)}function a(e){for(var t in e)if(e.hasOwnProperty(t)&&e[t].length)return!1;return!0}function c(e){var t=[];return angular.forEach(e,function(e,n){"$"!==n.toString().charAt(0)&&t.push(e)}),t}function d(e,t,n,o,r){var i,s,l,u,a,c=r?[].concat(e):[];for(i=0,l=e.length;i=y&&u.contains(r[0],t.target,"select-dropdown")||(e.inputHide&&e.removeItem(0),!e.isOpen||!lt.closeList||"INPUT"===t.target.nodeName&&e.query.length?J(e.query):(Z({query:lt.editItem&&!at}),e.$evalAsync()))}function V(){e.isFocused||(e.isFocused=!0,c.disabled||(e.backspaceFocus=!1))}function q(){e.isFocused=!1,w||I(),E("blur")||Z(),e.$evalAsync()}function E(o,r){r||(r=o,o=e.query);var i,s=lt.saveTrigger.split(" ").indexOf(r)+1,l=lt.newItem&&o,u="blur"!==r?e.order[e.selectorPosition]:null;return s&&(l||u)?(e.showLoader=!0,i=t.when(u||S(e.$parent,{$query:o})),i.then(function(o){if(void 0===o)return t.reject();e.addItem(o);var r=e.order.length-1;e.selectorPosition===r&&et(ot,0),lt.newItemFn&&!u||n(angular.noop),Z()}).catch(function(){f("invalid-item"),e.showLoader=!1}),!0):void 0}function x(){var e=w&&Y(d.$modelValue)?it:rt;nt.attr("placeholder",e)}function C(t){return u.getValue(F,t,e.$parent,N)}function j(t){return u.getValue(F,t,e.$parent,H)}function W(t){return u.getValue(F,t,e.$parent,O)}function B(t){return u.getValue(F,t,e.$parent,D)}function G(t){return u.getValue(F,t,e.$parent,A)||""}function z(t){return u.getValue(P,t,e.$parent,T)}function X(e){return e=e instanceof Array?e:e?[e]:[],e.filter(function(e){return e&&(e instanceof Array&&e.length||H||W(e))})}function Y(e){return!!X(e).length}function J(o,i){return v&&ct&&n.cancel(v),v=n(function(){var s=_(e.$parent,{$query:o,$selectedAs:i})||"";return e.selectorPosition="prompt"===lt.newItem?!1:0,o||i||(e.oldQuery=null),(s.$promise&&!s.$resolved||angular.isFunction(s.then))&&(ct=lt.debounce),e.showLoader=!0,t.when(s.$promise||s).then(function(t){if(e.groups={},t&&!i){var n=w?e.output:[],s=vt(u.objToArr(t),o,W,$t(e.$parent),r),l=u.intersection(s,n,C,C,!0),a=z(l);e.groups=tt(a)}return K(),t}).finally(function(){e.showLoader=!1,lt.closeList&&!lt.cleanModel&&n(function(){et(ot,0)})})},ct)}function K(){var t,n,o,r=[],i=0;e.order=[],e.groupPos={};for(n in e.groups)e.groups.hasOwnProperty(n)&&"$"!=n.charAt(0)&&r.push(n);for(R&&r.sort(),t=0;t=y)return void f("limited");var n=e.groups[G(t)]=e.groups[G(t)]||[],o=H?j(t):t;n.splice(n.indexOf(t),1),w?d.$setViewValue(angular.isArray(d.$modelValue)?d.$modelValue.concat(o):[o]):(d.$setViewValue(o),I()),u.groupsIsEmpty(e.groups)&&(e.groups={}),w||lt.closeList||Z({query:!0}),p(),e.oldQuery=e.oldQuery||e.query,e.query="",e.backspaceFocus=!1}},e.removeItem=function(n){c.disabled||w&&0>n||(b=w?d.$modelValue[n]:d.$modelValue,t.when(pt(e.$parent,{$item:b})).then(function(){(w||e.inputHide)&&(w?(d.$modelValue.splice(n,1),d.$setViewValue([].concat(d.$modelValue))):(k(),lt.cleanModel&&d.$setViewValue(void 0)),(w||!e.backspaceFocus)&&(e.query=dt(b,$,W,at,r)||""),w&<.closeList&&Z({query:!0}))}))},e.setSelection=function(t){m||e.selectorPosition===t?m=!1:et(ot,t)},e.keyUp=function(t){switch(t.keyCode){case 8:e.query.length||w&&e.output.length||Z()}},e.keyDown=function(t){var n=0,o=e.order.length-1;switch(t.keyCode){case 38:e.selectorPosition=angular.isNumber(e.selectorPosition)?e.selectorPosition:n,et(ot,e.selectorPosition===n?o:e.selectorPosition-1),m=!0;break;case 40:e.selectorPosition=angular.isNumber(e.selectorPosition)?e.selectorPosition:n-1,et(ot,e.selectorPosition===o?n:e.selectorPosition+1),m=!0,e.query.length||e.isOpen||J(),e.inputHide&&k();break;case 37:case 39:break;case 9:E("tab");break;case 13:E("enter"),t.preventDefault();break;case 32:E("space");break;case 27:w||(I(),lt.cleanModel&&d.$setViewValue(b)),Z();break;case 8:if(!e.query.length){if((!w||ut)&&(e.backspaceFocus=!0),e.backspaceFocus&&e.output&&(!w||e.output.length)){e.removeItem(e.output.length-1),ut&&t.preventDefault();break}e.backspaceFocus=!e.backspaceFocus;break}default:return e.inputHide&&k(),e.backspaceFocus=!1,!1}},e.getSearchLabel=function(t){var n=W(t);return ft(n,e.oldQuery||e.query,t,gt(e.$parent),r)},e.getDropdownLabel=function(t){var n=W(t);return mt(n,e.oldQuery||e.query,t,ht(e.$parent),r)},e.getGroupLabel=function(t,n){return bt(t,e.oldQuery||e.query,n,wt(e.$parent),r)},e.getDisableWhen=B,Z(),r[0].addEventListener("click",L,!0),r.on("focus",V),r.on("blur",q)}}}}]),angular.module("oi.select").filter("oiSelectGroup",["$sce",function(e){return function(t){return e.trustAsHtml(t)}}]).filter("oiSelectCloseIcon",["$sce",function(e){return function(t){var n='×';return e.trustAsHtml(t+n)}}]).filter("oiSelectHighlight",["$sce","oiSelectEscape",function(e,t){return function(n,o){var r;return o.length>0||angular.isNumber(o)?(n=n.toString(),o=t(o.toString()),r=n.replace(new RegExp(o,"gi"),"$&")):r=n,e.trustAsHtml(r)}}]).filter("oiSelectAscSort",["oiSelectEscape",function(e){function t(t,n,o,r){var i,s,l,u,a=[],c=[],d=[],p=[];if(n){for(n=e(String(n)),i=0,l=!1;i
')}]); \ No newline at end of file +angular.module("oi.select",[]),angular.module("oi.select").provider("oiSelect",function(){return{options:{debounce:500,searchFilter:"oiSelectCloseIcon",dropdownFilter:"oiSelectHighlight",listFilter:"oiSelectAscSort",groupFilter:"oiSelectGroup",editItem:!1,newItem:!1,closeList:!0,saveTrigger:"enter tab blur"},version:{full:"0.2.21",major:0,minor:2,dot:21},$get:function(){return{options:this.options,version:this.version}}}}).factory("oiSelectEscape",function(){var e=/[-\/\\^$*+?.()|[\]{}]/g,t="\\$&";return function(n){return String(n).replace(e,t)}}).factory("oiSelectEditItem",function(){return function(e,t,n,o){return o?"":n(e)}}).factory("oiUtils",["$document","$timeout",function(e,t){function n(e,t,n){for(var o=t;o&&o.ownerDocument&&11!==o.nodeType;){if(n){if(o===e)return!1;if(o.className.indexOf(n)>=0)return!0}else if(o===e)return!0;o=o.parentNode}return!1}function o(o,r){function i(e){return e&&"INPUT"!==e.target.nodeName?void 0:(d=!1,c?void(d=!0):void t(function(){o.triggerHandler("blur")}))}function s(){u||(u=!0,t(function(){o.triggerHandler("focus")}))}function l(){c=!0}function a(e){c=!1;var s=e.target,l=n(o[0],s);d&&!l&&i(),l&&"INPUT"!==s.nodeName&&t(function(){r[0].focus()}),!l&&u&&(u=!1)}var u,c,d;return e[0].addEventListener("click",a,!0),o[0].addEventListener("mousedown",l,!0),o[0].addEventListener("blur",i,!0),r.on("focus",s),function(){e[0].removeEventListener("click",a),o[0].removeEventListener("mousedown",l,!0),o[0].removeEventListener("blur",i,!0),r.off("focus",s)}}function r(e,t){var n,o,r,i,l,u;t&&(o=e.offsetHeight,r=a(t,"height","margin"),i=e.scrollTop||0,n=s(t).top-s(e).top+i,l=n,u=n-o+r,n+r>o+i?e.scrollTop=u:i>n&&(e.scrollTop=l))}function i(e,t,n,o,r){function i(e){return parseFloat(r[e])}for(var s=n===(o?"border":"content")?4:"width"===t?1:0,l=0,a=["Top","Right","Bottom","Left"];4>s;s+=2)"margin"===n&&(l+=i(n+a[s])),o?("content"===n&&(l-=i("padding"+a[s])),"margin"!==n&&(l-=i("border"+a[s]+"Width"))):(l+=i("padding"+a[s]),"padding"!==n&&(l+=i("border"+a[s]+"Width")));return l}function s(e){var t,n,o=e.getBoundingClientRect(),r=e&&e.ownerDocument;if(r)return t=r.documentElement,n=l(r),{top:o.top+n.pageYOffset-t.clientTop,left:o.left+n.pageXOffset-t.clientLeft}}function l(e){return null!=e&&e===e.window?e:9===e.nodeType&&e.defaultView}function a(e,t,n){var o=!0,r="width"===t?e.offsetWidth:e.offsetHeight,s=window.getComputedStyle(e,null),l=!1;if(0>=r||null==r){if(r=s[t],(0>r||null==r)&&(r=e.style[t]),f.test(r))return r;r=parseFloat(r)||0}return r+i(e,t,n||(l?"border":"content"),o,s)}function u(e){for(var t in e)if(e.hasOwnProperty(t)&&e[t].length)return!1;return!0}function c(e,t,n,o,r){var i,s,l,a,u,c=r?[].concat(e):[];for(i=0,l=e.length;i=P&&a.contains(r[0],t.target,"select-dropdown")||(e.inputHide&&e.removeItem(0),!e.isOpen||!pt.closeList||"INPUT"===t.target.nodeName&&e.query.length?tt(e.query):(ot({query:pt.editItem&&!gt}),e.$evalAsync()))}function b(){e.isFocused||(e.isFocused=!0,c.disabled||(e.backspaceFocus=!1))}function y(){e.isFocused=!1,q||h(),L("blur")||ot(),e.$evalAsync()}function L(o,r){r||(r=o,o=e.query);var i,s=pt.saveTrigger.split(" ").indexOf(r)+1,l=pt.newItem&&o,a="blur"!==r?e.order[e.selectorPosition]:null;return s&&(l||a)?(e.showLoader=!0,i=t.when(a||x(e.$parent,{$query:o})),i.then(function(o){if(void 0===o)return t.reject();e.addItem(o);var r=e.order.length-1;e.selectorPosition===r&&rt(lt,0),pt.newItemFn&&!a||n(angular.noop),ot()}).catch(function(){f("invalid-item"),e.showLoader=!1}),!0):void 0}function O(){var e=q&&et(d.$modelValue)?ut:at;st.attr("placeholder",e)}function A(t){return a.getValue(v,t,e.$parent,U)}function z(t){return a.getValue(v,t,e.$parent,D)}function X(t){return a.getValue(v,t,e.$parent,_)}function Y(t){return e.isEmptyList||a.getValue(v,t,e.$parent,N)}function J(t){return a.getValue(v,t,e.$parent,T)||""}function K(t){return a.getValue(H,t,e.$parent,M)}function Z(e){return e=e instanceof Array?e:e?[e]:[],e.filter(function(e){return e&&(e instanceof Array&&e.length||D||X(e))})}function et(e){return!!Z(e).length}function tt(o,i){return e.isEmptyList=!1,E&&mt&&n.cancel(E),E=n(function(){var s=Q(e.$parent,{$query:o,$selectedAs:i})||"";return e.selectorPosition="prompt"===pt.newItem?!1:0,o||i||(e.oldQuery=null),(s.$promise&&!s.$resolved||angular.isFunction(s.then))&&(mt=pt.debounce),e.showLoader=!0,t.when(s.$promise||s).then(function(t){if(e.groups={},t&&$){var n=[];angular.forEach(t,function(e,t){if("$"!==t.toString().charAt(0)){var o={};o[S]=t,o[k]=e,n.push(o)}}),t=n}if(t&&!i){var s=q?e.output:[],l=Lt(t,o,X,kt(e.$parent),r),u=a.intersection(l,s,A,A,!0),c=K(u);if(!c.length&&(e.isEmptyList=!0,ct)){var d={};_.assign(d,ct),c=[d[v]]}e.groups=it(c)}return nt(),t}).finally(function(){e.showLoader=!1,pt.closeList&&!pt.cleanModel&&n(function(){rt(lt,0)})})},mt)}function nt(){var t,n,o,r=[],i=0;e.order=[],e.groupPos={};for(n in e.groups)e.groups.hasOwnProperty(n)&&"$"!=n.charAt(0)&&r.push(n);for(G&&r.sort(),t=0;t=P)return void f("limited");var n=e.groups[J(t)]=e.groups[J(t)]||[],o=D?z(t):t;n.splice(n.indexOf(t),1),q?d.$setViewValue(angular.isArray(d.$modelValue)?d.$modelValue.concat(o):[o]):(d.$setViewValue(o),h()),a.groupsIsEmpty(e.groups)&&(e.groups={}),q||pt.closeList||ot({query:!0}),p(),e.oldQuery=e.oldQuery||e.query,e.query="",e.backspaceFocus=!1}},e.removeItem=function(n){c.disabled||q&&0>n||(V=q?d.$modelValue[n]:d.$modelValue,t.when(vt(e.$parent,{$item:V})).then(function(){(q||e.inputHide)&&(q?(d.$modelValue.splice(n,1),d.$setViewValue([].concat(d.$modelValue))):(m(),pt.cleanModel&&d.$setViewValue(void 0)),(q||!e.backspaceFocus)&&(e.query=ht(V,C,X,gt,r)||""),q&&pt.closeList&&ot({query:!0}))}))},e.setSelection=function(t){I||e.selectorPosition===t?I=!1:rt(lt,t)},e.keyUp=function(t){switch(t.keyCode){case 8:e.query.length||q&&e.output.length||ot()}},e.keyDown=function(t){var n=0,o=e.order.length-1;switch(t.keyCode){case 38:e.selectorPosition=angular.isNumber(e.selectorPosition)?e.selectorPosition:n,rt(lt,e.selectorPosition===n?o:e.selectorPosition-1),I=!0;break;case 40:e.selectorPosition=angular.isNumber(e.selectorPosition)?e.selectorPosition:n-1,rt(lt,e.selectorPosition===o?n:e.selectorPosition+1),I=!0,e.query.length||e.isOpen||tt(),e.inputHide&&m();break;case 37:case 39:break;case 9:L("tab");break;case 13:L("enter"),t.preventDefault();break;case 32:L("space");break;case 27:q||(h(),pt.cleanModel&&d.$setViewValue(V)),ot();break;case 8:if(!e.query.length){if((!q||ft)&&(e.backspaceFocus=!0),e.backspaceFocus&&e.output&&(!q||e.output.length)){e.removeItem(e.output.length-1),ft&&t.preventDefault();break}e.backspaceFocus=!e.backspaceFocus;break}default:return e.inputHide&&m(),e.backspaceFocus=!1,!1}},e.getSearchLabel=function(t){var n=X(t);return $t(n,e.oldQuery||e.query,t,wt(e.$parent),r)},e.getDropdownLabel=function(t){var n=X(t);return bt(n,e.oldQuery||e.query,t,yt(e.$parent),r)},e.getGroupLabel=function(t,n){return St(t,e.oldQuery||e.query,n,It(e.$parent),r)},e.getDisableWhen=Y,ot(),r[0].addEventListener("click",w,!0),r.on("focus",b),r.on("blur",y)}}}}]),angular.module("oi.select").filter("oiSelectGroup",["$sce",function(e){return function(t){return e.trustAsHtml(t)}}]).filter("oiSelectCloseIcon",["$sce",function(e){return function(t){var n='×';return e.trustAsHtml(t+n)}}]).filter("oiSelectHighlight",["$sce","oiSelectEscape",function(e,t){return function(n,o){var r;return o.length>0||angular.isNumber(o)?(n=n.toString(),o=t(o),r=n.replace(new RegExp(o,"gi"),"$&")):r=n,e.trustAsHtml(r)}}]).filter("oiSelectAscSort",["oiSelectEscape",function(e){function t(t,n,o,r){var i,s,l,a,u=[],c=[],d=[],p=[];if(n){for(n=e(n).toLocaleLowerCase(),i=0,l=!1;i
')}]); \ No newline at end of file diff --git a/dist/select.css b/dist/select.css index a07ad32..9f502ad 100644 --- a/dist/select.css +++ b/dist/select.css @@ -185,3 +185,6 @@ oi-select.open:not(.multiple) .select-search:after { oi-select.loading:not(.multiple) .select-search:after { border-width: 0; } +oi-select.emptyList .select-dropdown-optgroup-option strong { + font-weight: normal; +} diff --git a/dist/select.js b/dist/select.js index b95dd5b..4dd65f6 100644 --- a/dist/select.js +++ b/dist/select.js @@ -15,10 +15,10 @@ angular.module('oi.select') saveTrigger: 'enter tab blur' }, version: { - full: '0.2.20', + full: '0.2.21', major: 0, minor: 2, - dot: 20 + dot: 21 }, $get: function() { return { @@ -292,18 +292,6 @@ angular.module('oi.select') return true; } - function objToArr(obj) { - var arr = []; - - angular.forEach(obj, function (value, key) { - if (key.toString().charAt(0) !== '$') { - arr.push(value); - } - }); - - return arr; - } - //lodash _.intersection + filter + invert function intersection(xArr, yArr, xFilter, yFilter, invert) { var i, j, n, filteredX, filteredY, out = invert ? [].concat(xArr) : []; @@ -326,7 +314,7 @@ angular.module('oi.select') function getValue(valueName, item, scope, getter) { var locals = {}; - //'name.subname' -> {name: {subname: list}}' + //'name.subname' -> {name: {subname: item}} -> locals' valueName.split('.').reduce(function (previousValue, currentItem, index, arr) { return previousValue[currentItem] = index < arr.length - 1 ? {} : item; }, locals); @@ -339,7 +327,6 @@ angular.module('oi.select') bindFocusBlur: bindFocusBlur, scrollActiveOption: scrollActiveOption, groupsIsEmpty: groupsIsEmpty, - objToArr: objToArr, getValue: getValue, intersection: intersection } @@ -365,11 +352,24 @@ angular.module('oi.select') var selectAsName = / as /.test(match[0]) && match[1], //item.modelValue displayName = match[2] || match[1], //item.label - valueName = match[5] || match[7], //item + valueName = match[5] || match[7], //item (value) + keyName = match[6], //(key) groupByName = match[3] || '', //item.groupName disableWhenName = match[4] || '', //item.disableWhenName trackByName = match[9] || displayName, //item.id - valueMatches = match[8].match(VALUES_REGEXP); //collection + valueMatches = match[8].match(VALUES_REGEXP), //collection + valueTitle = valueName, + keyTitle = keyName; + + if (keyName) { //convert object data sources format to array data sources format + valueName = 'i'; + selectAsName = valueName + '.' + (selectAsName || valueTitle); + trackByName = valueName + '.' + keyName; + displayName = valueName + '.' + displayName; + keyName = valueName + '.' + keyName; + groupByName = groupByName ? valueName + '.' + groupByName: undefined; + disableWhenName = disableWhenName ? valueName + '.' + disableWhenName: undefined; + } var valuesName = valueMatches[1], //collection filteredValuesName = valuesName + (valueMatches[3] || ''), //collection | filter @@ -384,6 +384,7 @@ angular.module('oi.select') trackByFn = $parse(trackByName); var multiplePlaceholderFn = $interpolate(attrs.multiplePlaceholder || ''), + listPlaceholderFn = $interpolate(attrs.listPlaceholder || ''), placeholderFn = $interpolate(attrs.placeholder || ''), optionsFn = $parse(attrs.oiSelectOptions), isOldAngular = angular.version.major <= 1 && angular.version.minor <= 3; @@ -405,6 +406,7 @@ angular.module('oi.select') listElement = angular.element(element[0].querySelector('.select-dropdown')), placeholder = placeholderFn(scope), multiplePlaceholder = multiplePlaceholderFn(scope), + listPlaceholder = listPlaceholderFn(scope), elementOptions = optionsFn(scope.$parent) || {}, options = angular.extend({cleanModel: elementOptions.newItem === 'prompt'}, oiSelect.options, elementOptions), editItem = options.editItem, @@ -572,6 +574,12 @@ angular.module('oi.select') }); }); + scope.$watch('isEmptyList', function(isEmptyList) { + $animate[isEmptyList ? 'addClass' : 'removeClass'](element, 'emptyList', !isOldAngular && { + tempClasses: 'emptyList-animate' + }); + }); + scope.$watch('showLoader', function(isLoading) { $animate[isLoading ? 'addClass' : 'removeClass'](element, 'loading', !isOldAngular && { tempClasses: 'loading-animate' @@ -891,7 +899,7 @@ angular.module('oi.select') } function getDisableWhen(item) { - return oiUtils.getValue(valueName, item, scope.$parent, disableWhenFn); + return scope.isEmptyList || oiUtils.getValue(valueName, item, scope.$parent, disableWhenFn); } function getGroupName(option) { @@ -915,6 +923,8 @@ angular.module('oi.select') } function getMatches(query, selectedAs) { + scope.isEmptyList = false; + if (timeoutPromise && waitTime) { $timeout.cancel(timeoutPromise); //cancel previous timeout } @@ -936,14 +946,44 @@ angular.module('oi.select') return $q.when(values.$promise || values) .then(function(values) { + scope.groups = {}; + if (values && keyName) { + //convert object data sources format to array data sources format + var arr = []; + + angular.forEach(values, function (value, key) { + if (key.toString().charAt(0) !== '$') { + var item = {}; + + item[keyTitle] = key; + item[valueTitle] = value; + arr.push(item); + } + }); + + values = arr; + } + if (values && !selectedAs) { var outputValues = multiple ? scope.output : []; - var filteredList = listFilter(oiUtils.objToArr(values), query, getLabel, listFilterOptionsFn(scope.$parent), element); + var filteredList = listFilter(values, query, getLabel, listFilterOptionsFn(scope.$parent), element); var withoutIntersection = oiUtils.intersection(filteredList, outputValues, trackBy, trackBy, true); var filteredOutput = filter(withoutIntersection); + //add element with placeholder to empty list + if (!filteredOutput.length) { + scope.isEmptyList = true; + + if (listPlaceholder) { + var context = {}; + + displayFn.assign(context, listPlaceholder); + filteredOutput = [context[valueName]] + } + } + scope.groups = group(filteredOutput); } updateGroupPos(); @@ -1058,7 +1098,7 @@ angular.module('oi.select') if (query.length > 0 || angular.isNumber(query)) { label = label.toString(); - query = oiSelectEscape(query.toString()); + query = oiSelectEscape(query); html = label.replace(new RegExp(query, 'gi'), '$&'); } else { @@ -1074,16 +1114,16 @@ angular.module('oi.select') var i, j, isFound, output, output1 = [], output2 = [], output3 = [], output4 = []; if (query) { - query = oiSelectEscape(String(query)); + query = oiSelectEscape(query).toLocaleLowerCase(); for (i = 0, isFound = false; i < input.length; i++) { - isFound = getLabel(input[i]).match(new RegExp(query, "i")); + isFound = getLabel(input[i]).toLocaleLowerCase().match(new RegExp(query)); if (!isFound && options && (options.length || options.fields)) { for (j = 0; j < options.length; j++) { if (isFound) break; - isFound = String(input[i][options[j]]).match(new RegExp(query, "i")); + isFound = String(input[i][options[j]]).toLocaleLowerCase().match(new RegExp(query)); } } @@ -1092,7 +1132,7 @@ angular.module('oi.select') } } for (i = 0; i < output1.length; i++) { - if (getLabel(output1[i]).match(new RegExp('^' + query, "i"))) { + if (getLabel(output1[i]).toLocaleLowerCase().match(new RegExp('^' + query))) { output2.push(output1[i]); } else { output3.push(output1[i]); diff --git a/dist/select.min.css b/dist/select.min.css index 1711cb7..076fbdb 100644 --- a/dist/select.min.css +++ b/dist/select.min.css @@ -1 +1 @@ -oi-select{display:block;position:relative;width:100%}oi-select .select-search{cursor:text;border:1px solid #d9d9d9;background-color:#fff;overflow:hidden!important;-moz-box-sizing:border-box;box-sizing:border-box;border-radius:4px}oi-select .select-search-list{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap;-webkit-box-pack:start;-webkit-justify-content:flex-start;-moz-box-pack:start;-ms-flex-pack:start;justify-content:flex-start;margin:0;padding:2px 4px;list-style:none}oi-select .select-search-list-item{font-size:14px;margin:2px 4px 2px 0;vertical-align:middle;white-space:normal}oi-select .select-search-list-item_selection{cursor:pointer;background:#efefef;border-color:#ebebeb}oi-select .select-search-list-item_selection:hover{border-color:#e5e5e5}oi-select .select-search-list-item_selection.focused,oi-select .select-search-list-item_selection:active{border:1px solid #fff;border-radius:0;box-shadow:inset 0 0 10px 5px #fff}oi-select .select-search-list-item_selection.focused .close{display:none}oi-select .select-search-list-item_selection-remove{padding-left:2px}oi-select .select-search-list-item_loader{float:right;margin-top:6px;width:16px;height:16px;background:url(data:image/gif;base64,R0lGODlhEAAQAPYAAP///wAAANTU1JSUlGFhYUFBQUVFRW9vb6Kiotzc3KSkpCUlJSkpKTExMTc3Nz8/P2tra7q6uh0dHXNzc+zs7O7u7sLCwoqKilFRUV9fX76+vtDQ0Ds7OxcXF4yMjKqqql1dXX19feLi4oaGhg8PD2lpaZycnGdnZ7a2tkdHRwsLC7CwsJaWlhkZGQcHB+jo6PT09Hl5eYSEhPb29oKCgqioqPr6+vz8/MDAwMrKyvj4+NbW1q6urvDw8NLS0uTk5N7e3s7OzsbGxry8vODg4NjY2PLy8tra2nt7e7S0tLKysk1NTVNTU1tbW2NjY0NDQz09PcTExHd3dzMzM+rq6isrK46OjllZWS0tLR8fH6CgoE9PTxMTE4iIiGVlZTU1NcjIyMzMzObm5ri4uH9/f5KSkp6enldXV5CQkEtLS0lJSSMjI6amphEREQ0NDaysrAUFBZqamicnJxUVFTk5OXV1dS8vLwkJCXFxcSEhIVVVVW1tbYCAgAAAAAAAAAAAACH5BAkKAAAAIf4aQ3JlYXRlZCB3aXRoIGFqYXhsb2FkLmluZm8AIf8LTkVUU0NBUEUyLjADAQAAACwAAAAAEAAQAAAHjYAAgoOEhYUbIykthoUIHCQqLoI2OjeFCgsdJSsvgjcwPTaDAgYSHoY2FBSWAAMLE4wAPT89ggQMEbEzQD+CBQ0UsQA7RYIGDhWxN0E+ggcPFrEUQjuCCAYXsT5DRIIJEBgfhjsrFkaDERkgJhswMwk4CDzdhBohJwcxNB4sPAmMIlCwkOGhRo5gwhIGAgAh+QQJCgAAACwAAAAAEAAQAAAHjIAAgoOEhYU7A1dYDFtdG4YAPBhVC1ktXCRfJoVKT1NIERRUSl4qXIRHBFCbhTKFCgYjkII3g0hLUbMAOjaCBEw9ukZGgidNxLMUFYIXTkGzOmLLAEkQCLNUQMEAPxdSGoYvAkS9gjkyNEkJOjovRWAb04NBJlYsWh9KQ2FUkFQ5SWqsEJIAhq6DAAIBACH5BAkKAAAALAAAAAAQABAAAAeJgACCg4SFhQkKE2kGXiwChgBDB0sGDw4NDGpshTheZ2hRFRVDUmsMCIMiZE48hmgtUBuCYxBmkAAQbV2CLBM+t0puaoIySDC3VC4tgh40M7eFNRdH0IRgZUO3NjqDFB9mv4U6Pc+DRzUfQVQ3NzAULxU2hUBDKENCQTtAL9yGRgkbcvggEq9atUAAIfkECQoAAAAsAAAAABAAEAAAB4+AAIKDhIWFPygeEE4hbEeGADkXBycZZ1tqTkqFQSNIbBtGPUJdD088g1QmMjiGZl9MO4I5ViiQAEgMA4JKLAm3EWtXgmxmOrcUElWCb2zHkFQdcoIWPGK3Sm1LgkcoPrdOKiOCRmA4IpBwDUGDL2A5IjCCN/QAcYUURQIJIlQ9MzZu6aAgRgwFGAFvKRwUCAAh+QQJCgAAACwAAAAAEAAQAAAHjIAAgoOEhYUUYW9lHiYRP4YACStxZRc0SBMyFoVEPAoWQDMzAgolEBqDRjg8O4ZKIBNAgkBjG5AAZVtsgj44VLdCanWCYUI3txUPS7xBx5AVDgazAjC3Q3ZeghUJv5B1cgOCNmI/1YUeWSkCgzNUFDODKydzCwqFNkYwOoIubnQIt244MzDC1q2DggIBACH5BAkKAAAALAAAAAAQABAAAAeJgACCg4SFhTBAOSgrEUEUhgBUQThjSh8IcQo+hRUbYEdUNjoiGlZWQYM2QD4vhkI0ZWKCPQmtkG9SEYJURDOQAD4HaLuyv0ZeB4IVj8ZNJ4IwRje/QkxkgjYz05BdamyDN9uFJg9OR4YEK1RUYzFTT0qGdnduXC1Zchg8kEEjaQsMzpTZ8avgoEAAIfkECQoAAAAsAAAAABAAEAAAB4iAAIKDhIWFNz0/Oz47IjCGADpURAkCQUI4USKFNhUvFTMANxU7KElAhDA9OoZHH0oVgjczrJBRZkGyNpCCRCw8vIUzHmXBhDM0HoIGLsCQAjEmgjIqXrxaBxGCGw5cF4Y8TnybglprLXhjFBUWVnpeOIUIT3lydg4PantDz2UZDwYOIEhgzFggACH5BAkKAAAALAAAAAAQABAAAAeLgACCg4SFhjc6RhUVRjaGgzYzRhRiREQ9hSaGOhRFOxSDQQ0uj1RBPjOCIypOjwAJFkSCSyQrrhRDOYILXFSuNkpjggwtvo86H7YAZ1korkRaEYJlC3WuESxBggJLWHGGFhcIxgBvUHQyUT1GQWwhFxuFKyBPakxNXgceYY9HCDEZTlxA8cOVwUGBAAA7) top}oi-select .select-search-list-item_input{-webkit-box-flex:1;-webkit-flex-grow:1;-moz-box-flex:1;-ms-flex-positive:1;flex-grow:1;margin:4px 0 5px 5px}oi-select .select-search-list-item_input input{padding:0;outline:0;border:0;width:100%}oi-select .select-search-list-item_hide{position:fixed;width:0;height:0;margin:0;opacity:0;pointer-events:none;text-indent:-9999em}oi-select .select-dropdown{position:absolute;width:inherit;overflow-y:scroll;max-height:100px;min-width:160px;font-size:14px;background-color:#fff;border-radius:0 0 4px 4px;border:1px solid #66afe9;border-top:0;outline:0;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);background-clip:padding-box;z-index:1000}oi-select .select-dropdown-optgroup{margin:0;padding:0}oi-select .select-dropdown-optgroup-header{font-weight:bolder;padding:3px 10px}oi-select .select-dropdown-optgroup-option{padding:3px 20px}oi-select .select-dropdown-optgroup-option.active:not(.disabled){background-color:#f1f1f1;cursor:pointer}oi-select .select-dropdown-optgroup-option.disabled{color:#aaa}oi-select:not(.multiple) .select-search-list-item_selection{color:#000;width:100%;border-color:#fff;text-align:left}oi-select:not(.multiple) .select-search-list-item_selection:not(:active){background:0 0}oi-select:not(.multiple):not(.cleanMode) .select-search-list-item_selection-remove{display:none}oi-select:not(.multiple):not(.cleanMode) .select-search:after{content:"";position:absolute;display:block;right:10px;width:0;height:0;margin-top:-19px;border-color:#000 transparent transparent;border-style:solid;border-width:5px 5px 0}oi-select[disabled=disabled] .select-search{cursor:not-allowed;background:#eee;border:1px solid #bdbdbd;opacity:.5}oi-select[disabled=disabled] .select-search-list-item_selection{cursor:not-allowed;box-shadow:none;border-color:transparent}oi-select[disabled=disabled] .select-search-list-item_selection-remove{visibility:hidden}oi-select[disabled=disabled] .select-search-list-item_input input:disabled{cursor:not-allowed;background:0 0}oi-select.focused .select-search{border-color:#66afe9;outline:0;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}oi-select.invalid-item .select-dropdown,oi-select.invalid-item .select-search,oi-select.limited .select-dropdown,oi-select.limited .select-search{border-color:#f1bc28;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(230,189,46,.6)}oi-select.open .select-search{border-radius:4px 4px 0 0;border-bottom:1px solid rgba(0,0,0,.075)}oi-select.open:not(.multiple) .select-search:after{border-color:transparent transparent #000;border-width:0 5px 5px}oi-select.loading:not(.multiple) .select-search:after{border-width:0} \ No newline at end of file +oi-select{display:block;position:relative;width:100%}oi-select .select-search{cursor:text;border:1px solid #d9d9d9;background-color:#fff;overflow:hidden!important;-moz-box-sizing:border-box;box-sizing:border-box;border-radius:4px}oi-select .select-search-list{display:-webkit-box;display:-webkit-flex;display:-moz-box;display:-ms-flexbox;display:flex;-webkit-flex-flow:row wrap;-ms-flex-flow:row wrap;flex-flow:row wrap;-webkit-box-pack:start;-webkit-justify-content:flex-start;-moz-box-pack:start;-ms-flex-pack:start;justify-content:flex-start;margin:0;padding:2px 4px;list-style:none}oi-select .select-search-list-item{font-size:14px;margin:2px 4px 2px 0;vertical-align:middle;white-space:normal}oi-select .select-search-list-item_selection{cursor:pointer;background:#efefef;border-color:#ebebeb}oi-select .select-search-list-item_selection:hover{border-color:#e5e5e5}oi-select .select-search-list-item_selection.focused,oi-select .select-search-list-item_selection:active{border:1px solid #fff;border-radius:0;box-shadow:inset 0 0 10px 5px #fff}oi-select .select-search-list-item_selection.focused .close{display:none}oi-select .select-search-list-item_selection-remove{padding-left:2px}oi-select .select-search-list-item_loader{float:right;margin-top:6px;width:16px;height:16px;background:url(data:image/gif;base64,R0lGODlhEAAQAPYAAP///wAAANTU1JSUlGFhYUFBQUVFRW9vb6Kiotzc3KSkpCUlJSkpKTExMTc3Nz8/P2tra7q6uh0dHXNzc+zs7O7u7sLCwoqKilFRUV9fX76+vtDQ0Ds7OxcXF4yMjKqqql1dXX19feLi4oaGhg8PD2lpaZycnGdnZ7a2tkdHRwsLC7CwsJaWlhkZGQcHB+jo6PT09Hl5eYSEhPb29oKCgqioqPr6+vz8/MDAwMrKyvj4+NbW1q6urvDw8NLS0uTk5N7e3s7OzsbGxry8vODg4NjY2PLy8tra2nt7e7S0tLKysk1NTVNTU1tbW2NjY0NDQz09PcTExHd3dzMzM+rq6isrK46OjllZWS0tLR8fH6CgoE9PTxMTE4iIiGVlZTU1NcjIyMzMzObm5ri4uH9/f5KSkp6enldXV5CQkEtLS0lJSSMjI6amphEREQ0NDaysrAUFBZqamicnJxUVFTk5OXV1dS8vLwkJCXFxcSEhIVVVVW1tbYCAgAAAAAAAAAAAACH5BAkKAAAAIf4aQ3JlYXRlZCB3aXRoIGFqYXhsb2FkLmluZm8AIf8LTkVUU0NBUEUyLjADAQAAACwAAAAAEAAQAAAHjYAAgoOEhYUbIykthoUIHCQqLoI2OjeFCgsdJSsvgjcwPTaDAgYSHoY2FBSWAAMLE4wAPT89ggQMEbEzQD+CBQ0UsQA7RYIGDhWxN0E+ggcPFrEUQjuCCAYXsT5DRIIJEBgfhjsrFkaDERkgJhswMwk4CDzdhBohJwcxNB4sPAmMIlCwkOGhRo5gwhIGAgAh+QQJCgAAACwAAAAAEAAQAAAHjIAAgoOEhYU7A1dYDFtdG4YAPBhVC1ktXCRfJoVKT1NIERRUSl4qXIRHBFCbhTKFCgYjkII3g0hLUbMAOjaCBEw9ukZGgidNxLMUFYIXTkGzOmLLAEkQCLNUQMEAPxdSGoYvAkS9gjkyNEkJOjovRWAb04NBJlYsWh9KQ2FUkFQ5SWqsEJIAhq6DAAIBACH5BAkKAAAALAAAAAAQABAAAAeJgACCg4SFhQkKE2kGXiwChgBDB0sGDw4NDGpshTheZ2hRFRVDUmsMCIMiZE48hmgtUBuCYxBmkAAQbV2CLBM+t0puaoIySDC3VC4tgh40M7eFNRdH0IRgZUO3NjqDFB9mv4U6Pc+DRzUfQVQ3NzAULxU2hUBDKENCQTtAL9yGRgkbcvggEq9atUAAIfkECQoAAAAsAAAAABAAEAAAB4+AAIKDhIWFPygeEE4hbEeGADkXBycZZ1tqTkqFQSNIbBtGPUJdD088g1QmMjiGZl9MO4I5ViiQAEgMA4JKLAm3EWtXgmxmOrcUElWCb2zHkFQdcoIWPGK3Sm1LgkcoPrdOKiOCRmA4IpBwDUGDL2A5IjCCN/QAcYUURQIJIlQ9MzZu6aAgRgwFGAFvKRwUCAAh+QQJCgAAACwAAAAAEAAQAAAHjIAAgoOEhYUUYW9lHiYRP4YACStxZRc0SBMyFoVEPAoWQDMzAgolEBqDRjg8O4ZKIBNAgkBjG5AAZVtsgj44VLdCanWCYUI3txUPS7xBx5AVDgazAjC3Q3ZeghUJv5B1cgOCNmI/1YUeWSkCgzNUFDODKydzCwqFNkYwOoIubnQIt244MzDC1q2DggIBACH5BAkKAAAALAAAAAAQABAAAAeJgACCg4SFhTBAOSgrEUEUhgBUQThjSh8IcQo+hRUbYEdUNjoiGlZWQYM2QD4vhkI0ZWKCPQmtkG9SEYJURDOQAD4HaLuyv0ZeB4IVj8ZNJ4IwRje/QkxkgjYz05BdamyDN9uFJg9OR4YEK1RUYzFTT0qGdnduXC1Zchg8kEEjaQsMzpTZ8avgoEAAIfkECQoAAAAsAAAAABAAEAAAB4iAAIKDhIWFNz0/Oz47IjCGADpURAkCQUI4USKFNhUvFTMANxU7KElAhDA9OoZHH0oVgjczrJBRZkGyNpCCRCw8vIUzHmXBhDM0HoIGLsCQAjEmgjIqXrxaBxGCGw5cF4Y8TnybglprLXhjFBUWVnpeOIUIT3lydg4PantDz2UZDwYOIEhgzFggACH5BAkKAAAALAAAAAAQABAAAAeLgACCg4SFhjc6RhUVRjaGgzYzRhRiREQ9hSaGOhRFOxSDQQ0uj1RBPjOCIypOjwAJFkSCSyQrrhRDOYILXFSuNkpjggwtvo86H7YAZ1korkRaEYJlC3WuESxBggJLWHGGFhcIxgBvUHQyUT1GQWwhFxuFKyBPakxNXgceYY9HCDEZTlxA8cOVwUGBAAA7) top}oi-select .select-search-list-item_input{-webkit-box-flex:1;-webkit-flex-grow:1;-moz-box-flex:1;-ms-flex-positive:1;flex-grow:1;margin:4px 0 5px 5px}oi-select .select-search-list-item_input input{padding:0;outline:0;border:0;width:100%}oi-select .select-search-list-item_hide{position:fixed;width:0;height:0;margin:0;opacity:0;pointer-events:none;text-indent:-9999em}oi-select .select-dropdown{position:absolute;width:inherit;overflow-y:scroll;max-height:100px;min-width:160px;font-size:14px;background-color:#fff;border-radius:0 0 4px 4px;border:1px solid #66afe9;border-top:0;outline:0;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6);background-clip:padding-box;z-index:1000}oi-select .select-dropdown-optgroup{margin:0;padding:0}oi-select .select-dropdown-optgroup-header{font-weight:bolder;padding:3px 10px}oi-select .select-dropdown-optgroup-option{padding:3px 20px}oi-select .select-dropdown-optgroup-option.active:not(.disabled){background-color:#f1f1f1;cursor:pointer}oi-select .select-dropdown-optgroup-option.disabled{color:#aaa}oi-select:not(.multiple) .select-search-list-item_selection{color:#000;width:100%;border-color:#fff;text-align:left}oi-select:not(.multiple) .select-search-list-item_selection:not(:active){background:0 0}oi-select:not(.multiple):not(.cleanMode) .select-search-list-item_selection-remove{display:none}oi-select:not(.multiple):not(.cleanMode) .select-search:after{content:"";position:absolute;display:block;right:10px;width:0;height:0;margin-top:-19px;border-color:#000 transparent transparent;border-style:solid;border-width:5px 5px 0}oi-select[disabled=disabled] .select-search{cursor:not-allowed;background:#eee;border:1px solid #bdbdbd;opacity:.5}oi-select[disabled=disabled] .select-search-list-item_selection{cursor:not-allowed;box-shadow:none;border-color:transparent}oi-select[disabled=disabled] .select-search-list-item_selection-remove{visibility:hidden}oi-select[disabled=disabled] .select-search-list-item_input input:disabled{cursor:not-allowed;background:0 0}oi-select.focused .select-search{border-color:#66afe9;outline:0;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}oi-select.invalid-item .select-dropdown,oi-select.invalid-item .select-search,oi-select.limited .select-dropdown,oi-select.limited .select-search{border-color:#f1bc28;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(230,189,46,.6)}oi-select.open .select-search{border-radius:4px 4px 0 0;border-bottom:1px solid rgba(0,0,0,.075)}oi-select.open:not(.multiple) .select-search:after{border-color:transparent transparent #000;border-width:0 5px 5px}oi-select.loading:not(.multiple) .select-search:after{border-width:0}oi-select.emptyList .select-dropdown-optgroup-option strong{font-weight:400} \ No newline at end of file diff --git a/dist/select.min.js b/dist/select.min.js index 3b92423..bae23c6 100644 --- a/dist/select.min.js +++ b/dist/select.min.js @@ -1 +1 @@ -angular.module("oi.select",[]),angular.module("oi.select").provider("oiSelect",function(){return{options:{debounce:500,searchFilter:"oiSelectCloseIcon",dropdownFilter:"oiSelectHighlight",listFilter:"oiSelectAscSort",groupFilter:"oiSelectGroup",editItem:!1,newItem:!1,closeList:!0,saveTrigger:"enter tab blur"},version:{full:"0.2.20",major:0,minor:2,dot:20},$get:function(){return{options:this.options,version:this.version}}}}).factory("oiSelectEscape",function(){var e=/[-\/\\^$*+?.()|[\]{}]/g,t="\\$&";return function(n){return String(n).replace(e,t)}}).factory("oiSelectEditItem",function(){return function(e,t,n,r){return r?"":n(e)}}).factory("oiUtils",["$document","$timeout",function(e,t){function n(e,t,n){for(var r=t;r&&r.ownerDocument&&11!==r.nodeType;){if(n){if(r===e)return!1;if(r.className.indexOf(n)>=0)return!0}else if(r===e)return!0;r=r.parentNode}return!1}function r(r,o){function i(e){return e&&"INPUT"!==e.target.nodeName?void 0:(d=!1,c?void(d=!0):void t(function(){r.triggerHandler("blur")}))}function u(){a||(a=!0,t(function(){r.triggerHandler("focus")}))}function l(){c=!0}function s(e){c=!1;var u=e.target,l=n(r[0],u);d&&!l&&i(),l&&"INPUT"!==u.nodeName&&t(function(){o[0].focus()}),!l&&a&&(a=!1)}var a,c,d;return e[0].addEventListener("click",s,!0),r[0].addEventListener("mousedown",l,!0),r[0].addEventListener("blur",i,!0),o.on("focus",u),function(){e[0].removeEventListener("click",s),r[0].removeEventListener("mousedown",l,!0),r[0].removeEventListener("blur",i,!0),o.off("focus",u)}}function o(e,t){var n,r,o,i,l,a;t&&(r=e.offsetHeight,o=s(t,"height","margin"),i=e.scrollTop||0,n=u(t).top-u(e).top+i,l=n,a=n-r+o,n+o>r+i?e.scrollTop=a:i>n&&(e.scrollTop=l))}function i(e,t,n,r,o){function i(e){return parseFloat(o[e])}for(var u=n===(r?"border":"content")?4:"width"===t?1:0,l=0,s=["Top","Right","Bottom","Left"];4>u;u+=2)"margin"===n&&(l+=i(n+s[u])),r?("content"===n&&(l-=i("padding"+s[u])),"margin"!==n&&(l-=i("border"+s[u]+"Width"))):(l+=i("padding"+s[u]),"padding"!==n&&(l+=i("border"+s[u]+"Width")));return l}function u(e){var t,n,r=e.getBoundingClientRect(),o=e&&e.ownerDocument;if(o)return t=o.documentElement,n=l(o),{top:r.top+n.pageYOffset-t.clientTop,left:r.left+n.pageXOffset-t.clientLeft}}function l(e){return null!=e&&e===e.window?e:9===e.nodeType&&e.defaultView}function s(e,t,n){var r=!0,o="width"===t?e.offsetWidth:e.offsetHeight,u=window.getComputedStyle(e,null),l=!1;if(0>=o||null==o){if(o=u[t],(0>o||null==o)&&(o=e.style[t]),g.test(o))return o;o=parseFloat(o)||0}return o+i(e,t,n||(l?"border":"content"),r,u)}function a(e){for(var t in e)if(e.hasOwnProperty(t)&&e[t].length)return!1;return!0}function c(e){var t=[];return angular.forEach(e,function(e,n){"$"!==n.toString().charAt(0)&&t.push(e)}),t}function d(e,t,n,r,o){var i,u,l,s,a,c=o?[].concat(e):[];for(i=0,l=e.length;i=y&&s.contains(o[0],t.target,"select-dropdown")||(e.inputHide&&e.removeItem(0),!e.isOpen||!lt.closeList||"INPUT"===t.target.nodeName&&e.query.length?J(e.query):(Z({query:lt.editItem&&!at}),e.$evalAsync()))}function E(){e.isFocused||(e.isFocused=!0,c.disabled||(e.backspaceFocus=!1))}function q(){e.isFocused=!1,b||I(),L("blur")||Z(),e.$evalAsync()}function L(r,o){o||(o=r,r=e.query);var i,u=lt.saveTrigger.split(" ").indexOf(o)+1,l=lt.newItem&&r,s="blur"!==o?e.order[e.selectorPosition]:null;return u&&(l||s)?(e.showLoader=!0,i=t.when(s||S(e.$parent,{$query:r})),i.then(function(r){if(void 0===r)return t.reject();e.addItem(r);var o=e.order.length-1;e.selectorPosition===o&&et(rt,0),lt.newItemFn&&!s||n(angular.noop),Z()}).catch(function(){p("invalid-item"),e.showLoader=!1}),!0):void 0}function C(){var e=b&&Y(d.$modelValue)?it:ot;nt.attr("placeholder",e)}function x(t){return s.getValue(k,t,e.$parent,_)}function j(t){return s.getValue(k,t,e.$parent,A)}function B(t){return s.getValue(k,t,e.$parent,H)}function W(t){return s.getValue(k,t,e.$parent,T)}function G(t){return s.getValue(k,t,e.$parent,O)||""}function z(t){return s.getValue(P,t,e.$parent,N)}function X(e){return e=e instanceof Array?e:e?[e]:[],e.filter(function(e){return e&&(e instanceof Array&&e.length||A||B(e))})}function Y(e){return!!X(e).length}function J(r,i){return v&&ct&&n.cancel(v),v=n(function(){var u=D(e.$parent,{$query:r,$selectedAs:i})||"";return e.selectorPosition="prompt"===lt.newItem?!1:0,r||i||(e.oldQuery=null),(u.$promise&&!u.$resolved||angular.isFunction(u.then))&&(ct=lt.debounce),e.showLoader=!0,t.when(u.$promise||u).then(function(t){if(e.groups={},t&&!i){var n=b?e.output:[],u=vt(s.objToArr(t),r,B,$t(e.$parent),o),l=s.intersection(u,n,x,x,!0),a=z(l);e.groups=tt(a)}return K(),t}).finally(function(){e.showLoader=!1,lt.closeList&&!lt.cleanModel&&n(function(){et(rt,0)})})},ct)}function K(){var t,n,r,o=[],i=0;e.order=[],e.groupPos={};for(n in e.groups)e.groups.hasOwnProperty(n)&&"$"!=n.charAt(0)&&o.push(n);for(U&&o.sort(),t=0;t=y)return void p("limited");var n=e.groups[G(t)]=e.groups[G(t)]||[],r=A?j(t):t;n.splice(n.indexOf(t),1),b?d.$setViewValue(angular.isArray(d.$modelValue)?d.$modelValue.concat(r):[r]):(d.$setViewValue(r),I()),s.groupsIsEmpty(e.groups)&&(e.groups={}),b||lt.closeList||Z({query:!0}),f(),e.oldQuery=e.oldQuery||e.query,e.query="",e.backspaceFocus=!1}},e.removeItem=function(n){c.disabled||b&&0>n||(w=b?d.$modelValue[n]:d.$modelValue,t.when(ft(e.$parent,{$item:w})).then(function(){(b||e.inputHide)&&(b?(d.$modelValue.splice(n,1),d.$setViewValue([].concat(d.$modelValue))):(F(),lt.cleanModel&&d.$setViewValue(void 0)),(b||!e.backspaceFocus)&&(e.query=dt(w,$,B,at,o)||""),b&<.closeList&&Z({query:!0}))}))},e.setSelection=function(t){m||e.selectorPosition===t?m=!1:et(rt,t)},e.keyUp=function(t){switch(t.keyCode){case 8:e.query.length||b&&e.output.length||Z()}},e.keyDown=function(t){var n=0,r=e.order.length-1;switch(t.keyCode){case 38:e.selectorPosition=angular.isNumber(e.selectorPosition)?e.selectorPosition:n,et(rt,e.selectorPosition===n?r:e.selectorPosition-1),m=!0;break;case 40:e.selectorPosition=angular.isNumber(e.selectorPosition)?e.selectorPosition:n-1,et(rt,e.selectorPosition===r?n:e.selectorPosition+1),m=!0,e.query.length||e.isOpen||J(),e.inputHide&&F();break;case 37:case 39:break;case 9:L("tab");break;case 13:L("enter"),t.preventDefault();break;case 32:L("space");break;case 27:b||(I(),lt.cleanModel&&d.$setViewValue(w)),Z();break;case 8:if(!e.query.length){if((!b||st)&&(e.backspaceFocus=!0),e.backspaceFocus&&e.output&&(!b||e.output.length)){e.removeItem(e.output.length-1),st&&t.preventDefault();break}e.backspaceFocus=!e.backspaceFocus;break}default:return e.inputHide&&F(),e.backspaceFocus=!1,!1}},e.getSearchLabel=function(t){var n=B(t);return pt(n,e.oldQuery||e.query,t,gt(e.$parent),o)},e.getDropdownLabel=function(t){var n=B(t);return mt(n,e.oldQuery||e.query,t,ht(e.$parent),o)},e.getGroupLabel=function(t,n){return wt(t,e.oldQuery||e.query,n,bt(e.$parent),o)},e.getDisableWhen=W,Z(),o[0].addEventListener("click",V,!0),o.on("focus",E),o.on("blur",q)}}}}]),angular.module("oi.select").filter("oiSelectGroup",["$sce",function(e){return function(t){return e.trustAsHtml(t)}}]).filter("oiSelectCloseIcon",["$sce",function(e){return function(t){var n='×';return e.trustAsHtml(t+n)}}]).filter("oiSelectHighlight",["$sce","oiSelectEscape",function(e,t){return function(n,r){var o;return r.length>0||angular.isNumber(r)?(n=n.toString(),r=t(r.toString()),o=n.replace(new RegExp(r,"gi"),"$&")):o=n,e.trustAsHtml(o)}}]).filter("oiSelectAscSort",["oiSelectEscape",function(e){function t(t,n,r,o){var i,u,l,s,a=[],c=[],d=[],f=[];if(n){for(n=e(String(n)),i=0,l=!1;i=0)return!0}else if(r===e)return!0;r=r.parentNode}return!1}function r(r,o){function i(e){return e&&"INPUT"!==e.target.nodeName?void 0:(d=!1,c?void(d=!0):void t(function(){r.triggerHandler("blur")}))}function s(){a||(a=!0,t(function(){r.triggerHandler("focus")}))}function u(){c=!0}function l(e){c=!1;var s=e.target,u=n(r[0],s);d&&!u&&i(),u&&"INPUT"!==s.nodeName&&t(function(){o[0].focus()}),!u&&a&&(a=!1)}var a,c,d;return e[0].addEventListener("click",l,!0),r[0].addEventListener("mousedown",u,!0),r[0].addEventListener("blur",i,!0),o.on("focus",s),function(){e[0].removeEventListener("click",l),r[0].removeEventListener("mousedown",u,!0),r[0].removeEventListener("blur",i,!0),o.off("focus",s)}}function o(e,t){var n,r,o,i,u,a;t&&(r=e.offsetHeight,o=l(t,"height","margin"),i=e.scrollTop||0,n=s(t).top-s(e).top+i,u=n,a=n-r+o,n+o>r+i?e.scrollTop=a:i>n&&(e.scrollTop=u))}function i(e,t,n,r,o){function i(e){return parseFloat(o[e])}for(var s=n===(r?"border":"content")?4:"width"===t?1:0,u=0,l=["Top","Right","Bottom","Left"];4>s;s+=2)"margin"===n&&(u+=i(n+l[s])),r?("content"===n&&(u-=i("padding"+l[s])),"margin"!==n&&(u-=i("border"+l[s]+"Width"))):(u+=i("padding"+l[s]),"padding"!==n&&(u+=i("border"+l[s]+"Width")));return u}function s(e){var t,n,r=e.getBoundingClientRect(),o=e&&e.ownerDocument;if(o)return t=o.documentElement,n=u(o),{top:r.top+n.pageYOffset-t.clientTop,left:r.left+n.pageXOffset-t.clientLeft}}function u(e){return null!=e&&e===e.window?e:9===e.nodeType&&e.defaultView}function l(e,t,n){var r=!0,o="width"===t?e.offsetWidth:e.offsetHeight,s=window.getComputedStyle(e,null),u=!1;if(0>=o||null==o){if(o=s[t],(0>o||null==o)&&(o=e.style[t]),p.test(o))return o;o=parseFloat(o)||0}return o+i(e,t,n||(u?"border":"content"),r,s)}function a(e){for(var t in e)if(e.hasOwnProperty(t)&&e[t].length)return!1;return!0}function c(e,t,n,r,o){var i,s,u,l,a,c=o?[].concat(e):[];for(i=0,u=e.length;i=P&&l.contains(o[0],t.target,"select-dropdown")||(e.inputHide&&e.removeItem(0),!e.isOpen||!ft.closeList||"INPUT"===t.target.nodeName&&e.query.length?tt(e.query):(rt({query:ft.editItem&&!gt}),e.$evalAsync()))}function y(){e.isFocused||(e.isFocused=!0,c.disabled||(e.backspaceFocus=!1))}function b(){e.isFocused=!1,q||h(),L("blur")||rt(),e.$evalAsync()}function L(r,o){o||(o=r,r=e.query);var i,s=ft.saveTrigger.split(" ").indexOf(o)+1,u=ft.newItem&&r,l="blur"!==o?e.order[e.selectorPosition]:null;return s&&(u||l)?(e.showLoader=!0,i=t.when(l||x(e.$parent,{$query:r})),i.then(function(r){if(void 0===r)return t.reject();e.addItem(r);var o=e.order.length-1;e.selectorPosition===o&&ot(ut,0),ft.newItemFn&&!l||n(angular.noop),rt()}).catch(function(){p("invalid-item"),e.showLoader=!1}),!0):void 0}function O(){var e=q&&et(d.$modelValue)?at:lt;st.attr("placeholder",e)}function A(t){return l.getValue(v,t,e.$parent,R)}function z(t){return l.getValue(v,t,e.$parent,T)}function X(t){return l.getValue(v,t,e.$parent,N)}function Y(t){return e.isEmptyList||l.getValue(v,t,e.$parent,_)}function J(t){return l.getValue(v,t,e.$parent,D)||""}function K(t){return l.getValue(H,t,e.$parent,M)}function Z(e){return e=e instanceof Array?e:e?[e]:[],e.filter(function(e){return e&&(e instanceof Array&&e.length||T||X(e))})}function et(e){return!!Z(e).length}function tt(r,i){return e.isEmptyList=!1,k&&mt&&n.cancel(k),k=n(function(){var s=Q(e.$parent,{$query:r,$selectedAs:i})||"";return e.selectorPosition="prompt"===ft.newItem?!1:0,r||i||(e.oldQuery=null),(s.$promise&&!s.$resolved||angular.isFunction(s.then))&&(mt=ft.debounce),e.showLoader=!0,t.when(s.$promise||s).then(function(t){if(e.groups={},t&&$){var n=[];angular.forEach(t,function(e,t){if("$"!==t.toString().charAt(0)){var r={};r[E]=t,r[S]=e,n.push(r)}}),t=n}if(t&&!i){var s=q?e.output:[],u=Lt(t,r,X,St(e.$parent),o),a=l.intersection(u,s,A,A,!0),c=K(a);if(!c.length&&(e.isEmptyList=!0,ct)){var d={};N.assign(d,ct),c=[d[v]]}e.groups=it(c)}return nt(),t}).finally(function(){e.showLoader=!1,ft.closeList&&!ft.cleanModel&&n(function(){ot(ut,0)})})},mt)}function nt(){var t,n,r,o=[],i=0;e.order=[],e.groupPos={};for(n in e.groups)e.groups.hasOwnProperty(n)&&"$"!=n.charAt(0)&&o.push(n);for(G&&o.sort(),t=0;t=P)return void p("limited");var n=e.groups[J(t)]=e.groups[J(t)]||[],r=T?z(t):t;n.splice(n.indexOf(t),1),q?d.$setViewValue(angular.isArray(d.$modelValue)?d.$modelValue.concat(r):[r]):(d.$setViewValue(r),h()),l.groupsIsEmpty(e.groups)&&(e.groups={}),q||ft.closeList||rt({query:!0}),f(),e.oldQuery=e.oldQuery||e.query,e.query="",e.backspaceFocus=!1}},e.removeItem=function(n){c.disabled||q&&0>n||(V=q?d.$modelValue[n]:d.$modelValue,t.when(vt(e.$parent,{$item:V})).then(function(){(q||e.inputHide)&&(q?(d.$modelValue.splice(n,1),d.$setViewValue([].concat(d.$modelValue))):(m(),ft.cleanModel&&d.$setViewValue(void 0)),(q||!e.backspaceFocus)&&(e.query=ht(V,C,X,gt,o)||""),q&&ft.closeList&&rt({query:!0}))}))},e.setSelection=function(t){F||e.selectorPosition===t?F=!1:ot(ut,t)},e.keyUp=function(t){switch(t.keyCode){case 8:e.query.length||q&&e.output.length||rt()}},e.keyDown=function(t){var n=0,r=e.order.length-1;switch(t.keyCode){case 38:e.selectorPosition=angular.isNumber(e.selectorPosition)?e.selectorPosition:n,ot(ut,e.selectorPosition===n?r:e.selectorPosition-1),F=!0;break;case 40:e.selectorPosition=angular.isNumber(e.selectorPosition)?e.selectorPosition:n-1,ot(ut,e.selectorPosition===r?n:e.selectorPosition+1),F=!0,e.query.length||e.isOpen||tt(),e.inputHide&&m();break;case 37:case 39:break;case 9:L("tab");break;case 13:L("enter"),t.preventDefault();break;case 32:L("space");break;case 27:q||(h(),ft.cleanModel&&d.$setViewValue(V)),rt();break;case 8:if(!e.query.length){if((!q||pt)&&(e.backspaceFocus=!0),e.backspaceFocus&&e.output&&(!q||e.output.length)){e.removeItem(e.output.length-1),pt&&t.preventDefault();break}e.backspaceFocus=!e.backspaceFocus;break}default:return e.inputHide&&m(),e.backspaceFocus=!1,!1}},e.getSearchLabel=function(t){var n=X(t);return $t(n,e.oldQuery||e.query,t,wt(e.$parent),o)},e.getDropdownLabel=function(t){var n=X(t);return yt(n,e.oldQuery||e.query,t,bt(e.$parent),o)},e.getGroupLabel=function(t,n){return Et(t,e.oldQuery||e.query,n,Ft(e.$parent),o)},e.getDisableWhen=Y,rt(),o[0].addEventListener("click",w,!0),o.on("focus",y),o.on("blur",b)}}}}]),angular.module("oi.select").filter("oiSelectGroup",["$sce",function(e){return function(t){return e.trustAsHtml(t)}}]).filter("oiSelectCloseIcon",["$sce",function(e){return function(t){var n='×';return e.trustAsHtml(t+n)}}]).filter("oiSelectHighlight",["$sce","oiSelectEscape",function(e,t){return function(n,r){var o;return r.length>0||angular.isNumber(r)?(n=n.toString(),r=t(r),o=n.replace(new RegExp(r,"gi"),"$&")):o=n,e.trustAsHtml(o)}}]).filter("oiSelectAscSort",["oiSelectEscape",function(e){function t(t,n,r,o){var i,s,u,l,a=[],c=[],d=[],f=[];if(n){for(n=e(n).toLocaleLowerCase(),i=0,u=!1;iMultiple

Use multiple-placeholder if you need to set placeholder if model not empty

+

Use list-placeholder if you need to set label for empty list

Multiple ng-model="bundle3" multiple multiple-placeholder="add" + list-placeholder="not found" placeholder="Select" >
@@ -75,6 +77,7 @@

Multiple

ng-model="bundle3" multiple multiple-placeholder="add" +list-placeholder="not found"
 {{bundle3}}
diff --git a/src/directives.js b/src/directives.js
index 001a0a4..65cdcd3 100644
--- a/src/directives.js
+++ b/src/directives.js
@@ -51,6 +51,7 @@ angular.module('oi.select')
                 trackByFn             = $parse(trackByName);
 
             var multiplePlaceholderFn = $interpolate(attrs.multiplePlaceholder || ''),
+                listPlaceholderFn     = $interpolate(attrs.listPlaceholder || ''),
                 placeholderFn         = $interpolate(attrs.placeholder || ''),
                 optionsFn             = $parse(attrs.oiSelectOptions),
                 isOldAngular          = angular.version.major <= 1 && angular.version.minor <= 3;
@@ -72,6 +73,7 @@ angular.module('oi.select')
                     listElement         = angular.element(element[0].querySelector('.select-dropdown')),
                     placeholder         = placeholderFn(scope),
                     multiplePlaceholder = multiplePlaceholderFn(scope),
+                    listPlaceholder     = listPlaceholderFn(scope),
                     elementOptions      = optionsFn(scope.$parent) || {},
                     options             = angular.extend({cleanModel: elementOptions.newItem === 'prompt'}, oiSelect.options, elementOptions),
                     editItem            = options.editItem,
@@ -239,6 +241,12 @@ angular.module('oi.select')
                     });
                 });
 
+                scope.$watch('isEmptyList', function(isEmptyList) {
+                    $animate[isEmptyList ? 'addClass' : 'removeClass'](element, 'emptyList', !isOldAngular && {
+                        tempClasses: 'emptyList-animate'
+                    });
+                });
+
                 scope.$watch('showLoader', function(isLoading) {
                     $animate[isLoading ? 'addClass' : 'removeClass'](element, 'loading', !isOldAngular && {
                         tempClasses: 'loading-animate'
@@ -558,7 +566,7 @@ angular.module('oi.select')
                 }
 
                 function getDisableWhen(item) {
-                    return oiUtils.getValue(valueName, item, scope.$parent, disableWhenFn);
+                    return scope.isEmptyList || oiUtils.getValue(valueName, item, scope.$parent, disableWhenFn);
                 }
 
                 function getGroupName(option) {
@@ -582,6 +590,8 @@ angular.module('oi.select')
                 }
 
                 function getMatches(query, selectedAs) {
+                    scope.isEmptyList = false;
+
                     if (timeoutPromise && waitTime) {
                         $timeout.cancel(timeoutPromise); //cancel previous timeout
                     }
@@ -629,6 +639,18 @@ angular.module('oi.select')
                                     var withoutIntersection = oiUtils.intersection(filteredList, outputValues, trackBy, trackBy, true);
                                     var filteredOutput = filter(withoutIntersection);
 
+                                    //add element with placeholder to empty list
+                                    if (!filteredOutput.length) {
+                                        scope.isEmptyList = true;
+
+                                        if (listPlaceholder) {
+                                            var context = {};
+
+                                            displayFn.assign(context, listPlaceholder);
+                                            filteredOutput = [context[valueName]]
+                                        }
+                                    }
+
                                     scope.groups = group(filteredOutput);
                                 }
                                 updateGroupPos();
diff --git a/src/style.styl b/src/style.styl
index 7e554f8..2b2f43f 100644
--- a/src/style.styl
+++ b/src/style.styl
@@ -189,4 +189,9 @@ oi-select
 
   &.loading:not(.multiple)
     .select-search:after
-      border-width 0
\ No newline at end of file
+      border-width 0
+
+  &.emptyList
+    .select-dropdown-optgroup-option
+      strong
+        font-weight normal
\ No newline at end of file

From 9507de0f17cd44ae9949a11847a0f488d484404d Mon Sep 17 00:00:00 2001
From: tamtakoe 
Date: Tue, 10 May 2016 20:38:36 +0300
Subject: [PATCH 05/11] add minlength

---
 CHANGELOG.md                           |  4 +++-
 README.md                              |  1 +
 dist/select-tpls.js                    | 10 ++++++++--
 dist/select-tpls.min.js                |  2 +-
 dist/select.js                         | 10 ++++++++--
 dist/select.min.js                     |  2 +-
 docs/examples/validation/template.html |  8 +++++---
 src/directives.js                      | 11 ++++++++---
 src/services.js                        |  3 ++-
 9 files changed, 37 insertions(+), 14 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index d281b60..c72bf22 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,7 +2,9 @@
 
 #### Bug Fixes
 
-- **oi-select:** `select as`  works correct with object data source
+- **oi-select:**
+    - `select as` works correct with object data source
+    - `minlength` is minimum length of query for searching
 
 - **list-placeholder:** placeholder for dropdown list if no items found
 
diff --git a/README.md b/README.md
index d9beb69..329543d 100644
--- a/README.md
+++ b/README.md
@@ -107,6 +107,7 @@ Use `oi-select` directive:
   * `newItemFn` — function which get query and return new item object or promise. F.e. `'addItem($query)'`
   * `removeItemFn` — function which get removed item model and return any value or promise. If promise was rejected, item wouldn't removed. F.e. `'removeItem($item)'`
   * `maxlength` — maximum number of characters allowed in the input
+  * `minlength` — minimum number of characters for searching
 
 ### oiSelect service
  * `options` — default options which we can override in `oiSelectProvider.options`
diff --git a/dist/select-tpls.js b/dist/select-tpls.js
index f126fb3..ea67259 100644
--- a/dist/select-tpls.js
+++ b/dist/select-tpls.js
@@ -12,7 +12,8 @@ angular.module('oi.select')
             editItem:       false,
             newItem:        false,
             closeList:      true,
-            saveTrigger:    'enter tab blur'
+            saveTrigger:    'enter tab blur',
+            minlength:      0
         },
         version: {
             full: '0.2.21',
@@ -533,10 +534,12 @@ angular.module('oi.select')
                 });
 
                 scope.$watch('query', function(inputValue, oldValue) {
-                    if (saveOn(inputValue.slice(0, -1), inputValue.slice(-1))) {
+                    if (saveOn(inputValue.slice(0, -1), inputValue.slice(-1)) || //terminated symbol
+                        String(inputValue).length < options.minlength) { //length less then minlength
                         return;
                     }
 
+
                     //We don't get matches if nothing added into matches list
                     if (inputValue !== oldValue && (!scope.oldQuery || inputValue) && !matchesWereReset) {
                         listElement[0].scrollTop = 0;
@@ -799,6 +802,9 @@ angular.module('oi.select')
                 }
 
                 function click(event) {
+                    //query length less then minlength
+                    if (scope.query.length < options.minlength) return;
+                    
                     //option is disabled
                     if (oiUtils.contains(element[0], event.target, 'disabled')) return;
 
diff --git a/dist/select-tpls.min.js b/dist/select-tpls.min.js
index 2c6c1ee..a093d9a 100644
--- a/dist/select-tpls.min.js
+++ b/dist/select-tpls.min.js
@@ -1 +1 @@
-angular.module("oi.select",[]),angular.module("oi.select").provider("oiSelect",function(){return{options:{debounce:500,searchFilter:"oiSelectCloseIcon",dropdownFilter:"oiSelectHighlight",listFilter:"oiSelectAscSort",groupFilter:"oiSelectGroup",editItem:!1,newItem:!1,closeList:!0,saveTrigger:"enter tab blur"},version:{full:"0.2.21",major:0,minor:2,dot:21},$get:function(){return{options:this.options,version:this.version}}}}).factory("oiSelectEscape",function(){var e=/[-\/\\^$*+?.()|[\]{}]/g,t="\\$&";return function(n){return String(n).replace(e,t)}}).factory("oiSelectEditItem",function(){return function(e,t,n,o){return o?"":n(e)}}).factory("oiUtils",["$document","$timeout",function(e,t){function n(e,t,n){for(var o=t;o&&o.ownerDocument&&11!==o.nodeType;){if(n){if(o===e)return!1;if(o.className.indexOf(n)>=0)return!0}else if(o===e)return!0;o=o.parentNode}return!1}function o(o,r){function i(e){return e&&"INPUT"!==e.target.nodeName?void 0:(d=!1,c?void(d=!0):void t(function(){o.triggerHandler("blur")}))}function s(){u||(u=!0,t(function(){o.triggerHandler("focus")}))}function l(){c=!0}function a(e){c=!1;var s=e.target,l=n(o[0],s);d&&!l&&i(),l&&"INPUT"!==s.nodeName&&t(function(){r[0].focus()}),!l&&u&&(u=!1)}var u,c,d;return e[0].addEventListener("click",a,!0),o[0].addEventListener("mousedown",l,!0),o[0].addEventListener("blur",i,!0),r.on("focus",s),function(){e[0].removeEventListener("click",a),o[0].removeEventListener("mousedown",l,!0),o[0].removeEventListener("blur",i,!0),r.off("focus",s)}}function r(e,t){var n,o,r,i,l,u;t&&(o=e.offsetHeight,r=a(t,"height","margin"),i=e.scrollTop||0,n=s(t).top-s(e).top+i,l=n,u=n-o+r,n+r>o+i?e.scrollTop=u:i>n&&(e.scrollTop=l))}function i(e,t,n,o,r){function i(e){return parseFloat(r[e])}for(var s=n===(o?"border":"content")?4:"width"===t?1:0,l=0,a=["Top","Right","Bottom","Left"];4>s;s+=2)"margin"===n&&(l+=i(n+a[s])),o?("content"===n&&(l-=i("padding"+a[s])),"margin"!==n&&(l-=i("border"+a[s]+"Width"))):(l+=i("padding"+a[s]),"padding"!==n&&(l+=i("border"+a[s]+"Width")));return l}function s(e){var t,n,o=e.getBoundingClientRect(),r=e&&e.ownerDocument;if(r)return t=r.documentElement,n=l(r),{top:o.top+n.pageYOffset-t.clientTop,left:o.left+n.pageXOffset-t.clientLeft}}function l(e){return null!=e&&e===e.window?e:9===e.nodeType&&e.defaultView}function a(e,t,n){var o=!0,r="width"===t?e.offsetWidth:e.offsetHeight,s=window.getComputedStyle(e,null),l=!1;if(0>=r||null==r){if(r=s[t],(0>r||null==r)&&(r=e.style[t]),f.test(r))return r;r=parseFloat(r)||0}return r+i(e,t,n||(l?"border":"content"),o,s)}function u(e){for(var t in e)if(e.hasOwnProperty(t)&&e[t].length)return!1;return!0}function c(e,t,n,o,r){var i,s,l,a,u,c=r?[].concat(e):[];for(i=0,l=e.length;i=P&&a.contains(r[0],t.target,"select-dropdown")||(e.inputHide&&e.removeItem(0),!e.isOpen||!pt.closeList||"INPUT"===t.target.nodeName&&e.query.length?tt(e.query):(ot({query:pt.editItem&&!gt}),e.$evalAsync()))}function b(){e.isFocused||(e.isFocused=!0,c.disabled||(e.backspaceFocus=!1))}function y(){e.isFocused=!1,q||h(),L("blur")||ot(),e.$evalAsync()}function L(o,r){r||(r=o,o=e.query);var i,s=pt.saveTrigger.split(" ").indexOf(r)+1,l=pt.newItem&&o,a="blur"!==r?e.order[e.selectorPosition]:null;return s&&(l||a)?(e.showLoader=!0,i=t.when(a||x(e.$parent,{$query:o})),i.then(function(o){if(void 0===o)return t.reject();e.addItem(o);var r=e.order.length-1;e.selectorPosition===r&&rt(lt,0),pt.newItemFn&&!a||n(angular.noop),ot()}).catch(function(){f("invalid-item"),e.showLoader=!1}),!0):void 0}function O(){var e=q&&et(d.$modelValue)?ut:at;st.attr("placeholder",e)}function A(t){return a.getValue(v,t,e.$parent,U)}function z(t){return a.getValue(v,t,e.$parent,D)}function X(t){return a.getValue(v,t,e.$parent,_)}function Y(t){return e.isEmptyList||a.getValue(v,t,e.$parent,N)}function J(t){return a.getValue(v,t,e.$parent,T)||""}function K(t){return a.getValue(H,t,e.$parent,M)}function Z(e){return e=e instanceof Array?e:e?[e]:[],e.filter(function(e){return e&&(e instanceof Array&&e.length||D||X(e))})}function et(e){return!!Z(e).length}function tt(o,i){return e.isEmptyList=!1,E&&mt&&n.cancel(E),E=n(function(){var s=Q(e.$parent,{$query:o,$selectedAs:i})||"";return e.selectorPosition="prompt"===pt.newItem?!1:0,o||i||(e.oldQuery=null),(s.$promise&&!s.$resolved||angular.isFunction(s.then))&&(mt=pt.debounce),e.showLoader=!0,t.when(s.$promise||s).then(function(t){if(e.groups={},t&&$){var n=[];angular.forEach(t,function(e,t){if("$"!==t.toString().charAt(0)){var o={};o[S]=t,o[k]=e,n.push(o)}}),t=n}if(t&&!i){var s=q?e.output:[],l=Lt(t,o,X,kt(e.$parent),r),u=a.intersection(l,s,A,A,!0),c=K(u);if(!c.length&&(e.isEmptyList=!0,ct)){var d={};_.assign(d,ct),c=[d[v]]}e.groups=it(c)}return nt(),t}).finally(function(){e.showLoader=!1,pt.closeList&&!pt.cleanModel&&n(function(){rt(lt,0)})})},mt)}function nt(){var t,n,o,r=[],i=0;e.order=[],e.groupPos={};for(n in e.groups)e.groups.hasOwnProperty(n)&&"$"!=n.charAt(0)&&r.push(n);for(G&&r.sort(),t=0;t=P)return void f("limited");var n=e.groups[J(t)]=e.groups[J(t)]||[],o=D?z(t):t;n.splice(n.indexOf(t),1),q?d.$setViewValue(angular.isArray(d.$modelValue)?d.$modelValue.concat(o):[o]):(d.$setViewValue(o),h()),a.groupsIsEmpty(e.groups)&&(e.groups={}),q||pt.closeList||ot({query:!0}),p(),e.oldQuery=e.oldQuery||e.query,e.query="",e.backspaceFocus=!1}},e.removeItem=function(n){c.disabled||q&&0>n||(V=q?d.$modelValue[n]:d.$modelValue,t.when(vt(e.$parent,{$item:V})).then(function(){(q||e.inputHide)&&(q?(d.$modelValue.splice(n,1),d.$setViewValue([].concat(d.$modelValue))):(m(),pt.cleanModel&&d.$setViewValue(void 0)),(q||!e.backspaceFocus)&&(e.query=ht(V,C,X,gt,r)||""),q&&pt.closeList&&ot({query:!0}))}))},e.setSelection=function(t){I||e.selectorPosition===t?I=!1:rt(lt,t)},e.keyUp=function(t){switch(t.keyCode){case 8:e.query.length||q&&e.output.length||ot()}},e.keyDown=function(t){var n=0,o=e.order.length-1;switch(t.keyCode){case 38:e.selectorPosition=angular.isNumber(e.selectorPosition)?e.selectorPosition:n,rt(lt,e.selectorPosition===n?o:e.selectorPosition-1),I=!0;break;case 40:e.selectorPosition=angular.isNumber(e.selectorPosition)?e.selectorPosition:n-1,rt(lt,e.selectorPosition===o?n:e.selectorPosition+1),I=!0,e.query.length||e.isOpen||tt(),e.inputHide&&m();break;case 37:case 39:break;case 9:L("tab");break;case 13:L("enter"),t.preventDefault();break;case 32:L("space");break;case 27:q||(h(),pt.cleanModel&&d.$setViewValue(V)),ot();break;case 8:if(!e.query.length){if((!q||ft)&&(e.backspaceFocus=!0),e.backspaceFocus&&e.output&&(!q||e.output.length)){e.removeItem(e.output.length-1),ft&&t.preventDefault();break}e.backspaceFocus=!e.backspaceFocus;break}default:return e.inputHide&&m(),e.backspaceFocus=!1,!1}},e.getSearchLabel=function(t){var n=X(t);return $t(n,e.oldQuery||e.query,t,wt(e.$parent),r)},e.getDropdownLabel=function(t){var n=X(t);return bt(n,e.oldQuery||e.query,t,yt(e.$parent),r)},e.getGroupLabel=function(t,n){return St(t,e.oldQuery||e.query,n,It(e.$parent),r)},e.getDisableWhen=Y,ot(),r[0].addEventListener("click",w,!0),r.on("focus",b),r.on("blur",y)}}}}]),angular.module("oi.select").filter("oiSelectGroup",["$sce",function(e){return function(t){return e.trustAsHtml(t)}}]).filter("oiSelectCloseIcon",["$sce",function(e){return function(t){var n='×';return e.trustAsHtml(t+n)}}]).filter("oiSelectHighlight",["$sce","oiSelectEscape",function(e,t){return function(n,o){var r;return o.length>0||angular.isNumber(o)?(n=n.toString(),o=t(o),r=n.replace(new RegExp(o,"gi"),"$&")):r=n,e.trustAsHtml(r)}}]).filter("oiSelectAscSort",["oiSelectEscape",function(e){function t(t,n,o,r){var i,s,l,a,u=[],c=[],d=[],p=[];if(n){for(n=e(n).toLocaleLowerCase(),i=0,l=!1;i
')}]); \ No newline at end of file +angular.module("oi.select",[]),angular.module("oi.select").provider("oiSelect",function(){return{options:{debounce:500,searchFilter:"oiSelectCloseIcon",dropdownFilter:"oiSelectHighlight",listFilter:"oiSelectAscSort",groupFilter:"oiSelectGroup",editItem:!1,newItem:!1,closeList:!0,saveTrigger:"enter tab blur",minlength:0},version:{full:"0.2.21",major:0,minor:2,dot:21},$get:function(){return{options:this.options,version:this.version}}}}).factory("oiSelectEscape",function(){var e=/[-\/\\^$*+?.()|[\]{}]/g,t="\\$&";return function(n){return String(n).replace(e,t)}}).factory("oiSelectEditItem",function(){return function(e,t,n,o){return o?"":n(e)}}).factory("oiUtils",["$document","$timeout",function(e,t){function n(e,t,n){for(var o=t;o&&o.ownerDocument&&11!==o.nodeType;){if(n){if(o===e)return!1;if(o.className.indexOf(n)>=0)return!0}else if(o===e)return!0;o=o.parentNode}return!1}function o(o,r){function i(e){return e&&"INPUT"!==e.target.nodeName?void 0:(d=!1,c?void(d=!0):void t(function(){o.triggerHandler("blur")}))}function s(){a||(a=!0,t(function(){o.triggerHandler("focus")}))}function l(){c=!0}function u(e){c=!1;var s=e.target,l=n(o[0],s);d&&!l&&i(),l&&"INPUT"!==s.nodeName&&t(function(){r[0].focus()}),!l&&a&&(a=!1)}var a,c,d;return e[0].addEventListener("click",u,!0),o[0].addEventListener("mousedown",l,!0),o[0].addEventListener("blur",i,!0),r.on("focus",s),function(){e[0].removeEventListener("click",u),o[0].removeEventListener("mousedown",l,!0),o[0].removeEventListener("blur",i,!0),r.off("focus",s)}}function r(e,t){var n,o,r,i,l,a;t&&(o=e.offsetHeight,r=u(t,"height","margin"),i=e.scrollTop||0,n=s(t).top-s(e).top+i,l=n,a=n-o+r,n+r>o+i?e.scrollTop=a:i>n&&(e.scrollTop=l))}function i(e,t,n,o,r){function i(e){return parseFloat(r[e])}for(var s=n===(o?"border":"content")?4:"width"===t?1:0,l=0,u=["Top","Right","Bottom","Left"];4>s;s+=2)"margin"===n&&(l+=i(n+u[s])),o?("content"===n&&(l-=i("padding"+u[s])),"margin"!==n&&(l-=i("border"+u[s]+"Width"))):(l+=i("padding"+u[s]),"padding"!==n&&(l+=i("border"+u[s]+"Width")));return l}function s(e){var t,n,o=e.getBoundingClientRect(),r=e&&e.ownerDocument;if(r)return t=r.documentElement,n=l(r),{top:o.top+n.pageYOffset-t.clientTop,left:o.left+n.pageXOffset-t.clientLeft}}function l(e){return null!=e&&e===e.window?e:9===e.nodeType&&e.defaultView}function u(e,t,n){var o=!0,r="width"===t?e.offsetWidth:e.offsetHeight,s=window.getComputedStyle(e,null),l=!1;if(0>=r||null==r){if(r=s[t],(0>r||null==r)&&(r=e.style[t]),f.test(r))return r;r=parseFloat(r)||0}return r+i(e,t,n||(l?"border":"content"),o,s)}function a(e){for(var t in e)if(e.hasOwnProperty(t)&&e[t].length)return!1;return!0}function c(e,t,n,o,r){var i,s,l,u,a,c=r?[].concat(e):[];for(i=0,l=e.length;i=P&&u.contains(r[0],t.target,"select-dropdown")||(e.inputHide&&e.removeItem(0),!e.isOpen||!pt.closeList||"INPUT"===t.target.nodeName&&e.query.length?tt(e.query):(ot({query:pt.editItem&&!gt}),e.$evalAsync()))}function b(){e.isFocused||(e.isFocused=!0,c.disabled||(e.backspaceFocus=!1))}function y(){e.isFocused=!1,V||h(),L("blur")||ot(),e.$evalAsync()}function L(o,r){r||(r=o,o=e.query);var i,s=pt.saveTrigger.split(" ").indexOf(r)+1,l=pt.newItem&&o,u="blur"!==r?e.order[e.selectorPosition]:null;return s&&(l||u)?(e.showLoader=!0,i=t.when(u||x(e.$parent,{$query:o})),i.then(function(o){if(void 0===o)return t.reject();e.addItem(o);var r=e.order.length-1;e.selectorPosition===r&&rt(lt,0),pt.newItemFn&&!u||n(angular.noop),ot()}).catch(function(){f("invalid-item"),e.showLoader=!1}),!0):void 0}function O(){var e=V&&et(d.$modelValue)?at:ut;st.attr("placeholder",e)}function A(t){return u.getValue(v,t,e.$parent,U)}function z(t){return u.getValue(v,t,e.$parent,D)}function X(t){return u.getValue(v,t,e.$parent,_)}function Y(t){return e.isEmptyList||u.getValue(v,t,e.$parent,N)}function J(t){return u.getValue(v,t,e.$parent,T)||""}function K(t){return u.getValue(H,t,e.$parent,M)}function Z(e){return e=e instanceof Array?e:e?[e]:[],e.filter(function(e){return e&&(e instanceof Array&&e.length||D||X(e))})}function et(e){return!!Z(e).length}function tt(o,i){return e.isEmptyList=!1,E&&mt&&n.cancel(E),E=n(function(){var s=Q(e.$parent,{$query:o,$selectedAs:i})||"";return e.selectorPosition="prompt"===pt.newItem?!1:0,o||i||(e.oldQuery=null),(s.$promise&&!s.$resolved||angular.isFunction(s.then))&&(mt=pt.debounce),e.showLoader=!0,t.when(s.$promise||s).then(function(t){if(e.groups={},t&&$){var n=[];angular.forEach(t,function(e,t){if("$"!==t.toString().charAt(0)){var o={};o[S]=t,o[k]=e,n.push(o)}}),t=n}if(t&&!i){var s=V?e.output:[],l=Lt(t,o,X,kt(e.$parent),r),a=u.intersection(l,s,A,A,!0),c=K(a);if(!c.length&&(e.isEmptyList=!0,ct)){var d={};_.assign(d,ct),c=[d[v]]}e.groups=it(c)}return nt(),t}).finally(function(){e.showLoader=!1,pt.closeList&&!pt.cleanModel&&n(function(){rt(lt,0)})})},mt)}function nt(){var t,n,o,r=[],i=0;e.order=[],e.groupPos={};for(n in e.groups)e.groups.hasOwnProperty(n)&&"$"!=n.charAt(0)&&r.push(n);for(G&&r.sort(),t=0;t=P)return void f("limited");var n=e.groups[J(t)]=e.groups[J(t)]||[],o=D?z(t):t;n.splice(n.indexOf(t),1),V?d.$setViewValue(angular.isArray(d.$modelValue)?d.$modelValue.concat(o):[o]):(d.$setViewValue(o),h()),u.groupsIsEmpty(e.groups)&&(e.groups={}),V||pt.closeList||ot({query:!0}),p(),e.oldQuery=e.oldQuery||e.query,e.query="",e.backspaceFocus=!1}},e.removeItem=function(n){c.disabled||V&&0>n||(q=V?d.$modelValue[n]:d.$modelValue,t.when(vt(e.$parent,{$item:q})).then(function(){(V||e.inputHide)&&(V?(d.$modelValue.splice(n,1),d.$setViewValue([].concat(d.$modelValue))):(m(),pt.cleanModel&&d.$setViewValue(void 0)),(V||!e.backspaceFocus)&&(e.query=ht(q,C,X,gt,r)||""),V&&pt.closeList&&ot({query:!0}))}))},e.setSelection=function(t){I||e.selectorPosition===t?I=!1:rt(lt,t)},e.keyUp=function(t){switch(t.keyCode){case 8:e.query.length||V&&e.output.length||ot()}},e.keyDown=function(t){var n=0,o=e.order.length-1;switch(t.keyCode){case 38:e.selectorPosition=angular.isNumber(e.selectorPosition)?e.selectorPosition:n,rt(lt,e.selectorPosition===n?o:e.selectorPosition-1),I=!0;break;case 40:e.selectorPosition=angular.isNumber(e.selectorPosition)?e.selectorPosition:n-1,rt(lt,e.selectorPosition===o?n:e.selectorPosition+1),I=!0,e.query.length||e.isOpen||tt(),e.inputHide&&m();break;case 37:case 39:break;case 9:L("tab");break;case 13:L("enter"),t.preventDefault();break;case 32:L("space");break;case 27:V||(h(),pt.cleanModel&&d.$setViewValue(q)),ot();break;case 8:if(!e.query.length){if((!V||ft)&&(e.backspaceFocus=!0),e.backspaceFocus&&e.output&&(!V||e.output.length)){e.removeItem(e.output.length-1),ft&&t.preventDefault();break}e.backspaceFocus=!e.backspaceFocus;break}default:return e.inputHide&&m(),e.backspaceFocus=!1,!1}},e.getSearchLabel=function(t){var n=X(t);return $t(n,e.oldQuery||e.query,t,wt(e.$parent),r)},e.getDropdownLabel=function(t){var n=X(t);return bt(n,e.oldQuery||e.query,t,yt(e.$parent),r)},e.getGroupLabel=function(t,n){return St(t,e.oldQuery||e.query,n,It(e.$parent),r)},e.getDisableWhen=Y,ot(),r[0].addEventListener("click",w,!0),r.on("focus",b),r.on("blur",y)}}}}]),angular.module("oi.select").filter("oiSelectGroup",["$sce",function(e){return function(t){return e.trustAsHtml(t)}}]).filter("oiSelectCloseIcon",["$sce",function(e){return function(t){var n='×';return e.trustAsHtml(t+n)}}]).filter("oiSelectHighlight",["$sce","oiSelectEscape",function(e,t){return function(n,o){var r;return o.length>0||angular.isNumber(o)?(n=n.toString(),o=t(o),r=n.replace(new RegExp(o,"gi"),"$&")):r=n,e.trustAsHtml(r)}}]).filter("oiSelectAscSort",["oiSelectEscape",function(e){function t(t,n,o,r){var i,s,l,u,a=[],c=[],d=[],p=[];if(n){for(n=e(n).toLocaleLowerCase(),i=0,l=!1;i
')}]); \ No newline at end of file diff --git a/dist/select.js b/dist/select.js index 4dd65f6..6b85f0b 100644 --- a/dist/select.js +++ b/dist/select.js @@ -12,7 +12,8 @@ angular.module('oi.select') editItem: false, newItem: false, closeList: true, - saveTrigger: 'enter tab blur' + saveTrigger: 'enter tab blur', + minlength: 0 }, version: { full: '0.2.21', @@ -533,10 +534,12 @@ angular.module('oi.select') }); scope.$watch('query', function(inputValue, oldValue) { - if (saveOn(inputValue.slice(0, -1), inputValue.slice(-1))) { + if (saveOn(inputValue.slice(0, -1), inputValue.slice(-1)) || //terminated symbol + String(inputValue).length < options.minlength) { //length less then minlength return; } + //We don't get matches if nothing added into matches list if (inputValue !== oldValue && (!scope.oldQuery || inputValue) && !matchesWereReset) { listElement[0].scrollTop = 0; @@ -799,6 +802,9 @@ angular.module('oi.select') } function click(event) { + //query length less then minlength + if (scope.query.length < options.minlength) return; + //option is disabled if (oiUtils.contains(element[0], event.target, 'disabled')) return; diff --git a/dist/select.min.js b/dist/select.min.js index bae23c6..1dfd0e5 100644 --- a/dist/select.min.js +++ b/dist/select.min.js @@ -1 +1 @@ -angular.module("oi.select",[]),angular.module("oi.select").provider("oiSelect",function(){return{options:{debounce:500,searchFilter:"oiSelectCloseIcon",dropdownFilter:"oiSelectHighlight",listFilter:"oiSelectAscSort",groupFilter:"oiSelectGroup",editItem:!1,newItem:!1,closeList:!0,saveTrigger:"enter tab blur"},version:{full:"0.2.21",major:0,minor:2,dot:21},$get:function(){return{options:this.options,version:this.version}}}}).factory("oiSelectEscape",function(){var e=/[-\/\\^$*+?.()|[\]{}]/g,t="\\$&";return function(n){return String(n).replace(e,t)}}).factory("oiSelectEditItem",function(){return function(e,t,n,r){return r?"":n(e)}}).factory("oiUtils",["$document","$timeout",function(e,t){function n(e,t,n){for(var r=t;r&&r.ownerDocument&&11!==r.nodeType;){if(n){if(r===e)return!1;if(r.className.indexOf(n)>=0)return!0}else if(r===e)return!0;r=r.parentNode}return!1}function r(r,o){function i(e){return e&&"INPUT"!==e.target.nodeName?void 0:(d=!1,c?void(d=!0):void t(function(){r.triggerHandler("blur")}))}function s(){a||(a=!0,t(function(){r.triggerHandler("focus")}))}function u(){c=!0}function l(e){c=!1;var s=e.target,u=n(r[0],s);d&&!u&&i(),u&&"INPUT"!==s.nodeName&&t(function(){o[0].focus()}),!u&&a&&(a=!1)}var a,c,d;return e[0].addEventListener("click",l,!0),r[0].addEventListener("mousedown",u,!0),r[0].addEventListener("blur",i,!0),o.on("focus",s),function(){e[0].removeEventListener("click",l),r[0].removeEventListener("mousedown",u,!0),r[0].removeEventListener("blur",i,!0),o.off("focus",s)}}function o(e,t){var n,r,o,i,u,a;t&&(r=e.offsetHeight,o=l(t,"height","margin"),i=e.scrollTop||0,n=s(t).top-s(e).top+i,u=n,a=n-r+o,n+o>r+i?e.scrollTop=a:i>n&&(e.scrollTop=u))}function i(e,t,n,r,o){function i(e){return parseFloat(o[e])}for(var s=n===(r?"border":"content")?4:"width"===t?1:0,u=0,l=["Top","Right","Bottom","Left"];4>s;s+=2)"margin"===n&&(u+=i(n+l[s])),r?("content"===n&&(u-=i("padding"+l[s])),"margin"!==n&&(u-=i("border"+l[s]+"Width"))):(u+=i("padding"+l[s]),"padding"!==n&&(u+=i("border"+l[s]+"Width")));return u}function s(e){var t,n,r=e.getBoundingClientRect(),o=e&&e.ownerDocument;if(o)return t=o.documentElement,n=u(o),{top:r.top+n.pageYOffset-t.clientTop,left:r.left+n.pageXOffset-t.clientLeft}}function u(e){return null!=e&&e===e.window?e:9===e.nodeType&&e.defaultView}function l(e,t,n){var r=!0,o="width"===t?e.offsetWidth:e.offsetHeight,s=window.getComputedStyle(e,null),u=!1;if(0>=o||null==o){if(o=s[t],(0>o||null==o)&&(o=e.style[t]),p.test(o))return o;o=parseFloat(o)||0}return o+i(e,t,n||(u?"border":"content"),r,s)}function a(e){for(var t in e)if(e.hasOwnProperty(t)&&e[t].length)return!1;return!0}function c(e,t,n,r,o){var i,s,u,l,a,c=o?[].concat(e):[];for(i=0,u=e.length;i=P&&l.contains(o[0],t.target,"select-dropdown")||(e.inputHide&&e.removeItem(0),!e.isOpen||!ft.closeList||"INPUT"===t.target.nodeName&&e.query.length?tt(e.query):(rt({query:ft.editItem&&!gt}),e.$evalAsync()))}function y(){e.isFocused||(e.isFocused=!0,c.disabled||(e.backspaceFocus=!1))}function b(){e.isFocused=!1,q||h(),L("blur")||rt(),e.$evalAsync()}function L(r,o){o||(o=r,r=e.query);var i,s=ft.saveTrigger.split(" ").indexOf(o)+1,u=ft.newItem&&r,l="blur"!==o?e.order[e.selectorPosition]:null;return s&&(u||l)?(e.showLoader=!0,i=t.when(l||x(e.$parent,{$query:r})),i.then(function(r){if(void 0===r)return t.reject();e.addItem(r);var o=e.order.length-1;e.selectorPosition===o&&ot(ut,0),ft.newItemFn&&!l||n(angular.noop),rt()}).catch(function(){p("invalid-item"),e.showLoader=!1}),!0):void 0}function O(){var e=q&&et(d.$modelValue)?at:lt;st.attr("placeholder",e)}function A(t){return l.getValue(v,t,e.$parent,R)}function z(t){return l.getValue(v,t,e.$parent,T)}function X(t){return l.getValue(v,t,e.$parent,N)}function Y(t){return e.isEmptyList||l.getValue(v,t,e.$parent,_)}function J(t){return l.getValue(v,t,e.$parent,D)||""}function K(t){return l.getValue(H,t,e.$parent,M)}function Z(e){return e=e instanceof Array?e:e?[e]:[],e.filter(function(e){return e&&(e instanceof Array&&e.length||T||X(e))})}function et(e){return!!Z(e).length}function tt(r,i){return e.isEmptyList=!1,k&&mt&&n.cancel(k),k=n(function(){var s=Q(e.$parent,{$query:r,$selectedAs:i})||"";return e.selectorPosition="prompt"===ft.newItem?!1:0,r||i||(e.oldQuery=null),(s.$promise&&!s.$resolved||angular.isFunction(s.then))&&(mt=ft.debounce),e.showLoader=!0,t.when(s.$promise||s).then(function(t){if(e.groups={},t&&$){var n=[];angular.forEach(t,function(e,t){if("$"!==t.toString().charAt(0)){var r={};r[E]=t,r[S]=e,n.push(r)}}),t=n}if(t&&!i){var s=q?e.output:[],u=Lt(t,r,X,St(e.$parent),o),a=l.intersection(u,s,A,A,!0),c=K(a);if(!c.length&&(e.isEmptyList=!0,ct)){var d={};N.assign(d,ct),c=[d[v]]}e.groups=it(c)}return nt(),t}).finally(function(){e.showLoader=!1,ft.closeList&&!ft.cleanModel&&n(function(){ot(ut,0)})})},mt)}function nt(){var t,n,r,o=[],i=0;e.order=[],e.groupPos={};for(n in e.groups)e.groups.hasOwnProperty(n)&&"$"!=n.charAt(0)&&o.push(n);for(G&&o.sort(),t=0;t=P)return void p("limited");var n=e.groups[J(t)]=e.groups[J(t)]||[],r=T?z(t):t;n.splice(n.indexOf(t),1),q?d.$setViewValue(angular.isArray(d.$modelValue)?d.$modelValue.concat(r):[r]):(d.$setViewValue(r),h()),l.groupsIsEmpty(e.groups)&&(e.groups={}),q||ft.closeList||rt({query:!0}),f(),e.oldQuery=e.oldQuery||e.query,e.query="",e.backspaceFocus=!1}},e.removeItem=function(n){c.disabled||q&&0>n||(V=q?d.$modelValue[n]:d.$modelValue,t.when(vt(e.$parent,{$item:V})).then(function(){(q||e.inputHide)&&(q?(d.$modelValue.splice(n,1),d.$setViewValue([].concat(d.$modelValue))):(m(),ft.cleanModel&&d.$setViewValue(void 0)),(q||!e.backspaceFocus)&&(e.query=ht(V,C,X,gt,o)||""),q&&ft.closeList&&rt({query:!0}))}))},e.setSelection=function(t){F||e.selectorPosition===t?F=!1:ot(ut,t)},e.keyUp=function(t){switch(t.keyCode){case 8:e.query.length||q&&e.output.length||rt()}},e.keyDown=function(t){var n=0,r=e.order.length-1;switch(t.keyCode){case 38:e.selectorPosition=angular.isNumber(e.selectorPosition)?e.selectorPosition:n,ot(ut,e.selectorPosition===n?r:e.selectorPosition-1),F=!0;break;case 40:e.selectorPosition=angular.isNumber(e.selectorPosition)?e.selectorPosition:n-1,ot(ut,e.selectorPosition===r?n:e.selectorPosition+1),F=!0,e.query.length||e.isOpen||tt(),e.inputHide&&m();break;case 37:case 39:break;case 9:L("tab");break;case 13:L("enter"),t.preventDefault();break;case 32:L("space");break;case 27:q||(h(),ft.cleanModel&&d.$setViewValue(V)),rt();break;case 8:if(!e.query.length){if((!q||pt)&&(e.backspaceFocus=!0),e.backspaceFocus&&e.output&&(!q||e.output.length)){e.removeItem(e.output.length-1),pt&&t.preventDefault();break}e.backspaceFocus=!e.backspaceFocus;break}default:return e.inputHide&&m(),e.backspaceFocus=!1,!1}},e.getSearchLabel=function(t){var n=X(t);return $t(n,e.oldQuery||e.query,t,wt(e.$parent),o)},e.getDropdownLabel=function(t){var n=X(t);return yt(n,e.oldQuery||e.query,t,bt(e.$parent),o)},e.getGroupLabel=function(t,n){return Et(t,e.oldQuery||e.query,n,Ft(e.$parent),o)},e.getDisableWhen=Y,rt(),o[0].addEventListener("click",w,!0),o.on("focus",y),o.on("blur",b)}}}}]),angular.module("oi.select").filter("oiSelectGroup",["$sce",function(e){return function(t){return e.trustAsHtml(t)}}]).filter("oiSelectCloseIcon",["$sce",function(e){return function(t){var n='×';return e.trustAsHtml(t+n)}}]).filter("oiSelectHighlight",["$sce","oiSelectEscape",function(e,t){return function(n,r){var o;return r.length>0||angular.isNumber(r)?(n=n.toString(),r=t(r),o=n.replace(new RegExp(r,"gi"),"$&")):o=n,e.trustAsHtml(o)}}]).filter("oiSelectAscSort",["oiSelectEscape",function(e){function t(t,n,r,o){var i,s,u,l,a=[],c=[],d=[],f=[];if(n){for(n=e(n).toLocaleLowerCase(),i=0,u=!1;i=0)return!0}else if(r===e)return!0;r=r.parentNode}return!1}function r(r,o){function i(e){return e&&"INPUT"!==e.target.nodeName?void 0:(d=!1,c?void(d=!0):void t(function(){r.triggerHandler("blur")}))}function s(){a||(a=!0,t(function(){r.triggerHandler("focus")}))}function u(){c=!0}function l(e){c=!1;var s=e.target,u=n(r[0],s);d&&!u&&i(),u&&"INPUT"!==s.nodeName&&t(function(){o[0].focus()}),!u&&a&&(a=!1)}var a,c,d;return e[0].addEventListener("click",l,!0),r[0].addEventListener("mousedown",u,!0),r[0].addEventListener("blur",i,!0),o.on("focus",s),function(){e[0].removeEventListener("click",l),r[0].removeEventListener("mousedown",u,!0),r[0].removeEventListener("blur",i,!0),o.off("focus",s)}}function o(e,t){var n,r,o,i,u,a;t&&(r=e.offsetHeight,o=l(t,"height","margin"),i=e.scrollTop||0,n=s(t).top-s(e).top+i,u=n,a=n-r+o,n+o>r+i?e.scrollTop=a:i>n&&(e.scrollTop=u))}function i(e,t,n,r,o){function i(e){return parseFloat(o[e])}for(var s=n===(r?"border":"content")?4:"width"===t?1:0,u=0,l=["Top","Right","Bottom","Left"];4>s;s+=2)"margin"===n&&(u+=i(n+l[s])),r?("content"===n&&(u-=i("padding"+l[s])),"margin"!==n&&(u-=i("border"+l[s]+"Width"))):(u+=i("padding"+l[s]),"padding"!==n&&(u+=i("border"+l[s]+"Width")));return u}function s(e){var t,n,r=e.getBoundingClientRect(),o=e&&e.ownerDocument;if(o)return t=o.documentElement,n=u(o),{top:r.top+n.pageYOffset-t.clientTop,left:r.left+n.pageXOffset-t.clientLeft}}function u(e){return null!=e&&e===e.window?e:9===e.nodeType&&e.defaultView}function l(e,t,n){var r=!0,o="width"===t?e.offsetWidth:e.offsetHeight,s=window.getComputedStyle(e,null),u=!1;if(0>=o||null==o){if(o=s[t],(0>o||null==o)&&(o=e.style[t]),p.test(o))return o;o=parseFloat(o)||0}return o+i(e,t,n||(u?"border":"content"),r,s)}function a(e){for(var t in e)if(e.hasOwnProperty(t)&&e[t].length)return!1;return!0}function c(e,t,n,r,o){var i,s,u,l,a,c=o?[].concat(e):[];for(i=0,u=e.length;i=P&&l.contains(o[0],t.target,"select-dropdown")||(e.inputHide&&e.removeItem(0),!e.isOpen||!ft.closeList||"INPUT"===t.target.nodeName&&e.query.length?tt(e.query):(rt({query:ft.editItem&&!gt}),e.$evalAsync()))}function y(){e.isFocused||(e.isFocused=!0,c.disabled||(e.backspaceFocus=!1))}function b(){e.isFocused=!1,q||h(),L("blur")||rt(),e.$evalAsync()}function L(r,o){o||(o=r,r=e.query);var i,s=ft.saveTrigger.split(" ").indexOf(o)+1,u=ft.newItem&&r,l="blur"!==o?e.order[e.selectorPosition]:null;return s&&(u||l)?(e.showLoader=!0,i=t.when(l||x(e.$parent,{$query:r})),i.then(function(r){if(void 0===r)return t.reject();e.addItem(r);var o=e.order.length-1;e.selectorPosition===o&&ot(ut,0),ft.newItemFn&&!l||n(angular.noop),rt()}).catch(function(){p("invalid-item"),e.showLoader=!1}),!0):void 0}function O(){var e=q&&et(d.$modelValue)?at:lt;st.attr("placeholder",e)}function A(t){return l.getValue(v,t,e.$parent,R)}function z(t){return l.getValue(v,t,e.$parent,T)}function X(t){return l.getValue(v,t,e.$parent,N)}function Y(t){return e.isEmptyList||l.getValue(v,t,e.$parent,_)}function J(t){return l.getValue(v,t,e.$parent,D)||""}function K(t){return l.getValue(H,t,e.$parent,M)}function Z(e){return e=e instanceof Array?e:e?[e]:[],e.filter(function(e){return e&&(e instanceof Array&&e.length||T||X(e))})}function et(e){return!!Z(e).length}function tt(r,i){return e.isEmptyList=!1,k&&mt&&n.cancel(k),k=n(function(){var s=Q(e.$parent,{$query:r,$selectedAs:i})||"";return e.selectorPosition="prompt"===ft.newItem?!1:0,r||i||(e.oldQuery=null),(s.$promise&&!s.$resolved||angular.isFunction(s.then))&&(mt=ft.debounce),e.showLoader=!0,t.when(s.$promise||s).then(function(t){if(e.groups={},t&&$){var n=[];angular.forEach(t,function(e,t){if("$"!==t.toString().charAt(0)){var r={};r[E]=t,r[S]=e,n.push(r)}}),t=n}if(t&&!i){var s=q?e.output:[],u=Lt(t,r,X,St(e.$parent),o),a=l.intersection(u,s,A,A,!0),c=K(a);if(!c.length&&(e.isEmptyList=!0,ct)){var d={};N.assign(d,ct),c=[d[v]]}e.groups=it(c)}return nt(),t}).finally(function(){e.showLoader=!1,ft.closeList&&!ft.cleanModel&&n(function(){ot(ut,0)})})},mt)}function nt(){var t,n,r,o=[],i=0;e.order=[],e.groupPos={};for(n in e.groups)e.groups.hasOwnProperty(n)&&"$"!=n.charAt(0)&&o.push(n);for(G&&o.sort(),t=0;t=P)return void p("limited");var n=e.groups[J(t)]=e.groups[J(t)]||[],r=T?z(t):t;n.splice(n.indexOf(t),1),q?d.$setViewValue(angular.isArray(d.$modelValue)?d.$modelValue.concat(r):[r]):(d.$setViewValue(r),h()),l.groupsIsEmpty(e.groups)&&(e.groups={}),q||ft.closeList||rt({query:!0}),f(),e.oldQuery=e.oldQuery||e.query,e.query="",e.backspaceFocus=!1}},e.removeItem=function(n){c.disabled||q&&0>n||(V=q?d.$modelValue[n]:d.$modelValue,t.when(vt(e.$parent,{$item:V})).then(function(){(q||e.inputHide)&&(q?(d.$modelValue.splice(n,1),d.$setViewValue([].concat(d.$modelValue))):(m(),ft.cleanModel&&d.$setViewValue(void 0)),(q||!e.backspaceFocus)&&(e.query=ht(V,C,X,gt,o)||""),q&&ft.closeList&&rt({query:!0}))}))},e.setSelection=function(t){F||e.selectorPosition===t?F=!1:ot(ut,t)},e.keyUp=function(t){switch(t.keyCode){case 8:e.query.length||q&&e.output.length||rt()}},e.keyDown=function(t){var n=0,r=e.order.length-1;switch(t.keyCode){case 38:e.selectorPosition=angular.isNumber(e.selectorPosition)?e.selectorPosition:n,ot(ut,e.selectorPosition===n?r:e.selectorPosition-1),F=!0;break;case 40:e.selectorPosition=angular.isNumber(e.selectorPosition)?e.selectorPosition:n-1,ot(ut,e.selectorPosition===r?n:e.selectorPosition+1),F=!0,e.query.length||e.isOpen||tt(),e.inputHide&&m();break;case 37:case 39:break;case 9:L("tab");break;case 13:L("enter"),t.preventDefault();break;case 32:L("space");break;case 27:q||(h(),ft.cleanModel&&d.$setViewValue(V)),rt();break;case 8:if(!e.query.length){if((!q||pt)&&(e.backspaceFocus=!0),e.backspaceFocus&&e.output&&(!q||e.output.length)){e.removeItem(e.output.length-1),pt&&t.preventDefault();break}e.backspaceFocus=!e.backspaceFocus;break}default:return e.inputHide&&m(),e.backspaceFocus=!1,!1}},e.getSearchLabel=function(t){var n=X(t);return $t(n,e.oldQuery||e.query,t,wt(e.$parent),o)},e.getDropdownLabel=function(t){var n=X(t);return yt(n,e.oldQuery||e.query,t,bt(e.$parent),o)},e.getGroupLabel=function(t,n){return Et(t,e.oldQuery||e.query,n,Ft(e.$parent),o)},e.getDisableWhen=Y,rt(),o[0].addEventListener("click",w,!0),o.on("focus",y),o.on("blur",b)}}}}]),angular.module("oi.select").filter("oiSelectGroup",["$sce",function(e){return function(t){return e.trustAsHtml(t)}}]).filter("oiSelectCloseIcon",["$sce",function(e){return function(t){var n='×';return e.trustAsHtml(t+n)}}]).filter("oiSelectHighlight",["$sce","oiSelectEscape",function(e,t){return function(n,r){var o;return r.length>0||angular.isNumber(r)?(n=n.toString(),r=t(r),o=n.replace(new RegExp(r,"gi"),"$&")):o=n,e.trustAsHtml(o)}}]).filter("oiSelectAscSort",["oiSelectEscape",function(e){function t(t,n,r,o){var i,s,u,l,a=[],c=[],d=[],f=[];if(n){for(n=e(n).toLocaleLowerCase(),i=0,u=!1;iValidation
-

Also you can set maximum number of characters allowed in the input

+

Also you can set maximum number of characters allowed in the input and minimum number of characters to prevent searching if query is too small

@@ -96,7 +97,8 @@

Validation

oi-options="item.name for item in shopArr" ng-model="bundle3" oi-select-options="{ - maxlength: 3 + maxlength: 4, + minlength: 2 }"
diff --git a/src/directives.js b/src/directives.js
index 65cdcd3..14b0383 100644
--- a/src/directives.js
+++ b/src/directives.js
@@ -200,10 +200,12 @@ angular.module('oi.select')
                 });
 
                 scope.$watch('query', function(inputValue, oldValue) {
-                    if (saveOn(inputValue.slice(0, -1), inputValue.slice(-1))) {
-                        return;
-                    }
+                    //terminated symbol
+                    if (saveOn(inputValue.slice(0, -1), inputValue.slice(-1))) return;
 
+                    //length less then minlength
+                    if (String(inputValue).length < options.minlength) return;
+                    
                     //We don't get matches if nothing added into matches list
                     if (inputValue !== oldValue && (!scope.oldQuery || inputValue) && !matchesWereReset) {
                         listElement[0].scrollTop = 0;
@@ -466,6 +468,9 @@ angular.module('oi.select')
                 }
 
                 function click(event) {
+                    //query length less then minlength
+                    if (scope.query.length < options.minlength) return;
+                    
                     //option is disabled
                     if (oiUtils.contains(element[0], event.target, 'disabled')) return;
 
diff --git a/src/services.js b/src/services.js
index cbe39f6..127b4ab 100644
--- a/src/services.js
+++ b/src/services.js
@@ -11,7 +11,8 @@ angular.module('oi.select')
             editItem:       false,
             newItem:        false,
             closeList:      true,
-            saveTrigger:    'enter tab blur'
+            saveTrigger:    'enter tab blur',
+            minlength:      0
         },
         version: {
             full: '0.2.21',

From c377bef217148348f09e7c7bd429724fcce1d6a7 Mon Sep 17 00:00:00 2001
From: tamtakoe 
Date: Tue, 10 May 2016 20:57:46 +0300
Subject: [PATCH 06/11] fix bug when disabled element adds on ENTER click

---
 CHANGELOG.md      | 15 ++++++++++++---
 src/directives.js |  2 +-
 2 files changed, 13 insertions(+), 4 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index c72bf22..c7cbc53 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,15 +1,24 @@
 ## 0.2.21
 
-#### Bug Fixes
+#### Features
 
-- **oi-select:**
-    - `select as` works correct with object data source
+- **oi-select-options:**
     - `minlength` is minimum length of query for searching
 
 - **list-placeholder:** placeholder for dropdown list if no items found
 
+#### Bug Fixes
+
+- **oi-options:**
+    - `select as` works correct with object data source
+    - `disable when` items don't add on click `enter`
+
 - **oiSelectAscSort** works correct with different locales (f.e. Turkish)
 
+- **oi-select-options:**
+    - maxlength is maximum number of characters allowed in the input
+    - groupFilter for customizing group header
+
 ## 0.2.20
 
 #### Features
diff --git a/src/directives.js b/src/directives.js
index 14b0383..f016025 100644
--- a/src/directives.js
+++ b/src/directives.js
@@ -524,7 +524,7 @@ angular.module('oi.select')
                         selectedOrder  = triggerName !== 'blur' ? scope.order[scope.selectorPosition] : null, //do not save selected element in dropdown list on blur
                         itemPromise;
 
-                    if (isTriggered && (isNewItem || selectedOrder)) {
+                    if (isTriggered && (isNewItem || selectedOrder && !getDisableWhen(selectedOrder))) {
                         scope.showLoader = true;
                         itemPromise = $q.when(selectedOrder || newItemFn(scope.$parent, {$query: query}));
 

From 02f369bcc47981661059541402d744fd2d7f6344 Mon Sep 17 00:00:00 2001
From: tamtakoe 
Date: Tue, 10 May 2016 21:50:46 +0300
Subject: [PATCH 07/11] fix bug when select_as works incorrect with zero id

---
 CHANGELOG.md                |  2 +-
 dist/select-tpls.js         | 14 +++++++-------
 dist/select-tpls.min.js     |  2 +-
 dist/select.js              | 14 +++++++-------
 dist/select.min.js          |  2 +-
 docs/data/shopArr.json      | 22 +++++++++++-----------
 docs/data/shopObj.json      | 22 +++++++++++-----------
 docs/data/shopObjShort.json | 22 +++++++++++-----------
 src/directives.js           |  2 +-
 9 files changed, 51 insertions(+), 51 deletions(-)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index c7cbc53..1dbbeec 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,7 +10,7 @@
 #### Bug Fixes
 
 - **oi-options:**
-    - `select as` works correct with object data source
+    - `select as` works correct with object data source, and with zero id
     - `disable when` items don't add on click `enter`
 
 - **oiSelectAscSort** works correct with different locales (f.e. Turkish)
diff --git a/dist/select-tpls.js b/dist/select-tpls.js
index ea67259..8e0d911 100644
--- a/dist/select-tpls.js
+++ b/dist/select-tpls.js
@@ -534,12 +534,12 @@ angular.module('oi.select')
                 });
 
                 scope.$watch('query', function(inputValue, oldValue) {
-                    if (saveOn(inputValue.slice(0, -1), inputValue.slice(-1)) || //terminated symbol
-                        String(inputValue).length < options.minlength) { //length less then minlength
-                        return;
-                    }
-
+                    //terminated symbol
+                    if (saveOn(inputValue.slice(0, -1), inputValue.slice(-1))) return;
 
+                    //length less then minlength
+                    if (String(inputValue).length < options.minlength) return;
+                    
                     //We don't get matches if nothing added into matches list
                     if (inputValue !== oldValue && (!scope.oldQuery || inputValue) && !matchesWereReset) {
                         listElement[0].scrollTop = 0;
@@ -858,7 +858,7 @@ angular.module('oi.select')
                         selectedOrder  = triggerName !== 'blur' ? scope.order[scope.selectorPosition] : null, //do not save selected element in dropdown list on blur
                         itemPromise;
 
-                    if (isTriggered && (isNewItem || selectedOrder)) {
+                    if (isTriggered && (isNewItem || selectedOrder && !getDisableWhen(selectedOrder))) {
                         scope.showLoader = true;
                         itemPromise = $q.when(selectedOrder || newItemFn(scope.$parent, {$query: query}));
 
@@ -920,7 +920,7 @@ angular.module('oi.select')
                     value = value instanceof Array ? value : value ? [value]: [];
 
                     return value.filter(function(item) {
-                        return item && (item instanceof Array && item.length || selectAsFn || getLabel(item));
+                        return item !== undefined && (item instanceof Array && item.length || selectAsFn || getLabel(item));
                     });
                 }
 
diff --git a/dist/select-tpls.min.js b/dist/select-tpls.min.js
index a093d9a..d7d8ba4 100644
--- a/dist/select-tpls.min.js
+++ b/dist/select-tpls.min.js
@@ -1 +1 @@
-angular.module("oi.select",[]),angular.module("oi.select").provider("oiSelect",function(){return{options:{debounce:500,searchFilter:"oiSelectCloseIcon",dropdownFilter:"oiSelectHighlight",listFilter:"oiSelectAscSort",groupFilter:"oiSelectGroup",editItem:!1,newItem:!1,closeList:!0,saveTrigger:"enter tab blur",minlength:0},version:{full:"0.2.21",major:0,minor:2,dot:21},$get:function(){return{options:this.options,version:this.version}}}}).factory("oiSelectEscape",function(){var e=/[-\/\\^$*+?.()|[\]{}]/g,t="\\$&";return function(n){return String(n).replace(e,t)}}).factory("oiSelectEditItem",function(){return function(e,t,n,o){return o?"":n(e)}}).factory("oiUtils",["$document","$timeout",function(e,t){function n(e,t,n){for(var o=t;o&&o.ownerDocument&&11!==o.nodeType;){if(n){if(o===e)return!1;if(o.className.indexOf(n)>=0)return!0}else if(o===e)return!0;o=o.parentNode}return!1}function o(o,r){function i(e){return e&&"INPUT"!==e.target.nodeName?void 0:(d=!1,c?void(d=!0):void t(function(){o.triggerHandler("blur")}))}function s(){a||(a=!0,t(function(){o.triggerHandler("focus")}))}function l(){c=!0}function u(e){c=!1;var s=e.target,l=n(o[0],s);d&&!l&&i(),l&&"INPUT"!==s.nodeName&&t(function(){r[0].focus()}),!l&&a&&(a=!1)}var a,c,d;return e[0].addEventListener("click",u,!0),o[0].addEventListener("mousedown",l,!0),o[0].addEventListener("blur",i,!0),r.on("focus",s),function(){e[0].removeEventListener("click",u),o[0].removeEventListener("mousedown",l,!0),o[0].removeEventListener("blur",i,!0),r.off("focus",s)}}function r(e,t){var n,o,r,i,l,a;t&&(o=e.offsetHeight,r=u(t,"height","margin"),i=e.scrollTop||0,n=s(t).top-s(e).top+i,l=n,a=n-o+r,n+r>o+i?e.scrollTop=a:i>n&&(e.scrollTop=l))}function i(e,t,n,o,r){function i(e){return parseFloat(r[e])}for(var s=n===(o?"border":"content")?4:"width"===t?1:0,l=0,u=["Top","Right","Bottom","Left"];4>s;s+=2)"margin"===n&&(l+=i(n+u[s])),o?("content"===n&&(l-=i("padding"+u[s])),"margin"!==n&&(l-=i("border"+u[s]+"Width"))):(l+=i("padding"+u[s]),"padding"!==n&&(l+=i("border"+u[s]+"Width")));return l}function s(e){var t,n,o=e.getBoundingClientRect(),r=e&&e.ownerDocument;if(r)return t=r.documentElement,n=l(r),{top:o.top+n.pageYOffset-t.clientTop,left:o.left+n.pageXOffset-t.clientLeft}}function l(e){return null!=e&&e===e.window?e:9===e.nodeType&&e.defaultView}function u(e,t,n){var o=!0,r="width"===t?e.offsetWidth:e.offsetHeight,s=window.getComputedStyle(e,null),l=!1;if(0>=r||null==r){if(r=s[t],(0>r||null==r)&&(r=e.style[t]),f.test(r))return r;r=parseFloat(r)||0}return r+i(e,t,n||(l?"border":"content"),o,s)}function a(e){for(var t in e)if(e.hasOwnProperty(t)&&e[t].length)return!1;return!0}function c(e,t,n,o,r){var i,s,l,u,a,c=r?[].concat(e):[];for(i=0,l=e.length;i=P&&u.contains(r[0],t.target,"select-dropdown")||(e.inputHide&&e.removeItem(0),!e.isOpen||!pt.closeList||"INPUT"===t.target.nodeName&&e.query.length?tt(e.query):(ot({query:pt.editItem&&!gt}),e.$evalAsync()))}function b(){e.isFocused||(e.isFocused=!0,c.disabled||(e.backspaceFocus=!1))}function y(){e.isFocused=!1,V||h(),L("blur")||ot(),e.$evalAsync()}function L(o,r){r||(r=o,o=e.query);var i,s=pt.saveTrigger.split(" ").indexOf(r)+1,l=pt.newItem&&o,u="blur"!==r?e.order[e.selectorPosition]:null;return s&&(l||u)?(e.showLoader=!0,i=t.when(u||x(e.$parent,{$query:o})),i.then(function(o){if(void 0===o)return t.reject();e.addItem(o);var r=e.order.length-1;e.selectorPosition===r&&rt(lt,0),pt.newItemFn&&!u||n(angular.noop),ot()}).catch(function(){f("invalid-item"),e.showLoader=!1}),!0):void 0}function O(){var e=V&&et(d.$modelValue)?at:ut;st.attr("placeholder",e)}function A(t){return u.getValue(v,t,e.$parent,U)}function z(t){return u.getValue(v,t,e.$parent,D)}function X(t){return u.getValue(v,t,e.$parent,_)}function Y(t){return e.isEmptyList||u.getValue(v,t,e.$parent,N)}function J(t){return u.getValue(v,t,e.$parent,T)||""}function K(t){return u.getValue(H,t,e.$parent,M)}function Z(e){return e=e instanceof Array?e:e?[e]:[],e.filter(function(e){return e&&(e instanceof Array&&e.length||D||X(e))})}function et(e){return!!Z(e).length}function tt(o,i){return e.isEmptyList=!1,E&&mt&&n.cancel(E),E=n(function(){var s=Q(e.$parent,{$query:o,$selectedAs:i})||"";return e.selectorPosition="prompt"===pt.newItem?!1:0,o||i||(e.oldQuery=null),(s.$promise&&!s.$resolved||angular.isFunction(s.then))&&(mt=pt.debounce),e.showLoader=!0,t.when(s.$promise||s).then(function(t){if(e.groups={},t&&$){var n=[];angular.forEach(t,function(e,t){if("$"!==t.toString().charAt(0)){var o={};o[S]=t,o[k]=e,n.push(o)}}),t=n}if(t&&!i){var s=V?e.output:[],l=Lt(t,o,X,kt(e.$parent),r),a=u.intersection(l,s,A,A,!0),c=K(a);if(!c.length&&(e.isEmptyList=!0,ct)){var d={};_.assign(d,ct),c=[d[v]]}e.groups=it(c)}return nt(),t}).finally(function(){e.showLoader=!1,pt.closeList&&!pt.cleanModel&&n(function(){rt(lt,0)})})},mt)}function nt(){var t,n,o,r=[],i=0;e.order=[],e.groupPos={};for(n in e.groups)e.groups.hasOwnProperty(n)&&"$"!=n.charAt(0)&&r.push(n);for(G&&r.sort(),t=0;t=P)return void f("limited");var n=e.groups[J(t)]=e.groups[J(t)]||[],o=D?z(t):t;n.splice(n.indexOf(t),1),V?d.$setViewValue(angular.isArray(d.$modelValue)?d.$modelValue.concat(o):[o]):(d.$setViewValue(o),h()),u.groupsIsEmpty(e.groups)&&(e.groups={}),V||pt.closeList||ot({query:!0}),p(),e.oldQuery=e.oldQuery||e.query,e.query="",e.backspaceFocus=!1}},e.removeItem=function(n){c.disabled||V&&0>n||(q=V?d.$modelValue[n]:d.$modelValue,t.when(vt(e.$parent,{$item:q})).then(function(){(V||e.inputHide)&&(V?(d.$modelValue.splice(n,1),d.$setViewValue([].concat(d.$modelValue))):(m(),pt.cleanModel&&d.$setViewValue(void 0)),(V||!e.backspaceFocus)&&(e.query=ht(q,C,X,gt,r)||""),V&&pt.closeList&&ot({query:!0}))}))},e.setSelection=function(t){I||e.selectorPosition===t?I=!1:rt(lt,t)},e.keyUp=function(t){switch(t.keyCode){case 8:e.query.length||V&&e.output.length||ot()}},e.keyDown=function(t){var n=0,o=e.order.length-1;switch(t.keyCode){case 38:e.selectorPosition=angular.isNumber(e.selectorPosition)?e.selectorPosition:n,rt(lt,e.selectorPosition===n?o:e.selectorPosition-1),I=!0;break;case 40:e.selectorPosition=angular.isNumber(e.selectorPosition)?e.selectorPosition:n-1,rt(lt,e.selectorPosition===o?n:e.selectorPosition+1),I=!0,e.query.length||e.isOpen||tt(),e.inputHide&&m();break;case 37:case 39:break;case 9:L("tab");break;case 13:L("enter"),t.preventDefault();break;case 32:L("space");break;case 27:V||(h(),pt.cleanModel&&d.$setViewValue(q)),ot();break;case 8:if(!e.query.length){if((!V||ft)&&(e.backspaceFocus=!0),e.backspaceFocus&&e.output&&(!V||e.output.length)){e.removeItem(e.output.length-1),ft&&t.preventDefault();break}e.backspaceFocus=!e.backspaceFocus;break}default:return e.inputHide&&m(),e.backspaceFocus=!1,!1}},e.getSearchLabel=function(t){var n=X(t);return $t(n,e.oldQuery||e.query,t,wt(e.$parent),r)},e.getDropdownLabel=function(t){var n=X(t);return bt(n,e.oldQuery||e.query,t,yt(e.$parent),r)},e.getGroupLabel=function(t,n){return St(t,e.oldQuery||e.query,n,It(e.$parent),r)},e.getDisableWhen=Y,ot(),r[0].addEventListener("click",w,!0),r.on("focus",b),r.on("blur",y)}}}}]),angular.module("oi.select").filter("oiSelectGroup",["$sce",function(e){return function(t){return e.trustAsHtml(t)}}]).filter("oiSelectCloseIcon",["$sce",function(e){return function(t){var n='×';return e.trustAsHtml(t+n)}}]).filter("oiSelectHighlight",["$sce","oiSelectEscape",function(e,t){return function(n,o){var r;return o.length>0||angular.isNumber(o)?(n=n.toString(),o=t(o),r=n.replace(new RegExp(o,"gi"),"$&")):r=n,e.trustAsHtml(r)}}]).filter("oiSelectAscSort",["oiSelectEscape",function(e){function t(t,n,o,r){var i,s,l,u,a=[],c=[],d=[],p=[];if(n){for(n=e(n).toLocaleLowerCase(),i=0,l=!1;i
')}]); \ No newline at end of file +angular.module("oi.select",[]),angular.module("oi.select").provider("oiSelect",function(){return{options:{debounce:500,searchFilter:"oiSelectCloseIcon",dropdownFilter:"oiSelectHighlight",listFilter:"oiSelectAscSort",groupFilter:"oiSelectGroup",editItem:!1,newItem:!1,closeList:!0,saveTrigger:"enter tab blur",minlength:0},version:{full:"0.2.21",major:0,minor:2,dot:21},$get:function(){return{options:this.options,version:this.version}}}}).factory("oiSelectEscape",function(){var e=/[-\/\\^$*+?.()|[\]{}]/g,t="\\$&";return function(n){return String(n).replace(e,t)}}).factory("oiSelectEditItem",function(){return function(e,t,n,o){return o?"":n(e)}}).factory("oiUtils",["$document","$timeout",function(e,t){function n(e,t,n){for(var o=t;o&&o.ownerDocument&&11!==o.nodeType;){if(n){if(o===e)return!1;if(o.className.indexOf(n)>=0)return!0}else if(o===e)return!0;o=o.parentNode}return!1}function o(o,r){function i(e){return e&&"INPUT"!==e.target.nodeName?void 0:(d=!1,c?void(d=!0):void t(function(){o.triggerHandler("blur")}))}function s(){a||(a=!0,t(function(){o.triggerHandler("focus")}))}function l(){c=!0}function u(e){c=!1;var s=e.target,l=n(o[0],s);d&&!l&&i(),l&&"INPUT"!==s.nodeName&&t(function(){r[0].focus()}),!l&&a&&(a=!1)}var a,c,d;return e[0].addEventListener("click",u,!0),o[0].addEventListener("mousedown",l,!0),o[0].addEventListener("blur",i,!0),r.on("focus",s),function(){e[0].removeEventListener("click",u),o[0].removeEventListener("mousedown",l,!0),o[0].removeEventListener("blur",i,!0),r.off("focus",s)}}function r(e,t){var n,o,r,i,l,a;t&&(o=e.offsetHeight,r=u(t,"height","margin"),i=e.scrollTop||0,n=s(t).top-s(e).top+i,l=n,a=n-o+r,n+r>o+i?e.scrollTop=a:i>n&&(e.scrollTop=l))}function i(e,t,n,o,r){function i(e){return parseFloat(r[e])}for(var s=n===(o?"border":"content")?4:"width"===t?1:0,l=0,u=["Top","Right","Bottom","Left"];4>s;s+=2)"margin"===n&&(l+=i(n+u[s])),o?("content"===n&&(l-=i("padding"+u[s])),"margin"!==n&&(l-=i("border"+u[s]+"Width"))):(l+=i("padding"+u[s]),"padding"!==n&&(l+=i("border"+u[s]+"Width")));return l}function s(e){var t,n,o=e.getBoundingClientRect(),r=e&&e.ownerDocument;if(r)return t=r.documentElement,n=l(r),{top:o.top+n.pageYOffset-t.clientTop,left:o.left+n.pageXOffset-t.clientLeft}}function l(e){return null!=e&&e===e.window?e:9===e.nodeType&&e.defaultView}function u(e,t,n){var o=!0,r="width"===t?e.offsetWidth:e.offsetHeight,s=window.getComputedStyle(e,null),l=!1;if(0>=r||null==r){if(r=s[t],(0>r||null==r)&&(r=e.style[t]),f.test(r))return r;r=parseFloat(r)||0}return r+i(e,t,n||(l?"border":"content"),o,s)}function a(e){for(var t in e)if(e.hasOwnProperty(t)&&e[t].length)return!1;return!0}function c(e,t,n,o,r){var i,s,l,u,a,c=r?[].concat(e):[];for(i=0,l=e.length;i=P&&u.contains(r[0],t.target,"select-dropdown")||(e.inputHide&&e.removeItem(0),!e.isOpen||!pt.closeList||"INPUT"===t.target.nodeName&&e.query.length?tt(e.query):(ot({query:pt.editItem&&!gt}),e.$evalAsync()))}function b(){e.isFocused||(e.isFocused=!0,c.disabled||(e.backspaceFocus=!1))}function y(){e.isFocused=!1,V||h(),L("blur")||ot(),e.$evalAsync()}function L(o,r){r||(r=o,o=e.query);var i,s=pt.saveTrigger.split(" ").indexOf(r)+1,l=pt.newItem&&o,u="blur"!==r?e.order[e.selectorPosition]:null;return s&&(l||u&&!Y(u))?(e.showLoader=!0,i=t.when(u||x(e.$parent,{$query:o})),i.then(function(o){if(void 0===o)return t.reject();e.addItem(o);var r=e.order.length-1;e.selectorPosition===r&&rt(lt,0),pt.newItemFn&&!u||n(angular.noop),ot()}).catch(function(){f("invalid-item"),e.showLoader=!1}),!0):void 0}function O(){var e=V&&et(d.$modelValue)?at:ut;st.attr("placeholder",e)}function A(t){return u.getValue(v,t,e.$parent,U)}function z(t){return u.getValue(v,t,e.$parent,D)}function X(t){return u.getValue(v,t,e.$parent,_)}function Y(t){return e.isEmptyList||u.getValue(v,t,e.$parent,N)}function J(t){return u.getValue(v,t,e.$parent,T)||""}function K(t){return u.getValue(H,t,e.$parent,M)}function Z(e){return e=e instanceof Array?e:e?[e]:[],e.filter(function(e){return void 0!==e&&(e instanceof Array&&e.length||D||X(e))})}function et(e){return!!Z(e).length}function tt(o,i){return e.isEmptyList=!1,E&&mt&&n.cancel(E),E=n(function(){var s=Q(e.$parent,{$query:o,$selectedAs:i})||"";return e.selectorPosition="prompt"===pt.newItem?!1:0,o||i||(e.oldQuery=null),(s.$promise&&!s.$resolved||angular.isFunction(s.then))&&(mt=pt.debounce),e.showLoader=!0,t.when(s.$promise||s).then(function(t){if(e.groups={},t&&$){var n=[];angular.forEach(t,function(e,t){if("$"!==t.toString().charAt(0)){var o={};o[S]=t,o[k]=e,n.push(o)}}),t=n}if(t&&!i){var s=V?e.output:[],l=Lt(t,o,X,kt(e.$parent),r),a=u.intersection(l,s,A,A,!0),c=K(a);if(!c.length&&(e.isEmptyList=!0,ct)){var d={};_.assign(d,ct),c=[d[v]]}e.groups=it(c)}return nt(),t}).finally(function(){e.showLoader=!1,pt.closeList&&!pt.cleanModel&&n(function(){rt(lt,0)})})},mt)}function nt(){var t,n,o,r=[],i=0;e.order=[],e.groupPos={};for(n in e.groups)e.groups.hasOwnProperty(n)&&"$"!=n.charAt(0)&&r.push(n);for(G&&r.sort(),t=0;t=P)return void f("limited");var n=e.groups[J(t)]=e.groups[J(t)]||[],o=D?z(t):t;n.splice(n.indexOf(t),1),V?d.$setViewValue(angular.isArray(d.$modelValue)?d.$modelValue.concat(o):[o]):(d.$setViewValue(o),h()),u.groupsIsEmpty(e.groups)&&(e.groups={}),V||pt.closeList||ot({query:!0}),p(),e.oldQuery=e.oldQuery||e.query,e.query="",e.backspaceFocus=!1}},e.removeItem=function(n){c.disabled||V&&0>n||(q=V?d.$modelValue[n]:d.$modelValue,t.when(vt(e.$parent,{$item:q})).then(function(){(V||e.inputHide)&&(V?(d.$modelValue.splice(n,1),d.$setViewValue([].concat(d.$modelValue))):(m(),pt.cleanModel&&d.$setViewValue(void 0)),(V||!e.backspaceFocus)&&(e.query=ht(q,C,X,gt,r)||""),V&&pt.closeList&&ot({query:!0}))}))},e.setSelection=function(t){I||e.selectorPosition===t?I=!1:rt(lt,t)},e.keyUp=function(t){switch(t.keyCode){case 8:e.query.length||V&&e.output.length||ot()}},e.keyDown=function(t){var n=0,o=e.order.length-1;switch(t.keyCode){case 38:e.selectorPosition=angular.isNumber(e.selectorPosition)?e.selectorPosition:n,rt(lt,e.selectorPosition===n?o:e.selectorPosition-1),I=!0;break;case 40:e.selectorPosition=angular.isNumber(e.selectorPosition)?e.selectorPosition:n-1,rt(lt,e.selectorPosition===o?n:e.selectorPosition+1),I=!0,e.query.length||e.isOpen||tt(),e.inputHide&&m();break;case 37:case 39:break;case 9:L("tab");break;case 13:L("enter"),t.preventDefault();break;case 32:L("space");break;case 27:V||(h(),pt.cleanModel&&d.$setViewValue(q)),ot();break;case 8:if(!e.query.length){if((!V||ft)&&(e.backspaceFocus=!0),e.backspaceFocus&&e.output&&(!V||e.output.length)){e.removeItem(e.output.length-1),ft&&t.preventDefault();break}e.backspaceFocus=!e.backspaceFocus;break}default:return e.inputHide&&m(),e.backspaceFocus=!1,!1}},e.getSearchLabel=function(t){var n=X(t);return $t(n,e.oldQuery||e.query,t,wt(e.$parent),r)},e.getDropdownLabel=function(t){var n=X(t);return bt(n,e.oldQuery||e.query,t,yt(e.$parent),r)},e.getGroupLabel=function(t,n){return St(t,e.oldQuery||e.query,n,It(e.$parent),r)},e.getDisableWhen=Y,ot(),r[0].addEventListener("click",w,!0),r.on("focus",b),r.on("blur",y)}}}}]),angular.module("oi.select").filter("oiSelectGroup",["$sce",function(e){return function(t){return e.trustAsHtml(t)}}]).filter("oiSelectCloseIcon",["$sce",function(e){return function(t){var n='×';return e.trustAsHtml(t+n)}}]).filter("oiSelectHighlight",["$sce","oiSelectEscape",function(e,t){return function(n,o){var r;return o.length>0||angular.isNumber(o)?(n=n.toString(),o=t(o),r=n.replace(new RegExp(o,"gi"),"$&")):r=n,e.trustAsHtml(r)}}]).filter("oiSelectAscSort",["oiSelectEscape",function(e){function t(t,n,o,r){var i,s,l,u,a=[],c=[],d=[],p=[];if(n){for(n=e(n).toLocaleLowerCase(),i=0,l=!1;i
')}]); \ No newline at end of file diff --git a/dist/select.js b/dist/select.js index 6b85f0b..4d08afd 100644 --- a/dist/select.js +++ b/dist/select.js @@ -534,12 +534,12 @@ angular.module('oi.select') }); scope.$watch('query', function(inputValue, oldValue) { - if (saveOn(inputValue.slice(0, -1), inputValue.slice(-1)) || //terminated symbol - String(inputValue).length < options.minlength) { //length less then minlength - return; - } - + //terminated symbol + if (saveOn(inputValue.slice(0, -1), inputValue.slice(-1))) return; + //length less then minlength + if (String(inputValue).length < options.minlength) return; + //We don't get matches if nothing added into matches list if (inputValue !== oldValue && (!scope.oldQuery || inputValue) && !matchesWereReset) { listElement[0].scrollTop = 0; @@ -858,7 +858,7 @@ angular.module('oi.select') selectedOrder = triggerName !== 'blur' ? scope.order[scope.selectorPosition] : null, //do not save selected element in dropdown list on blur itemPromise; - if (isTriggered && (isNewItem || selectedOrder)) { + if (isTriggered && (isNewItem || selectedOrder && !getDisableWhen(selectedOrder))) { scope.showLoader = true; itemPromise = $q.when(selectedOrder || newItemFn(scope.$parent, {$query: query})); @@ -920,7 +920,7 @@ angular.module('oi.select') value = value instanceof Array ? value : value ? [value]: []; return value.filter(function(item) { - return item && (item instanceof Array && item.length || selectAsFn || getLabel(item)); + return item !== undefined && (item instanceof Array && item.length || selectAsFn || getLabel(item)); }); } diff --git a/dist/select.min.js b/dist/select.min.js index 1dfd0e5..735ee19 100644 --- a/dist/select.min.js +++ b/dist/select.min.js @@ -1 +1 @@ -angular.module("oi.select",[]),angular.module("oi.select").provider("oiSelect",function(){return{options:{debounce:500,searchFilter:"oiSelectCloseIcon",dropdownFilter:"oiSelectHighlight",listFilter:"oiSelectAscSort",groupFilter:"oiSelectGroup",editItem:!1,newItem:!1,closeList:!0,saveTrigger:"enter tab blur",minlength:0},version:{full:"0.2.21",major:0,minor:2,dot:21},$get:function(){return{options:this.options,version:this.version}}}}).factory("oiSelectEscape",function(){var e=/[-\/\\^$*+?.()|[\]{}]/g,t="\\$&";return function(n){return String(n).replace(e,t)}}).factory("oiSelectEditItem",function(){return function(e,t,n,r){return r?"":n(e)}}).factory("oiUtils",["$document","$timeout",function(e,t){function n(e,t,n){for(var r=t;r&&r.ownerDocument&&11!==r.nodeType;){if(n){if(r===e)return!1;if(r.className.indexOf(n)>=0)return!0}else if(r===e)return!0;r=r.parentNode}return!1}function r(r,o){function i(e){return e&&"INPUT"!==e.target.nodeName?void 0:(d=!1,c?void(d=!0):void t(function(){r.triggerHandler("blur")}))}function s(){a||(a=!0,t(function(){r.triggerHandler("focus")}))}function u(){c=!0}function l(e){c=!1;var s=e.target,u=n(r[0],s);d&&!u&&i(),u&&"INPUT"!==s.nodeName&&t(function(){o[0].focus()}),!u&&a&&(a=!1)}var a,c,d;return e[0].addEventListener("click",l,!0),r[0].addEventListener("mousedown",u,!0),r[0].addEventListener("blur",i,!0),o.on("focus",s),function(){e[0].removeEventListener("click",l),r[0].removeEventListener("mousedown",u,!0),r[0].removeEventListener("blur",i,!0),o.off("focus",s)}}function o(e,t){var n,r,o,i,u,a;t&&(r=e.offsetHeight,o=l(t,"height","margin"),i=e.scrollTop||0,n=s(t).top-s(e).top+i,u=n,a=n-r+o,n+o>r+i?e.scrollTop=a:i>n&&(e.scrollTop=u))}function i(e,t,n,r,o){function i(e){return parseFloat(o[e])}for(var s=n===(r?"border":"content")?4:"width"===t?1:0,u=0,l=["Top","Right","Bottom","Left"];4>s;s+=2)"margin"===n&&(u+=i(n+l[s])),r?("content"===n&&(u-=i("padding"+l[s])),"margin"!==n&&(u-=i("border"+l[s]+"Width"))):(u+=i("padding"+l[s]),"padding"!==n&&(u+=i("border"+l[s]+"Width")));return u}function s(e){var t,n,r=e.getBoundingClientRect(),o=e&&e.ownerDocument;if(o)return t=o.documentElement,n=u(o),{top:r.top+n.pageYOffset-t.clientTop,left:r.left+n.pageXOffset-t.clientLeft}}function u(e){return null!=e&&e===e.window?e:9===e.nodeType&&e.defaultView}function l(e,t,n){var r=!0,o="width"===t?e.offsetWidth:e.offsetHeight,s=window.getComputedStyle(e,null),u=!1;if(0>=o||null==o){if(o=s[t],(0>o||null==o)&&(o=e.style[t]),p.test(o))return o;o=parseFloat(o)||0}return o+i(e,t,n||(u?"border":"content"),r,s)}function a(e){for(var t in e)if(e.hasOwnProperty(t)&&e[t].length)return!1;return!0}function c(e,t,n,r,o){var i,s,u,l,a,c=o?[].concat(e):[];for(i=0,u=e.length;i=P&&l.contains(o[0],t.target,"select-dropdown")||(e.inputHide&&e.removeItem(0),!e.isOpen||!ft.closeList||"INPUT"===t.target.nodeName&&e.query.length?tt(e.query):(rt({query:ft.editItem&&!gt}),e.$evalAsync()))}function y(){e.isFocused||(e.isFocused=!0,c.disabled||(e.backspaceFocus=!1))}function b(){e.isFocused=!1,q||h(),L("blur")||rt(),e.$evalAsync()}function L(r,o){o||(o=r,r=e.query);var i,s=ft.saveTrigger.split(" ").indexOf(o)+1,u=ft.newItem&&r,l="blur"!==o?e.order[e.selectorPosition]:null;return s&&(u||l)?(e.showLoader=!0,i=t.when(l||x(e.$parent,{$query:r})),i.then(function(r){if(void 0===r)return t.reject();e.addItem(r);var o=e.order.length-1;e.selectorPosition===o&&ot(ut,0),ft.newItemFn&&!l||n(angular.noop),rt()}).catch(function(){p("invalid-item"),e.showLoader=!1}),!0):void 0}function O(){var e=q&&et(d.$modelValue)?at:lt;st.attr("placeholder",e)}function A(t){return l.getValue(v,t,e.$parent,R)}function z(t){return l.getValue(v,t,e.$parent,T)}function X(t){return l.getValue(v,t,e.$parent,N)}function Y(t){return e.isEmptyList||l.getValue(v,t,e.$parent,_)}function J(t){return l.getValue(v,t,e.$parent,D)||""}function K(t){return l.getValue(H,t,e.$parent,M)}function Z(e){return e=e instanceof Array?e:e?[e]:[],e.filter(function(e){return e&&(e instanceof Array&&e.length||T||X(e))})}function et(e){return!!Z(e).length}function tt(r,i){return e.isEmptyList=!1,k&&mt&&n.cancel(k),k=n(function(){var s=Q(e.$parent,{$query:r,$selectedAs:i})||"";return e.selectorPosition="prompt"===ft.newItem?!1:0,r||i||(e.oldQuery=null),(s.$promise&&!s.$resolved||angular.isFunction(s.then))&&(mt=ft.debounce),e.showLoader=!0,t.when(s.$promise||s).then(function(t){if(e.groups={},t&&$){var n=[];angular.forEach(t,function(e,t){if("$"!==t.toString().charAt(0)){var r={};r[E]=t,r[S]=e,n.push(r)}}),t=n}if(t&&!i){var s=q?e.output:[],u=Lt(t,r,X,St(e.$parent),o),a=l.intersection(u,s,A,A,!0),c=K(a);if(!c.length&&(e.isEmptyList=!0,ct)){var d={};N.assign(d,ct),c=[d[v]]}e.groups=it(c)}return nt(),t}).finally(function(){e.showLoader=!1,ft.closeList&&!ft.cleanModel&&n(function(){ot(ut,0)})})},mt)}function nt(){var t,n,r,o=[],i=0;e.order=[],e.groupPos={};for(n in e.groups)e.groups.hasOwnProperty(n)&&"$"!=n.charAt(0)&&o.push(n);for(G&&o.sort(),t=0;t=P)return void p("limited");var n=e.groups[J(t)]=e.groups[J(t)]||[],r=T?z(t):t;n.splice(n.indexOf(t),1),q?d.$setViewValue(angular.isArray(d.$modelValue)?d.$modelValue.concat(r):[r]):(d.$setViewValue(r),h()),l.groupsIsEmpty(e.groups)&&(e.groups={}),q||ft.closeList||rt({query:!0}),f(),e.oldQuery=e.oldQuery||e.query,e.query="",e.backspaceFocus=!1}},e.removeItem=function(n){c.disabled||q&&0>n||(V=q?d.$modelValue[n]:d.$modelValue,t.when(vt(e.$parent,{$item:V})).then(function(){(q||e.inputHide)&&(q?(d.$modelValue.splice(n,1),d.$setViewValue([].concat(d.$modelValue))):(m(),ft.cleanModel&&d.$setViewValue(void 0)),(q||!e.backspaceFocus)&&(e.query=ht(V,C,X,gt,o)||""),q&&ft.closeList&&rt({query:!0}))}))},e.setSelection=function(t){F||e.selectorPosition===t?F=!1:ot(ut,t)},e.keyUp=function(t){switch(t.keyCode){case 8:e.query.length||q&&e.output.length||rt()}},e.keyDown=function(t){var n=0,r=e.order.length-1;switch(t.keyCode){case 38:e.selectorPosition=angular.isNumber(e.selectorPosition)?e.selectorPosition:n,ot(ut,e.selectorPosition===n?r:e.selectorPosition-1),F=!0;break;case 40:e.selectorPosition=angular.isNumber(e.selectorPosition)?e.selectorPosition:n-1,ot(ut,e.selectorPosition===r?n:e.selectorPosition+1),F=!0,e.query.length||e.isOpen||tt(),e.inputHide&&m();break;case 37:case 39:break;case 9:L("tab");break;case 13:L("enter"),t.preventDefault();break;case 32:L("space");break;case 27:q||(h(),ft.cleanModel&&d.$setViewValue(V)),rt();break;case 8:if(!e.query.length){if((!q||pt)&&(e.backspaceFocus=!0),e.backspaceFocus&&e.output&&(!q||e.output.length)){e.removeItem(e.output.length-1),pt&&t.preventDefault();break}e.backspaceFocus=!e.backspaceFocus;break}default:return e.inputHide&&m(),e.backspaceFocus=!1,!1}},e.getSearchLabel=function(t){var n=X(t);return $t(n,e.oldQuery||e.query,t,wt(e.$parent),o)},e.getDropdownLabel=function(t){var n=X(t);return yt(n,e.oldQuery||e.query,t,bt(e.$parent),o)},e.getGroupLabel=function(t,n){return Et(t,e.oldQuery||e.query,n,Ft(e.$parent),o)},e.getDisableWhen=Y,rt(),o[0].addEventListener("click",w,!0),o.on("focus",y),o.on("blur",b)}}}}]),angular.module("oi.select").filter("oiSelectGroup",["$sce",function(e){return function(t){return e.trustAsHtml(t)}}]).filter("oiSelectCloseIcon",["$sce",function(e){return function(t){var n='×';return e.trustAsHtml(t+n)}}]).filter("oiSelectHighlight",["$sce","oiSelectEscape",function(e,t){return function(n,r){var o;return r.length>0||angular.isNumber(r)?(n=n.toString(),r=t(r),o=n.replace(new RegExp(r,"gi"),"$&")):o=n,e.trustAsHtml(o)}}]).filter("oiSelectAscSort",["oiSelectEscape",function(e){function t(t,n,r,o){var i,s,u,l,a=[],c=[],d=[],f=[];if(n){for(n=e(n).toLocaleLowerCase(),i=0,u=!1;i=0)return!0}else if(r===e)return!0;r=r.parentNode}return!1}function r(r,o){function i(e){return e&&"INPUT"!==e.target.nodeName?void 0:(d=!1,c?void(d=!0):void t(function(){r.triggerHandler("blur")}))}function s(){a||(a=!0,t(function(){r.triggerHandler("focus")}))}function u(){c=!0}function l(e){c=!1;var s=e.target,u=n(r[0],s);d&&!u&&i(),u&&"INPUT"!==s.nodeName&&t(function(){o[0].focus()}),!u&&a&&(a=!1)}var a,c,d;return e[0].addEventListener("click",l,!0),r[0].addEventListener("mousedown",u,!0),r[0].addEventListener("blur",i,!0),o.on("focus",s),function(){e[0].removeEventListener("click",l),r[0].removeEventListener("mousedown",u,!0),r[0].removeEventListener("blur",i,!0),o.off("focus",s)}}function o(e,t){var n,r,o,i,u,a;t&&(r=e.offsetHeight,o=l(t,"height","margin"),i=e.scrollTop||0,n=s(t).top-s(e).top+i,u=n,a=n-r+o,n+o>r+i?e.scrollTop=a:i>n&&(e.scrollTop=u))}function i(e,t,n,r,o){function i(e){return parseFloat(o[e])}for(var s=n===(r?"border":"content")?4:"width"===t?1:0,u=0,l=["Top","Right","Bottom","Left"];4>s;s+=2)"margin"===n&&(u+=i(n+l[s])),r?("content"===n&&(u-=i("padding"+l[s])),"margin"!==n&&(u-=i("border"+l[s]+"Width"))):(u+=i("padding"+l[s]),"padding"!==n&&(u+=i("border"+l[s]+"Width")));return u}function s(e){var t,n,r=e.getBoundingClientRect(),o=e&&e.ownerDocument;if(o)return t=o.documentElement,n=u(o),{top:r.top+n.pageYOffset-t.clientTop,left:r.left+n.pageXOffset-t.clientLeft}}function u(e){return null!=e&&e===e.window?e:9===e.nodeType&&e.defaultView}function l(e,t,n){var r=!0,o="width"===t?e.offsetWidth:e.offsetHeight,s=window.getComputedStyle(e,null),u=!1;if(0>=o||null==o){if(o=s[t],(0>o||null==o)&&(o=e.style[t]),p.test(o))return o;o=parseFloat(o)||0}return o+i(e,t,n||(u?"border":"content"),r,s)}function a(e){for(var t in e)if(e.hasOwnProperty(t)&&e[t].length)return!1;return!0}function c(e,t,n,r,o){var i,s,u,l,a,c=o?[].concat(e):[];for(i=0,u=e.length;i=P&&l.contains(o[0],t.target,"select-dropdown")||(e.inputHide&&e.removeItem(0),!e.isOpen||!ft.closeList||"INPUT"===t.target.nodeName&&e.query.length?tt(e.query):(rt({query:ft.editItem&&!gt}),e.$evalAsync()))}function y(){e.isFocused||(e.isFocused=!0,c.disabled||(e.backspaceFocus=!1))}function b(){e.isFocused=!1,q||h(),L("blur")||rt(),e.$evalAsync()}function L(r,o){o||(o=r,r=e.query);var i,s=ft.saveTrigger.split(" ").indexOf(o)+1,u=ft.newItem&&r,l="blur"!==o?e.order[e.selectorPosition]:null;return s&&(u||l&&!Y(l))?(e.showLoader=!0,i=t.when(l||x(e.$parent,{$query:r})),i.then(function(r){if(void 0===r)return t.reject();e.addItem(r);var o=e.order.length-1;e.selectorPosition===o&&ot(ut,0),ft.newItemFn&&!l||n(angular.noop),rt()}).catch(function(){p("invalid-item"),e.showLoader=!1}),!0):void 0}function O(){var e=q&&et(d.$modelValue)?at:lt;st.attr("placeholder",e)}function A(t){return l.getValue(v,t,e.$parent,R)}function z(t){return l.getValue(v,t,e.$parent,T)}function X(t){return l.getValue(v,t,e.$parent,N)}function Y(t){return e.isEmptyList||l.getValue(v,t,e.$parent,_)}function J(t){return l.getValue(v,t,e.$parent,D)||""}function K(t){return l.getValue(H,t,e.$parent,M)}function Z(e){return e=e instanceof Array?e:e?[e]:[],e.filter(function(e){return void 0!==e&&(e instanceof Array&&e.length||T||X(e))})}function et(e){return!!Z(e).length}function tt(r,i){return e.isEmptyList=!1,k&&mt&&n.cancel(k),k=n(function(){var s=Q(e.$parent,{$query:r,$selectedAs:i})||"";return e.selectorPosition="prompt"===ft.newItem?!1:0,r||i||(e.oldQuery=null),(s.$promise&&!s.$resolved||angular.isFunction(s.then))&&(mt=ft.debounce),e.showLoader=!0,t.when(s.$promise||s).then(function(t){if(e.groups={},t&&$){var n=[];angular.forEach(t,function(e,t){if("$"!==t.toString().charAt(0)){var r={};r[E]=t,r[S]=e,n.push(r)}}),t=n}if(t&&!i){var s=q?e.output:[],u=Lt(t,r,X,St(e.$parent),o),a=l.intersection(u,s,A,A,!0),c=K(a);if(!c.length&&(e.isEmptyList=!0,ct)){var d={};N.assign(d,ct),c=[d[v]]}e.groups=it(c)}return nt(),t}).finally(function(){e.showLoader=!1,ft.closeList&&!ft.cleanModel&&n(function(){ot(ut,0)})})},mt)}function nt(){var t,n,r,o=[],i=0;e.order=[],e.groupPos={};for(n in e.groups)e.groups.hasOwnProperty(n)&&"$"!=n.charAt(0)&&o.push(n);for(G&&o.sort(),t=0;t=P)return void p("limited");var n=e.groups[J(t)]=e.groups[J(t)]||[],r=T?z(t):t;n.splice(n.indexOf(t),1),q?d.$setViewValue(angular.isArray(d.$modelValue)?d.$modelValue.concat(r):[r]):(d.$setViewValue(r),h()),l.groupsIsEmpty(e.groups)&&(e.groups={}),q||ft.closeList||rt({query:!0}),f(),e.oldQuery=e.oldQuery||e.query,e.query="",e.backspaceFocus=!1}},e.removeItem=function(n){c.disabled||q&&0>n||(V=q?d.$modelValue[n]:d.$modelValue,t.when(vt(e.$parent,{$item:V})).then(function(){(q||e.inputHide)&&(q?(d.$modelValue.splice(n,1),d.$setViewValue([].concat(d.$modelValue))):(m(),ft.cleanModel&&d.$setViewValue(void 0)),(q||!e.backspaceFocus)&&(e.query=ht(V,C,X,gt,o)||""),q&&ft.closeList&&rt({query:!0}))}))},e.setSelection=function(t){F||e.selectorPosition===t?F=!1:ot(ut,t)},e.keyUp=function(t){switch(t.keyCode){case 8:e.query.length||q&&e.output.length||rt()}},e.keyDown=function(t){var n=0,r=e.order.length-1;switch(t.keyCode){case 38:e.selectorPosition=angular.isNumber(e.selectorPosition)?e.selectorPosition:n,ot(ut,e.selectorPosition===n?r:e.selectorPosition-1),F=!0;break;case 40:e.selectorPosition=angular.isNumber(e.selectorPosition)?e.selectorPosition:n-1,ot(ut,e.selectorPosition===r?n:e.selectorPosition+1),F=!0,e.query.length||e.isOpen||tt(),e.inputHide&&m();break;case 37:case 39:break;case 9:L("tab");break;case 13:L("enter"),t.preventDefault();break;case 32:L("space");break;case 27:q||(h(),ft.cleanModel&&d.$setViewValue(V)),rt();break;case 8:if(!e.query.length){if((!q||pt)&&(e.backspaceFocus=!0),e.backspaceFocus&&e.output&&(!q||e.output.length)){e.removeItem(e.output.length-1),pt&&t.preventDefault();break}e.backspaceFocus=!e.backspaceFocus;break}default:return e.inputHide&&m(),e.backspaceFocus=!1,!1}},e.getSearchLabel=function(t){var n=X(t);return $t(n,e.oldQuery||e.query,t,wt(e.$parent),o)},e.getDropdownLabel=function(t){var n=X(t);return yt(n,e.oldQuery||e.query,t,bt(e.$parent),o)},e.getGroupLabel=function(t,n){return Et(t,e.oldQuery||e.query,n,Ft(e.$parent),o)},e.getDisableWhen=Y,rt(),o[0].addEventListener("click",w,!0),o.on("focus",y),o.on("blur",b)}}}}]),angular.module("oi.select").filter("oiSelectGroup",["$sce",function(e){return function(t){return e.trustAsHtml(t)}}]).filter("oiSelectCloseIcon",["$sce",function(e){return function(t){var n='×';return e.trustAsHtml(t+n)}}]).filter("oiSelectHighlight",["$sce","oiSelectEscape",function(e,t){return function(n,r){var o;return r.length>0||angular.isNumber(r)?(n=n.toString(),r=t(r),o=n.replace(new RegExp(r,"gi"),"$&")):o=n,e.trustAsHtml(o)}}]).filter("oiSelectAscSort",["oiSelectEscape",function(e){function t(t,n,r,o){var i,s,u,l,a=[],c=[],d=[],f=[];if(n){for(n=e(n).toLocaleLowerCase(),i=0,u=!1;i Date: Tue, 10 May 2016 22:10:10 +0300 Subject: [PATCH 08/11] new angular version --- index.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/index.html b/index.html index efad9a3..7f00ffb 100644 --- a/index.html +++ b/index.html @@ -10,9 +10,9 @@ - - - + + + From 39e2e5af8c74187bd2e2cbcff93946f7c5d8c4fe Mon Sep 17 00:00:00 2001 From: tamtakoe Date: Tue, 10 May 2016 22:10:31 +0300 Subject: [PATCH 09/11] new angular version --- index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/index.html b/index.html index 7f00ffb..13cdb74 100644 --- a/index.html +++ b/index.html @@ -52,4 +52,4 @@ - \ No newline at end of file From f82293192dd03fc3b28c2632bc3462820b04ed00 Mon Sep 17 00:00:00 2001 From: tamtakoe Date: Tue, 10 May 2016 22:12:57 +0300 Subject: [PATCH 10/11] some fixes --- CHANGELOG.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1dbbeec..c849f44 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,10 +15,6 @@ - **oiSelectAscSort** works correct with different locales (f.e. Turkish) -- **oi-select-options:** - - maxlength is maximum number of characters allowed in the input - - groupFilter for customizing group header - ## 0.2.20 #### Features From 4165b0992bc453417009f2b852632da17a57123a Mon Sep 17 00:00:00 2001 From: tamtakoe Date: Tue, 10 May 2016 22:28:07 +0300 Subject: [PATCH 11/11] some fixes --- CHANGELOG.md | 2 ++ dist/select-tpls.js | 6 +++++- dist/select-tpls.min.js | 2 +- dist/select.js | 6 +++++- dist/select.min.js | 2 +- 5 files changed, 14 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c849f44..6fa8b3d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -15,6 +15,8 @@ - **oiSelectAscSort** works correct with different locales (f.e. Turkish) +- **oi-select** fix memory leak + ## 0.2.20 #### Features diff --git a/dist/select-tpls.js b/dist/select-tpls.js index 8e0d911..83981b7 100644 --- a/dist/select-tpls.js +++ b/dist/select-tpls.js @@ -142,7 +142,7 @@ angular.module('oi.select') } return function () { - $document[0].removeEventListener('click', clickHandler); + $document[0].removeEventListener('click', clickHandler, true); element[0].removeEventListener('mousedown', mousedownHandler, true); element[0].removeEventListener('blur', blurHandler, true); inputElement.off('focus', focusHandler); @@ -332,6 +332,7 @@ angular.module('oi.select') intersection: intersection } }]); + angular.module('oi.select') .directive('oiSelect', ['$document', '$q', '$timeout', '$parse', '$interpolate', '$injector', '$filter', '$animate', 'oiUtils', 'oiSelect', function($document, $q, $timeout, $parse, $interpolate, $injector, $filter, $animate, oiUtils, oiSelect) { @@ -777,6 +778,9 @@ angular.module('oi.select') resetMatches(); element[0].addEventListener('click', click, true); //triggered before add or delete item event + scope.$on('$destroy', function() { + element[0].removeEventListener('click', click, true); + }); element.on('focus', focus); element.on('blur', blur); diff --git a/dist/select-tpls.min.js b/dist/select-tpls.min.js index d7d8ba4..0366da1 100644 --- a/dist/select-tpls.min.js +++ b/dist/select-tpls.min.js @@ -1 +1 @@ -angular.module("oi.select",[]),angular.module("oi.select").provider("oiSelect",function(){return{options:{debounce:500,searchFilter:"oiSelectCloseIcon",dropdownFilter:"oiSelectHighlight",listFilter:"oiSelectAscSort",groupFilter:"oiSelectGroup",editItem:!1,newItem:!1,closeList:!0,saveTrigger:"enter tab blur",minlength:0},version:{full:"0.2.21",major:0,minor:2,dot:21},$get:function(){return{options:this.options,version:this.version}}}}).factory("oiSelectEscape",function(){var e=/[-\/\\^$*+?.()|[\]{}]/g,t="\\$&";return function(n){return String(n).replace(e,t)}}).factory("oiSelectEditItem",function(){return function(e,t,n,o){return o?"":n(e)}}).factory("oiUtils",["$document","$timeout",function(e,t){function n(e,t,n){for(var o=t;o&&o.ownerDocument&&11!==o.nodeType;){if(n){if(o===e)return!1;if(o.className.indexOf(n)>=0)return!0}else if(o===e)return!0;o=o.parentNode}return!1}function o(o,r){function i(e){return e&&"INPUT"!==e.target.nodeName?void 0:(d=!1,c?void(d=!0):void t(function(){o.triggerHandler("blur")}))}function s(){a||(a=!0,t(function(){o.triggerHandler("focus")}))}function l(){c=!0}function u(e){c=!1;var s=e.target,l=n(o[0],s);d&&!l&&i(),l&&"INPUT"!==s.nodeName&&t(function(){r[0].focus()}),!l&&a&&(a=!1)}var a,c,d;return e[0].addEventListener("click",u,!0),o[0].addEventListener("mousedown",l,!0),o[0].addEventListener("blur",i,!0),r.on("focus",s),function(){e[0].removeEventListener("click",u),o[0].removeEventListener("mousedown",l,!0),o[0].removeEventListener("blur",i,!0),r.off("focus",s)}}function r(e,t){var n,o,r,i,l,a;t&&(o=e.offsetHeight,r=u(t,"height","margin"),i=e.scrollTop||0,n=s(t).top-s(e).top+i,l=n,a=n-o+r,n+r>o+i?e.scrollTop=a:i>n&&(e.scrollTop=l))}function i(e,t,n,o,r){function i(e){return parseFloat(r[e])}for(var s=n===(o?"border":"content")?4:"width"===t?1:0,l=0,u=["Top","Right","Bottom","Left"];4>s;s+=2)"margin"===n&&(l+=i(n+u[s])),o?("content"===n&&(l-=i("padding"+u[s])),"margin"!==n&&(l-=i("border"+u[s]+"Width"))):(l+=i("padding"+u[s]),"padding"!==n&&(l+=i("border"+u[s]+"Width")));return l}function s(e){var t,n,o=e.getBoundingClientRect(),r=e&&e.ownerDocument;if(r)return t=r.documentElement,n=l(r),{top:o.top+n.pageYOffset-t.clientTop,left:o.left+n.pageXOffset-t.clientLeft}}function l(e){return null!=e&&e===e.window?e:9===e.nodeType&&e.defaultView}function u(e,t,n){var o=!0,r="width"===t?e.offsetWidth:e.offsetHeight,s=window.getComputedStyle(e,null),l=!1;if(0>=r||null==r){if(r=s[t],(0>r||null==r)&&(r=e.style[t]),f.test(r))return r;r=parseFloat(r)||0}return r+i(e,t,n||(l?"border":"content"),o,s)}function a(e){for(var t in e)if(e.hasOwnProperty(t)&&e[t].length)return!1;return!0}function c(e,t,n,o,r){var i,s,l,u,a,c=r?[].concat(e):[];for(i=0,l=e.length;i=P&&u.contains(r[0],t.target,"select-dropdown")||(e.inputHide&&e.removeItem(0),!e.isOpen||!pt.closeList||"INPUT"===t.target.nodeName&&e.query.length?tt(e.query):(ot({query:pt.editItem&&!gt}),e.$evalAsync()))}function b(){e.isFocused||(e.isFocused=!0,c.disabled||(e.backspaceFocus=!1))}function y(){e.isFocused=!1,V||h(),L("blur")||ot(),e.$evalAsync()}function L(o,r){r||(r=o,o=e.query);var i,s=pt.saveTrigger.split(" ").indexOf(r)+1,l=pt.newItem&&o,u="blur"!==r?e.order[e.selectorPosition]:null;return s&&(l||u&&!Y(u))?(e.showLoader=!0,i=t.when(u||x(e.$parent,{$query:o})),i.then(function(o){if(void 0===o)return t.reject();e.addItem(o);var r=e.order.length-1;e.selectorPosition===r&&rt(lt,0),pt.newItemFn&&!u||n(angular.noop),ot()}).catch(function(){f("invalid-item"),e.showLoader=!1}),!0):void 0}function O(){var e=V&&et(d.$modelValue)?at:ut;st.attr("placeholder",e)}function A(t){return u.getValue(v,t,e.$parent,U)}function z(t){return u.getValue(v,t,e.$parent,D)}function X(t){return u.getValue(v,t,e.$parent,_)}function Y(t){return e.isEmptyList||u.getValue(v,t,e.$parent,N)}function J(t){return u.getValue(v,t,e.$parent,T)||""}function K(t){return u.getValue(H,t,e.$parent,M)}function Z(e){return e=e instanceof Array?e:e?[e]:[],e.filter(function(e){return void 0!==e&&(e instanceof Array&&e.length||D||X(e))})}function et(e){return!!Z(e).length}function tt(o,i){return e.isEmptyList=!1,E&&mt&&n.cancel(E),E=n(function(){var s=Q(e.$parent,{$query:o,$selectedAs:i})||"";return e.selectorPosition="prompt"===pt.newItem?!1:0,o||i||(e.oldQuery=null),(s.$promise&&!s.$resolved||angular.isFunction(s.then))&&(mt=pt.debounce),e.showLoader=!0,t.when(s.$promise||s).then(function(t){if(e.groups={},t&&$){var n=[];angular.forEach(t,function(e,t){if("$"!==t.toString().charAt(0)){var o={};o[S]=t,o[k]=e,n.push(o)}}),t=n}if(t&&!i){var s=V?e.output:[],l=Lt(t,o,X,kt(e.$parent),r),a=u.intersection(l,s,A,A,!0),c=K(a);if(!c.length&&(e.isEmptyList=!0,ct)){var d={};_.assign(d,ct),c=[d[v]]}e.groups=it(c)}return nt(),t}).finally(function(){e.showLoader=!1,pt.closeList&&!pt.cleanModel&&n(function(){rt(lt,0)})})},mt)}function nt(){var t,n,o,r=[],i=0;e.order=[],e.groupPos={};for(n in e.groups)e.groups.hasOwnProperty(n)&&"$"!=n.charAt(0)&&r.push(n);for(G&&r.sort(),t=0;t=P)return void f("limited");var n=e.groups[J(t)]=e.groups[J(t)]||[],o=D?z(t):t;n.splice(n.indexOf(t),1),V?d.$setViewValue(angular.isArray(d.$modelValue)?d.$modelValue.concat(o):[o]):(d.$setViewValue(o),h()),u.groupsIsEmpty(e.groups)&&(e.groups={}),V||pt.closeList||ot({query:!0}),p(),e.oldQuery=e.oldQuery||e.query,e.query="",e.backspaceFocus=!1}},e.removeItem=function(n){c.disabled||V&&0>n||(q=V?d.$modelValue[n]:d.$modelValue,t.when(vt(e.$parent,{$item:q})).then(function(){(V||e.inputHide)&&(V?(d.$modelValue.splice(n,1),d.$setViewValue([].concat(d.$modelValue))):(m(),pt.cleanModel&&d.$setViewValue(void 0)),(V||!e.backspaceFocus)&&(e.query=ht(q,C,X,gt,r)||""),V&&pt.closeList&&ot({query:!0}))}))},e.setSelection=function(t){I||e.selectorPosition===t?I=!1:rt(lt,t)},e.keyUp=function(t){switch(t.keyCode){case 8:e.query.length||V&&e.output.length||ot()}},e.keyDown=function(t){var n=0,o=e.order.length-1;switch(t.keyCode){case 38:e.selectorPosition=angular.isNumber(e.selectorPosition)?e.selectorPosition:n,rt(lt,e.selectorPosition===n?o:e.selectorPosition-1),I=!0;break;case 40:e.selectorPosition=angular.isNumber(e.selectorPosition)?e.selectorPosition:n-1,rt(lt,e.selectorPosition===o?n:e.selectorPosition+1),I=!0,e.query.length||e.isOpen||tt(),e.inputHide&&m();break;case 37:case 39:break;case 9:L("tab");break;case 13:L("enter"),t.preventDefault();break;case 32:L("space");break;case 27:V||(h(),pt.cleanModel&&d.$setViewValue(q)),ot();break;case 8:if(!e.query.length){if((!V||ft)&&(e.backspaceFocus=!0),e.backspaceFocus&&e.output&&(!V||e.output.length)){e.removeItem(e.output.length-1),ft&&t.preventDefault();break}e.backspaceFocus=!e.backspaceFocus;break}default:return e.inputHide&&m(),e.backspaceFocus=!1,!1}},e.getSearchLabel=function(t){var n=X(t);return $t(n,e.oldQuery||e.query,t,wt(e.$parent),r)},e.getDropdownLabel=function(t){var n=X(t);return bt(n,e.oldQuery||e.query,t,yt(e.$parent),r)},e.getGroupLabel=function(t,n){return St(t,e.oldQuery||e.query,n,It(e.$parent),r)},e.getDisableWhen=Y,ot(),r[0].addEventListener("click",w,!0),r.on("focus",b),r.on("blur",y)}}}}]),angular.module("oi.select").filter("oiSelectGroup",["$sce",function(e){return function(t){return e.trustAsHtml(t)}}]).filter("oiSelectCloseIcon",["$sce",function(e){return function(t){var n='×';return e.trustAsHtml(t+n)}}]).filter("oiSelectHighlight",["$sce","oiSelectEscape",function(e,t){return function(n,o){var r;return o.length>0||angular.isNumber(o)?(n=n.toString(),o=t(o),r=n.replace(new RegExp(o,"gi"),"$&")):r=n,e.trustAsHtml(r)}}]).filter("oiSelectAscSort",["oiSelectEscape",function(e){function t(t,n,o,r){var i,s,l,u,a=[],c=[],d=[],p=[];if(n){for(n=e(n).toLocaleLowerCase(),i=0,l=!1;i
')}]); \ No newline at end of file +angular.module("oi.select",[]),angular.module("oi.select").provider("oiSelect",function(){return{options:{debounce:500,searchFilter:"oiSelectCloseIcon",dropdownFilter:"oiSelectHighlight",listFilter:"oiSelectAscSort",groupFilter:"oiSelectGroup",editItem:!1,newItem:!1,closeList:!0,saveTrigger:"enter tab blur",minlength:0},version:{full:"0.2.21",major:0,minor:2,dot:21},$get:function(){return{options:this.options,version:this.version}}}}).factory("oiSelectEscape",function(){var e=/[-\/\\^$*+?.()|[\]{}]/g,t="\\$&";return function(n){return String(n).replace(e,t)}}).factory("oiSelectEditItem",function(){return function(e,t,n,o){return o?"":n(e)}}).factory("oiUtils",["$document","$timeout",function(e,t){function n(e,t,n){for(var o=t;o&&o.ownerDocument&&11!==o.nodeType;){if(n){if(o===e)return!1;if(o.className.indexOf(n)>=0)return!0}else if(o===e)return!0;o=o.parentNode}return!1}function o(o,r){function i(e){return e&&"INPUT"!==e.target.nodeName?void 0:(d=!1,c?void(d=!0):void t(function(){o.triggerHandler("blur")}))}function s(){a||(a=!0,t(function(){o.triggerHandler("focus")}))}function l(){c=!0}function u(e){c=!1;var s=e.target,l=n(o[0],s);d&&!l&&i(),l&&"INPUT"!==s.nodeName&&t(function(){r[0].focus()}),!l&&a&&(a=!1)}var a,c,d;return e[0].addEventListener("click",u,!0),o[0].addEventListener("mousedown",l,!0),o[0].addEventListener("blur",i,!0),r.on("focus",s),function(){e[0].removeEventListener("click",u,!0),o[0].removeEventListener("mousedown",l,!0),o[0].removeEventListener("blur",i,!0),r.off("focus",s)}}function r(e,t){var n,o,r,i,l,a;t&&(o=e.offsetHeight,r=u(t,"height","margin"),i=e.scrollTop||0,n=s(t).top-s(e).top+i,l=n,a=n-o+r,n+r>o+i?e.scrollTop=a:i>n&&(e.scrollTop=l))}function i(e,t,n,o,r){function i(e){return parseFloat(r[e])}for(var s=n===(o?"border":"content")?4:"width"===t?1:0,l=0,u=["Top","Right","Bottom","Left"];4>s;s+=2)"margin"===n&&(l+=i(n+u[s])),o?("content"===n&&(l-=i("padding"+u[s])),"margin"!==n&&(l-=i("border"+u[s]+"Width"))):(l+=i("padding"+u[s]),"padding"!==n&&(l+=i("border"+u[s]+"Width")));return l}function s(e){var t,n,o=e.getBoundingClientRect(),r=e&&e.ownerDocument;if(r)return t=r.documentElement,n=l(r),{top:o.top+n.pageYOffset-t.clientTop,left:o.left+n.pageXOffset-t.clientLeft}}function l(e){return null!=e&&e===e.window?e:9===e.nodeType&&e.defaultView}function u(e,t,n){var o=!0,r="width"===t?e.offsetWidth:e.offsetHeight,s=window.getComputedStyle(e,null),l=!1;if(0>=r||null==r){if(r=s[t],(0>r||null==r)&&(r=e.style[t]),f.test(r))return r;r=parseFloat(r)||0}return r+i(e,t,n||(l?"border":"content"),o,s)}function a(e){for(var t in e)if(e.hasOwnProperty(t)&&e[t].length)return!1;return!0}function c(e,t,n,o,r){var i,s,l,u,a,c=r?[].concat(e):[];for(i=0,l=e.length;i=P&&u.contains(r[0],t.target,"select-dropdown")||(e.inputHide&&e.removeItem(0),!e.isOpen||!pt.closeList||"INPUT"===t.target.nodeName&&e.query.length?tt(e.query):(ot({query:pt.editItem&&!gt}),e.$evalAsync()))}function b(){e.isFocused||(e.isFocused=!0,c.disabled||(e.backspaceFocus=!1))}function y(){e.isFocused=!1,V||h(),L("blur")||ot(),e.$evalAsync()}function L(o,r){r||(r=o,o=e.query);var i,s=pt.saveTrigger.split(" ").indexOf(r)+1,l=pt.newItem&&o,u="blur"!==r?e.order[e.selectorPosition]:null;return s&&(l||u&&!Y(u))?(e.showLoader=!0,i=t.when(u||x(e.$parent,{$query:o})),i.then(function(o){if(void 0===o)return t.reject();e.addItem(o);var r=e.order.length-1;e.selectorPosition===r&&rt(lt,0),pt.newItemFn&&!u||n(angular.noop),ot()}).catch(function(){f("invalid-item"),e.showLoader=!1}),!0):void 0}function O(){var e=V&&et(d.$modelValue)?at:ut;st.attr("placeholder",e)}function A(t){return u.getValue(v,t,e.$parent,U)}function z(t){return u.getValue(v,t,e.$parent,D)}function X(t){return u.getValue(v,t,e.$parent,_)}function Y(t){return e.isEmptyList||u.getValue(v,t,e.$parent,N)}function J(t){return u.getValue(v,t,e.$parent,T)||""}function K(t){return u.getValue(H,t,e.$parent,M)}function Z(e){return e=e instanceof Array?e:e?[e]:[],e.filter(function(e){return void 0!==e&&(e instanceof Array&&e.length||D||X(e))})}function et(e){return!!Z(e).length}function tt(o,i){return e.isEmptyList=!1,F&&mt&&n.cancel(F),F=n(function(){var s=Q(e.$parent,{$query:o,$selectedAs:i})||"";return e.selectorPosition="prompt"===pt.newItem?!1:0,o||i||(e.oldQuery=null),(s.$promise&&!s.$resolved||angular.isFunction(s.then))&&(mt=pt.debounce),e.showLoader=!0,t.when(s.$promise||s).then(function(t){if(e.groups={},t&&$){var n=[];angular.forEach(t,function(e,t){if("$"!==t.toString().charAt(0)){var o={};o[S]=t,o[k]=e,n.push(o)}}),t=n}if(t&&!i){var s=V?e.output:[],l=Lt(t,o,X,kt(e.$parent),r),a=u.intersection(l,s,A,A,!0),c=K(a);if(!c.length&&(e.isEmptyList=!0,ct)){var d={};_.assign(d,ct),c=[d[v]]}e.groups=it(c)}return nt(),t}).finally(function(){e.showLoader=!1,pt.closeList&&!pt.cleanModel&&n(function(){rt(lt,0)})})},mt)}function nt(){var t,n,o,r=[],i=0;e.order=[],e.groupPos={};for(n in e.groups)e.groups.hasOwnProperty(n)&&"$"!=n.charAt(0)&&r.push(n);for(G&&r.sort(),t=0;t=P)return void f("limited");var n=e.groups[J(t)]=e.groups[J(t)]||[],o=D?z(t):t;n.splice(n.indexOf(t),1),V?d.$setViewValue(angular.isArray(d.$modelValue)?d.$modelValue.concat(o):[o]):(d.$setViewValue(o),h()),u.groupsIsEmpty(e.groups)&&(e.groups={}),V||pt.closeList||ot({query:!0}),p(),e.oldQuery=e.oldQuery||e.query,e.query="",e.backspaceFocus=!1}},e.removeItem=function(n){c.disabled||V&&0>n||(q=V?d.$modelValue[n]:d.$modelValue,t.when(vt(e.$parent,{$item:q})).then(function(){(V||e.inputHide)&&(V?(d.$modelValue.splice(n,1),d.$setViewValue([].concat(d.$modelValue))):(m(),pt.cleanModel&&d.$setViewValue(void 0)),(V||!e.backspaceFocus)&&(e.query=ht(q,C,X,gt,r)||""),V&&pt.closeList&&ot({query:!0}))}))},e.setSelection=function(t){I||e.selectorPosition===t?I=!1:rt(lt,t)},e.keyUp=function(t){switch(t.keyCode){case 8:e.query.length||V&&e.output.length||ot()}},e.keyDown=function(t){var n=0,o=e.order.length-1;switch(t.keyCode){case 38:e.selectorPosition=angular.isNumber(e.selectorPosition)?e.selectorPosition:n,rt(lt,e.selectorPosition===n?o:e.selectorPosition-1),I=!0;break;case 40:e.selectorPosition=angular.isNumber(e.selectorPosition)?e.selectorPosition:n-1,rt(lt,e.selectorPosition===o?n:e.selectorPosition+1),I=!0,e.query.length||e.isOpen||tt(),e.inputHide&&m();break;case 37:case 39:break;case 9:L("tab");break;case 13:L("enter"),t.preventDefault();break;case 32:L("space");break;case 27:V||(h(),pt.cleanModel&&d.$setViewValue(q)),ot();break;case 8:if(!e.query.length){if((!V||ft)&&(e.backspaceFocus=!0),e.backspaceFocus&&e.output&&(!V||e.output.length)){e.removeItem(e.output.length-1),ft&&t.preventDefault();break}e.backspaceFocus=!e.backspaceFocus;break}default:return e.inputHide&&m(),e.backspaceFocus=!1,!1}},e.getSearchLabel=function(t){var n=X(t);return $t(n,e.oldQuery||e.query,t,wt(e.$parent),r)},e.getDropdownLabel=function(t){var n=X(t);return bt(n,e.oldQuery||e.query,t,yt(e.$parent),r)},e.getGroupLabel=function(t,n){return St(t,e.oldQuery||e.query,n,It(e.$parent),r)},e.getDisableWhen=Y,ot(),r[0].addEventListener("click",w,!0),e.$on("$destroy",function(){r[0].removeEventListener("click",w,!0)}),r.on("focus",b),r.on("blur",y)}}}}]),angular.module("oi.select").filter("oiSelectGroup",["$sce",function(e){return function(t){return e.trustAsHtml(t)}}]).filter("oiSelectCloseIcon",["$sce",function(e){return function(t){var n='×';return e.trustAsHtml(t+n)}}]).filter("oiSelectHighlight",["$sce","oiSelectEscape",function(e,t){return function(n,o){var r;return o.length>0||angular.isNumber(o)?(n=n.toString(),o=t(o),r=n.replace(new RegExp(o,"gi"),"$&")):r=n,e.trustAsHtml(r)}}]).filter("oiSelectAscSort",["oiSelectEscape",function(e){function t(t,n,o,r){var i,s,l,u,a=[],c=[],d=[],p=[];if(n){for(n=e(n).toLocaleLowerCase(),i=0,l=!1;i
')}]); \ No newline at end of file diff --git a/dist/select.js b/dist/select.js index 4d08afd..88b5537 100644 --- a/dist/select.js +++ b/dist/select.js @@ -142,7 +142,7 @@ angular.module('oi.select') } return function () { - $document[0].removeEventListener('click', clickHandler); + $document[0].removeEventListener('click', clickHandler, true); element[0].removeEventListener('mousedown', mousedownHandler, true); element[0].removeEventListener('blur', blurHandler, true); inputElement.off('focus', focusHandler); @@ -332,6 +332,7 @@ angular.module('oi.select') intersection: intersection } }]); + angular.module('oi.select') .directive('oiSelect', ['$document', '$q', '$timeout', '$parse', '$interpolate', '$injector', '$filter', '$animate', 'oiUtils', 'oiSelect', function($document, $q, $timeout, $parse, $interpolate, $injector, $filter, $animate, oiUtils, oiSelect) { @@ -777,6 +778,9 @@ angular.module('oi.select') resetMatches(); element[0].addEventListener('click', click, true); //triggered before add or delete item event + scope.$on('$destroy', function() { + element[0].removeEventListener('click', click, true); + }); element.on('focus', focus); element.on('blur', blur); diff --git a/dist/select.min.js b/dist/select.min.js index 735ee19..43dd7c2 100644 --- a/dist/select.min.js +++ b/dist/select.min.js @@ -1 +1 @@ -angular.module("oi.select",[]),angular.module("oi.select").provider("oiSelect",function(){return{options:{debounce:500,searchFilter:"oiSelectCloseIcon",dropdownFilter:"oiSelectHighlight",listFilter:"oiSelectAscSort",groupFilter:"oiSelectGroup",editItem:!1,newItem:!1,closeList:!0,saveTrigger:"enter tab blur",minlength:0},version:{full:"0.2.21",major:0,minor:2,dot:21},$get:function(){return{options:this.options,version:this.version}}}}).factory("oiSelectEscape",function(){var e=/[-\/\\^$*+?.()|[\]{}]/g,t="\\$&";return function(n){return String(n).replace(e,t)}}).factory("oiSelectEditItem",function(){return function(e,t,n,r){return r?"":n(e)}}).factory("oiUtils",["$document","$timeout",function(e,t){function n(e,t,n){for(var r=t;r&&r.ownerDocument&&11!==r.nodeType;){if(n){if(r===e)return!1;if(r.className.indexOf(n)>=0)return!0}else if(r===e)return!0;r=r.parentNode}return!1}function r(r,o){function i(e){return e&&"INPUT"!==e.target.nodeName?void 0:(d=!1,c?void(d=!0):void t(function(){r.triggerHandler("blur")}))}function s(){a||(a=!0,t(function(){r.triggerHandler("focus")}))}function u(){c=!0}function l(e){c=!1;var s=e.target,u=n(r[0],s);d&&!u&&i(),u&&"INPUT"!==s.nodeName&&t(function(){o[0].focus()}),!u&&a&&(a=!1)}var a,c,d;return e[0].addEventListener("click",l,!0),r[0].addEventListener("mousedown",u,!0),r[0].addEventListener("blur",i,!0),o.on("focus",s),function(){e[0].removeEventListener("click",l),r[0].removeEventListener("mousedown",u,!0),r[0].removeEventListener("blur",i,!0),o.off("focus",s)}}function o(e,t){var n,r,o,i,u,a;t&&(r=e.offsetHeight,o=l(t,"height","margin"),i=e.scrollTop||0,n=s(t).top-s(e).top+i,u=n,a=n-r+o,n+o>r+i?e.scrollTop=a:i>n&&(e.scrollTop=u))}function i(e,t,n,r,o){function i(e){return parseFloat(o[e])}for(var s=n===(r?"border":"content")?4:"width"===t?1:0,u=0,l=["Top","Right","Bottom","Left"];4>s;s+=2)"margin"===n&&(u+=i(n+l[s])),r?("content"===n&&(u-=i("padding"+l[s])),"margin"!==n&&(u-=i("border"+l[s]+"Width"))):(u+=i("padding"+l[s]),"padding"!==n&&(u+=i("border"+l[s]+"Width")));return u}function s(e){var t,n,r=e.getBoundingClientRect(),o=e&&e.ownerDocument;if(o)return t=o.documentElement,n=u(o),{top:r.top+n.pageYOffset-t.clientTop,left:r.left+n.pageXOffset-t.clientLeft}}function u(e){return null!=e&&e===e.window?e:9===e.nodeType&&e.defaultView}function l(e,t,n){var r=!0,o="width"===t?e.offsetWidth:e.offsetHeight,s=window.getComputedStyle(e,null),u=!1;if(0>=o||null==o){if(o=s[t],(0>o||null==o)&&(o=e.style[t]),p.test(o))return o;o=parseFloat(o)||0}return o+i(e,t,n||(u?"border":"content"),r,s)}function a(e){for(var t in e)if(e.hasOwnProperty(t)&&e[t].length)return!1;return!0}function c(e,t,n,r,o){var i,s,u,l,a,c=o?[].concat(e):[];for(i=0,u=e.length;i=P&&l.contains(o[0],t.target,"select-dropdown")||(e.inputHide&&e.removeItem(0),!e.isOpen||!ft.closeList||"INPUT"===t.target.nodeName&&e.query.length?tt(e.query):(rt({query:ft.editItem&&!gt}),e.$evalAsync()))}function y(){e.isFocused||(e.isFocused=!0,c.disabled||(e.backspaceFocus=!1))}function b(){e.isFocused=!1,q||h(),L("blur")||rt(),e.$evalAsync()}function L(r,o){o||(o=r,r=e.query);var i,s=ft.saveTrigger.split(" ").indexOf(o)+1,u=ft.newItem&&r,l="blur"!==o?e.order[e.selectorPosition]:null;return s&&(u||l&&!Y(l))?(e.showLoader=!0,i=t.when(l||x(e.$parent,{$query:r})),i.then(function(r){if(void 0===r)return t.reject();e.addItem(r);var o=e.order.length-1;e.selectorPosition===o&&ot(ut,0),ft.newItemFn&&!l||n(angular.noop),rt()}).catch(function(){p("invalid-item"),e.showLoader=!1}),!0):void 0}function O(){var e=q&&et(d.$modelValue)?at:lt;st.attr("placeholder",e)}function A(t){return l.getValue(v,t,e.$parent,R)}function z(t){return l.getValue(v,t,e.$parent,T)}function X(t){return l.getValue(v,t,e.$parent,N)}function Y(t){return e.isEmptyList||l.getValue(v,t,e.$parent,_)}function J(t){return l.getValue(v,t,e.$parent,D)||""}function K(t){return l.getValue(H,t,e.$parent,M)}function Z(e){return e=e instanceof Array?e:e?[e]:[],e.filter(function(e){return void 0!==e&&(e instanceof Array&&e.length||T||X(e))})}function et(e){return!!Z(e).length}function tt(r,i){return e.isEmptyList=!1,k&&mt&&n.cancel(k),k=n(function(){var s=Q(e.$parent,{$query:r,$selectedAs:i})||"";return e.selectorPosition="prompt"===ft.newItem?!1:0,r||i||(e.oldQuery=null),(s.$promise&&!s.$resolved||angular.isFunction(s.then))&&(mt=ft.debounce),e.showLoader=!0,t.when(s.$promise||s).then(function(t){if(e.groups={},t&&$){var n=[];angular.forEach(t,function(e,t){if("$"!==t.toString().charAt(0)){var r={};r[E]=t,r[S]=e,n.push(r)}}),t=n}if(t&&!i){var s=q?e.output:[],u=Lt(t,r,X,St(e.$parent),o),a=l.intersection(u,s,A,A,!0),c=K(a);if(!c.length&&(e.isEmptyList=!0,ct)){var d={};N.assign(d,ct),c=[d[v]]}e.groups=it(c)}return nt(),t}).finally(function(){e.showLoader=!1,ft.closeList&&!ft.cleanModel&&n(function(){ot(ut,0)})})},mt)}function nt(){var t,n,r,o=[],i=0;e.order=[],e.groupPos={};for(n in e.groups)e.groups.hasOwnProperty(n)&&"$"!=n.charAt(0)&&o.push(n);for(G&&o.sort(),t=0;t=P)return void p("limited");var n=e.groups[J(t)]=e.groups[J(t)]||[],r=T?z(t):t;n.splice(n.indexOf(t),1),q?d.$setViewValue(angular.isArray(d.$modelValue)?d.$modelValue.concat(r):[r]):(d.$setViewValue(r),h()),l.groupsIsEmpty(e.groups)&&(e.groups={}),q||ft.closeList||rt({query:!0}),f(),e.oldQuery=e.oldQuery||e.query,e.query="",e.backspaceFocus=!1}},e.removeItem=function(n){c.disabled||q&&0>n||(V=q?d.$modelValue[n]:d.$modelValue,t.when(vt(e.$parent,{$item:V})).then(function(){(q||e.inputHide)&&(q?(d.$modelValue.splice(n,1),d.$setViewValue([].concat(d.$modelValue))):(m(),ft.cleanModel&&d.$setViewValue(void 0)),(q||!e.backspaceFocus)&&(e.query=ht(V,C,X,gt,o)||""),q&&ft.closeList&&rt({query:!0}))}))},e.setSelection=function(t){F||e.selectorPosition===t?F=!1:ot(ut,t)},e.keyUp=function(t){switch(t.keyCode){case 8:e.query.length||q&&e.output.length||rt()}},e.keyDown=function(t){var n=0,r=e.order.length-1;switch(t.keyCode){case 38:e.selectorPosition=angular.isNumber(e.selectorPosition)?e.selectorPosition:n,ot(ut,e.selectorPosition===n?r:e.selectorPosition-1),F=!0;break;case 40:e.selectorPosition=angular.isNumber(e.selectorPosition)?e.selectorPosition:n-1,ot(ut,e.selectorPosition===r?n:e.selectorPosition+1),F=!0,e.query.length||e.isOpen||tt(),e.inputHide&&m();break;case 37:case 39:break;case 9:L("tab");break;case 13:L("enter"),t.preventDefault();break;case 32:L("space");break;case 27:q||(h(),ft.cleanModel&&d.$setViewValue(V)),rt();break;case 8:if(!e.query.length){if((!q||pt)&&(e.backspaceFocus=!0),e.backspaceFocus&&e.output&&(!q||e.output.length)){e.removeItem(e.output.length-1),pt&&t.preventDefault();break}e.backspaceFocus=!e.backspaceFocus;break}default:return e.inputHide&&m(),e.backspaceFocus=!1,!1}},e.getSearchLabel=function(t){var n=X(t);return $t(n,e.oldQuery||e.query,t,wt(e.$parent),o)},e.getDropdownLabel=function(t){var n=X(t);return yt(n,e.oldQuery||e.query,t,bt(e.$parent),o)},e.getGroupLabel=function(t,n){return Et(t,e.oldQuery||e.query,n,Ft(e.$parent),o)},e.getDisableWhen=Y,rt(),o[0].addEventListener("click",w,!0),o.on("focus",y),o.on("blur",b)}}}}]),angular.module("oi.select").filter("oiSelectGroup",["$sce",function(e){return function(t){return e.trustAsHtml(t)}}]).filter("oiSelectCloseIcon",["$sce",function(e){return function(t){var n='×';return e.trustAsHtml(t+n)}}]).filter("oiSelectHighlight",["$sce","oiSelectEscape",function(e,t){return function(n,r){var o;return r.length>0||angular.isNumber(r)?(n=n.toString(),r=t(r),o=n.replace(new RegExp(r,"gi"),"$&")):o=n,e.trustAsHtml(o)}}]).filter("oiSelectAscSort",["oiSelectEscape",function(e){function t(t,n,r,o){var i,s,u,l,a=[],c=[],d=[],f=[];if(n){for(n=e(n).toLocaleLowerCase(),i=0,u=!1;i=0)return!0}else if(r===e)return!0;r=r.parentNode}return!1}function r(r,o){function i(e){return e&&"INPUT"!==e.target.nodeName?void 0:(d=!1,c?void(d=!0):void t(function(){r.triggerHandler("blur")}))}function s(){a||(a=!0,t(function(){r.triggerHandler("focus")}))}function u(){c=!0}function l(e){c=!1;var s=e.target,u=n(r[0],s);d&&!u&&i(),u&&"INPUT"!==s.nodeName&&t(function(){o[0].focus()}),!u&&a&&(a=!1)}var a,c,d;return e[0].addEventListener("click",l,!0),r[0].addEventListener("mousedown",u,!0),r[0].addEventListener("blur",i,!0),o.on("focus",s),function(){e[0].removeEventListener("click",l,!0),r[0].removeEventListener("mousedown",u,!0),r[0].removeEventListener("blur",i,!0),o.off("focus",s)}}function o(e,t){var n,r,o,i,u,a;t&&(r=e.offsetHeight,o=l(t,"height","margin"),i=e.scrollTop||0,n=s(t).top-s(e).top+i,u=n,a=n-r+o,n+o>r+i?e.scrollTop=a:i>n&&(e.scrollTop=u))}function i(e,t,n,r,o){function i(e){return parseFloat(o[e])}for(var s=n===(r?"border":"content")?4:"width"===t?1:0,u=0,l=["Top","Right","Bottom","Left"];4>s;s+=2)"margin"===n&&(u+=i(n+l[s])),r?("content"===n&&(u-=i("padding"+l[s])),"margin"!==n&&(u-=i("border"+l[s]+"Width"))):(u+=i("padding"+l[s]),"padding"!==n&&(u+=i("border"+l[s]+"Width")));return u}function s(e){var t,n,r=e.getBoundingClientRect(),o=e&&e.ownerDocument;if(o)return t=o.documentElement,n=u(o),{top:r.top+n.pageYOffset-t.clientTop,left:r.left+n.pageXOffset-t.clientLeft}}function u(e){return null!=e&&e===e.window?e:9===e.nodeType&&e.defaultView}function l(e,t,n){var r=!0,o="width"===t?e.offsetWidth:e.offsetHeight,s=window.getComputedStyle(e,null),u=!1;if(0>=o||null==o){if(o=s[t],(0>o||null==o)&&(o=e.style[t]),p.test(o))return o;o=parseFloat(o)||0}return o+i(e,t,n||(u?"border":"content"),r,s)}function a(e){for(var t in e)if(e.hasOwnProperty(t)&&e[t].length)return!1;return!0}function c(e,t,n,r,o){var i,s,u,l,a,c=o?[].concat(e):[];for(i=0,u=e.length;i=P&&l.contains(o[0],t.target,"select-dropdown")||(e.inputHide&&e.removeItem(0),!e.isOpen||!ft.closeList||"INPUT"===t.target.nodeName&&e.query.length?tt(e.query):(rt({query:ft.editItem&&!gt}),e.$evalAsync()))}function y(){e.isFocused||(e.isFocused=!0,c.disabled||(e.backspaceFocus=!1))}function b(){e.isFocused=!1,q||h(),L("blur")||rt(),e.$evalAsync()}function L(r,o){o||(o=r,r=e.query);var i,s=ft.saveTrigger.split(" ").indexOf(o)+1,u=ft.newItem&&r,l="blur"!==o?e.order[e.selectorPosition]:null;return s&&(u||l&&!Y(l))?(e.showLoader=!0,i=t.when(l||x(e.$parent,{$query:r})),i.then(function(r){if(void 0===r)return t.reject();e.addItem(r);var o=e.order.length-1;e.selectorPosition===o&&ot(ut,0),ft.newItemFn&&!l||n(angular.noop),rt()}).catch(function(){p("invalid-item"),e.showLoader=!1}),!0):void 0}function O(){var e=q&&et(d.$modelValue)?at:lt;st.attr("placeholder",e)}function A(t){return l.getValue(v,t,e.$parent,R)}function z(t){return l.getValue(v,t,e.$parent,T)}function X(t){return l.getValue(v,t,e.$parent,N)}function Y(t){return e.isEmptyList||l.getValue(v,t,e.$parent,_)}function J(t){return l.getValue(v,t,e.$parent,D)||""}function K(t){return l.getValue(H,t,e.$parent,M)}function Z(e){return e=e instanceof Array?e:e?[e]:[],e.filter(function(e){return void 0!==e&&(e instanceof Array&&e.length||T||X(e))})}function et(e){return!!Z(e).length}function tt(r,i){return e.isEmptyList=!1,k&&mt&&n.cancel(k),k=n(function(){var s=Q(e.$parent,{$query:r,$selectedAs:i})||"";return e.selectorPosition="prompt"===ft.newItem?!1:0,r||i||(e.oldQuery=null),(s.$promise&&!s.$resolved||angular.isFunction(s.then))&&(mt=ft.debounce),e.showLoader=!0,t.when(s.$promise||s).then(function(t){if(e.groups={},t&&$){var n=[];angular.forEach(t,function(e,t){if("$"!==t.toString().charAt(0)){var r={};r[E]=t,r[S]=e,n.push(r)}}),t=n}if(t&&!i){var s=q?e.output:[],u=Lt(t,r,X,St(e.$parent),o),a=l.intersection(u,s,A,A,!0),c=K(a);if(!c.length&&(e.isEmptyList=!0,ct)){var d={};N.assign(d,ct),c=[d[v]]}e.groups=it(c)}return nt(),t}).finally(function(){e.showLoader=!1,ft.closeList&&!ft.cleanModel&&n(function(){ot(ut,0)})})},mt)}function nt(){var t,n,r,o=[],i=0;e.order=[],e.groupPos={};for(n in e.groups)e.groups.hasOwnProperty(n)&&"$"!=n.charAt(0)&&o.push(n);for(G&&o.sort(),t=0;t=P)return void p("limited");var n=e.groups[J(t)]=e.groups[J(t)]||[],r=T?z(t):t;n.splice(n.indexOf(t),1),q?d.$setViewValue(angular.isArray(d.$modelValue)?d.$modelValue.concat(r):[r]):(d.$setViewValue(r),h()),l.groupsIsEmpty(e.groups)&&(e.groups={}),q||ft.closeList||rt({query:!0}),f(),e.oldQuery=e.oldQuery||e.query,e.query="",e.backspaceFocus=!1}},e.removeItem=function(n){c.disabled||q&&0>n||(V=q?d.$modelValue[n]:d.$modelValue,t.when(vt(e.$parent,{$item:V})).then(function(){(q||e.inputHide)&&(q?(d.$modelValue.splice(n,1),d.$setViewValue([].concat(d.$modelValue))):(m(),ft.cleanModel&&d.$setViewValue(void 0)),(q||!e.backspaceFocus)&&(e.query=ht(V,C,X,gt,o)||""),q&&ft.closeList&&rt({query:!0}))}))},e.setSelection=function(t){F||e.selectorPosition===t?F=!1:ot(ut,t)},e.keyUp=function(t){switch(t.keyCode){case 8:e.query.length||q&&e.output.length||rt()}},e.keyDown=function(t){var n=0,r=e.order.length-1;switch(t.keyCode){case 38:e.selectorPosition=angular.isNumber(e.selectorPosition)?e.selectorPosition:n,ot(ut,e.selectorPosition===n?r:e.selectorPosition-1),F=!0;break;case 40:e.selectorPosition=angular.isNumber(e.selectorPosition)?e.selectorPosition:n-1,ot(ut,e.selectorPosition===r?n:e.selectorPosition+1),F=!0,e.query.length||e.isOpen||tt(),e.inputHide&&m();break;case 37:case 39:break;case 9:L("tab");break;case 13:L("enter"),t.preventDefault();break;case 32:L("space");break;case 27:q||(h(),ft.cleanModel&&d.$setViewValue(V)),rt();break;case 8:if(!e.query.length){if((!q||pt)&&(e.backspaceFocus=!0),e.backspaceFocus&&e.output&&(!q||e.output.length)){e.removeItem(e.output.length-1),pt&&t.preventDefault();break}e.backspaceFocus=!e.backspaceFocus;break}default:return e.inputHide&&m(),e.backspaceFocus=!1,!1}},e.getSearchLabel=function(t){var n=X(t);return $t(n,e.oldQuery||e.query,t,wt(e.$parent),o)},e.getDropdownLabel=function(t){var n=X(t);return yt(n,e.oldQuery||e.query,t,bt(e.$parent),o)},e.getGroupLabel=function(t,n){return Et(t,e.oldQuery||e.query,n,Ft(e.$parent),o)},e.getDisableWhen=Y,rt(),o[0].addEventListener("click",w,!0),e.$on("$destroy",function(){o[0].removeEventListener("click",w,!0)}),o.on("focus",y),o.on("blur",b)}}}}]),angular.module("oi.select").filter("oiSelectGroup",["$sce",function(e){return function(t){return e.trustAsHtml(t)}}]).filter("oiSelectCloseIcon",["$sce",function(e){return function(t){var n='×';return e.trustAsHtml(t+n)}}]).filter("oiSelectHighlight",["$sce","oiSelectEscape",function(e,t){return function(n,r){var o;return r.length>0||angular.isNumber(r)?(n=n.toString(),r=t(r),o=n.replace(new RegExp(r,"gi"),"$&")):o=n,e.trustAsHtml(o)}}]).filter("oiSelectAscSort",["oiSelectEscape",function(e){function t(t,n,r,o){var i,s,u,l,a=[],c=[],d=[],f=[];if(n){for(n=e(n).toLocaleLowerCase(),i=0,u=!1;i