PATH:
home
/
letacommog
/
crmleta
/
consumerportal
/
libraries
/
angularjs
/
directives
/
tagbox
/** * A directive to enable tagging auto-complete on an input or textarea. * * For documentation, see the README.md file in this directory * * Created by Michael on 27/03/14. * Copyright Michael Bromley 2014 * Available under the MIT license. */ angular.module('angularUtils.directives.dirTagBox', []) .directive('dirTagbox', function($compile, $parse) { return { restrict: 'A', scope: { tags: '=dirTagbox', callback: '&dirOnTagSelect' }, link: function(scope, element, attrs) { var TOKEN = attrs.dirTagtoken !== undefined ? attrs.dirTagtoken : ''; var input = element; var isValidInputType = (input[0].nodeName === 'INPUT' && (input[0].type === 'text' || input[0].type === 'search' || input[0].type === 'email')); if (input[0].nodeName !== 'TEXTAREA' && !isValidInputType) { return; } // create wrapper div var wrapper = angular.element('<div class="dir-tagbox-wrapper" style="position: relative; display: inline-block"></div>'); input.wrap(wrapper); // create the suggestions div var suggestions = makeSuggestionsBox(); input.parent().append(suggestions); scope.candidateHashtag = "?"; scope.candidate = { start: 0, end: 0 }; scope.selectedIndex = null; scope.filteredTags = []; scope.isFocussed = ('autofocus' in input[0]); var mouseIsOverSuggestions = false; suggestions.on('click', function(e) { var selectedTag = e.target.innerHTML.substring(TOKEN.length); insertSelectedTag(selectedTag); input[0].focus(); scope.$apply(function() { scope.candidateHashtag = "?"; }); }); suggestions.on('mouseover', function() { mouseIsOverSuggestions = true; scope.$apply(function() { scope.selectedIndex = null; }); }); suggestions.on('mouseout', function() { mouseIsOverSuggestions = false; }); input.on('focus', function() { scope.$apply(function() { scope.isFocussed = true; }); }); input.on('blur', function() { if (!mouseIsOverSuggestions) { scope.$apply(function() { scope.isFocussed = false; }); } }); input.on('keyup', function() { // is the caret inside a hashtag? var candidateChanged = false; var currentCaretIndex = getCaret(input[0]); var text = input.val(); var regexp; if (TOKEN !== '') { regexp = new RegExp('\\B' + TOKEN + '\\w+', 'g'); } else { regexp = new RegExp('\\b\\w+', 'g'); } var match; while ((match = regexp.exec(text)) !== null) { var startOfHashtag = match.index; var endOfHashtag = startOfHashtag + match[0].length; if (startOfHashtag <= currentCaretIndex && currentCaretIndex <= endOfHashtag) { candidateChanged = match[0].substring(TOKEN.length); scope.candidate.start = startOfHashtag; scope.candidate.end = endOfHashtag; } } scope.$apply(function() { scope.candidateHashtag = candidateChanged ? candidateChanged : "?"; }); }); input.on('keydown', function(e) { var listLength = scope.filteredTags.length; if (0 < listLength) { var currentIndex; var nextIndex = null; if (e.keyCode === 40) { // down arrow pressed e.preventDefault(); currentIndex = scope.selectedIndex === null ? -1 : parseInt(scope.selectedIndex, 10); nextIndex = currentIndex === listLength - 1 ? 0 : currentIndex + 1; } else if (e.keyCode === 38) { // up arrow pressed e.preventDefault(); currentIndex = scope.selectedIndex === null ? 0 : parseInt(scope.selectedIndex, 10); nextIndex = currentIndex === 0 ? listLength - 1 : currentIndex - 1; } else if (e.keyCode === 13) { // enter key pressed e.preventDefault(); var selectedTag = scope.filteredTags[scope.selectedIndex]; insertSelectedTag(selectedTag); } scope.$apply(function() { scope.selectedIndex = nextIndex; }); } }); function makeSuggestionsBox() { var suggestions =angular.element( '<div class="suggestions-container" ng-show="isFocussed && 0 < filteredTags.length" tabindex="-1">' + '<div class="suggestion" ng-class="{selected: $index == selectedIndex}" ng-repeat="tag in filteredTags = (tags | startsWith : candidateHashtag)">' + TOKEN + '{{ tag }}</div>' + '</div>'); suggestions.css({ 'position': 'absolute', 'width': input[0].offsetWidth + 'px', 'left': input[0].offsetLeft + 'px', 'max-height': '200px', 'overflow': 'auto', 'z-index': 100 }); $compile(suggestions)(scope); return suggestions; } function insertSelectedTag(selectedTag) { var inputVal = input.val(); var output = inputVal.substring(0, scope.candidate.start) + TOKEN + selectedTag + inputVal.substring(scope.candidate.end); scope.$parent.$apply(function() { if (attrs.ngModel) { var setter = $parse(attrs.ngModel).assign; setter(scope.$parent, output); } input.val(output); }); if(scope.callback) { scope.callback(); } } /** * function taken from http://stackoverflow.com/a/263796/772859 * @param el * @returns {*} */ function getCaret(el) { if (el.selectionStart) { return el.selectionStart; } else if (document.selection) { el.focus(); var r = document.selection.createRange(); if (r === null) { return 0; } var re = el.createTextRange(), rc = re.duplicate(); re.moveToBookmark(r.getBookmark()); rc.setEndPoint('EndToStart', re); return rc.text.length; } return 0; } } }; }) /** * Note - this filter is included since the default Angular `filter` filter will match a string that appears anywhere in the target string, but typically in a tag autocomplete, we only care about * matching the start of the string. */ .filter('startsWith', function() { return function(array, search) { var matches = []; for(var i = 0; i < array.length; i++) { if (array[i].indexOf(search) === 0 && search.length < array[i].length) { matches.push(array[i]); } } return matches; }; });
[+]
..
[-] dirTagbox.js
[edit]
[-] dirTagbox.spec.js
[edit]
[-] README.md
[edit]