From 3143d83059bb9ef02e18aef8fb404d5b1b6cd95e Mon Sep 17 00:00:00 2001 From: Ahsan Ayaz Date: Tue, 20 Jan 2015 18:31:07 +0500 Subject: [PATCH 1/2] included onchangefunction to work for selectedobject as ngChange works for ngModel --- angucomplete.js | 393 +++++++++++++++++++++++++----------------------- 1 file changed, 201 insertions(+), 192 deletions(-) diff --git a/angucomplete.js b/angucomplete.js index 7a42bf0..b8ffb45 100644 --- a/angucomplete.js +++ b/angucomplete.js @@ -6,241 +6,250 @@ angular.module('angucomplete', [] ) .directive('angucomplete', function ($parse, $http, $sce, $timeout) { - return { - restrict: 'EA', - scope: { - "id": "@id", - "placeholder": "@placeholder", - "selectedObject": "=selectedobject", - "url": "@url", - "dataField": "@datafield", - "titleField": "@titlefield", - "descriptionField": "@descriptionfield", - "imageField": "@imagefield", - "imageUri": "@imageuri", - "inputClass": "@inputclass", - "userPause": "@pause", - "localData": "=localdata", - "searchFields": "@searchfields", - "minLengthUser": "@minlength", - "matchClass": "@matchclass" - }, - template: '
Searching...
No results found
{{ result.title }}
{{result.description}}
', - - link: function($scope, elem, attrs) { - $scope.lastSearchTerm = null; - $scope.currentIndex = null; - $scope.justChanged = false; - $scope.searchTimer = null; - $scope.hideTimer = null; - $scope.searching = false; - $scope.pause = 500; - $scope.minLength = 3; - $scope.searchStr = null; - - if ($scope.minLengthUser && $scope.minLengthUser != "") { - $scope.minLength = $scope.minLengthUser; - } + return { + restrict: 'EA', + scope: { + "id": "@id", + "placeholder": "@placeholder", + "selectedObject": "=selectedobject", + "onChangeFunction":"=onchangefunction", //this will work as ng-change works for ng-model + "url": "@url", + "dataField": "@datafield", + "titleField": "@titlefield", + "descriptionField": "@descriptionfield", + "imageField": "@imagefield", + "imageUri": "@imageuri", + "inputClass": "@inputclass", + "userPause": "@pause", + "localData": "=localdata", + "searchFields": "@searchfields", + "minLengthUser": "@minlength", + "matchClass": "@matchclass" + }, + template: '
Searching...
No results found
{{ result.title }}
{{result.description}}
', + + link: function($scope, elem, attrs) { + $scope.lastSearchTerm = null; + $scope.currentIndex = null; + $scope.justChanged = false; + $scope.searchTimer = null; + $scope.hideTimer = null; + $scope.searching = false; + $scope.pause = 500; + $scope.minLength = 3; + $scope.searchStr = null; + + if ($scope.minLengthUser && $scope.minLengthUser != "") { + $scope.minLength = $scope.minLengthUser; + } - if ($scope.userPause) { - $scope.pause = $scope.userPause; - } + if ($scope.userPause) { + $scope.pause = $scope.userPause; + } - isNewSearchNeeded = function(newTerm, oldTerm) { - return newTerm.length >= $scope.minLength && newTerm != oldTerm - } + isNewSearchNeeded = function(newTerm, oldTerm) { + return newTerm.length >= $scope.minLength && newTerm != oldTerm + } - $scope.processResults = function(responseData, str) { - if (responseData && responseData.length > 0) { - $scope.results = []; + $scope.processResults = function(responseData, str) { + if (responseData && responseData.length > 0) { + $scope.results = []; - var titleFields = []; - if ($scope.titleField && $scope.titleField != "") { - titleFields = $scope.titleField.split(","); - } + var titleFields = []; + if ($scope.titleField && $scope.titleField != "") { + titleFields = $scope.titleField.split(","); + } - for (var i = 0; i < responseData.length; i++) { - // Get title variables - var titleCode = []; + for (var i = 0; i < responseData.length; i++) { + // Get title variables + var titleCode = []; - for (var t = 0; t < titleFields.length; t++) { - titleCode.push(responseData[i][titleFields[t]]); - } + for (var t = 0; t < titleFields.length; t++) { + titleCode.push(responseData[i][titleFields[t]]); + } - var description = ""; - if ($scope.descriptionField) { - description = responseData[i][$scope.descriptionField]; - } + var description = ""; + if ($scope.descriptionField) { + description = responseData[i][$scope.descriptionField]; + } - var imageUri = ""; - if ($scope.imageUri) { - imageUri = $scope.imageUri; - } + var imageUri = ""; + if ($scope.imageUri) { + imageUri = $scope.imageUri; + } - var image = ""; - if ($scope.imageField) { - image = imageUri + responseData[i][$scope.imageField]; - } + var image = ""; + if ($scope.imageField) { + image = imageUri + responseData[i][$scope.imageField]; + } - var text = titleCode.join(' '); - if ($scope.matchClass) { - var re = new RegExp(str, 'i'); - var strPart = text.match(re)[0]; - text = $sce.trustAsHtml(text.replace(re, ''+ strPart +'')); - } + var text = titleCode.join(' '); + if ($scope.matchClass) { + var re = new RegExp(str, 'i'); + var strPart = text.match(re)[0]; + text = $sce.trustAsHtml(text.replace(re, ''+ strPart +'')); + } - var resultRow = { - title: text, - description: description, - image: image, - originalObject: responseData[i] - } + var resultRow = { + title: text, + description: description, + image: image, + originalObject: responseData[i] + } - $scope.results[$scope.results.length] = resultRow; - } + $scope.results[$scope.results.length] = resultRow; + } - } else { - $scope.results = []; + } else { + $scope.results = []; + } } - } - $scope.searchTimerComplete = function(str) { - // Begin the search + $scope.searchTimerComplete = function(str) { + // Begin the search - if (str.length >= $scope.minLength) { - if ($scope.localData) { - var searchFields = $scope.searchFields.split(","); + if (str.length >= $scope.minLength) { + if ($scope.localData) { + var searchFields = $scope.searchFields.split(","); - var matches = []; + var matches = []; - for (var i = 0; i < $scope.localData.length; i++) { - var match = false; + for (var i = 0; i < $scope.localData.length; i++) { + var match = false; - for (var s = 0; s < searchFields.length; s++) { - match = match || (typeof $scope.localData[i][searchFields[s]] === 'string' && typeof str === 'string' && $scope.localData[i][searchFields[s]].toLowerCase().indexOf(str.toLowerCase()) >= 0); - } + for (var s = 0; s < searchFields.length; s++) { + match = match || (typeof $scope.localData[i][searchFields[s]] === 'string' && typeof str === 'string' && $scope.localData[i][searchFields[s]].toLowerCase().indexOf(str.toLowerCase()) >= 0); + } - if (match) { - matches[matches.length] = $scope.localData[i]; + if (match) { + matches[matches.length] = $scope.localData[i]; + } } - } - - $scope.searching = false; - $scope.processResults(matches, str); - } else { - $http.get($scope.url + str, {}). - success(function(responseData, status, headers, config) { - $scope.searching = false; - $scope.processResults((($scope.dataField) ? responseData[$scope.dataField] : responseData ), str); - }). - error(function(data, status, headers, config) { - console.log("error"); - }); + $scope.searching = false; + $scope.processResults(matches, str); + + } else { + $http.get($scope.url + str, {}). + success(function(responseData, status, headers, config) { + $scope.searching = false; + $scope.processResults((($scope.dataField) ? responseData[$scope.dataField] : responseData ), str); + }). + error(function(data, status, headers, config) { + console.log("error"); + }); + } } } - } - - $scope.hideResults = function() { - $scope.hideTimer = $timeout(function() { - $scope.showDropdown = false; - }, $scope.pause); - }; - $scope.resetHideResults = function() { - if($scope.hideTimer) { - $timeout.cancel($scope.hideTimer); + $scope.hideResults = function() { + $scope.hideTimer = $timeout(function() { + $scope.showDropdown = false; + }, $scope.pause); }; - }; - $scope.hoverRow = function(index) { - $scope.currentIndex = index; - } + $scope.resetHideResults = function() { + if($scope.hideTimer) { + $timeout.cancel($scope.hideTimer); + }; + }; - $scope.keyPressed = function(event) { - if (!(event.which == 38 || event.which == 40 || event.which == 13)) { - if (!$scope.searchStr || $scope.searchStr == "") { - $scope.showDropdown = false; - $scope.lastSearchTerm = null - } else if (isNewSearchNeeded($scope.searchStr, $scope.lastSearchTerm)) { - $scope.lastSearchTerm = $scope.searchStr - $scope.showDropdown = true; - $scope.currentIndex = -1; - $scope.results = []; + $scope.hoverRow = function(index) { + $scope.currentIndex = index; + } - if ($scope.searchTimer) { - $timeout.cancel($scope.searchTimer); - } + $scope.keyPressed = function(event) { + if (!(event.which == 38 || event.which == 40 || event.which == 13)) { + if (!$scope.searchStr || $scope.searchStr == "") { + $scope.showDropdown = false; + $scope.lastSearchTerm = null + } else if (isNewSearchNeeded($scope.searchStr, $scope.lastSearchTerm)) { + $scope.lastSearchTerm = $scope.searchStr + $scope.showDropdown = true; + $scope.currentIndex = -1; + $scope.results = []; + + if ($scope.searchTimer) { + $timeout.cancel($scope.searchTimer); + } - $scope.searching = true; + $scope.searching = true; - $scope.searchTimer = $timeout(function() { - $scope.searchTimerComplete($scope.searchStr); - }, $scope.pause); + $scope.searchTimer = $timeout(function() { + $scope.searchTimerComplete($scope.searchStr); + }, $scope.pause); + } + } else { + event.preventDefault(); + } + if($scope.searchStr==""){ + $scope.selectedObject = {} + if($scope.onChangeFunction){ + $scope.onChangeFunction(null); + } } - } else { - event.preventDefault(); } - } - $scope.selectResult = function(result) { - if ($scope.matchClass) { - result.title = result.title.toString().replace(/(<([^>]+)>)/ig, ''); + $scope.selectResult = function(result) { + if ($scope.matchClass) { + result.title = result.title.toString().replace(/(<([^>]+)>)/ig, ''); + } + $scope.searchStr = $scope.lastSearchTerm = result.title; + $scope.selectedObject = result; + $scope.showDropdown = false; + $scope.results = []; + if($scope.onChangeFunction){ + $scope.onChangeFunction(result); + } + //$scope.$apply(); } - $scope.searchStr = $scope.lastSearchTerm = result.title; - $scope.selectedObject = result; - $scope.showDropdown = false; - $scope.results = []; - //$scope.$apply(); - } - var inputField = elem.find('input'); + var inputField = elem.find('input'); - inputField.on('keyup', $scope.keyPressed); + inputField.on('keyup', $scope.keyPressed); - elem.on("keyup", function (event) { - if(event.which === 40) { - if ($scope.results && ($scope.currentIndex + 1) < $scope.results.length) { - $scope.currentIndex ++; - $scope.$apply(); - event.preventDefault; - event.stopPropagation(); - } + elem.on("keyup", function (event) { + if(event.which === 40) { + if ($scope.results && ($scope.currentIndex + 1) < $scope.results.length) { + $scope.currentIndex ++; + $scope.$apply(); + event.preventDefault; + event.stopPropagation(); + } - $scope.$apply(); - } else if(event.which == 38) { - if ($scope.currentIndex >= 1) { - $scope.currentIndex --; $scope.$apply(); - event.preventDefault; - event.stopPropagation(); - } + } else if(event.which == 38) { + if ($scope.currentIndex >= 1) { + $scope.currentIndex --; + $scope.$apply(); + event.preventDefault; + event.stopPropagation(); + } - } else if (event.which == 13) { - if ($scope.results && $scope.currentIndex >= 0 && $scope.currentIndex < $scope.results.length) { - $scope.selectResult($scope.results[$scope.currentIndex]); - $scope.$apply(); - event.preventDefault; - event.stopPropagation(); - } else { + } else if (event.which == 13) { + if ($scope.results && $scope.currentIndex >= 0 && $scope.currentIndex < $scope.results.length) { + $scope.selectResult($scope.results[$scope.currentIndex]); + $scope.$apply(); + event.preventDefault; + event.stopPropagation(); + } else { + $scope.results = []; + $scope.$apply(); + event.preventDefault; + event.stopPropagation(); + } + + } else if (event.which == 27) { $scope.results = []; + $scope.showDropdown = false; + $scope.$apply(); + } else if (event.which == 8) { + $scope.selectedObject = null; $scope.$apply(); - event.preventDefault; - event.stopPropagation(); } + }); - } else if (event.which == 27) { - $scope.results = []; - $scope.showDropdown = false; - $scope.$apply(); - } else if (event.which == 8) { - $scope.selectedObject = null; - $scope.$apply(); - } - }); - - } - }; -}); - + } + }; + }); From b140d9779d51412948b331e047d63f7ecf8ca926 Mon Sep 17 00:00:00 2001 From: Ahsan Ayaz Date: Sat, 7 Feb 2015 13:01:09 +0500 Subject: [PATCH 2/2] Included a promisefunction. If a user has a local (processed) data which he fetches from server and then modifies and then want's to search through it, he'll pass the searchStr into the promisefunction, the promise function might use it for http request to gather data, then process it for instance and then it'll resolve the data back to angucomplete, and the angucomplete can search through that data. This is specific for cases where url is not of the type: example.com/get?s= --- angucomplete.js | 97 +++++++++++++++++++++++++++++-------------------- 1 file changed, 58 insertions(+), 39 deletions(-) diff --git a/angucomplete.js b/angucomplete.js index b8ffb45..9d5f067 100644 --- a/angucomplete.js +++ b/angucomplete.js @@ -1,3 +1,7 @@ +/** + * Modified by Ahsan-KoderLabs on 1/20/2015. + */ + /** * Angucomplete * Autocomplete directive for AngularJS @@ -12,7 +16,7 @@ angular.module('angucomplete', [] ) "id": "@id", "placeholder": "@placeholder", "selectedObject": "=selectedobject", - "onChangeFunction":"=onchangefunction", //this will work as ng-change works for ng-model + "onChangeFunction":"=onchangefunction", "url": "@url", "dataField": "@datafield", "titleField": "@titlefield", @@ -24,7 +28,8 @@ angular.module('angucomplete', [] ) "localData": "=localdata", "searchFields": "@searchfields", "minLengthUser": "@minlength", - "matchClass": "@matchclass" + "matchClass": "@matchclass", + "promiseFunction": "=promisefunction" }, template: '
Searching...
No results found
{{ result.title }}
{{result.description}}
', @@ -47,9 +52,9 @@ angular.module('angucomplete', [] ) $scope.pause = $scope.userPause; } - isNewSearchNeeded = function(newTerm, oldTerm) { + var isNewSearchNeeded = function(newTerm, oldTerm) { return newTerm.length >= $scope.minLength && newTerm != oldTerm - } + }; $scope.processResults = function(responseData, str) { if (responseData && responseData.length > 0) { @@ -95,7 +100,7 @@ angular.module('angucomplete', [] ) description: description, image: image, originalObject: responseData[i] - } + }; $scope.results[$scope.results.length] = resultRow; } @@ -108,40 +113,54 @@ angular.module('angucomplete', [] ) $scope.searchTimerComplete = function(str) { // Begin the search + var searchLocal = function(data){ + if(data) $scope.localData = data; + var searchFields = $scope.searchFields.split(","); - if (str.length >= $scope.minLength) { - if ($scope.localData) { - var searchFields = $scope.searchFields.split(","); - - var matches = []; + var matches = []; - for (var i = 0; i < $scope.localData.length; i++) { - var match = false; + for (var i = 0; i < $scope.localData.length; i++) { + var match = false; - for (var s = 0; s < searchFields.length; s++) { - match = match || (typeof $scope.localData[i][searchFields[s]] === 'string' && typeof str === 'string' && $scope.localData[i][searchFields[s]].toLowerCase().indexOf(str.toLowerCase()) >= 0); - } + for (var s = 0; s < searchFields.length; s++) { + match = match || (typeof $scope.localData[i][searchFields[s]] === 'string' && typeof str === 'string' && $scope.localData[i][searchFields[s]].toLowerCase().indexOf(str.toLowerCase()) >= 0); + } - if (match) { - matches[matches.length] = $scope.localData[i]; - } + if (match) { + matches[matches.length] = $scope.localData[i]; } + } - $scope.searching = false; - $scope.processResults(matches, str); + $scope.searching = false; + $scope.processResults(matches, str); + }; - } else { - $http.get($scope.url + str, {}). - success(function(responseData, status, headers, config) { - $scope.searching = false; - $scope.processResults((($scope.dataField) ? responseData[$scope.dataField] : responseData ), str); - }). - error(function(data, status, headers, config) { - console.log("error"); + var getFromURL = function(){ + $http.get($scope.url + str, {}). + success(function(responseData, status, headers, config) { + $scope.searching = false; + $scope.processResults((($scope.dataField) ? responseData[$scope.dataField] : responseData ), str); + }). + error(function(data, status, headers, config) { + console.log("error"); + }); + }; + if (str.length >= $scope.minLength) { + if($scope.localData) { // if the search is to be done from a localData + if($scope.promiseFunction){ // if the localData is gathered from a http call not of the form "url?s=", based on the query of angucomplete input's value + $scope.promiseFunction(angular.copy($scope.searchStr)).then(function(data){ //send the searchStr to promiseFunc to query the serve + searchLocal(data); //now search from the data that's returned after the query }); + } + else{ + searchLocal(); + } + } else { + getFromURL(); } + } - } + }; $scope.hideResults = function() { $scope.hideTimer = $timeout(function() { @@ -152,12 +171,12 @@ angular.module('angucomplete', [] ) $scope.resetHideResults = function() { if($scope.hideTimer) { $timeout.cancel($scope.hideTimer); - }; + } }; $scope.hoverRow = function(index) { $scope.currentIndex = index; - } + }; $scope.keyPressed = function(event) { if (!(event.which == 38 || event.which == 40 || event.which == 13)) { @@ -165,7 +184,7 @@ angular.module('angucomplete', [] ) $scope.showDropdown = false; $scope.lastSearchTerm = null } else if (isNewSearchNeeded($scope.searchStr, $scope.lastSearchTerm)) { - $scope.lastSearchTerm = $scope.searchStr + $scope.lastSearchTerm = $scope.searchStr; $scope.showDropdown = true; $scope.currentIndex = -1; $scope.results = []; @@ -184,12 +203,12 @@ angular.module('angucomplete', [] ) event.preventDefault(); } if($scope.searchStr==""){ - $scope.selectedObject = {} + $scope.selectedObject = {}; if($scope.onChangeFunction){ $scope.onChangeFunction(null); } } - } + }; $scope.selectResult = function(result) { if ($scope.matchClass) { @@ -203,7 +222,7 @@ angular.module('angucomplete', [] ) $scope.onChangeFunction(result); } //$scope.$apply(); - } + }; var inputField = elem.find('input'); @@ -214,7 +233,7 @@ angular.module('angucomplete', [] ) if ($scope.results && ($scope.currentIndex + 1) < $scope.results.length) { $scope.currentIndex ++; $scope.$apply(); - event.preventDefault; + event.preventDefault(); event.stopPropagation(); } @@ -223,7 +242,7 @@ angular.module('angucomplete', [] ) if ($scope.currentIndex >= 1) { $scope.currentIndex --; $scope.$apply(); - event.preventDefault; + event.preventDefault(); event.stopPropagation(); } @@ -231,12 +250,12 @@ angular.module('angucomplete', [] ) if ($scope.results && $scope.currentIndex >= 0 && $scope.currentIndex < $scope.results.length) { $scope.selectResult($scope.results[$scope.currentIndex]); $scope.$apply(); - event.preventDefault; + event.preventDefault(); event.stopPropagation(); } else { $scope.results = []; $scope.$apply(); - event.preventDefault; + event.preventDefault(); event.stopPropagation(); }