diff --git a/README.md b/README.md index 18f0ae4..8408a0a 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,55 @@ -angular-multiselect -=================== +# A Native AngularJS multiselect directive -Native AngularJS multiselect directive - Work in progress. Contributions welcome! -Example: http://plnkr.co/edit/LPGYIf?p=preview +#### index.html +```html + + + + + + + -License -======= -The MIT License + +
+ {{selectedCar}} +
+ + + +``` + + +#### app.js +```js +var app = angular.module('plunker', ['ui.multiselect']); + +app.controller('MainCtrl', function($scope) { + $scope.cars = [{id:1, name: 'Audi'}, {id:2, name: 'BMW'}, {id:3, name: 'Honda'}]; + $scope.selectedCar = []; +}); +``` + + +#### After selecting 'Audi' and 'Honda', the model will look like: +``` + $scope.selectedCar = [1, 3]; +``` + + +#### Change options to `car.name for car in cars` for a data model like: +``` + $scope.selectedCar = [{id:1, name: 'Audi'}, {id:3, name: 'Honda'}]; +``` + +#### Changing options to `car.id for car in cars` will change the options labels in the UI: +`'Audi', 'BMW', 'Honda'` -> `'1', '2', '3'` + + +## Example +http://plnkr.co/edit/LPGYIf?p=preview + +## License + +MIT diff --git a/src/multiselect.js b/src/multiselect.js index 5585734..5bac9fb 100644 --- a/src/multiselect.js +++ b/src/multiselect.js @@ -50,7 +50,7 @@ angular.module('ui.multiselect', []) scope.$destroy(); }); - var popUpEl = angular.element(''); + var popUpEl = angular.element(''); //required validator if (attrs.required || attrs.ngRequired) { @@ -236,37 +236,60 @@ angular.module('ui.multiselect', []) link: function (scope, element, attrs) { scope.isVisible = false; + scope.eventHandlerIsBound = false; + scope.multiple = attrs.multiple ? true : false; scope.toggleSelect = function () { if (element.hasClass('open')) { element.removeClass('open'); - $document.unbind('click', clickHandler); } else { element.addClass('open'); - $document.bind('click', clickHandler); + scope.bindEventHandler(); + scope.resize(); scope.focus(); } }; - function clickHandler(event) { - if (elementMatchesAnyInArray(event.target, element.find(event.target.tagName))) + scope.bindEventHandler = function() { + if (scope.eventHandlerIsBound) { return; - element.removeClass('open'); - $document.unbind('click', clickHandler); - scope.$apply(); + } + element.find('ul, ul *').bind('click', function(event) { + if ((scope.multiple && 'A' == event.target.tagName) || (!scope.multiple && 'A' != event.target.tagName)) { + event.stopPropagation(); + } + else { + var inSelection = false + , aTags = element.find('a'); + for (var i = 0; i < aTags.length; i++) { + if ($(event.target).parents('a:first')[0] == aTags[i]) { + inSelection = true; + break; + } + } + if (scope.multiple && inSelection) { + $(event.target).parents('a').click(); + event.stopPropagation(); + } + } + }); + scope.eventHandlerIsBound = true; + } + + scope.resize = function() { + var $ul = element.find('ul') + , margin = 50 + , top = $ul.position().top + , maxHeight = $(window).innerHeight(); + if (($ul.height() + top) > maxHeight) { + $ul.css({height: (maxHeight - top - margin), overflow: 'scroll'}); + } } scope.focus = function focus(){ var searchBox = element.find('input')[0]; searchBox.focus(); } - - var elementMatchesAnyInArray = function (element, elementArray) { - for (var i = 0; i < elementArray.length; i++) - if (element == elementArray[i]) - return true; - return false; - } } } }]);