diff --git a/app/__module.js b/app/__module.js index 9eaa6248d..881453c9a 100644 --- a/app/__module.js +++ b/app/__module.js @@ -1,5 +1,4 @@ import '../assets/css/app.css'; -import './libraries/isteven-angular-multiselect/isteven-multi-select.css'; import angular from 'angular'; import './agent/_module'; diff --git a/app/libraries/isteven-angular-multiselect/.npmignore b/app/libraries/isteven-angular-multiselect/.npmignore deleted file mode 100644 index 84a23b94d..000000000 --- a/app/libraries/isteven-angular-multiselect/.npmignore +++ /dev/null @@ -1,8 +0,0 @@ -.git -.gitignore -bower.json -CHANGELOG.md -package.json -README.md -screenshot.png -/doc diff --git a/app/libraries/isteven-angular-multiselect/LICENSE.txt b/app/libraries/isteven-angular-multiselect/LICENSE.txt deleted file mode 100644 index 6e524fa92..000000000 --- a/app/libraries/isteven-angular-multiselect/LICENSE.txt +++ /dev/null @@ -1,21 +0,0 @@ -The MIT License (MIT) - -Copyright (c) 2014-2015 Ignatius Steven (https://github.com/isteven) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/app/libraries/isteven-angular-multiselect/README.md b/app/libraries/isteven-angular-multiselect/README.md deleted file mode 100644 index 9c6255bcf..000000000 --- a/app/libraries/isteven-angular-multiselect/README.md +++ /dev/null @@ -1,50 +0,0 @@ -# AngularJS MultiSelect -Pure AngularJS directive which creates a dropdown button with multiple or single selections. -Doesn't require jQuery and works well with other Javascript libraries. - -![Screenshot](https://raw.githubusercontent.com/isteven/angular-multi-select/master/screenshot.png) - -### Demo & How To -Go to http://isteven.github.io/angular-multi-select - -### Current Version -4.0.0 - -### Change Log -See CHANGELOG.md. -For those who's upgrading from version 2.x.x, do note that this version is not backward-compatible. Please read the manual -thoroughly and update your code accordingly. - -### Bug Reporting -Please follow these steps: - -1. **READ THE MANUAL AGAIN**. You might have missed something. This includes the MINIMUM ANGULARJS VERSION and the SUPPORTED BROWSERS. -2. The next step is to search in Github's issue section first. There might already be an answer for similar issue. Do check both open and closed issues. -3. If there's no previous issue found, then please create a new issue in https://github.com/isteven/angular-multi-select/issues. -4. Please **replicate the problem in JSFiddle or Plunker** (or any other online JS collaboration tool), and include the URL in the issue you are creating. -5. When you're done, please close the issue you've created. - -### Licence -Released under the MIT license: - -The MIT License (MIT) - -Copyright (c) 2014-2015 Ignatius Steven (https://github.com/isteven) - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. diff --git a/app/libraries/isteven-angular-multiselect/isteven-multi-select.css b/app/libraries/isteven-angular-multiselect/isteven-multi-select.css deleted file mode 100644 index 44dfc95f5..000000000 --- a/app/libraries/isteven-angular-multiselect/isteven-multi-select.css +++ /dev/null @@ -1,299 +0,0 @@ -/* - * Don't modify things marked with ! - unless you know what you're doing - */ - -/* ! vertical layout */ -.multiSelect .vertical { - float: none; -} - -/* ! horizontal layout */ -.multiSelect .horizontal:not(.multiSelectGroup) { - float: left; -} - -/* ! create a "row" */ -.multiSelect .line { - padding: 2px 0px 4px 0px; - max-height: 30px; - overflow: hidden; - box-sizing: content-box; -} - -/* ! create a "column" */ -.multiSelect .acol { - display: inline-block; - min-width: 12px; -} - -/* ! */ -.multiSelect .inlineBlock { - display: inline-block; -} - -/* the multiselect button */ -.multiSelect > button { - display: inline-block; - position: relative; - text-align: center; - cursor: pointer; - border: 1px solid #c6c6c6; - padding: 1px 8px 1px 8px; - font-size: 14px; - min-height : 38px !important; - border-radius: 4px; - color: #555; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - -o-user-select: none; - user-select: none; - white-space:normal; - background-color: #fff; - background-image: linear-gradient(#fff, #f7f7f7); -} - -/* button: hover */ -.multiSelect > button:hover { - background-image: linear-gradient(#fff, #e9e9e9); -} - -/* button: disabled */ -.multiSelect > button:disabled { - background-image: linear-gradient(#fff, #fff); - border: 1px solid #ddd; - color: #999; -} - -/* button: clicked */ -.multiSelect .buttonClicked { - box-shadow: 0 2px 5px rgba(0, 0, 0, 0.15) inset, 0 1px 2px rgba(0, 0, 0, 0.05); -} - -/* labels on the button */ -.multiSelect .buttonLabel { - display: inline-block; - padding: 5px 0px 5px 0px; -} - -/* downward pointing arrow */ -.multiSelect .caret { - display: inline-block; - width: 0; - height: 0; - margin: 0px 0px 1px 12px !important; - vertical-align: middle; - border-top: 4px solid #333; - border-right: 4px solid transparent; - border-left: 4px solid transparent; - border-bottom: 0 dotted; -} - -/* the main checkboxes and helper layer */ -.multiSelect .checkboxLayer { - background-color: #fff; - position: absolute; - z-index: 999; - border: 1px solid rgba(0, 0, 0, 0.15); - border-radius: 4px; - -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); - box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175); - min-width:278px; - display: none !important; -} - -/* container of helper elements */ -.multiSelect .helperContainer { - border-bottom: 1px solid #ddd; - padding: 8px 8px 0px 8px; -} - -/* helper buttons (select all, none, reset); */ -.multiSelect .helperButton { - display: inline; - text-align: center; - cursor: pointer; - border: 1px solid #ccc; - height: 26px; - font-size: 13px; - border-radius: 2px; - color: #666; - background-color: #f1f1f1; - line-height: 1.6; - margin: 0px 0px 8px 0px; -} - -.multiSelect .helperButton.reset{ - float: right; -} - -.multiSelect .helperButton:not( .reset ) { - margin-right: 4px; -} - -/* clear button */ -.multiSelect .clearButton { - position: absolute; - display: inline; - text-align: center; - cursor: pointer; - border: 1px solid #ccc; - height: 22px; - width: 22px; - font-size: 13px; - border-radius: 2px; - color: #666; - background-color: #f1f1f1; - line-height: 1.4; - right : 2px; - top: 4px; -} - -/* filter */ -.multiSelect .inputFilter { - border-radius: 2px; - border: 1px solid #ccc; - height: 26px; - font-size: 14px; - width:100%; - padding-left:7px; - -webkit-box-sizing: border-box; /* Safari/Chrome, other WebKit */ - -moz-box-sizing: border-box; /* Firefox, other Gecko */ - box-sizing: border-box; /* Opera/IE 8+ */ - color: #888; - margin: 0px 0px 8px 0px; - -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); - box-shadow: inset 0 1px 1px rgba(0, 0, 0, .075); -} - -/* helper elements on hover & focus */ -.multiSelect .clearButton:hover, -.multiSelect .helperButton:hover { - border: 1px solid #ccc; - color: #999; - background-color: #f4f4f4; -} -.multiSelect .helperButton:disabled { - color: #ccc; - border: 1px solid #ddd; -} - -.multiSelect .clearButton:focus, -.multiSelect .helperButton:focus, -.multiSelect .inputFilter:focus { - border: 1px solid #66AFE9 !important; - outline: 0; - -webkit-box-shadow: inset 0 0 1px rgba(0,0,0,.065), 0 0 5px rgba(102, 175, 233, .6) !important; - box-shadow: inset 0 0 1px rgba(0,0,0,.065), 0 0 5px rgba(102, 175, 233, .6) !important; -} - -/* container of multi select items */ -.multiSelect .checkBoxContainer { - display: block; - padding: 8px; - overflow: hidden; -} - -/* ! to show / hide the checkbox layer above */ -.multiSelect .show { - display: block !important; -} - -/* item labels */ -.multiSelect .multiSelectItem { - display: block; - padding: 3px; - color: #444; - white-space: nowrap; - -webkit-user-select: none; - -moz-user-select: none; - -ms-user-select: none; - -o-user-select: none; - user-select: none; - border: 1px solid transparent; - position: relative; - min-width:278px; - min-height: 32px; -} - -/* Styling on selected items */ -.multiSelect .multiSelectItem:not(.multiSelectGroup).selected -{ - background-image: linear-gradient( #e9e9e9, #f1f1f1 ); - color: #555; - cursor: pointer; - border-top: 1px solid #e4e4e4; - border-left: 1px solid #e4e4e4; - border-right: 1px solid #d9d9d9; -} - -.multiSelect .multiSelectItem .acol label { - display: inline-block; - padding-right: 30px; - margin: 0px; - font-weight: normal; - line-height: normal; -} - -/* item labels focus on mouse hover */ -.multiSelect .multiSelectItem:hover, -.multiSelect .multiSelectGroup:hover { - background-image: linear-gradient( #c1c1c1, #999 ) !important; - color: #fff !important; - cursor: pointer; - border: 1px solid #ccc !important; -} - -/* item labels focus using keyboard */ -.multiSelect .multiSelectFocus { - background-image: linear-gradient( #c1c1c1, #999 ) !important; - color: #fff !important; - cursor: pointer; - border: 1px solid #ccc !important; -} - -/* change mouse pointer into the pointing finger */ -.multiSelect .multiSelectItem span:hover, -.multiSelect .multiSelectGroup span:hover -{ - cursor: pointer; -} - -/* ! group labels */ -.multiSelect .multiSelectGroup { - display: block; - clear: both; -} - -/* right-align the tick mark (✔) */ -.multiSelect .tickMark { - display:inline-block; - position: absolute; - right: 10px; - top: 7px; - font-size: 10px; -} - -/* hide the original HTML checkbox away */ -.multiSelect .checkbox { - color: #ddd !important; - position: absolute; - left: -9999px; - cursor: pointer; -} - -/* checkboxes currently disabled */ -.multiSelect .disabled, -.multiSelect .disabled:hover, -.multiSelect .disabled label input:hover ~ span { - color: #c4c4c4 !important; - cursor: not-allowed !important; -} - -/* If you use images in button / checkbox label, you might want to change the image style here. */ -.multiSelect img { - vertical-align: middle; - margin-bottom:0px; - max-height: 22px; - max-width:22px; -} diff --git a/app/libraries/isteven-angular-multiselect/isteven-multi-select.js b/app/libraries/isteven-angular-multiselect/isteven-multi-select.js deleted file mode 100644 index 02b136aa3..000000000 --- a/app/libraries/isteven-angular-multiselect/isteven-multi-select.js +++ /dev/null @@ -1,1127 +0,0 @@ -/* - * Angular JS Multi Select - * Creates a dropdown-like button with checkboxes. - * - * Project started on: Tue, 14 Jan 2014 - 5:18:02 PM - * Current version: 4.0.0 - * - * Released under the MIT License - * -------------------------------------------------------------------------------- - * The MIT License (MIT) - * - * Copyright (c) 2014 Ignatius Steven (https://github.com/isteven) - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all - * copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - * -------------------------------------------------------------------------------- - */ - -'use strict' - -angular.module( 'isteven-multi-select', ['ng'] ).directive( 'istevenMultiSelect' , [ '$sce', '$timeout', '$sanitize', function ( $sce, $timeout, $sanitize) { - return { - restrict: - 'AE', - - scope: - { - // models - inputModel : '=', - outputModel : '=', - - // settings based on attribute - isDisabled : '=', - - // callbacks - onClear : '&', - onClose : '&', - onSearchChange : '&', - onItemClick : '&', - onOpen : '&', - onReset : '&', - onSelectAll : '&', - onSelectNone : '&', - - // i18n - translation : '=' - }, - - /* - * The rest are attributes. They don't need to be parsed / binded, so we can safely access them by value. - * - buttonLabel, directiveId, helperElements, itemLabel, maxLabels, orientation, selectionMode, minSearchLength, - * tickProperty, disableProperty, groupProperty, searchProperty, maxHeight, outputProperties - */ - - templateUrl: - 'isteven-multi-select.htm', - - link: function ( $scope, element, attrs ) { - - $scope.backUp = []; - $scope.varButtonLabel = ''; - $scope.spacingProperty = ''; - $scope.indexProperty = ''; - $scope.orientationH = false; - $scope.orientationV = true; - $scope.filteredModel = []; - $scope.inputLabel = { labelFilter: '' }; - $scope.tabIndex = 0; - $scope.lang = {}; - $scope.helperStatus = { - all : true, - none : true, - reset : true, - filter : true - }; - - var - prevTabIndex = 0, - helperItems = [], - helperItemsLength = 0, - checkBoxLayer = '', - // scrolled = false, - // selectedItems = [], - formElements = [], - vMinSearchLength = 0, - clickedItem = null - - // v3.0.0 - // clear button clicked - $scope.clearClicked = function( e ) { - $scope.inputLabel.labelFilter = ''; - $scope.updateFilter(); - $scope.select( 'clear', e ); - } - - // A little hack so that AngularJS ng-repeat can loop using start and end index like a normal loop - // http://stackoverflow.com/questions/16824853/way-to-ng-repeat-defined-number-of-times-instead-of-repeating-over-array - $scope.numberToArray = function( num ) { - return new Array( num ); - } - - // Call this function when user type on the filter field - $scope.searchChanged = function() { - if ( $scope.inputLabel.labelFilter.length < vMinSearchLength && $scope.inputLabel.labelFilter.length > 0 ) { - return false; - } - $scope.updateFilter(); - } - - $scope.updateFilter = function() - { - // we check by looping from end of input-model - $scope.filteredModel = []; - var i = 0; - - if ( typeof $scope.inputModel === 'undefined' ) { - return false; - } - - for( i = $scope.inputModel.length - 1; i >= 0; i-- ) { - - // if it's group end, we push it to filteredModel[]; - if ( typeof $scope.inputModel[ i ][ attrs.groupProperty ] !== 'undefined' && $scope.inputModel[ i ][ attrs.groupProperty ] === false ) { - $scope.filteredModel.push( $scope.inputModel[ i ] ); - } - - // if it's data - var gotData = false; - if ( typeof $scope.inputModel[ i ][ attrs.groupProperty ] === 'undefined' ) { - - // If we set the search-key attribute, we use this loop. - if ( typeof attrs.searchProperty !== 'undefined' && attrs.searchProperty !== '' ) { - - for (const key in $scope.inputModel[ i ] ) { - if ( - typeof $scope.inputModel[ i ][ key ] !== 'boolean' - && String( $scope.inputModel[ i ][ key ] ).toUpperCase().indexOf( $scope.inputLabel.labelFilter.toUpperCase() ) >= 0 - && attrs.searchProperty.indexOf( key ) > -1 - ) { - gotData = true; - break; - } - } - } - // if there's no search-key attribute, we use this one. Much better on performance. - else { - for ( const key in $scope.inputModel[ i ] ) { - if ( - typeof $scope.inputModel[ i ][ key ] !== 'boolean' - && String( $scope.inputModel[ i ][ key ] ).toUpperCase().indexOf( $scope.inputLabel.labelFilter.toUpperCase() ) >= 0 - ) { - gotData = true; - break; - } - } - } - - if ( gotData === true ) { - // push - $scope.filteredModel.push( $scope.inputModel[ i ] ); - } - } - - // if it's group start - if ( typeof $scope.inputModel[ i ][ attrs.groupProperty ] !== 'undefined' && $scope.inputModel[ i ][ attrs.groupProperty ] === true ) { - - if ( typeof $scope.filteredModel[ $scope.filteredModel.length - 1 ][ attrs.groupProperty ] !== 'undefined' - && $scope.filteredModel[ $scope.filteredModel.length - 1 ][ attrs.groupProperty ] === false ) { - $scope.filteredModel.pop(); - } - else { - $scope.filteredModel.push( $scope.inputModel[ i ] ); - } - } - } - - $scope.filteredModel.reverse(); - - $timeout( function() { - - $scope.getFormElements(); - - // Callback: on filter change - if ( $scope.inputLabel.labelFilter.length > vMinSearchLength ) { - - var filterObj = []; - - angular.forEach( $scope.filteredModel, function( value ) { - if ( typeof value !== 'undefined' ) { - if ( typeof value[ attrs.groupProperty ] === 'undefined' ) { - var tempObj = angular.copy( value ); - var index = filterObj.push( tempObj ); - delete filterObj[ index - 1 ][ $scope.indexProperty ]; - delete filterObj[ index - 1 ][ $scope.spacingProperty ]; - } - } - }); - - $scope.onSearchChange({ - data: - { - keyword: $scope.inputLabel.labelFilter, - result: filterObj - } - }); - } - },0); - }; - - // List all the input elements. We need this for our keyboard navigation. - // This function will be called everytime the filter is updated. - // Depending on the size of filtered mode, might not good for performance, but oh well.. - $scope.getFormElements = function() { - formElements = []; - - var - selectButtons = [], - inputField = [], - checkboxes = [], - clearButton = []; - - // If available, then get select all, select none, and reset buttons - if ( $scope.helperStatus.all || $scope.helperStatus.none || $scope.helperStatus.reset ) { - selectButtons = element.children().children().next().children().children()[ 0 ].getElementsByTagName( 'button' ); - // If available, then get the search box and the clear button - if ( $scope.helperStatus.filter ) { - // Get helper - search and clear button. - inputField = element.children().children().next().children().children().next()[ 0 ].getElementsByTagName( 'input' ); - clearButton = element.children().children().next().children().children().next()[ 0 ].getElementsByTagName( 'button' ); - } - } - else { - if ( $scope.helperStatus.filter ) { - // Get helper - search and clear button. - inputField = element.children().children().next().children().children()[ 0 ].getElementsByTagName( 'input' ); - clearButton = element.children().children().next().children().children()[ 0 ].getElementsByTagName( 'button' ); - } - } - - // Get checkboxes - if ( !$scope.helperStatus.all && !$scope.helperStatus.none && !$scope.helperStatus.reset && !$scope.helperStatus.filter ) { - checkboxes = element.children().children().next()[ 0 ].getElementsByTagName( 'input' ); - } - else { - checkboxes = element.children().children().next().children().next()[ 0 ].getElementsByTagName( 'input' ); - } - - // Push them into global array formElements[] - for ( let i = 0; i < selectButtons.length ; i++ ) { formElements.push( selectButtons[ i ] ); } - for ( let i = 0; i < inputField.length ; i++ ) { formElements.push( inputField[ i ] ); } - for ( let i = 0; i < clearButton.length ; i++ ) { formElements.push( clearButton[ i ] ); } - for ( let i = 0; i < checkboxes.length ; i++ ) { formElements.push( checkboxes[ i ] ); } - } - - // check if an item has attrs.groupProperty (be it true or false) - $scope.isGroupMarker = function( item , type ) { - if ( typeof item[ attrs.groupProperty ] !== 'undefined' && item[ attrs.groupProperty ] === type ) return true; - return false; - } - - $scope.removeGroupEndMarker = function( item ) { - if ( typeof item[ attrs.groupProperty ] !== 'undefined' && item[ attrs.groupProperty ] === false ) return false; - return true; - } - - // call this function when an item is clicked - $scope.syncItems = function( item, e, ng_repeat_index ) { - - e.preventDefault(); - e.stopPropagation(); - - // if the directive is globaly disabled, do nothing - if ( typeof attrs.disableProperty !== 'undefined' && item[ attrs.disableProperty ] === true ) { - return false; - } - - // if item is disabled, do nothing - if ( typeof attrs.isDisabled !== 'undefined' && $scope.isDisabled === true ) { - return false; - } - - // if end group marker is clicked, do nothing - if ( typeof item[ attrs.groupProperty ] !== 'undefined' && item[ attrs.groupProperty ] === false ) { - return false; - } - - var index = $scope.filteredModel.indexOf( item ); - - // if the start of group marker is clicked ( only for multiple selection! ) - // how it works: - // - if, in a group, there are items which are not selected, then they all will be selected - // - if, in a group, all items are selected, then they all will be de-selected - if ( typeof item[ attrs.groupProperty ] !== 'undefined' && item[ attrs.groupProperty ] === true ) { - - // this is only for multiple selection, so if selection mode is single, do nothing - if ( typeof attrs.selectionMode !== 'undefined' && attrs.selectionMode.toUpperCase() === 'SINGLE' ) { - return false; - } - - var i, j; - var startIndex = 0; - var endIndex = $scope.filteredModel.length - 1; - var tempArr = []; - - // nest level is to mark the depth of the group. - // when you get into a group (start group marker), nestLevel++ - // when you exit a group (end group marker), nextLevel-- - var nestLevel = 0; - - // we loop throughout the filtered model (not whole model) - for( i = index ; i < $scope.filteredModel.length ; i++) { - - // this break will be executed when we're done processing each group - if ( nestLevel === 0 && i > index ) - { - break; - } - - if ( typeof $scope.filteredModel[ i ][ attrs.groupProperty ] !== 'undefined' && $scope.filteredModel[ i ][ attrs.groupProperty ] === true ) { - - // To cater multi level grouping - if ( tempArr.length === 0 ) { - startIndex = i + 1; - } - nestLevel = nestLevel + 1; - } - - // if group end - else if ( typeof $scope.filteredModel[ i ][ attrs.groupProperty ] !== 'undefined' && $scope.filteredModel[ i ][ attrs.groupProperty ] === false ) { - - nestLevel = nestLevel - 1; - - // cek if all are ticked or not - if ( tempArr.length > 0 && nestLevel === 0 ) { - - var allTicked = true; - - endIndex = i; - - for ( j = 0; j < tempArr.length ; j++ ) { - if ( typeof tempArr[ j ][ $scope.tickProperty ] !== 'undefined' && tempArr[ j ][ $scope.tickProperty ] === false ) { - allTicked = false; - break; - } - } - - if ( allTicked === true ) { - for ( j = startIndex; j <= endIndex ; j++ ) { - if ( typeof $scope.filteredModel[ j ][ attrs.groupProperty ] === 'undefined' ) { - if ( typeof attrs.disableProperty === 'undefined' ) { - $scope.filteredModel[ j ][ $scope.tickProperty ] = false; - // we refresh input model as well - inputModelIndex = $scope.filteredModel[ j ][ $scope.indexProperty ]; - $scope.inputModel[ inputModelIndex ][ $scope.tickProperty ] = false; - } - else if ( $scope.filteredModel[ j ][ attrs.disableProperty ] !== true ) { - $scope.filteredModel[ j ][ $scope.tickProperty ] = false; - // we refresh input model as well - inputModelIndex = $scope.filteredModel[ j ][ $scope.indexProperty ]; - $scope.inputModel[ inputModelIndex ][ $scope.tickProperty ] = false; - } - } - } - } - - else { - for ( j = startIndex; j <= endIndex ; j++ ) { - if ( typeof $scope.filteredModel[ j ][ attrs.groupProperty ] === 'undefined' ) { - if ( typeof attrs.disableProperty === 'undefined' ) { - $scope.filteredModel[ j ][ $scope.tickProperty ] = true; - // we refresh input model as well - inputModelIndex = $scope.filteredModel[ j ][ $scope.indexProperty ]; - $scope.inputModel[ inputModelIndex ][ $scope.tickProperty ] = true; - - } - else if ( $scope.filteredModel[ j ][ attrs.disableProperty ] !== true ) { - $scope.filteredModel[ j ][ $scope.tickProperty ] = true; - // we refresh input model as well - inputModelIndex = $scope.filteredModel[ j ][ $scope.indexProperty ]; - $scope.inputModel[ inputModelIndex ][ $scope.tickProperty ] = true; - } - } - } - } - } - } - - // if data - else { - tempArr.push( $scope.filteredModel[ i ] ); - } - } - } - - // if an item (not group marker) is clicked - else { - - // If it's single selection mode - if ( typeof attrs.selectionMode !== 'undefined' && attrs.selectionMode.toUpperCase() === 'SINGLE' ) { - - // first, set everything to false - for( i=0 ; i < $scope.filteredModel.length ; i++) { - $scope.filteredModel[ i ][ $scope.tickProperty ] = false; - } - for( i=0 ; i < $scope.inputModel.length ; i++) { - $scope.inputModel[ i ][ $scope.tickProperty ] = false; - } - - // then set the clicked item to true - $scope.filteredModel[ index ][ $scope.tickProperty ] = true; - } - - // Multiple - else { - $scope.filteredModel[ index ][ $scope.tickProperty ] = !$scope.filteredModel[ index ][ $scope.tickProperty ]; - } - - // we refresh input model as well - var inputModelIndex = $scope.filteredModel[ index ][ $scope.indexProperty ]; - $scope.inputModel[ inputModelIndex ][ $scope.tickProperty ] = $scope.filteredModel[ index ][ $scope.tickProperty ]; - } - - // we execute the callback function here - clickedItem = angular.copy( item ); - if ( clickedItem !== null ) { - $timeout( function() { - delete clickedItem[ $scope.indexProperty ]; - delete clickedItem[ $scope.spacingProperty ]; - $scope.onItemClick( { data: clickedItem } ); - clickedItem = null; - }, 0 ); - } - - $scope.refreshOutputModel(); - $scope.refreshButton(); - - // We update the index here - prevTabIndex = $scope.tabIndex; - $scope.tabIndex = ng_repeat_index + helperItemsLength; - - // Set focus on the hidden checkbox - e.target.focus(); - - // set & remove CSS style - $scope.removeFocusStyle( prevTabIndex ); - $scope.setFocusStyle( $scope.tabIndex ); - - if ( typeof attrs.selectionMode !== 'undefined' && attrs.selectionMode.toUpperCase() === 'SINGLE' ) { - // on single selection mode, we then hide the checkbox layer - $scope.toggleCheckboxes( e ); - } - } - - // update $scope.outputModel - $scope.refreshOutputModel = function() { - - $scope.outputModel = []; - var - outputProps = [], - tempObj = {}; - - // v4.0.0 - if ( typeof attrs.outputProperties !== 'undefined' ) { - outputProps = attrs.outputProperties.split(' '); - angular.forEach( $scope.inputModel, function( value ) { - if ( - typeof value !== 'undefined' - && typeof value[ attrs.groupProperty ] === 'undefined' - && value[ $scope.tickProperty ] === true - ) { - tempObj = {}; - angular.forEach( value, function( value1, key1 ) { - if ( outputProps.indexOf( key1 ) > -1 ) { - tempObj[ key1 ] = value1; - } - }); - var index = $scope.outputModel.push( tempObj ); - delete $scope.outputModel[ index - 1 ][ $scope.indexProperty ]; - delete $scope.outputModel[ index - 1 ][ $scope.spacingProperty ]; - } - }); - } - else { - angular.forEach( $scope.inputModel, function( value ) { - if ( - typeof value !== 'undefined' - && typeof value[ attrs.groupProperty ] === 'undefined' - && value[ $scope.tickProperty ] === true - ) { - var temp = angular.copy( value ); - var index = $scope.outputModel.push( temp ); - delete $scope.outputModel[ index - 1 ][ $scope.indexProperty ]; - delete $scope.outputModel[ index - 1 ][ $scope.spacingProperty ]; - } - }); - } - } - - // refresh button label - $scope.refreshButton = function() { - - $scope.varButtonLabel = ''; - var ctr = 0; - - // refresh button label... - if ( $scope.outputModel.length === 0 ) { - // https://github.com/isteven/angular-multi-select/pull/19 - $scope.varButtonLabel = $scope.lang.nothingSelected; - } - else { - var tempMaxLabels = $scope.outputModel.length; - if ( typeof attrs.maxLabels !== 'undefined' && attrs.maxLabels !== '' ) { - tempMaxLabels = attrs.maxLabels; - } - - // if max amount of labels displayed.. - if ( $scope.outputModel.length > tempMaxLabels ) { - $scope.more = true; - } - else { - $scope.more = false; - } - - angular.forEach( $scope.inputModel, function( value ) { - if ( typeof value !== 'undefined' && value[ attrs.tickProperty ] === true ) { - if ( ctr < tempMaxLabels ) { - $scope.varButtonLabel += ( $scope.varButtonLabel.length > 0 ? ',
' : '
') + $scope.writeLabel( value, 'buttonLabel' ); - } - ctr++; - } - }); - - if ( $scope.more === true ) { - // https://github.com/isteven/angular-multi-select/pull/16 - if (tempMaxLabels > 0) { - $scope.varButtonLabel += ', ... '; - } - $scope.varButtonLabel += '(' + $scope.outputModel.length + ')'; - } - } - // $scope.varButtonLabel = $sce.trustAsHtml( $scope.varButtonLabel + '' ); - $scope.varButtonLabel = $sanitize($scope.varButtonLabel + ''); - } - - // Check if a checkbox is disabled or enabled. It will check the granular control (disableProperty) and global control (isDisabled) - // Take note that the granular control has higher priority. - $scope.itemIsDisabled = function( item ) { - - if ( typeof attrs.disableProperty !== 'undefined' && item[ attrs.disableProperty ] === true ) { - return true; - } - else { - if ( $scope.isDisabled === true ) { - return true; - } - else { - return false; - } - } - - } - - // A simple function to parse the item label settings. Used on the buttons and checkbox labels. - $scope.writeLabel = function( item, type ) { - // type is either 'itemLabel' or 'buttonLabel' - var temp = attrs[ type ].split( ' ' ); - var label = ''; - - angular.forEach( temp, function( value ) { - item[ value ] && ( label += ' ' + value.split( '.' ).reduce( function( prev, current ) { - return prev[ current ]; - }, item )); - }); - - if ( type.toUpperCase() === 'BUTTONLABEL' ) { - return label; - } - // return $sce.trustAsHtml( label ); - return $sanitize(label); - } - - // UI operations to show/hide checkboxes based on click event.. - $scope.toggleCheckboxes = function( ) { - - // We grab the button - var clickedEl = element.children()[0]; - - // Just to make sure.. had a bug where key events were recorded twice - angular.element( document ).off( 'click', $scope.externalClickListener ); - angular.element( document ).off( 'keydown', $scope.keyboardListener ); - - // The idea below was taken from another multi-select directive - https://github.com/amitava82/angular-multiselect - // His version is awesome if you need a more simple multi-select approach. - - // close - if ( angular.element( checkBoxLayer ).hasClass( 'show' )) { - - angular.element( checkBoxLayer ).removeClass( 'show' ); - angular.element( clickedEl ).removeClass( 'buttonClicked' ); - angular.element( document ).off( 'click', $scope.externalClickListener ); - angular.element( document ).off( 'keydown', $scope.keyboardListener ); - - // clear the focused element; - $scope.removeFocusStyle( $scope.tabIndex ); - if ( typeof formElements[ $scope.tabIndex ] !== 'undefined' ) { - formElements[ $scope.tabIndex ].blur(); - } - - // close callback - $timeout( function() { - $scope.onClose(); - }, 0 ); - - // set focus on button again - element.children().children()[ 0 ].focus(); - } - // open - else - { - // clear filter - $scope.inputLabel.labelFilter = ''; - $scope.updateFilter(); - - helperItems = []; - helperItemsLength = 0; - - angular.element( checkBoxLayer ).addClass( 'show' ); - angular.element( clickedEl ).addClass( 'buttonClicked' ); - - // Attach change event listener on the input filter. - // We need this because ng-change is apparently not an event listener. - angular.element( document ).on( 'click', $scope.externalClickListener ); - angular.element( document ).on( 'keydown', $scope.keyboardListener ); - - // to get the initial tab index, depending on how many helper elements we have. - // priority is to always focus it on the input filter - $scope.getFormElements(); - $scope.tabIndex = 0; - - var helperContainer = angular.element( element[ 0 ].querySelector( '.helperContainer' ) )[0]; - - if ( typeof helperContainer !== 'undefined' ) { - for ( var i = 0; i < helperContainer.getElementsByTagName( 'BUTTON' ).length ; i++ ) { - helperItems[ i ] = helperContainer.getElementsByTagName( 'BUTTON' )[ i ]; - } - helperItemsLength = helperItems.length + helperContainer.getElementsByTagName( 'INPUT' ).length; - } - - // focus on the filter element on open. - if ( element[ 0 ].querySelector( '.inputFilter' ) ) { - element[ 0 ].querySelector( '.inputFilter' ).focus(); - $scope.tabIndex = $scope.tabIndex + helperItemsLength - 2; - // blur button in vain - angular.element( element ).children()[ 0 ].blur(); - } - // if there's no filter then just focus on the first checkbox item - else { - if ( !$scope.isDisabled ) { - $scope.tabIndex = $scope.tabIndex + helperItemsLength; - if ( $scope.inputModel.length > 0 ) { - formElements[ $scope.tabIndex ].focus(); - $scope.setFocusStyle( $scope.tabIndex ); - // blur button in vain - angular.element( element ).children()[ 0 ].blur(); - } - } - } - - // open callback - $scope.onOpen(); - } - } - - // handle clicks outside the button / multi select layer - $scope.externalClickListener = function( e ) { - - var targetsArr = element.find( e.target.tagName ); - for (var i = 0; i < targetsArr.length; i++) { - if ( e.target == targetsArr[i] ) { - return; - } - } - - angular.element( checkBoxLayer.previousSibling ).removeClass( 'buttonClicked' ); - angular.element( checkBoxLayer ).removeClass( 'show' ); - angular.element( document ).off( 'click', $scope.externalClickListener ); - angular.element( document ).off( 'keydown', $scope.keyboardListener ); - - // close callback - $timeout( function() { - $scope.onClose(); - }, 0 ); - - // set focus on button again - element.children().children()[ 0 ].focus(); - } - - // select All / select None / reset buttons - $scope.select = function( type, e ) { - - var helperIndex = helperItems.indexOf( e.target ); - $scope.tabIndex = helperIndex; - - switch( type.toUpperCase() ) { - case 'ALL': - angular.forEach( $scope.filteredModel, function( value ) { - if ( typeof value !== 'undefined' && value[ attrs.disableProperty ] !== true ) { - if ( typeof value[ attrs.groupProperty ] === 'undefined' ) { - value[ $scope.tickProperty ] = true; - } - } - }); - $scope.refreshOutputModel(); - $scope.refreshButton(); - $scope.onSelectAll(); - break; - case 'NONE': - angular.forEach( $scope.filteredModel, function( value ) { - if ( typeof value !== 'undefined' && value[ attrs.disableProperty ] !== true ) { - if ( typeof value[ attrs.groupProperty ] === 'undefined' ) { - value[ $scope.tickProperty ] = false; - } - } - }); - $scope.refreshOutputModel(); - $scope.refreshButton(); - $scope.onSelectNone(); - break; - case 'RESET': - angular.forEach( $scope.filteredModel, function( value ) { - if ( typeof value[ attrs.groupProperty ] === 'undefined' && typeof value !== 'undefined' && value[ attrs.disableProperty ] !== true ) { - var temp = value[ $scope.indexProperty ]; - value[ $scope.tickProperty ] = $scope.backUp[ temp ][ $scope.tickProperty ]; - } - }); - $scope.refreshOutputModel(); - $scope.refreshButton(); - $scope.onReset(); - break; - case 'CLEAR': - $scope.tabIndex = $scope.tabIndex + 1; - $scope.onClear(); - break; - case 'FILTER': - $scope.tabIndex = helperItems.length - 1; - break; - default: - } - } - - // just to create a random variable name - function genRandomString( length ) { - var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; - var temp = ''; - for( var i=0; i < length; i++ ) { - temp += possible.charAt( Math.floor( Math.random() * possible.length )); - } - return temp; - } - - // count leading spaces - $scope.prepareGrouping = function() { - var spacing = 0; - angular.forEach( $scope.filteredModel, function( value ) { - value[ $scope.spacingProperty ] = spacing; - if ( value[ attrs.groupProperty ] === true ) { - spacing+=2; - } - else if ( value[ attrs.groupProperty ] === false ) { - spacing-=2; - } - }); - } - - // prepare original index - $scope.prepareIndex = function() { - var ctr = 0; - angular.forEach( $scope.filteredModel, function( value ) { - value[ $scope.indexProperty ] = ctr; - ctr++; - }); - } - - // navigate using up and down arrow - $scope.keyboardListener = function( e ) { - - var key = e.keyCode ? e.keyCode : e.which; - var isNavigationKey = false; - - // ESC key (close) - if ( key === 27 ) { - e.preventDefault(); - e.stopPropagation(); - $scope.toggleCheckboxes( e ); - } - - - // next element ( tab, down & right key ) - else if ( key === 40 || key === 39 || ( !e.shiftKey && key == 9 ) ) { - - isNavigationKey = true; - prevTabIndex = $scope.tabIndex; - $scope.tabIndex++; - if ( $scope.tabIndex > formElements.length - 1 ) { - $scope.tabIndex = 0; - prevTabIndex = formElements.length - 1; - } - while ( formElements[ $scope.tabIndex ].disabled === true ) { - $scope.tabIndex++; - if ( $scope.tabIndex > formElements.length - 1 ) { - $scope.tabIndex = 0; - } - if ( $scope.tabIndex === prevTabIndex ) { - break; - } - } - } - - // prev element ( shift+tab, up & left key ) - else if ( key === 38 || key === 37 || ( e.shiftKey && key == 9 ) ) { - isNavigationKey = true; - prevTabIndex = $scope.tabIndex; - $scope.tabIndex--; - if ( $scope.tabIndex < 0 ) { - $scope.tabIndex = formElements.length - 1; - prevTabIndex = 0; - } - while ( formElements[ $scope.tabIndex ].disabled === true ) { - $scope.tabIndex--; - if ( $scope.tabIndex === prevTabIndex ) { - break; - } - if ( $scope.tabIndex < 0 ) { - $scope.tabIndex = formElements.length - 1; - } - } - } - - if ( isNavigationKey === true ) { - - e.preventDefault(); - - // set focus on the checkbox - formElements[ $scope.tabIndex ].focus(); - var actEl = document.activeElement; - - if ( actEl.type.toUpperCase() === 'CHECKBOX' ) { - $scope.setFocusStyle( $scope.tabIndex ); - $scope.removeFocusStyle( prevTabIndex ); - } - else { - $scope.removeFocusStyle( prevTabIndex ); - $scope.removeFocusStyle( helperItemsLength ); - $scope.removeFocusStyle( formElements.length - 1 ); - } - } - - isNavigationKey = false; - } - - // set (add) CSS style on selected row - $scope.setFocusStyle = function( tabIndex ) { - angular.element( formElements[ tabIndex ] ).parent().parent().parent().addClass( 'multiSelectFocus' ); - } - - // remove CSS style on selected row - $scope.removeFocusStyle = function( tabIndex ) { - angular.element( formElements[ tabIndex ] ).parent().parent().parent().removeClass( 'multiSelectFocus' ); - } - - /********************* - ********************* - * - * 1) Initializations - * - ********************* - *********************/ - - // attrs to $scope - attrs-$scope - attrs - $scope - // Copy some properties that will be used on the template. They need to be in the $scope. - $scope.groupProperty = attrs.groupProperty; - $scope.tickProperty = attrs.tickProperty; - $scope.directiveId = attrs.directiveId; - - // Unfortunately I need to add these grouping properties into the input model - var tempStr = genRandomString( 5 ); - $scope.indexProperty = 'idx_' + tempStr; - $scope.spacingProperty = 'spc_' + tempStr; - - // set orientation css - if ( typeof attrs.orientation !== 'undefined' ) { - - if ( attrs.orientation.toUpperCase() === 'HORIZONTAL' ) { - $scope.orientationH = true; - $scope.orientationV = false; - } - else - { - $scope.orientationH = false; - $scope.orientationV = true; - } - } - - // get elements required for DOM operation - checkBoxLayer = element.children().children().next()[0]; - - // set max-height property if provided - if ( typeof attrs.maxHeight !== 'undefined' ) { - var layer = element.children().children().children()[0]; - angular.element( layer ).attr( "style", "height:" + attrs.maxHeight + "; overflow-y:scroll;" ); - } - - // some flags for easier checking - for ( var property in $scope.helperStatus ) { - if ( $scope.helperStatus.hasOwnProperty( property )) { - if ( - typeof attrs.helperElements !== 'undefined' - && attrs.helperElements.toUpperCase().indexOf( property.toUpperCase() ) === -1 - ) { - $scope.helperStatus[ property ] = false; - } - } - } - if ( typeof attrs.selectionMode !== 'undefined' && attrs.selectionMode.toUpperCase() === 'SINGLE' ) { - $scope.helperStatus[ 'all' ] = false; - $scope.helperStatus[ 'none' ] = false; - } - - // helper button icons.. I guess you can use html tag here if you want to. - $scope.icon = {}; - $scope.icon.selectAll = '✓'; // a tick icon - $scope.icon.selectNone = '×'; // x icon - $scope.icon.reset = '↶'; // undo icon - // this one is for the selected items - $scope.icon.tickMark = '✓'; // a tick icon - - // configurable button labels - // if ( typeof attrs.translation !== 'undefined' ) { - // $scope.lang.selectAll = $sce.trustAsHtml( $scope.icon.selectAll + '  ' + $scope.translation.selectAll ); - // $scope.lang.selectNone = $sce.trustAsHtml( $scope.icon.selectNone + '  ' + $scope.translation.selectNone ); - // $scope.lang.reset = $sce.trustAsHtml( $scope.icon.reset + '  ' + $scope.translation.reset ); - // $scope.lang.search = $scope.translation.search; - // $scope.lang.nothingSelected = $sce.trustAsHtml( $scope.translation.nothingSelected ); - // } - // else { - // $scope.lang.selectAll = $sce.trustAsHtml( $scope.icon.selectAll + '  Select All' ); - // $scope.lang.selectNone = $sce.trustAsHtml( $scope.icon.selectNone + '  Select None' ); - // $scope.lang.reset = $sce.trustAsHtml( $scope.icon.reset + '  Reset' ); - // $scope.lang.search = 'Search...'; - // $scope.lang.nothingSelected = 'None Selected'; - // } - // $scope.icon.tickMark = $sce.trustAsHtml( $scope.icon.tickMark ); - if ( typeof attrs.translation !== 'undefined' ) { - $scope.lang.selectAll = $sanitize( $scope.icon.selectAll + '  ' + $scope.translation.selectAll ); - $scope.lang.selectNone = $sanitize( $scope.icon.selectNone + '  ' + $scope.translation.selectNone ); - $scope.lang.reset = $sanitize( $scope.icon.reset + '  ' + $scope.translation.reset ); - $scope.lang.search = $scope.translation.search; - $scope.lang.nothingSelected = $sanitize( $scope.translation.nothingSelected ); - } - else { - $scope.lang.selectAll = $sanitize( $scope.icon.selectAll + '  Select All' ); - $scope.lang.selectNone = $sanitize( $scope.icon.selectNone + '  Select None' ); - $scope.lang.reset = $sanitize( $scope.icon.reset + '  Reset' ); - $scope.lang.search = 'Search...'; - $scope.lang.nothingSelected = 'None Selected'; - } - $scope.icon.tickMark = $sanitize( $scope.icon.tickMark ); - - // min length of keyword to trigger the filter function - if ( typeof attrs.MinSearchLength !== 'undefined' && parseInt( attrs.MinSearchLength ) > 0 ) { - vMinSearchLength = Math.floor( parseInt( attrs.MinSearchLength ) ); - } - - /******************************************************* - ******************************************************* - * - * 2) Logic starts here, initiated by watch 1 & watch 2 - * - ******************************************************* - *******************************************************/ - - // watch1, for changes in input model property - // updates multi-select when user select/deselect a single checkbox programatically - // https://github.com/isteven/angular-multi-select/issues/8 - $scope.$watch( 'inputModel' , function( newVal ) { - if ( newVal ) { - $scope.refreshOutputModel(); - $scope.refreshButton(); - } - }, true ); - - // watch2 for changes in input model as a whole - // this on updates the multi-select when a user load a whole new input-model. We also update the $scope.backUp variable - $scope.$watch( 'inputModel' , function( newVal ) { - if ( newVal ) { - $scope.backUp = angular.copy( $scope.inputModel ); - $scope.updateFilter(); - $scope.prepareGrouping(); - $scope.prepareIndex(); - $scope.refreshOutputModel(); - $scope.refreshButton(); - } - }); - - // watch for changes in directive state (disabled or enabled) - $scope.$watch( 'isDisabled' , function( newVal ) { - $scope.isDisabled = newVal; - }); - - // this is for touch enabled devices. We don't want to hide checkboxes on scroll. - var onTouchStart = function() { - $scope.$apply( function() { - $scope.scrolled = false; - }); - }; - angular.element( document ).bind( 'touchstart', onTouchStart); - var onTouchMove = function() { - $scope.$apply( function() { - $scope.scrolled = true; - }); - }; - angular.element( document ).bind( 'touchmove', onTouchMove); - - // unbind document events to prevent memory leaks - $scope.$on( '$destroy', function () { - angular.element( document ).unbind( 'touchstart', onTouchStart); - angular.element( document ).unbind( 'touchmove', onTouchMove); - }); - } - } -}]).run( [ '$templateCache' , function( $templateCache ) { - var template = - '' + - // main button - '' + - // overlay layer - '
' + - // container of the helper elements - '
' + - // container of the first 3 buttons, select all, none and reset - '
' + - // select all - ''+ - // select none - ''+ - // reset - '' + - '
' + - // the search box - '
'+ - // textfield - ''+ - // clear button - ' '+ - '
'+ - '
'+ - // selection items - '
'+ - '
'+ - // this is the spacing for grouped items - '
'+ - '
'+ - '
'+ - ''+ - '
'+ - // the tick/check mark - ''+ - '
'+ - '
'+ - '
'+ - '
'; - $templateCache.put( 'isteven-multi-select.htm' , template ); -}]); diff --git a/app/libraries/isteven-angular-multiselect/package.json b/app/libraries/isteven-angular-multiselect/package.json deleted file mode 100644 index 9aa2e3960..000000000 --- a/app/libraries/isteven-angular-multiselect/package.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "name": "isteven-angular-multiselect", - "version": "v4.0.0", - "description": "A multi select dropdown directive for AngularJS", - "main": [ - "isteven-multi-select.js", - "isteven-multi-select.css" - ], - "repository": { - "type": "git", - "url": "https://github.com/isteven/angular-multi-select.git" - }, - "keywords": [ - "angular" - ], - "author": "Ignatius Steven (https://github.com/isteven)", - "license": "MIT", - "bugs": { - "url": "https://github.com/isteven/angular-multi-select/issues" - }, - "homepage": "https://github.com/isteven/angular-multi-select" -} diff --git a/app/vendors.js b/app/vendors.js index bf1f680dc..51ec8c035 100644 --- a/app/vendors.js +++ b/app/vendors.js @@ -12,6 +12,7 @@ import 'angular-json-tree/dist/angular-json-tree.css'; import 'angular-loading-bar/build/loading-bar.css'; import 'rdash-ui/dist/css/rdash.css'; import 'angular-moment-picker/dist/angular-moment-picker.min.css'; +import 'angular-multiselect/isteven-multi-select.css'; import angular from 'angular'; window.angular = angular; @@ -37,3 +38,4 @@ import 'bootstrap/dist/js/bootstrap.js'; import 'js-yaml/dist/js-yaml.js' import 'angular-ui-bootstrap'; import 'angular-moment-picker'; +import 'angular-multiselect/isteven-multi-select.js'; diff --git a/package.json b/package.json index e1cf4fdde..a1713a5f1 100644 --- a/package.json +++ b/package.json @@ -59,6 +59,7 @@ "angular-messages": "~1.5.0", "angular-mocks": "~1.5.0", "angular-moment-picker": "^0.10.2", + "angular-multiselect": "github:portainer/angular-multi-select#semver:~v4.0.1", "angular-resource": "~1.5.0", "angular-sanitize": "~1.5.0", "angular-ui-bootstrap": "~2.5.0", diff --git a/yarn.lock b/yarn.lock index 55fb60149..d5911ee68 100644 --- a/yarn.lock +++ b/yarn.lock @@ -953,6 +953,11 @@ angular-messages@~1.5.0: resolved "https://registry.yarnpkg.com/angular-messages/-/angular-messages-1.5.11.tgz#ea99f0163594fcb0a2db701b3038339250decc90" integrity sha1-6pnwFjWU/LCi23AbMDgzklDezJA= +angular-mocks@1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/angular-mocks/-/angular-mocks-1.6.1.tgz#2f44a1b3ac608e93751305bce176c274221d8abd" + integrity sha1-L0Shs6xgjpN1EwW84XbCdCIdir0= + angular-mocks@~1.5.0: version "1.5.11" resolved "https://registry.yarnpkg.com/angular-mocks/-/angular-mocks-1.5.11.tgz#a0e1dd0ea55fd77ee7a757d75536c5e964c86f81" @@ -965,11 +970,23 @@ angular-moment-picker@^0.10.2: angular "^1.3" moment "^2.16.0" +"angular-multiselect@github:portainer/angular-multi-select#semver:~v4.0.1": + version "4.0.0" + resolved "https://codeload.github.com/portainer/angular-multi-select/tar.gz/933b066e0aa9e8879967a35a9c5bf7e89c72f86d" + dependencies: + angular-mocks "1.6.1" + angular-sanitize "1.6.1" + angular-resource@~1.5.0: version "1.5.11" resolved "https://registry.yarnpkg.com/angular-resource/-/angular-resource-1.5.11.tgz#d93ea619184a2e0ee3ae338265758363172929f0" integrity sha1-2T6mGRhKLg7jrjOCZXWDYxcpKfA= +angular-sanitize@1.6.1: + version "1.6.1" + resolved "https://registry.yarnpkg.com/angular-sanitize/-/angular-sanitize-1.6.1.tgz#cacffec3199ed66297afbb1ef366ec66616b3b3f" + integrity sha1-ys/+wxme1mKXr7se82bsZmFrOz8= + angular-sanitize@~1.5.0: version "1.5.11" resolved "https://registry.yarnpkg.com/angular-sanitize/-/angular-sanitize-1.5.11.tgz#ebfb3f343e543f9b2ef050fb4c2e9ee048d1772f"