summaryrefslogtreecommitdiffstats
path: root/ecomp-portal-FE/client/bower_components/ui-select
diff options
context:
space:
mode:
Diffstat (limited to 'ecomp-portal-FE/client/bower_components/ui-select')
-rw-r--r--ecomp-portal-FE/client/bower_components/ui-select/.bower.json41
-rw-r--r--ecomp-portal-FE/client/bower_components/ui-select/CHANGELOG.md180
-rw-r--r--ecomp-portal-FE/client/bower_components/ui-select/CONTRIBUTING.md161
-rw-r--r--ecomp-portal-FE/client/bower_components/ui-select/LICENSE20
-rw-r--r--ecomp-portal-FE/client/bower_components/ui-select/README.md57
-rw-r--r--ecomp-portal-FE/client/bower_components/ui-select/bower.json31
-rw-r--r--ecomp-portal-FE/client/bower_components/ui-select/composer.json29
-rw-r--r--ecomp-portal-FE/client/bower_components/ui-select/deploy-docs.sh31
-rw-r--r--ecomp-portal-FE/client/bower_components/ui-select/dist/select.css271
-rw-r--r--ecomp-portal-FE/client/bower_components/ui-select/dist/select.js2217
-rw-r--r--ecomp-portal-FE/client/bower_components/ui-select/dist/select.min.css7
-rw-r--r--ecomp-portal-FE/client/bower_components/ui-select/dist/select.min.js9
-rw-r--r--ecomp-portal-FE/client/bower_components/ui-select/docs/assets/app.js1
-rw-r--r--ecomp-portal-FE/client/bower_components/ui-select/docs/assets/demo.js461
-rw-r--r--ecomp-portal-FE/client/bower_components/ui-select/docs/assets/docs.css339
-rw-r--r--ecomp-portal-FE/client/bower_components/ui-select/docs/assets/plunkr.js110
-rw-r--r--ecomp-portal-FE/client/bower_components/ui-select/docs/index.html191
-rw-r--r--ecomp-portal-FE/client/bower_components/ui-select/docs/partials/_footer.html2
-rw-r--r--ecomp-portal-FE/client/bower_components/ui-select/docs/partials/_header.html64
-rw-r--r--ecomp-portal-FE/client/bower_components/ui-select/index.js2
-rw-r--r--ecomp-portal-FE/client/bower_components/ui-select/package.json61
21 files changed, 4285 insertions, 0 deletions
diff --git a/ecomp-portal-FE/client/bower_components/ui-select/.bower.json b/ecomp-portal-FE/client/bower_components/ui-select/.bower.json
new file mode 100644
index 00000000..a124749c
--- /dev/null
+++ b/ecomp-portal-FE/client/bower_components/ui-select/.bower.json
@@ -0,0 +1,41 @@
+{
+ "name": "angular-ui-select",
+ "homepage": "https://github.com/angular-ui/ui-select",
+ "authors": [
+ "AngularUI"
+ ],
+ "description": "AngularJS ui-select",
+ "main": [
+ "dist/select.js",
+ "dist/select.css"
+ ],
+ "license": "MIT",
+ "ignore": [
+ "**/.*",
+ "node_modules",
+ "bower_components",
+ "src",
+ "test",
+ "gulpfile.js",
+ "karma.conf.js",
+ "examples"
+ ],
+ "dependencies": {
+ "angular": ">=1.2.18"
+ },
+ "devDependencies": {
+ "jquery": "~1.11",
+ "angular-sanitize": ">=1.2.18",
+ "angular-mocks": ">=1.2.18"
+ },
+ "version": "0.17.1",
+ "_release": "0.17.1",
+ "_resolution": {
+ "type": "version",
+ "tag": "v0.17.1",
+ "commit": "66a2a5e8cae3421cf2c25cc56492e5674b7eeda3"
+ },
+ "_source": "https://github.com/angular-ui/ui-select.git",
+ "_target": "~0.17.1",
+ "_originalSource": "angular-ui-select"
+} \ No newline at end of file
diff --git a/ecomp-portal-FE/client/bower_components/ui-select/CHANGELOG.md b/ecomp-portal-FE/client/bower_components/ui-select/CHANGELOG.md
new file mode 100644
index 00000000..dcb85b8b
--- /dev/null
+++ b/ecomp-portal-FE/client/bower_components/ui-select/CHANGELOG.md
@@ -0,0 +1,180 @@
+<a name="0.17.1"></a>
+## [0.17.1](https://github.com/angular-ui/ui-select/compare/v0.17.0...v0.17.1) (2016-05-16)
+
+
+### Bug Fixes
+
+* **parserResult:** Ignore undefined parserResult when using custom tpl ([cee24e5](https://github.com/angular-ui/ui-select/commit/cee24e5)), closes [#1597](https://github.com/angular-ui/ui-select/issues/1597)
+* **select2:** hide dropdown if there are no items to show (same as #1588 for bootstrap) ([4c561ac](https://github.com/angular-ui/ui-select/commit/4c561ac))
+
+
+
+<a name="0.16.1"></a>
+## [0.16.1](https://github.com/angular-ui/ui-select/compare/v0.16.1...v0.17.0) (2016-05-11)
+
+
+### Bug Fixes
+
+* **a11y:** prevent list from being focusable ([4e9ab7e](https://github.com/angular-ui/ui-select/commit/4e9ab7e)), closes [#898](https://github.com/angular-ui/ui-select/issues/898)
+* **autocomplete:** change to type="search" ([48cf1ba](https://github.com/angular-ui/ui-select/commit/48cf1ba)), closes [#991](https://github.com/angular-ui/ui-select/issues/991)
+* **bootstrap:** hide clear button if disabled ([fe0c0c1](https://github.com/angular-ui/ui-select/commit/fe0c0c1)), closes [#1388](https://github.com/angular-ui/ui-select/issues/1388) [#980](https://github.com/angular-ui/ui-select/issues/980)
+* **bootstrap:** hide dropdown if there are no items to show ([7c8b3a0](https://github.com/angular-ui/ui-select/commit/7c8b3a0)), closes [#1588](https://github.com/angular-ui/ui-select/issues/1588)
+* **build:** fix sourcemap logic ([6d4849f](https://github.com/angular-ui/ui-select/commit/6d4849f))
+* **demo-tagging:** error in Object Tags for input "a" ([7963684](https://github.com/angular-ui/ui-select/commit/7963684))
+* **sortable:** remove classes properly ([4b1ed47](https://github.com/angular-ui/ui-select/commit/4b1ed47)), closes [#902](https://github.com/angular-ui/ui-select/issues/902)
+* **tagging:** do not remove selected items when invalid ([331f819](https://github.com/angular-ui/ui-select/commit/331f819)), closes [#1359](https://github.com/angular-ui/ui-select/issues/1359)
+* **tagging groupBy:** fix group-by to work with tagging ([80be85b](https://github.com/angular-ui/ui-select/commit/80be85b))
+* **tagging multiple:** hide tagging item if null returned ([2f14045](https://github.com/angular-ui/ui-select/commit/2f14045))
+* **uiSelectCtrl:** correcting input focus ([6444d6b](https://github.com/angular-ui/ui-select/commit/6444d6b)), closes [#1253](https://github.com/angular-ui/ui-select/issues/1253)
+* **uiSelectSingleDirective:** strictly compare matching value ([a574cd4](https://github.com/angular-ui/ui-select/commit/a574cd4)), closes [#1328](https://github.com/angular-ui/ui-select/issues/1328)
+* **uiSelectSort:** update model on sort completion ([9a40b6f](https://github.com/angular-ui/ui-select/commit/9a40b6f)), closes [#974](https://github.com/angular-ui/ui-select/issues/974) [#1036](https://github.com/angular-ui/ui-select/issues/1036)
+* ensure highlighted before selecting on tab ([06bbd31](https://github.com/angular-ui/ui-select/commit/06bbd31)), closes [#1030](https://github.com/angular-ui/ui-select/issues/1030)
+* properly gc on destruction ([95692e7](https://github.com/angular-ui/ui-select/commit/95692e7))
+* show input when search is disabled ([83132b0](https://github.com/angular-ui/ui-select/commit/83132b0)), closes [#595](https://github.com/angular-ui/ui-select/issues/595) [#453](https://github.com/angular-ui/ui-select/issues/453)
+* show select element when search is disabled ([f37bafd](https://github.com/angular-ui/ui-select/commit/f37bafd)), closes [#861](https://github.com/angular-ui/ui-select/issues/861)
+
+### Features
+
+* **perf:** debounce resize callback ([115ebf4](https://github.com/angular-ui/ui-select/commit/115ebf4))
+* **perf:** optimize width resizing ([d78ba5f](https://github.com/angular-ui/ui-select/commit/d78ba5f))
+
+### Performance Improvements
+
+* **tagging multiple:** transform tagging item only once when filtering ([2b4a9ea](https://github.com/angular-ui/ui-select/commit/2b4a9ea))
+* **uiSelectCtrl:** moving activate events out of $timeout ([926f462](https://github.com/angular-ui/ui-select/commit/926f462))
+* change test in ctrl.isActive ([d6c14d4](https://github.com/angular-ui/ui-select/commit/d6c14d4))
+
+
+
+<a name="0.16.1"></a>
+# [0.16.1](https://github.com/angular-ui/ui-select/compare/v0.16.0...v0.16.1) (2016-03-23)
+
+### Bug Fixes
+
+* **$window:** change input size on window resize ([ce24981](https://github.com/angular-ui/ui-select/commit/ce24981)), closes [#522](https://github.com/angular-ui/ui-select/issues/522)
+* **uiSelectMultipleDirective:** add $isEmpty handler ([fccc29a](https://github.com/angular-ui/ui-select/commit/fccc29a)), closes [#850](https://github.com/angular-ui/ui-select/issues/850)
+* **uiSelectMultipleDirective:** refresh choices upon selection change ([03293ff](https://github.com/angular-ui/ui-select/commit/03293ff)), closes [#1243](https://github.com/angular-ui/ui-select/issues/1243)
+
+<a name="0.16.0"></a>
+## [0.15.0](https://github.com/angular-ui/ui-select/compare/v0.15.0...v0.16.0)
+
+<a name="0.15.0"></a>
+## [0.15.0](https://github.com/angular-ui/ui-select/compare/v0.14.9...v0.15.0) (2016-03-15)
+
+### Bug Fixes
+
+* corrects out of scope variable ([d5e30fb](https://github.com/angular-ui/ui-select/commit/d5e30fb))
+
+### Features
+
+* provide a way to skip the focusser ([302e80f](https://github.com/angular-ui/ui-select/commit/302e80f)), closes [#869](https://github.com/angular-ui/ui-select/issues/869) [#401](https://github.com/angular-ui/ui-select/issues/401) [#818](https://github.com/angular-ui/ui-select/issues/818) [#603](https://github.com/angular-ui/ui-select/issues/603) [#432](https://github.com/angular-ui/ui-select/issues/432)
+
+<a name="0.14.10"></a>
+## [0.14.10](https://github.com/angular-ui/ui-select/compare/v0.14.9...v0.14.10) (2016-03-13)
+
+### Features
+
+* provide a way to skip the focusser ([302e80f](https://github.com/angular-ui/ui-select/commit/302e80f)), closes [#869](https://github.com/angular-ui/ui-select/issues/869) [#401](https://github.com/angular-ui/ui-select/issues/401) [#818](https://github.com/angular-ui/ui-select/issues/818) [#603](https://github.com/angular-ui/ui-select/issues/603) [#432](https://github.com/angular-ui/ui-select/issues/432)
+
+<a name="0.14.9"></a>
+## [0.14.9](https://github.com/angular-ui/ui-select/compare/v0.14.9...v0.14.9) (2016-03-06)
+
+<a name="0.14.8"></a>
+## [0.14.8](https://github.com/angular-ui/ui-select/compare/v0.14.7...v0.14.8) (2016-02-18)
+
+<a name="0.14.7"></a>
+## [0.14.7](https://github.com/angular-ui/ui-select/compare/v0.14.6...v0.14.7) (2016-02-18)
+
+### Bug Fixes
+
+* **IE:** selects not working on IE8 ([ee65677](https://github.com/angular-ui/ui-select/commit/ee65677)), closes [#158](https://github.com/angular-ui/ui-select/issues/158)
+
+<a name="0.14.6"></a>
+## [0.14.6](https://github.com/angular-ui/ui-select/compare/v0.14.5...v0.14.6) (2016-02-18)
+
+### Bug Fixes
+
+* **paste:** add paste support ([1ad6f60](https://github.com/angular-ui/ui-select/commit/1ad6f60)), closes [#910](https://github.com/angular-ui/ui-select/issues/910) [#704](https://github.com/angular-ui/ui-select/issues/704) [#789](https://github.com/angular-ui/ui-select/issues/789) [#848](https://github.com/angular-ui/ui-select/issues/848) [#429](https://github.com/angular-ui/ui-select/issues/429)
+* **uiSelectSort:** fix dependency not found error ([a5a6554](https://github.com/angular-ui/ui-select/commit/a5a6554))
+
+<a name="0.14.5"></a>
+## [0.14.5](https://github.com/angular-ui/ui-select/compare/v0.14.4...v0.14.5) (2016-02-18)
+
+### Bug Fixes
+
+* **uiSelectMultipleDirective:** fix track by error ([ced1cc0](https://github.com/angular-ui/ui-select/commit/ced1cc0)), closes [#1343](https://github.com/angular-ui/ui-select/issues/1343)
+
+<a name="0.14.4"></a>
+## [0.14.4](https://github.com/angular-ui/ui-select/compare/v0.14.3...v0.14.4) (2016-02-18)
+
+### Bug Fixes
+
+* Allow setting a ngClass on <ui-select> element ([6a99b08](https://github.com/angular-ui/ui-select/commit/6a99b08)), closes [#277](https://github.com/angular-ui/ui-select/issues/277)
+
+<a name="0.14.3"></a>
+## [0.14.3](https://github.com/angular-ui/ui-select/compare/v0.14.2...v0.14.3) (2016-02-18)
+
+<a name="0.14.2"></a>
+## [0.14.2](https://github.com/angular-ui/ui-select/compare/v0.14.1...v0.14.2) (2016-02-18)
+
+### Bug Fixes
+
+* make compatible with Angular 1.5 and non-cached templates ([0e85670](https://github.com/angular-ui/ui-select/commit/0e85670)), closes [#1422](https://github.com/angular-ui/ui-select/issues/1422) [#1356](https://github.com/angular-ui/ui-select/issues/1356) [#1325](https://github.com/angular-ui/ui-select/issues/1325) [#1239](https://github.com/angular-ui/ui-select/issues/1239)
+* **commonjs:** remove CSS require ([81b0f03](https://github.com/angular-ui/ui-select/commit/81b0f03))
+* **track by:** fix "track by" ([6c52e41](https://github.com/angular-ui/ui-select/commit/6c52e41)), closes [#806](https://github.com/angular-ui/ui-select/issues/806) [#665](https://github.com/angular-ui/ui-select/issues/665)
+
+<a name="0.14.1"></a>
+## [0.14.1](https://github.com/angular-ui/ui-select/compare/v0.14.0...v0.14.1) (2016-01-27)
+
+<a name="0.14.0"></a>
+# [0.14.0](https://github.com/angular-ui/ui-select/compare/v0.13.2...v0.14.0) (2016-01-25)
+
+### Features
+
+* **ngAnimate:** add support for ngAnimate ([8da8a6d](https://github.com/angular-ui/ui-select/commit/8da8a6d))
+
+<a name="0.13.3"></a>
+## 0.13.3 (2016-01-25)
+
+### Added
+
+- Add support for commonjs and npm
+
+<a name="0.13.2"></a>
+## [0.13.2](https://github.com/angular-ui/ui-select/compare/v0.13.1...v0.13.2) (2016-01-25)
+
+### Bug Fixes
+
+* **CSP:** avoid inline execution of javascript in choices template. ([fb88ec8](https://github.com/angular-ui/ui-select/commit/fb88ec8))
+
+<a name="0.13.1"></a>
+## [v0.13.1](https://github.com/angular-ui/ui-select/compare/v0.13.0...v0.13.1) (2015-09-29)
+
+### Fixed
+
+- Remove hardcoded source name when using (key,value) syntax [#1217](https://github.com/angular-ui/ui-select/pull/1217)
+- Modify regex to accept a full 'collection expression' when not using (key,value) syntax [#1216](https://github.com/angular-ui/ui-select/pull/1216)
+- Avoid to recalculate position when set 'down' [#1214](https://github.com/angular-ui/ui-select/issues/1214#issuecomment-144271352)
+
+<a name="0.13.0"></a>
+
+## [v0.13.0](https://github.com/angular-ui/ui-select/compare/v0.12.1...v0.13.0) (2015-09-29)
+
+### Added
+
+- Allow to configure default dropdown position [#1213](https://github.com/angular-ui/ui-select/pull/1213)
+- Can use object as source with (key,value) syntax [#1208](https://github.com/angular-ui/ui-select/pull/1208)
+- CHANGELOG.md file created
+
+### Changed
+
+- Do not run bower after install automatically [#982](https://github.com/angular-ui/ui-select/pull/982)
+- Avoid setting activeItem on mouseenter to improve performance [#1211](https://github.com/angular-ui/ui-select/pull/1211)
+
+### Fixed
+
+- Position dropdown UP or DOWN correctly depending on the available space [#1212](https://github.com/angular-ui/ui-select/pull/1212)
+- Scroll to selected item [#976](https://github.com/angular-ui/ui-select/issues/976)
+- Change `autocomplete='off'` to `autocomplete='false'` [#1210](https://github.com/angular-ui/ui-select/pull/1210)
+- Fix to work correctly with debugInfoEnabled(false) [#1131](https://github.com/angular-ui/ui-select/pull/1131)
+- Limit the maximum number of selections allowed in multiple mode [#1110](https://github.com/angular-ui/ui-select/pull/1110)
diff --git a/ecomp-portal-FE/client/bower_components/ui-select/CONTRIBUTING.md b/ecomp-portal-FE/client/bower_components/ui-select/CONTRIBUTING.md
new file mode 100644
index 00000000..13998a9c
--- /dev/null
+++ b/ecomp-portal-FE/client/bower_components/ui-select/CONTRIBUTING.md
@@ -0,0 +1,161 @@
+We are excited to have you working on the project and cordially request that you follow the Guidelines:
+
+ - [Got a question or problem?](#question)
+ - [You think you've found a bug?](#bug)
+ - [Code Style Guidelines](#rules)
+ - [Commit Message Guidelines](#commit)
+
+## <a name="question"></a> Got a question or problem?
+
+ Firstly, please go over our FAQ: https://github.com/angular-ui/ui-select/wiki/FAQs
+
+ Please, do not open issues for the general support questions as we want to keep GitHub issues for bug reports and feature requests. You've got much better chances of getting your question answered on [StackOverflow](http://stackoverflow.com/questions/tagged/angular-ui-select) where maintainers are looking at questions tagged with `angular-ui-select`.
+
+ StackOverflow is a much better place to ask questions since:
+ * there are hundreds of people willing to help on StackOverflow
+ * questions and answers stay available for public viewing so your question / answer might help someone else
+ * SO voting system assures that the best answers are prominently visible.
+
+ To save your and our time we will be systematically closing all the issues that are requests for general support and redirecting people to StackOverflow.
+
+## <a name="bug"></a> You think you've found a bug?
+
+ Oh, we are ashamed and want to fix it asap! But before fixing a bug we need to reproduce and confirm it. In order to reproduce bugs we will systematically ask you to provide a _minimal_ reproduce scenario using http://plnkr.co/. Having a live reproduce scenario gives us wealth of important information without going back & forth to you with additional questions like:
+ * version of AngularJS used
+ * version of this library that you are using
+ * 3rd-party libraries used, if any
+ * and most importantly - a use-case that fails
+
+ A minimal reproduce scenario using http://plnkr.co/ allows us to quickly confirm a bug (or point out coding problem) as well as confirm that we are fixing the right problem.
+
+ We will be insisting on a minimal reproduce scenario in order to save maintainers time and ultimately be able to fix more bugs. Interestingly, from our experience users often find coding problems themselves while preparing a minimal plunk. We understand that sometimes it might be hard to extract essentials bits of code from a larger code-base but we really need to isolate the problem before we can fix it.
+
+ The best part is that you don't need to create plunks from scratch - you can use one from our [demo page](http://plnkr.co/edit/a3KlK8dKH3wwiiksDSn2?p=preview).
+
+ Unfortunately we are not able to investigate / fix bugs without a minimal reproduce scenario using http://plnkr.co/, so if we don't hear back from you we are going to close an issue that don't have enough info to be reproduced.
+
+## <a name="rules"></a> Coding Rules
+To ensure consistency throughout the source code, keep these rules in mind as you are working:
+
+* All features or bug fixes **must pass all tests** (run `gulp` to jshint, build and test).
+* All public API methods **must be documented** with ngdoc, an extended version of jsdoc (we added
+ support for markdown and templating via @ngdoc tag). To see how we document our APIs, please check
+ out the existing ngdocs and see [this wiki page][ngDocs].
+
+## <a name="commit"></a> Git Commit Guidelines
+
+We have very precise rules over how our git commit messages can be formatted for maintenance of the changelog and semvar versioning. This leads to **more
+readable messages** that are easy to follow when looking through the **project history**. But also,
+we use the git commit messages to **generate the change log**.
+
+## Development
+
+### Prepare your environment
+* Install [Node.js](http://nodejs.org/) and NPM (should come with)
+* Install global dev dependencies: `npm install -g bower gulp`
+* Install local dev dependencies: `npm install && bower install` in repository directory
+
+### Development Commands
+
+* `gulp` to jshint, build and test
+* `gulp build` to jshint and build
+* `gulp test` for one-time test with karma (also build and jshint)
+* `gulp watch` to watch src files to jshint, build and test when changed
+
+## Recommended workflow
+
+1. Make changes
+2. Run `gulp` or `gulp test` to run Karma tests and ensure they pass.
+3. Reset all `dist/*` files
+4. Commit changes using the commit message conventions below.
+5. Push
+6. Create PR
+
+### Commit Message Format
+Each commit message consists of a **header**, a **body** and a **footer**. The header has a special
+format that includes a **type**, a **scope** and a **subject**:
+
+```
+<type>(<scope>): <subject>
+<BLANK LINE>
+<body>
+<BLANK LINE>
+<footer>
+```
+
+The **header** is mandatory and the **scope** of the header is optional.
+
+Any line of the commit message cannot be longer 100 characters! This allows the message to be easier
+to read on GitHub as well as in various git tools.
+
+### Revert
+If the commit reverts a previous commit, it should begin with `revert: `, followed by the header of the reverted commit. In the body it should say: `This reverts commit <hash>.`, where the hash is the SHA of the commit being reverted.
+
+### Type
+Must be one of the following:
+
+* **feat**: A new feature
+* **fix**: A bug fix
+* **docs**: Documentation only changes
+* **style**: Changes that do not affect the meaning of the code (white-space, formatting, missing
+ semi-colons, etc)
+* **refactor**: A code change that neither fixes a bug nor adds a feature
+* **perf**: A code change that improves performance
+* **test**: Adding missing tests
+* **chore**: Changes to the build process or auxiliary tools and libraries such as documentation
+ generation
+
+### Scope
+The scope could be anything specifying place of the commit change. For example `$location`,
+`$browser`, `$compile`, `$rootScope`, `ngHref`, `ngClick`, `ngView`, etc...
+
+### Subject
+The subject contains succinct description of the change:
+
+* use the imperative, present tense: "change" not "changed" nor "changes"
+* don't capitalize first letter
+* no dot (.) at the end
+
+### Body
+Just as in the **subject**, use the imperative, present tense: "change" not "changed" nor "changes".
+The body should include the motivation for the change and contrast this with previous behavior.
+
+### Footer
+The footer should contain any information about **Breaking Changes** and is also the place to
+reference github issues that this commit **Closes**.
+
+**Breaking Changes** should start with the word `BREAKING CHANGE:` with a space or two newlines. The rest of the commit message is then used for this.
+
+#### Examples
+
+Appears under "Features" header, pencil subheader:
+
+```
+feat(pencil): add 'graphiteWidth' option
+```
+
+Appears under "Bug Fixes" header, graphite subheader, with a link to issue #GSNP-28:
+
+```
+fix(graphite): stop graphite breaking when width < 0.1
+
+Closes #123
+```
+
+Appears under "Performance Improvements" header, and under "Breaking Changes" with the breaking change explanation:
+
+```
+perf(pencil): remove graphiteWidth option
+
+BREAKING CHANGE: The graphiteWidth option has been removed. The default graphite width of 10mm is always used for performance reason.
+```
+
+The following commit and commit `667ecc1` do not appear in the changelog if they are under the same release. If not, the revert commit appears under the "Reverts" header.
+
+```
+revert: feat(pencil): add 'graphiteWidth' option
+
+This reverts commit 667ecc1654a317a13331b17617d973392f415f02.
+```
+
+A detailed explanation can be found in this [document][https://docs.google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y/edit#].
diff --git a/ecomp-portal-FE/client/bower_components/ui-select/LICENSE b/ecomp-portal-FE/client/bower_components/ui-select/LICENSE
new file mode 100644
index 00000000..b62d482f
--- /dev/null
+++ b/ecomp-portal-FE/client/bower_components/ui-select/LICENSE
@@ -0,0 +1,20 @@
+The MIT License (MIT)
+
+Copyright (c) 2013-2014 AngularUI
+
+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/ecomp-portal-FE/client/bower_components/ui-select/README.md b/ecomp-portal-FE/client/bower_components/ui-select/README.md
new file mode 100644
index 00000000..71e42393
--- /dev/null
+++ b/ecomp-portal-FE/client/bower_components/ui-select/README.md
@@ -0,0 +1,57 @@
+# AngularJS ui-select [![Build Status](https://travis-ci.org/angular-ui/ui-select.svg?branch=master)](https://travis-ci.org/angular-ui/ui-select) [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/angular-ui/ui-select?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)
+
+AngularJS-native version of [Select2](http://ivaynberg.github.io/select2/) and [Selectize](http://brianreavis.github.io/selectize.js/). [http://angular-ui.github.io/ui-select/](http://angular-ui.github.io/ui-select/)
+
+[Getting Started](https://github.com/angular-ui/ui-select/wiki/Getting-Started)
+
+- [Examples](http://angular-ui.github.io/ui-select/#examples)
+- [Examples Source](./docs/examples)
+- [Documentation](https://github.com/angular-ui/ui-select/wiki)
+
+## Latest Changes
+
+- Check [CHANGELOG.md](/CHANGELOG.md)
+
+## Features
+
+- Search, Select, Multi-select and Tagging
+- Multiple Themes: Bootstrap, Select2 and Selectize
+- Keyboard support
+- No jQuery required (except for old browsers)
+- Small code base: 4.57KB min/gzipped vs 20KB for select2
+
+For the roadmap, check [issue #3](https://github.com/angular-ui/ui-select/issues/3) and the [Wiki page](https://github.com/angular-ui/ui-select/wiki/Roadmap).
+
+## Installation Methods
+
+### npm
+```
+$ npm install ui-select
+```
+### bower
+```
+$ bower install angular-ui-select
+```
+
+## Development
+
+### Prepare your environment
+* Install [Node.js](http://nodejs.org/) and NPM (should come with)
+* Install global dev dependencies: `npm install -g gulp`
+* Install local dev dependencies: `npm install` in repository directory
+
+### Development Commands
+
+* `gulp` to jshint, build and test
+* `gulp build` to jshint and build
+* `gulp test` for one-time test with karma (also build and jshint)
+* `gulp watch` to watch src files to jshint, build and test when changed
+* `gulp docs` build docs and examples
+
+## Contributing
+
+- Check [CONTRIBUTING.md](/CONTRIBUTING.md)
+- Run the tests
+- Try the [examples](./docs/examples)
+
+When issuing a pull request, please exclude changes from the "dist" folder to avoid merge conflicts.
diff --git a/ecomp-portal-FE/client/bower_components/ui-select/bower.json b/ecomp-portal-FE/client/bower_components/ui-select/bower.json
new file mode 100644
index 00000000..d7a7bafd
--- /dev/null
+++ b/ecomp-portal-FE/client/bower_components/ui-select/bower.json
@@ -0,0 +1,31 @@
+{
+ "name": "angular-ui-select",
+ "homepage": "https://github.com/angular-ui/ui-select",
+ "authors": [
+ "AngularUI"
+ ],
+ "description": "AngularJS ui-select",
+ "main": [
+ "dist/select.js",
+ "dist/select.css"
+ ],
+ "license": "MIT",
+ "ignore": [
+ "**/.*",
+ "node_modules",
+ "bower_components",
+ "src",
+ "test",
+ "gulpfile.js",
+ "karma.conf.js",
+ "examples"
+ ],
+ "dependencies": {
+ "angular": ">=1.2.18"
+ },
+ "devDependencies": {
+ "jquery": "~1.11",
+ "angular-sanitize": ">=1.2.18",
+ "angular-mocks": ">=1.2.18"
+ }
+}
diff --git a/ecomp-portal-FE/client/bower_components/ui-select/composer.json b/ecomp-portal-FE/client/bower_components/ui-select/composer.json
new file mode 100644
index 00000000..aeee32a4
--- /dev/null
+++ b/ecomp-portal-FE/client/bower_components/ui-select/composer.json
@@ -0,0 +1,29 @@
+{
+ "name": "components/ui-select",
+ "description": "AngularJS UI Select",
+ "keywords": ["angular", "angular-ui", "select", "select2", "angularjs"],
+ "type": "component",
+ "homepage": "https://github.com/angular-ui/ui-select",
+ "license": "MIT",
+ "support": {
+ "issues": "https://github.com/angular-ui/ui-select/issues",
+ "wiki": "https://github.com/angular-ui/ui-select/wiki",
+ "source": "https://github.com/angular-ui/ui-select"
+ },
+ "require": {
+ "robloach/component-installer": "*"
+ },
+ "extra": {
+ "component": {
+ "scripts": [
+ "dist/select.js"
+ ],
+ "files": [
+ "dist/select.js",
+ "dist/select.css",
+ "dist/select.min.js",
+ "dist/select.min.css"
+ ]
+ }
+ }
+} \ No newline at end of file
diff --git a/ecomp-portal-FE/client/bower_components/ui-select/deploy-docs.sh b/ecomp-portal-FE/client/bower_components/ui-select/deploy-docs.sh
new file mode 100644
index 00000000..f18e63a7
--- /dev/null
+++ b/ecomp-portal-FE/client/bower_components/ui-select/deploy-docs.sh
@@ -0,0 +1,31 @@
+#!/bin/bash
+set -e
+
+[[ $TRAVIS_SECURE_ENV_VARS == "true" ]] || { echo "No github key avaliable, aborting publishing"; exit 0; }
+
+ID_REF="$(git rev-parse --short HEAD)"
+
+git clone "https://${GH_KEY}@${GH_REF}" ./docs-out -b ${GH_PAGES_BRANCH} --single-branch --depth=1
+
+cd docs-out
+
+# clear out everything
+git rm -rf .
+git clean -fxd
+
+# get new content
+cp ../docs-built/* . -R
+
+git add .
+
+# inside this git repo we'll pretend to be a new user
+git config user.name "Travis CI"
+git config user.email "travisci@users.noreply.github.com"
+
+# The first and only commit to this new Git repo contains all the
+# files present with the commit message "Deploy to GitHub Pages".
+git commit -m "docs(*): new deploy (angular-ui/ui-select@${ID_REF})"
+
+
+git push origin --quiet
+#> /dev/null 2>&1 \ No newline at end of file
diff --git a/ecomp-portal-FE/client/bower_components/ui-select/dist/select.css b/ecomp-portal-FE/client/bower_components/ui-select/dist/select.css
new file mode 100644
index 00000000..cae019e5
--- /dev/null
+++ b/ecomp-portal-FE/client/bower_components/ui-select/dist/select.css
@@ -0,0 +1,271 @@
+/*!
+ * ui-select
+ * http://github.com/angular-ui/ui-select
+ * Version: 0.17.1 - 2016-05-16T19:31:33.034Z
+ * License: MIT
+ */
+
+
+/* Style when highlighting a search. */
+.ui-select-highlight {
+ font-weight: bold;
+}
+
+.ui-select-offscreen {
+ clip: rect(0 0 0 0) !important;
+ width: 1px !important;
+ height: 1px !important;
+ border: 0 !important;
+ margin: 0 !important;
+ padding: 0 !important;
+ overflow: hidden !important;
+ position: absolute !important;
+ outline: 0 !important;
+ left: 0px !important;
+ top: 0px !important;
+}
+
+
+.ui-select-choices-row:hover {
+ background-color: #f5f5f5;
+}
+
+/* Select2 theme */
+
+/* Mark invalid Select2 */
+.ng-dirty.ng-invalid > a.select2-choice {
+ border-color: #D44950;
+}
+
+.select2-result-single {
+ padding-left: 0;
+}
+
+.select2-locked > .select2-search-choice-close{
+ display:none;
+}
+
+.select-locked > .ui-select-match-close{
+ display:none;
+}
+
+body > .select2-container.open {
+ z-index: 9999; /* The z-index Select2 applies to the select2-drop */
+}
+
+/* Handle up direction Select2 */
+.ui-select-container[theme="select2"].direction-up .ui-select-match {
+ border-radius: 4px; /* FIXME hardcoded value :-/ */
+ border-top-left-radius: 0;
+ border-top-right-radius: 0;
+}
+.ui-select-container[theme="select2"].direction-up .ui-select-dropdown {
+ border-radius: 4px; /* FIXME hardcoded value :-/ */
+ border-bottom-left-radius: 0;
+ border-bottom-right-radius: 0;
+
+ border-top-width: 1px; /* FIXME hardcoded value :-/ */
+ border-top-style: solid;
+
+ box-shadow: 0 -4px 8px rgba(0, 0, 0, 0.25);
+
+ margin-top: -4px; /* FIXME hardcoded value :-/ */
+}
+.ui-select-container[theme="select2"].direction-up .ui-select-dropdown .select2-search {
+ margin-top: 4px; /* FIXME hardcoded value :-/ */
+}
+.ui-select-container[theme="select2"].direction-up.select2-dropdown-open .ui-select-match {
+ border-bottom-color: #5897fb;
+}
+
+/* Selectize theme */
+
+/* Helper class to show styles when focus */
+.selectize-input.selectize-focus{
+ border-color: #007FBB !important;
+}
+
+/* Fix input width for Selectize theme */
+.selectize-control > .selectize-input > input {
+ width: 100%;
+}
+
+/* Fix dropdown width for Selectize theme */
+.selectize-control > .selectize-dropdown {
+ width: 100%;
+}
+
+/* Mark invalid Selectize */
+.ng-dirty.ng-invalid > div.selectize-input {
+ border-color: #D44950;
+}
+
+/* Handle up direction Selectize */
+.ui-select-container[theme="selectize"].direction-up .ui-select-dropdown {
+ box-shadow: 0 -4px 8px rgba(0, 0, 0, 0.25);
+
+ margin-top: -2px; /* FIXME hardcoded value :-/ */
+}
+
+/* Bootstrap theme */
+
+/* Helper class to show styles when focus */
+.btn-default-focus {
+ color: #333;
+ background-color: #EBEBEB;
+ border-color: #ADADAD;
+ text-decoration: none;
+ outline: 5px auto -webkit-focus-ring-color;
+ outline-offset: -2px;
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 8px rgba(102, 175, 233, 0.6);
+}
+
+.ui-select-bootstrap .ui-select-toggle {
+ position: relative;
+}
+
+.ui-select-bootstrap .ui-select-toggle > .caret {
+ position: absolute;
+ height: 10px;
+ top: 50%;
+ right: 10px;
+ margin-top: -2px;
+}
+
+/* Fix Bootstrap dropdown position when inside a input-group */
+.input-group > .ui-select-bootstrap.dropdown {
+ /* Instead of relative */
+ position: static;
+}
+
+.input-group > .ui-select-bootstrap > input.ui-select-search.form-control {
+ border-radius: 4px; /* FIXME hardcoded value :-/ */
+ border-top-right-radius: 0;
+ border-bottom-right-radius: 0;
+}
+.input-group > .ui-select-bootstrap > input.ui-select-search.form-control.direction-up {
+ border-radius: 4px !important; /* FIXME hardcoded value :-/ */
+ border-top-right-radius: 0 !important;
+ border-bottom-right-radius: 0 !important;
+}
+
+.ui-select-bootstrap > .ui-select-match > .btn{
+ /* Instead of center because of .btn */
+ text-align: left !important;
+}
+
+.ui-select-bootstrap > .ui-select-match > .caret {
+ position: absolute;
+ top: 45%;
+ right: 15px;
+}
+
+/* See Scrollable Menu with Bootstrap 3 http://stackoverflow.com/questions/19227496 */
+.ui-select-bootstrap > .ui-select-choices ,.ui-select-bootstrap > .ui-select-no-choice {
+ width: 100%;
+ height: auto;
+ max-height: 200px;
+ overflow-x: hidden;
+ margin-top: -1px;
+}
+
+body > .ui-select-bootstrap.open {
+ z-index: 1000; /* Standard Bootstrap dropdown z-index */
+}
+
+.ui-select-multiple.ui-select-bootstrap {
+ height: auto;
+ padding: 3px 3px 0 3px;
+}
+
+.ui-select-multiple.ui-select-bootstrap input.ui-select-search {
+ background-color: transparent !important; /* To prevent double background when disabled */
+ border: none;
+ outline: none;
+ height: 1.666666em;
+ margin-bottom: 3px;
+}
+
+.ui-select-multiple.ui-select-bootstrap .ui-select-match .close {
+ font-size: 1.6em;
+ line-height: 0.75;
+}
+
+.ui-select-multiple.ui-select-bootstrap .ui-select-match-item {
+ outline: 0;
+ margin: 0 3px 3px 0;
+}
+
+.ui-select-multiple .ui-select-match-item {
+ position: relative;
+}
+
+.ui-select-multiple .ui-select-match-item.dropping .ui-select-match-close {
+ pointer-events: none;
+}
+
+.ui-select-multiple:hover .ui-select-match-item.dropping-before:before {
+ content: "";
+ position: absolute;
+ top: 0;
+ right: 100%;
+ height: 100%;
+ margin-right: 2px;
+ border-left: 1px solid #428bca;
+}
+
+.ui-select-multiple:hover .ui-select-match-item.dropping-after:after {
+ content: "";
+ position: absolute;
+ top: 0;
+ left: 100%;
+ height: 100%;
+ margin-left: 2px;
+ border-right: 1px solid #428bca;
+}
+
+.ui-select-bootstrap .ui-select-choices-row>a {
+ display: block;
+ padding: 3px 20px;
+ clear: both;
+ font-weight: 400;
+ line-height: 1.42857143;
+ color: #333;
+ white-space: nowrap;
+}
+
+.ui-select-bootstrap .ui-select-choices-row>a:hover, .ui-select-bootstrap .ui-select-choices-row>a:focus {
+ text-decoration: none;
+ color: #262626;
+ background-color: #f5f5f5;
+}
+
+.ui-select-bootstrap .ui-select-choices-row.active>a {
+ color: #fff;
+ text-decoration: none;
+ outline: 0;
+ background-color: #428bca;
+}
+
+.ui-select-bootstrap .ui-select-choices-row.disabled>a,
+.ui-select-bootstrap .ui-select-choices-row.active.disabled>a {
+ color: #777;
+ cursor: not-allowed;
+ background-color: #fff;
+}
+
+/* fix hide/show angular animation */
+.ui-select-match.ng-hide-add,
+.ui-select-search.ng-hide-add {
+ display: none !important;
+}
+
+/* Mark invalid Bootstrap */
+.ui-select-bootstrap.ng-dirty.ng-invalid > button.btn.ui-select-match {
+ border-color: #D44950;
+}
+
+/* Handle up direction Bootstrap */
+.ui-select-container[theme="bootstrap"].direction-up .ui-select-dropdown {
+ box-shadow: 0 -4px 8px rgba(0, 0, 0, 0.25);
+}
diff --git a/ecomp-portal-FE/client/bower_components/ui-select/dist/select.js b/ecomp-portal-FE/client/bower_components/ui-select/dist/select.js
new file mode 100644
index 00000000..8cae2096
--- /dev/null
+++ b/ecomp-portal-FE/client/bower_components/ui-select/dist/select.js
@@ -0,0 +1,2217 @@
+/*!
+ * ui-select
+ * http://github.com/angular-ui/ui-select
+ * Version: 0.17.1 - 2016-05-16T19:31:32.352Z
+ * License: MIT
+ */
+
+
+(function () {
+"use strict";
+var KEY = {
+ TAB: 9,
+ ENTER: 13,
+ ESC: 27,
+ SPACE: 32,
+ LEFT: 37,
+ UP: 38,
+ RIGHT: 39,
+ DOWN: 40,
+ SHIFT: 16,
+ CTRL: 17,
+ ALT: 18,
+ PAGE_UP: 33,
+ PAGE_DOWN: 34,
+ HOME: 36,
+ END: 35,
+ BACKSPACE: 8,
+ DELETE: 46,
+ COMMAND: 91,
+
+ MAP: { 91 : "COMMAND", 8 : "BACKSPACE" , 9 : "TAB" , 13 : "ENTER" , 16 : "SHIFT" , 17 : "CTRL" , 18 : "ALT" , 19 : "PAUSEBREAK" , 20 : "CAPSLOCK" , 27 : "ESC" , 32 : "SPACE" , 33 : "PAGE_UP", 34 : "PAGE_DOWN" , 35 : "END" , 36 : "HOME" , 37 : "LEFT" , 38 : "UP" , 39 : "RIGHT" , 40 : "DOWN" , 43 : "+" , 44 : "PRINTSCREEN" , 45 : "INSERT" , 46 : "DELETE", 48 : "0" , 49 : "1" , 50 : "2" , 51 : "3" , 52 : "4" , 53 : "5" , 54 : "6" , 55 : "7" , 56 : "8" , 57 : "9" , 59 : ";", 61 : "=" , 65 : "A" , 66 : "B" , 67 : "C" , 68 : "D" , 69 : "E" , 70 : "F" , 71 : "G" , 72 : "H" , 73 : "I" , 74 : "J" , 75 : "K" , 76 : "L", 77 : "M" , 78 : "N" , 79 : "O" , 80 : "P" , 81 : "Q" , 82 : "R" , 83 : "S" , 84 : "T" , 85 : "U" , 86 : "V" , 87 : "W" , 88 : "X" , 89 : "Y" , 90 : "Z", 96 : "0" , 97 : "1" , 98 : "2" , 99 : "3" , 100 : "4" , 101 : "5" , 102 : "6" , 103 : "7" , 104 : "8" , 105 : "9", 106 : "*" , 107 : "+" , 109 : "-" , 110 : "." , 111 : "/", 112 : "F1" , 113 : "F2" , 114 : "F3" , 115 : "F4" , 116 : "F5" , 117 : "F6" , 118 : "F7" , 119 : "F8" , 120 : "F9" , 121 : "F10" , 122 : "F11" , 123 : "F12", 144 : "NUMLOCK" , 145 : "SCROLLLOCK" , 186 : ";" , 187 : "=" , 188 : "," , 189 : "-" , 190 : "." , 191 : "/" , 192 : "`" , 219 : "[" , 220 : "\\" , 221 : "]" , 222 : "'"
+ },
+
+ isControl: function (e) {
+ var k = e.which;
+ switch (k) {
+ case KEY.COMMAND:
+ case KEY.SHIFT:
+ case KEY.CTRL:
+ case KEY.ALT:
+ return true;
+ }
+
+ if (e.metaKey || e.ctrlKey || e.altKey) return true;
+
+ return false;
+ },
+ isFunctionKey: function (k) {
+ k = k.which ? k.which : k;
+ return k >= 112 && k <= 123;
+ },
+ isVerticalMovement: function (k){
+ return ~[KEY.UP, KEY.DOWN].indexOf(k);
+ },
+ isHorizontalMovement: function (k){
+ return ~[KEY.LEFT,KEY.RIGHT,KEY.BACKSPACE,KEY.DELETE].indexOf(k);
+ },
+ toSeparator: function (k) {
+ var sep = {ENTER:"\n",TAB:"\t",SPACE:" "}[k];
+ if (sep) return sep;
+ // return undefined for special keys other than enter, tab or space.
+ // no way to use them to cut strings.
+ return KEY[k] ? undefined : k;
+ }
+ };
+
+/**
+ * Add querySelectorAll() to jqLite.
+ *
+ * jqLite find() is limited to lookups by tag name.
+ * TODO This will change with future versions of AngularJS, to be removed when this happens
+ *
+ * See jqLite.find - why not use querySelectorAll? https://github.com/angular/angular.js/issues/3586
+ * See feat(jqLite): use querySelectorAll instead of getElementsByTagName in jqLite.find https://github.com/angular/angular.js/pull/3598
+ */
+if (angular.element.prototype.querySelectorAll === undefined) {
+ angular.element.prototype.querySelectorAll = function(selector) {
+ return angular.element(this[0].querySelectorAll(selector));
+ };
+}
+
+/**
+ * Add closest() to jqLite.
+ */
+if (angular.element.prototype.closest === undefined) {
+ angular.element.prototype.closest = function( selector) {
+ var elem = this[0];
+ var matchesSelector = elem.matches || elem.webkitMatchesSelector || elem.mozMatchesSelector || elem.msMatchesSelector;
+
+ while (elem) {
+ if (matchesSelector.bind(elem)(selector)) {
+ return elem;
+ } else {
+ elem = elem.parentElement;
+ }
+ }
+ return false;
+ };
+}
+
+var latestId = 0;
+
+var uis = angular.module('ui.select', [])
+
+.constant('uiSelectConfig', {
+ theme: 'bootstrap',
+ searchEnabled: true,
+ sortable: false,
+ placeholder: '', // Empty by default, like HTML tag <select>
+ refreshDelay: 1000, // In milliseconds
+ closeOnSelect: true,
+ skipFocusser: false,
+ dropdownPosition: 'auto',
+ generateId: function() {
+ return latestId++;
+ },
+ appendToBody: false
+})
+
+// See Rename minErr and make it accessible from outside https://github.com/angular/angular.js/issues/6913
+.service('uiSelectMinErr', function() {
+ var minErr = angular.$$minErr('ui.select');
+ return function() {
+ var error = minErr.apply(this, arguments);
+ var message = error.message.replace(new RegExp('\nhttp://errors.angularjs.org/.*'), '');
+ return new Error(message);
+ };
+})
+
+// Recreates old behavior of ng-transclude. Used internally.
+.directive('uisTranscludeAppend', function () {
+ return {
+ link: function (scope, element, attrs, ctrl, transclude) {
+ transclude(scope, function (clone) {
+ element.append(clone);
+ });
+ }
+ };
+})
+
+/**
+ * Highlights text that matches $select.search.
+ *
+ * Taken from AngularUI Bootstrap Typeahead
+ * See https://github.com/angular-ui/bootstrap/blob/0.10.0/src/typeahead/typeahead.js#L340
+ */
+.filter('highlight', function() {
+ function escapeRegexp(queryToEscape) {
+ return ('' + queryToEscape).replace(/([.?*+^$[\]\\(){}|-])/g, '\\$1');
+ }
+
+ return function(matchItem, query) {
+ return query && matchItem ? ('' + matchItem).replace(new RegExp(escapeRegexp(query), 'gi'), '<span class="ui-select-highlight">$&</span>') : matchItem;
+ };
+})
+
+/**
+ * A read-only equivalent of jQuery's offset function: http://api.jquery.com/offset/
+ *
+ * Taken from AngularUI Bootstrap Position:
+ * See https://github.com/angular-ui/bootstrap/blob/master/src/position/position.js#L70
+ */
+.factory('uisOffset',
+ ['$document', '$window',
+ function ($document, $window) {
+
+ return function(element) {
+ var boundingClientRect = element[0].getBoundingClientRect();
+ return {
+ width: boundingClientRect.width || element.prop('offsetWidth'),
+ height: boundingClientRect.height || element.prop('offsetHeight'),
+ top: boundingClientRect.top + ($window.pageYOffset || $document[0].documentElement.scrollTop),
+ left: boundingClientRect.left + ($window.pageXOffset || $document[0].documentElement.scrollLeft)
+ };
+ };
+}]);
+
+/**
+ * Debounces functions
+ *
+ * Taken from UI Bootstrap $$debounce source code
+ * See https://github.com/angular-ui/bootstrap/blob/master/src/debounce/debounce.js
+ *
+ */
+uis.factory('$$uisDebounce', ['$timeout', function($timeout) {
+ return function(callback, debounceTime) {
+ var timeoutPromise;
+
+ return function() {
+ var self = this;
+ var args = Array.prototype.slice.call(arguments);
+ if (timeoutPromise) {
+ $timeout.cancel(timeoutPromise);
+ }
+
+ timeoutPromise = $timeout(function() {
+ callback.apply(self, args);
+ }, debounceTime);
+ };
+ };
+}]);
+
+uis.directive('uiSelectChoices',
+ ['uiSelectConfig', 'uisRepeatParser', 'uiSelectMinErr', '$compile', '$window',
+ function(uiSelectConfig, RepeatParser, uiSelectMinErr, $compile, $window) {
+
+ return {
+ restrict: 'EA',
+ require: '^uiSelect',
+ replace: true,
+ transclude: true,
+ templateUrl: function(tElement) {
+ // Needed so the uiSelect can detect the transcluded content
+ tElement.addClass('ui-select-choices');
+
+ // Gets theme attribute from parent (ui-select)
+ var theme = tElement.parent().attr('theme') || uiSelectConfig.theme;
+ return theme + '/choices.tpl.html';
+ },
+
+ compile: function(tElement, tAttrs) {
+
+ if (!tAttrs.repeat) throw uiSelectMinErr('repeat', "Expected 'repeat' expression.");
+
+ // var repeat = RepeatParser.parse(attrs.repeat);
+ var groupByExp = tAttrs.groupBy;
+ var groupFilterExp = tAttrs.groupFilter;
+
+ if (groupByExp) {
+ var groups = tElement.querySelectorAll('.ui-select-choices-group');
+ if (groups.length !== 1) throw uiSelectMinErr('rows', "Expected 1 .ui-select-choices-group but got '{0}'.", groups.length);
+ groups.attr('ng-repeat', RepeatParser.getGroupNgRepeatExpression());
+ }
+
+ var parserResult = RepeatParser.parse(tAttrs.repeat);
+
+ var choices = tElement.querySelectorAll('.ui-select-choices-row');
+ if (choices.length !== 1) {
+ throw uiSelectMinErr('rows', "Expected 1 .ui-select-choices-row but got '{0}'.", choices.length);
+ }
+
+ choices.attr('ng-repeat', parserResult.repeatExpression(groupByExp))
+ .attr('ng-if', '$select.open'); //Prevent unnecessary watches when dropdown is closed
+
+
+ var rowsInner = tElement.querySelectorAll('.ui-select-choices-row-inner');
+ if (rowsInner.length !== 1) {
+ throw uiSelectMinErr('rows', "Expected 1 .ui-select-choices-row-inner but got '{0}'.", rowsInner.length);
+ }
+ rowsInner.attr('uis-transclude-append', ''); //Adding uisTranscludeAppend directive to row element after choices element has ngRepeat
+
+ // If IE8 then need to target rowsInner to apply the ng-click attr as choices will not capture the event.
+ var clickTarget = $window.document.addEventListener ? choices : rowsInner;
+ clickTarget.attr('ng-click', '$select.select(' + parserResult.itemName + ',$select.skipFocusser,$event)');
+
+ return function link(scope, element, attrs, $select) {
+
+
+ $select.parseRepeatAttr(attrs.repeat, groupByExp, groupFilterExp); //Result ready at $select.parserResult
+
+ $select.disableChoiceExpression = attrs.uiDisableChoice;
+ $select.onHighlightCallback = attrs.onHighlight;
+
+ $select.dropdownPosition = attrs.position ? attrs.position.toLowerCase() : uiSelectConfig.dropdownPosition;
+
+ scope.$on('$destroy', function() {
+ choices.remove();
+ });
+
+ scope.$watch('$select.search', function(newValue) {
+ if(newValue && !$select.open && $select.multiple) $select.activate(false, true);
+ $select.activeIndex = $select.tagging.isActivated ? -1 : 0;
+ if (!attrs.minimumInputLength || $select.search.length >= attrs.minimumInputLength) {
+ $select.refresh(attrs.refresh);
+ } else {
+ $select.items = [];
+ }
+ });
+
+ attrs.$observe('refreshDelay', function() {
+ // $eval() is needed otherwise we get a string instead of a number
+ var refreshDelay = scope.$eval(attrs.refreshDelay);
+ $select.refreshDelay = refreshDelay !== undefined ? refreshDelay : uiSelectConfig.refreshDelay;
+ });
+ };
+ }
+ };
+}]);
+
+/**
+ * Contains ui-select "intelligence".
+ *
+ * The goal is to limit dependency on the DOM whenever possible and
+ * put as much logic in the controller (instead of the link functions) as possible so it can be easily tested.
+ */
+uis.controller('uiSelectCtrl',
+ ['$scope', '$element', '$timeout', '$filter', '$$uisDebounce', 'uisRepeatParser', 'uiSelectMinErr', 'uiSelectConfig', '$parse', '$injector', '$window',
+ function($scope, $element, $timeout, $filter, $$uisDebounce, RepeatParser, uiSelectMinErr, uiSelectConfig, $parse, $injector, $window) {
+
+ var ctrl = this;
+
+ var EMPTY_SEARCH = '';
+
+ ctrl.placeholder = uiSelectConfig.placeholder;
+ ctrl.searchEnabled = uiSelectConfig.searchEnabled;
+ ctrl.sortable = uiSelectConfig.sortable;
+ ctrl.refreshDelay = uiSelectConfig.refreshDelay;
+ ctrl.paste = uiSelectConfig.paste;
+
+ ctrl.removeSelected = false; //If selected item(s) should be removed from dropdown list
+ ctrl.closeOnSelect = true; //Initialized inside uiSelect directive link function
+ ctrl.skipFocusser = false; //Set to true to avoid returning focus to ctrl when item is selected
+ ctrl.search = EMPTY_SEARCH;
+
+ ctrl.activeIndex = 0; //Dropdown of choices
+ ctrl.items = []; //All available choices
+
+ ctrl.open = false;
+ ctrl.focus = false;
+ ctrl.disabled = false;
+ ctrl.selected = undefined;
+
+ ctrl.dropdownPosition = 'auto';
+
+ ctrl.focusser = undefined; //Reference to input element used to handle focus events
+ ctrl.resetSearchInput = true;
+ ctrl.multiple = undefined; // Initialized inside uiSelect directive link function
+ ctrl.disableChoiceExpression = undefined; // Initialized inside uiSelectChoices directive link function
+ ctrl.tagging = {isActivated: false, fct: undefined};
+ ctrl.taggingTokens = {isActivated: false, tokens: undefined};
+ ctrl.lockChoiceExpression = undefined; // Initialized inside uiSelectMatch directive link function
+ ctrl.clickTriggeredSelect = false;
+ ctrl.$filter = $filter;
+ ctrl.$element = $element;
+
+ // Use $injector to check for $animate and store a reference to it
+ ctrl.$animate = (function () {
+ try {
+ return $injector.get('$animate');
+ } catch (err) {
+ // $animate does not exist
+ return null;
+ }
+ })();
+
+ ctrl.searchInput = $element.querySelectorAll('input.ui-select-search');
+ if (ctrl.searchInput.length !== 1) {
+ throw uiSelectMinErr('searchInput', "Expected 1 input.ui-select-search but got '{0}'.", ctrl.searchInput.length);
+ }
+
+ ctrl.isEmpty = function() {
+ return angular.isUndefined(ctrl.selected) || ctrl.selected === null || ctrl.selected === '' || (ctrl.multiple && ctrl.selected.length === 0);
+ };
+
+ function _findIndex(collection, predicate, thisArg){
+ if (collection.findIndex){
+ return collection.findIndex(predicate, thisArg);
+ } else {
+ var list = Object(collection);
+ var length = list.length >>> 0;
+ var value;
+
+ for (var i = 0; i < length; i++) {
+ value = list[i];
+ if (predicate.call(thisArg, value, i, list)) {
+ return i;
+ }
+ }
+ return -1;
+ }
+ }
+
+ // Most of the time the user does not want to empty the search input when in typeahead mode
+ function _resetSearchInput() {
+ if (ctrl.resetSearchInput || (ctrl.resetSearchInput === undefined && uiSelectConfig.resetSearchInput)) {
+ ctrl.search = EMPTY_SEARCH;
+ //reset activeIndex
+ if (ctrl.selected && ctrl.items.length && !ctrl.multiple) {
+ ctrl.activeIndex = _findIndex(ctrl.items, function(item){
+ return angular.equals(this, item);
+ }, ctrl.selected);
+ }
+ }
+ }
+
+ function _groupsFilter(groups, groupNames) {
+ var i, j, result = [];
+ for(i = 0; i < groupNames.length ;i++){
+ for(j = 0; j < groups.length ;j++){
+ if(groups[j].name == [groupNames[i]]){
+ result.push(groups[j]);
+ }
+ }
+ }
+ return result;
+ }
+
+ // When the user clicks on ui-select, displays the dropdown list
+ ctrl.activate = function(initSearchValue, avoidReset) {
+ if (!ctrl.disabled && !ctrl.open) {
+ if(!avoidReset) _resetSearchInput();
+
+ $scope.$broadcast('uis:activate');
+
+ ctrl.open = true;
+
+ ctrl.activeIndex = ctrl.activeIndex >= ctrl.items.length ? 0 : ctrl.activeIndex;
+
+ // ensure that the index is set to zero for tagging variants
+ // that where first option is auto-selected
+ if ( ctrl.activeIndex === -1 && ctrl.taggingLabel !== false ) {
+ ctrl.activeIndex = 0;
+ }
+
+ var container = $element.querySelectorAll('.ui-select-choices-content');
+ var searchInput = $element.querySelectorAll('.ui-select-search');
+ if (ctrl.$animate && ctrl.$animate.enabled(container[0])) {
+ var animateHandler = function(elem, phase) {
+ if (phase === 'start' && ctrl.items.length === 0) {
+ // Only focus input after the animation has finished
+ ctrl.$animate.off('removeClass', searchInput[0], animateHandler);
+ $timeout(function () {
+ ctrl.focusSearchInput(initSearchValue);
+ });
+ } else if (phase === 'close') {
+ // Only focus input after the animation has finished
+ ctrl.$animate.off('enter', container[0], animateHandler);
+ $timeout(function () {
+ ctrl.focusSearchInput(initSearchValue);
+ });
+ }
+ };
+
+ if (ctrl.items.length > 0) {
+ ctrl.$animate.on('enter', container[0], animateHandler);
+ } else {
+ ctrl.$animate.on('removeClass', searchInput[0], animateHandler);
+ }
+ } else {
+ $timeout(function () {
+ ctrl.focusSearchInput(initSearchValue);
+ if(!ctrl.tagging.isActivated && ctrl.items.length > 1) {
+ _ensureHighlightVisible();
+ }
+ });
+ }
+ }
+ };
+
+ ctrl.focusSearchInput = function (initSearchValue) {
+ ctrl.search = initSearchValue || ctrl.search;
+ ctrl.searchInput[0].focus();
+ };
+
+ ctrl.findGroupByName = function(name) {
+ return ctrl.groups && ctrl.groups.filter(function(group) {
+ return group.name === name;
+ })[0];
+ };
+
+ ctrl.parseRepeatAttr = function(repeatAttr, groupByExp, groupFilterExp) {
+ function updateGroups(items) {
+ var groupFn = $scope.$eval(groupByExp);
+ ctrl.groups = [];
+ angular.forEach(items, function(item) {
+ var groupName = angular.isFunction(groupFn) ? groupFn(item) : item[groupFn];
+ var group = ctrl.findGroupByName(groupName);
+ if(group) {
+ group.items.push(item);
+ }
+ else {
+ ctrl.groups.push({name: groupName, items: [item]});
+ }
+ });
+ if(groupFilterExp){
+ var groupFilterFn = $scope.$eval(groupFilterExp);
+ if( angular.isFunction(groupFilterFn)){
+ ctrl.groups = groupFilterFn(ctrl.groups);
+ } else if(angular.isArray(groupFilterFn)){
+ ctrl.groups = _groupsFilter(ctrl.groups, groupFilterFn);
+ }
+ }
+ ctrl.items = [];
+ ctrl.groups.forEach(function(group) {
+ ctrl.items = ctrl.items.concat(group.items);
+ });
+ }
+
+ function setPlainItems(items) {
+ ctrl.items = items;
+ }
+
+ ctrl.setItemsFn = groupByExp ? updateGroups : setPlainItems;
+
+ ctrl.parserResult = RepeatParser.parse(repeatAttr);
+
+ ctrl.isGrouped = !!groupByExp;
+ ctrl.itemProperty = ctrl.parserResult.itemName;
+
+ //If collection is an Object, convert it to Array
+
+ var originalSource = ctrl.parserResult.source;
+
+ //When an object is used as source, we better create an array and use it as 'source'
+ var createArrayFromObject = function(){
+ var origSrc = originalSource($scope);
+ $scope.$uisSource = Object.keys(origSrc).map(function(v){
+ var result = {};
+ result[ctrl.parserResult.keyName] = v;
+ result.value = origSrc[v];
+ return result;
+ });
+ };
+
+ if (ctrl.parserResult.keyName){ // Check for (key,value) syntax
+ createArrayFromObject();
+ ctrl.parserResult.source = $parse('$uisSource' + ctrl.parserResult.filters);
+ $scope.$watch(originalSource, function(newVal, oldVal){
+ if (newVal !== oldVal) createArrayFromObject();
+ }, true);
+ }
+
+ ctrl.refreshItems = function (data){
+ data = data || ctrl.parserResult.source($scope);
+ var selectedItems = ctrl.selected;
+ //TODO should implement for single mode removeSelected
+ if (ctrl.isEmpty() || (angular.isArray(selectedItems) && !selectedItems.length) || !ctrl.removeSelected) {
+ ctrl.setItemsFn(data);
+ }else{
+ if ( data !== undefined ) {
+ var filteredItems = data.filter(function(i) {
+ return selectedItems.every(function(selectedItem) {
+ return !angular.equals(i, selectedItem);
+ });
+ });
+ ctrl.setItemsFn(filteredItems);
+ }
+ }
+ if (ctrl.dropdownPosition === 'auto' || ctrl.dropdownPosition === 'up'){
+ $scope.calculateDropdownPos();
+ }
+ };
+
+ // See https://github.com/angular/angular.js/blob/v1.2.15/src/ng/directive/ngRepeat.js#L259
+ $scope.$watchCollection(ctrl.parserResult.source, function(items) {
+ if (items === undefined || items === null) {
+ // If the user specifies undefined or null => reset the collection
+ // Special case: items can be undefined if the user did not initialized the collection on the scope
+ // i.e $scope.addresses = [] is missing
+ ctrl.items = [];
+ } else {
+ if (!angular.isArray(items)) {
+ throw uiSelectMinErr('items', "Expected an array but got '{0}'.", items);
+ } else {
+ //Remove already selected items (ex: while searching)
+ //TODO Should add a test
+ ctrl.refreshItems(items);
+
+ //update the view value with fresh data from items, if there is a valid model value
+ if(angular.isDefined(ctrl.ngModel.$modelValue)) {
+ ctrl.ngModel.$modelValue = null; //Force scope model value and ngModel value to be out of sync to re-run formatters
+ }
+ }
+ }
+ });
+
+ };
+
+ var _refreshDelayPromise;
+
+ /**
+ * Typeahead mode: lets the user refresh the collection using his own function.
+ *
+ * See Expose $select.search for external / remote filtering https://github.com/angular-ui/ui-select/pull/31
+ */
+ ctrl.refresh = function(refreshAttr) {
+ if (refreshAttr !== undefined) {
+
+ // Debounce
+ // See https://github.com/angular-ui/bootstrap/blob/0.10.0/src/typeahead/typeahead.js#L155
+ // FYI AngularStrap typeahead does not have debouncing: https://github.com/mgcrea/angular-strap/blob/v2.0.0-rc.4/src/typeahead/typeahead.js#L177
+ if (_refreshDelayPromise) {
+ $timeout.cancel(_refreshDelayPromise);
+ }
+ _refreshDelayPromise = $timeout(function() {
+ $scope.$eval(refreshAttr);
+ }, ctrl.refreshDelay);
+ }
+ };
+
+ ctrl.isActive = function(itemScope) {
+ if ( !ctrl.open ) {
+ return false;
+ }
+ var itemIndex = ctrl.items.indexOf(itemScope[ctrl.itemProperty]);
+ var isActive = itemIndex == ctrl.activeIndex;
+
+ if ( !isActive || itemIndex < 0 ) {
+ return false;
+ }
+
+ if (isActive && !angular.isUndefined(ctrl.onHighlightCallback)) {
+ itemScope.$eval(ctrl.onHighlightCallback);
+ }
+
+ return isActive;
+ };
+
+ ctrl.isDisabled = function(itemScope) {
+
+ if (!ctrl.open) return;
+
+ var itemIndex = ctrl.items.indexOf(itemScope[ctrl.itemProperty]);
+ var isDisabled = false;
+ var item;
+
+ if (itemIndex >= 0 && !angular.isUndefined(ctrl.disableChoiceExpression)) {
+ item = ctrl.items[itemIndex];
+ isDisabled = !!(itemScope.$eval(ctrl.disableChoiceExpression)); // force the boolean value
+ item._uiSelectChoiceDisabled = isDisabled; // store this for later reference
+ }
+
+ return isDisabled;
+ };
+
+
+ // When the user selects an item with ENTER or clicks the dropdown
+ ctrl.select = function(item, skipFocusser, $event) {
+ if (item === undefined || !item._uiSelectChoiceDisabled) {
+
+ if ( ! ctrl.items && ! ctrl.search && ! ctrl.tagging.isActivated) return;
+
+ if (!item || !item._uiSelectChoiceDisabled) {
+ if(ctrl.tagging.isActivated) {
+ // if taggingLabel is disabled, we pull from ctrl.search val
+ if ( ctrl.taggingLabel === false ) {
+ if ( ctrl.activeIndex < 0 ) {
+ item = ctrl.tagging.fct !== undefined ? ctrl.tagging.fct(ctrl.search) : ctrl.search;
+ if (!item || angular.equals( ctrl.items[0], item ) ) {
+ return;
+ }
+ } else {
+ // keyboard nav happened first, user selected from dropdown
+ item = ctrl.items[ctrl.activeIndex];
+ }
+ } else {
+ // tagging always operates at index zero, taggingLabel === false pushes
+ // the ctrl.search value without having it injected
+ if ( ctrl.activeIndex === 0 ) {
+ // ctrl.tagging pushes items to ctrl.items, so we only have empty val
+ // for `item` if it is a detected duplicate
+ if ( item === undefined ) return;
+
+ // create new item on the fly if we don't already have one;
+ // use tagging function if we have one
+ if ( ctrl.tagging.fct !== undefined && typeof item === 'string' ) {
+ item = ctrl.tagging.fct(item);
+ if (!item) return;
+ // if item type is 'string', apply the tagging label
+ } else if ( typeof item === 'string' ) {
+ // trim the trailing space
+ item = item.replace(ctrl.taggingLabel,'').trim();
+ }
+ }
+ }
+ // search ctrl.selected for dupes potentially caused by tagging and return early if found
+ if ( ctrl.selected && angular.isArray(ctrl.selected) && ctrl.selected.filter( function (selection) { return angular.equals(selection, item); }).length > 0 ) {
+ ctrl.close(skipFocusser);
+ return;
+ }
+ }
+
+ $scope.$broadcast('uis:select', item);
+
+ var locals = {};
+ locals[ctrl.parserResult.itemName] = item;
+
+ $timeout(function(){
+ ctrl.onSelectCallback($scope, {
+ $item: item,
+ $model: ctrl.parserResult.modelMapper($scope, locals)
+ });
+ });
+
+ if (ctrl.closeOnSelect) {
+ ctrl.close(skipFocusser);
+ }
+ if ($event && $event.type === 'click') {
+ ctrl.clickTriggeredSelect = true;
+ }
+ }
+ }
+ };
+
+ // Closes the dropdown
+ ctrl.close = function(skipFocusser) {
+ if (!ctrl.open) return;
+ if (ctrl.ngModel && ctrl.ngModel.$setTouched) ctrl.ngModel.$setTouched();
+ _resetSearchInput();
+ ctrl.open = false;
+
+ $scope.$broadcast('uis:close', skipFocusser);
+
+ };
+
+ ctrl.setFocus = function(){
+ if (!ctrl.focus) ctrl.focusInput[0].focus();
+ };
+
+ ctrl.clear = function($event) {
+ ctrl.select(undefined);
+ $event.stopPropagation();
+ $timeout(function() {
+ ctrl.focusser[0].focus();
+ }, 0, false);
+ };
+
+ // Toggle dropdown
+ ctrl.toggle = function(e) {
+ if (ctrl.open) {
+ ctrl.close();
+ e.preventDefault();
+ e.stopPropagation();
+ } else {
+ ctrl.activate();
+ }
+ };
+
+ ctrl.isLocked = function(itemScope, itemIndex) {
+ var isLocked, item = ctrl.selected[itemIndex];
+
+ if (item && !angular.isUndefined(ctrl.lockChoiceExpression)) {
+ isLocked = !!(itemScope.$eval(ctrl.lockChoiceExpression)); // force the boolean value
+ item._uiSelectChoiceLocked = isLocked; // store this for later reference
+ }
+
+ return isLocked;
+ };
+
+ var sizeWatch = null;
+ var updaterScheduled = false;
+ ctrl.sizeSearchInput = function() {
+
+ var input = ctrl.searchInput[0],
+ container = ctrl.searchInput.parent().parent()[0],
+ calculateContainerWidth = function() {
+ // Return the container width only if the search input is visible
+ return container.clientWidth * !!input.offsetParent;
+ },
+ updateIfVisible = function(containerWidth) {
+ if (containerWidth === 0) {
+ return false;
+ }
+ var inputWidth = containerWidth - input.offsetLeft - 10;
+ if (inputWidth < 50) inputWidth = containerWidth;
+ ctrl.searchInput.css('width', inputWidth+'px');
+ return true;
+ };
+
+ ctrl.searchInput.css('width', '10px');
+ $timeout(function() { //Give tags time to render correctly
+ if (sizeWatch === null && !updateIfVisible(calculateContainerWidth())) {
+ sizeWatch = $scope.$watch(angular.noop, function() {
+ if (!updaterScheduled) {
+ updaterScheduled = true;
+ $scope.$$postDigest(function() {
+ updaterScheduled = false;
+ if (updateIfVisible(calculateContainerWidth())) {
+ sizeWatch();
+ sizeWatch = null;
+ }
+ });
+ }
+ });
+ }
+ });
+ };
+
+ function _handleDropDownSelection(key) {
+ var processed = true;
+ switch (key) {
+ case KEY.DOWN:
+ if (!ctrl.open && ctrl.multiple) ctrl.activate(false, true); //In case its the search input in 'multiple' mode
+ else if (ctrl.activeIndex < ctrl.items.length - 1) { ctrl.activeIndex++; }
+ break;
+ case KEY.UP:
+ if (!ctrl.open && ctrl.multiple) ctrl.activate(false, true); //In case its the search input in 'multiple' mode
+ else if (ctrl.activeIndex > 0 || (ctrl.search.length === 0 && ctrl.tagging.isActivated && ctrl.activeIndex > -1)) { ctrl.activeIndex--; }
+ break;
+ case KEY.TAB:
+ if (!ctrl.multiple || ctrl.open) ctrl.select(ctrl.items[ctrl.activeIndex], true);
+ break;
+ case KEY.ENTER:
+ if(ctrl.open && (ctrl.tagging.isActivated || ctrl.activeIndex >= 0)){
+ ctrl.select(ctrl.items[ctrl.activeIndex], ctrl.skipFocusser); // Make sure at least one dropdown item is highlighted before adding if not in tagging mode
+ } else {
+ ctrl.activate(false, true); //In case its the search input in 'multiple' mode
+ }
+ break;
+ case KEY.ESC:
+ ctrl.close();
+ break;
+ default:
+ processed = false;
+ }
+ return processed;
+ }
+
+ // Bind to keyboard shortcuts
+ ctrl.searchInput.on('keydown', function(e) {
+
+ var key = e.which;
+
+ if (~[KEY.ENTER,KEY.ESC].indexOf(key)){
+ e.preventDefault();
+ e.stopPropagation();
+ }
+
+ // if(~[KEY.ESC,KEY.TAB].indexOf(key)){
+ // //TODO: SEGURO?
+ // ctrl.close();
+ // }
+
+ $scope.$apply(function() {
+
+ var tagged = false;
+
+ if (ctrl.items.length > 0 || ctrl.tagging.isActivated) {
+ _handleDropDownSelection(key);
+ if ( ctrl.taggingTokens.isActivated ) {
+ for (var i = 0; i < ctrl.taggingTokens.tokens.length; i++) {
+ if ( ctrl.taggingTokens.tokens[i] === KEY.MAP[e.keyCode] ) {
+ // make sure there is a new value to push via tagging
+ if ( ctrl.search.length > 0 ) {
+ tagged = true;
+ }
+ }
+ }
+ if ( tagged ) {
+ $timeout(function() {
+ ctrl.searchInput.triggerHandler('tagged');
+ var newItem = ctrl.search.replace(KEY.MAP[e.keyCode],'').trim();
+ if ( ctrl.tagging.fct ) {
+ newItem = ctrl.tagging.fct( newItem );
+ }
+ if (newItem) ctrl.select(newItem, true);
+ });
+ }
+ }
+ }
+
+ });
+
+ if(KEY.isVerticalMovement(key) && ctrl.items.length > 0){
+ _ensureHighlightVisible();
+ }
+
+ if (key === KEY.ENTER || key === KEY.ESC) {
+ e.preventDefault();
+ e.stopPropagation();
+ }
+
+ });
+
+ ctrl.searchInput.on('paste', function (e) {
+ var data;
+
+ if (window.clipboardData && window.clipboardData.getData) { // IE
+ data = window.clipboardData.getData('Text');
+ } else {
+ data = (e.originalEvent || e).clipboardData.getData('text/plain');
+ }
+
+ // Prepend the current input field text to the paste buffer.
+ data = ctrl.search + data;
+
+ if (data && data.length > 0) {
+ // If tagging try to split by tokens and add items
+ if (ctrl.taggingTokens.isActivated) {
+ var items = [];
+ for (var i = 0; i < ctrl.taggingTokens.tokens.length; i++) { // split by first token that is contained in data
+ var separator = KEY.toSeparator(ctrl.taggingTokens.tokens[i]) || ctrl.taggingTokens.tokens[i];
+ if (data.indexOf(separator) > -1) {
+ items = data.split(separator);
+ break; // only split by one token
+ }
+ }
+ if (items.length === 0) {
+ items = [data];
+ }
+ if (items.length > 0) {
+ var oldsearch = ctrl.search;
+ angular.forEach(items, function (item) {
+ var newItem = ctrl.tagging.fct ? ctrl.tagging.fct(item) : item;
+ if (newItem) {
+ ctrl.select(newItem, true);
+ }
+ });
+ ctrl.search = oldsearch || EMPTY_SEARCH;
+ e.preventDefault();
+ e.stopPropagation();
+ }
+ } else if (ctrl.paste) {
+ ctrl.paste(data);
+ ctrl.search = EMPTY_SEARCH;
+ e.preventDefault();
+ e.stopPropagation();
+ }
+ }
+ });
+
+ ctrl.searchInput.on('tagged', function() {
+ $timeout(function() {
+ _resetSearchInput();
+ });
+ });
+
+ // See https://github.com/ivaynberg/select2/blob/3.4.6/select2.js#L1431
+ function _ensureHighlightVisible() {
+ var container = $element.querySelectorAll('.ui-select-choices-content');
+ var choices = container.querySelectorAll('.ui-select-choices-row');
+ if (choices.length < 1) {
+ throw uiSelectMinErr('choices', "Expected multiple .ui-select-choices-row but got '{0}'.", choices.length);
+ }
+
+ if (ctrl.activeIndex < 0) {
+ return;
+ }
+
+ var highlighted = choices[ctrl.activeIndex];
+ var posY = highlighted.offsetTop + highlighted.clientHeight - container[0].scrollTop;
+ var height = container[0].offsetHeight;
+
+ if (posY > height) {
+ container[0].scrollTop += posY - height;
+ } else if (posY < highlighted.clientHeight) {
+ if (ctrl.isGrouped && ctrl.activeIndex === 0)
+ container[0].scrollTop = 0; //To make group header visible when going all the way up
+ else
+ container[0].scrollTop -= highlighted.clientHeight - posY;
+ }
+ }
+
+ var onResize = $$uisDebounce(function() {
+ ctrl.sizeSearchInput();
+ }, 50);
+
+ angular.element($window).bind('resize', onResize);
+
+ $scope.$on('$destroy', function() {
+ ctrl.searchInput.off('keyup keydown tagged blur paste');
+ angular.element($window).off('resize', onResize);
+ });
+}]);
+
+uis.directive('uiSelect',
+ ['$document', 'uiSelectConfig', 'uiSelectMinErr', 'uisOffset', '$compile', '$parse', '$timeout',
+ function($document, uiSelectConfig, uiSelectMinErr, uisOffset, $compile, $parse, $timeout) {
+
+ return {
+ restrict: 'EA',
+ templateUrl: function(tElement, tAttrs) {
+ var theme = tAttrs.theme || uiSelectConfig.theme;
+ return theme + (angular.isDefined(tAttrs.multiple) ? '/select-multiple.tpl.html' : '/select.tpl.html');
+ },
+ replace: true,
+ transclude: true,
+ require: ['uiSelect', '^ngModel'],
+ scope: true,
+
+ controller: 'uiSelectCtrl',
+ controllerAs: '$select',
+ compile: function(tElement, tAttrs) {
+
+ // Allow setting ngClass on uiSelect
+ var match = /{(.*)}\s*{(.*)}/.exec(tAttrs.ngClass);
+ if(match) {
+ var combined = '{'+ match[1] +', '+ match[2] +'}';
+ tAttrs.ngClass = combined;
+ tElement.attr('ng-class', combined);
+ }
+
+ //Multiple or Single depending if multiple attribute presence
+ if (angular.isDefined(tAttrs.multiple))
+ tElement.append('<ui-select-multiple/>').removeAttr('multiple');
+ else
+ tElement.append('<ui-select-single/>');
+
+ if (tAttrs.inputId)
+ tElement.querySelectorAll('input.ui-select-search')[0].id = tAttrs.inputId;
+
+ return function(scope, element, attrs, ctrls, transcludeFn) {
+
+ var $select = ctrls[0];
+ var ngModel = ctrls[1];
+
+ $select.generatedId = uiSelectConfig.generateId();
+ $select.baseTitle = attrs.title || 'Select box';
+ $select.focusserTitle = $select.baseTitle + ' focus';
+ $select.focusserId = 'focusser-' + $select.generatedId;
+
+ $select.closeOnSelect = function() {
+ if (angular.isDefined(attrs.closeOnSelect)) {
+ return $parse(attrs.closeOnSelect)();
+ } else {
+ return uiSelectConfig.closeOnSelect;
+ }
+ }();
+
+ scope.$watch('skipFocusser', function() {
+ var skipFocusser = scope.$eval(attrs.skipFocusser);
+ $select.skipFocusser = skipFocusser !== undefined ? skipFocusser : uiSelectConfig.skipFocusser;
+ });
+
+ $select.onSelectCallback = $parse(attrs.onSelect);
+ $select.onRemoveCallback = $parse(attrs.onRemove);
+
+ //Limit the number of selections allowed
+ $select.limit = (angular.isDefined(attrs.limit)) ? parseInt(attrs.limit, 10) : undefined;
+
+ //Set reference to ngModel from uiSelectCtrl
+ $select.ngModel = ngModel;
+
+ $select.choiceGrouped = function(group){
+ return $select.isGrouped && group && group.name;
+ };
+
+ if(attrs.tabindex){
+ attrs.$observe('tabindex', function(value) {
+ $select.focusInput.attr('tabindex', value);
+ element.removeAttr('tabindex');
+ });
+ }
+
+ scope.$watch('searchEnabled', function() {
+ var searchEnabled = scope.$eval(attrs.searchEnabled);
+ $select.searchEnabled = searchEnabled !== undefined ? searchEnabled : uiSelectConfig.searchEnabled;
+ });
+
+ scope.$watch('sortable', function() {
+ var sortable = scope.$eval(attrs.sortable);
+ $select.sortable = sortable !== undefined ? sortable : uiSelectConfig.sortable;
+ });
+
+ attrs.$observe('disabled', function() {
+ // No need to use $eval() (thanks to ng-disabled) since we already get a boolean instead of a string
+ $select.disabled = attrs.disabled !== undefined ? attrs.disabled : false;
+ });
+
+ attrs.$observe('resetSearchInput', function() {
+ // $eval() is needed otherwise we get a string instead of a boolean
+ var resetSearchInput = scope.$eval(attrs.resetSearchInput);
+ $select.resetSearchInput = resetSearchInput !== undefined ? resetSearchInput : true;
+ });
+
+ attrs.$observe('paste', function() {
+ $select.paste = scope.$eval(attrs.paste);
+ });
+
+ attrs.$observe('tagging', function() {
+ if(attrs.tagging !== undefined)
+ {
+ // $eval() is needed otherwise we get a string instead of a boolean
+ var taggingEval = scope.$eval(attrs.tagging);
+ $select.tagging = {isActivated: true, fct: taggingEval !== true ? taggingEval : undefined};
+ }
+ else
+ {
+ $select.tagging = {isActivated: false, fct: undefined};
+ }
+ });
+
+ attrs.$observe('taggingLabel', function() {
+ if(attrs.tagging !== undefined )
+ {
+ // check eval for FALSE, in this case, we disable the labels
+ // associated with tagging
+ if ( attrs.taggingLabel === 'false' ) {
+ $select.taggingLabel = false;
+ }
+ else
+ {
+ $select.taggingLabel = attrs.taggingLabel !== undefined ? attrs.taggingLabel : '(new)';
+ }
+ }
+ });
+
+ attrs.$observe('taggingTokens', function() {
+ if (attrs.tagging !== undefined) {
+ var tokens = attrs.taggingTokens !== undefined ? attrs.taggingTokens.split('|') : [',','ENTER'];
+ $select.taggingTokens = {isActivated: true, tokens: tokens };
+ }
+ });
+
+ //Automatically gets focus when loaded
+ if (angular.isDefined(attrs.autofocus)){
+ $timeout(function(){
+ $select.setFocus();
+ });
+ }
+
+ //Gets focus based on scope event name (e.g. focus-on='SomeEventName')
+ if (angular.isDefined(attrs.focusOn)){
+ scope.$on(attrs.focusOn, function() {
+ $timeout(function(){
+ $select.setFocus();
+ });
+ });
+ }
+
+ function onDocumentClick(e) {
+ if (!$select.open) return; //Skip it if dropdown is close
+
+ var contains = false;
+
+ if (window.jQuery) {
+ // Firefox 3.6 does not support element.contains()
+ // See Node.contains https://developer.mozilla.org/en-US/docs/Web/API/Node.contains
+ contains = window.jQuery.contains(element[0], e.target);
+ } else {
+ contains = element[0].contains(e.target);
+ }
+
+ if (!contains && !$select.clickTriggeredSelect) {
+ var skipFocusser;
+ if (!$select.skipFocusser) {
+ //Will lose focus only with certain targets
+ var focusableControls = ['input','button','textarea','select'];
+ var targetController = angular.element(e.target).controller('uiSelect'); //To check if target is other ui-select
+ skipFocusser = targetController && targetController !== $select; //To check if target is other ui-select
+ if (!skipFocusser) skipFocusser = ~focusableControls.indexOf(e.target.tagName.toLowerCase()); //Check if target is input, button or textarea
+ } else {
+ skipFocusser = true;
+ }
+ $select.close(skipFocusser);
+ scope.$digest();
+ }
+ $select.clickTriggeredSelect = false;
+ }
+
+ // See Click everywhere but here event http://stackoverflow.com/questions/12931369
+ $document.on('click', onDocumentClick);
+
+ scope.$on('$destroy', function() {
+ $document.off('click', onDocumentClick);
+ });
+
+ // Move transcluded elements to their correct position in main template
+ transcludeFn(scope, function(clone) {
+ // See Transclude in AngularJS http://blog.omkarpatil.com/2012/11/transclude-in-angularjs.html
+
+ // One day jqLite will be replaced by jQuery and we will be able to write:
+ // var transcludedElement = clone.filter('.my-class')
+ // instead of creating a hackish DOM element:
+ var transcluded = angular.element('<div>').append(clone);
+
+ var transcludedMatch = transcluded.querySelectorAll('.ui-select-match');
+ transcludedMatch.removeAttr('ui-select-match'); //To avoid loop in case directive as attr
+ transcludedMatch.removeAttr('data-ui-select-match'); // Properly handle HTML5 data-attributes
+ if (transcludedMatch.length !== 1) {
+ throw uiSelectMinErr('transcluded', "Expected 1 .ui-select-match but got '{0}'.", transcludedMatch.length);
+ }
+ element.querySelectorAll('.ui-select-match').replaceWith(transcludedMatch);
+
+ var transcludedChoices = transcluded.querySelectorAll('.ui-select-choices');
+ transcludedChoices.removeAttr('ui-select-choices'); //To avoid loop in case directive as attr
+ transcludedChoices.removeAttr('data-ui-select-choices'); // Properly handle HTML5 data-attributes
+ if (transcludedChoices.length !== 1) {
+ throw uiSelectMinErr('transcluded', "Expected 1 .ui-select-choices but got '{0}'.", transcludedChoices.length);
+ }
+ element.querySelectorAll('.ui-select-choices').replaceWith(transcludedChoices);
+
+ var transcludedNoChoice = transcluded.querySelectorAll('.ui-select-no-choice');
+ transcludedNoChoice.removeAttr('ui-select-no-choice'); //To avoid loop in case directive as attr
+ transcludedNoChoice.removeAttr('data-ui-select-no-choice'); // Properly handle HTML5 data-attributes
+ if (transcludedNoChoice.length == 1) {
+ element.querySelectorAll('.ui-select-no-choice').replaceWith(transcludedNoChoice);
+ }
+ });
+
+ // Support for appending the select field to the body when its open
+ var appendToBody = scope.$eval(attrs.appendToBody);
+ if (appendToBody !== undefined ? appendToBody : uiSelectConfig.appendToBody) {
+ scope.$watch('$select.open', function(isOpen) {
+ if (isOpen) {
+ positionDropdown();
+ } else {
+ resetDropdown();
+ }
+ });
+
+ // Move the dropdown back to its original location when the scope is destroyed. Otherwise
+ // it might stick around when the user routes away or the select field is otherwise removed
+ scope.$on('$destroy', function() {
+ resetDropdown();
+ });
+ }
+
+ // Hold on to a reference to the .ui-select-container element for appendToBody support
+ var placeholder = null,
+ originalWidth = '';
+
+ function positionDropdown() {
+ // Remember the absolute position of the element
+ var offset = uisOffset(element);
+
+ // Clone the element into a placeholder element to take its original place in the DOM
+ placeholder = angular.element('<div class="ui-select-placeholder"></div>');
+ placeholder[0].style.width = offset.width + 'px';
+ placeholder[0].style.height = offset.height + 'px';
+ element.after(placeholder);
+
+ // Remember the original value of the element width inline style, so it can be restored
+ // when the dropdown is closed
+ originalWidth = element[0].style.width;
+
+ // Now move the actual dropdown element to the end of the body
+ $document.find('body').append(element);
+
+ element[0].style.position = 'absolute';
+ element[0].style.left = offset.left + 'px';
+ element[0].style.top = offset.top + 'px';
+ element[0].style.width = offset.width + 'px';
+ }
+
+ function resetDropdown() {
+ if (placeholder === null) {
+ // The dropdown has not actually been display yet, so there's nothing to reset
+ return;
+ }
+
+ // Move the dropdown element back to its original location in the DOM
+ placeholder.replaceWith(element);
+ placeholder = null;
+
+ element[0].style.position = '';
+ element[0].style.left = '';
+ element[0].style.top = '';
+ element[0].style.width = originalWidth;
+
+ // Set focus back on to the moved element
+ $select.setFocus();
+ }
+
+ // Hold on to a reference to the .ui-select-dropdown element for direction support.
+ var dropdown = null,
+ directionUpClassName = 'direction-up';
+
+ // Support changing the direction of the dropdown if there isn't enough space to render it.
+ scope.$watch('$select.open', function() {
+
+ if ($select.dropdownPosition === 'auto' || $select.dropdownPosition === 'up'){
+ scope.calculateDropdownPos();
+ }
+
+ });
+
+ var setDropdownPosUp = function(offset, offsetDropdown){
+
+ offset = offset || uisOffset(element);
+ offsetDropdown = offsetDropdown || uisOffset(dropdown);
+
+ dropdown[0].style.position = 'absolute';
+ dropdown[0].style.top = (offsetDropdown.height * -1) + 'px';
+ element.addClass(directionUpClassName);
+
+ };
+
+ var setDropdownPosDown = function(offset, offsetDropdown){
+
+ element.removeClass(directionUpClassName);
+
+ offset = offset || uisOffset(element);
+ offsetDropdown = offsetDropdown || uisOffset(dropdown);
+
+ dropdown[0].style.position = '';
+ dropdown[0].style.top = '';
+
+ };
+
+ scope.calculateDropdownPos = function(){
+
+ if ($select.open) {
+ dropdown = angular.element(element).querySelectorAll('.ui-select-dropdown');
+ if (dropdown.length === 0) {
+ return;
+ }
+
+ // Hide the dropdown so there is no flicker until $timeout is done executing.
+ dropdown[0].style.opacity = 0;
+
+ // Delay positioning the dropdown until all choices have been added so its height is correct.
+ $timeout(function(){
+
+ if ($select.dropdownPosition === 'up'){
+ //Go UP
+ setDropdownPosUp();
+
+ }else{ //AUTO
+
+ element.removeClass(directionUpClassName);
+
+ var offset = uisOffset(element);
+ var offsetDropdown = uisOffset(dropdown);
+
+ //https://code.google.com/p/chromium/issues/detail?id=342307#c4
+ var scrollTop = $document[0].documentElement.scrollTop || $document[0].body.scrollTop; //To make it cross browser (blink, webkit, IE, Firefox).
+
+ // Determine if the direction of the dropdown needs to be changed.
+ if (offset.top + offset.height + offsetDropdown.height > scrollTop + $document[0].documentElement.clientHeight) {
+ //Go UP
+ setDropdownPosUp(offset, offsetDropdown);
+ }else{
+ //Go DOWN
+ setDropdownPosDown(offset, offsetDropdown);
+ }
+
+ }
+
+ // Display the dropdown once it has been positioned.
+ dropdown[0].style.opacity = 1;
+ });
+ } else {
+ if (dropdown === null || dropdown.length === 0) {
+ return;
+ }
+
+ // Reset the position of the dropdown.
+ dropdown[0].style.position = '';
+ dropdown[0].style.top = '';
+ element.removeClass(directionUpClassName);
+ }
+ };
+ };
+ }
+ };
+}]);
+
+uis.directive('uiSelectMatch', ['uiSelectConfig', function(uiSelectConfig) {
+ return {
+ restrict: 'EA',
+ require: '^uiSelect',
+ replace: true,
+ transclude: true,
+ templateUrl: function(tElement) {
+ // Needed so the uiSelect can detect the transcluded content
+ tElement.addClass('ui-select-match');
+
+ var parent = tElement.parent();
+ // Gets theme attribute from parent (ui-select)
+ var theme = getAttribute(parent, 'theme') || uiSelectConfig.theme;
+ var multi = angular.isDefined(getAttribute(parent, 'multiple'));
+
+ return theme + (multi ? '/match-multiple.tpl.html' : '/match.tpl.html');
+ },
+ link: function(scope, element, attrs, $select) {
+ $select.lockChoiceExpression = attrs.uiLockChoice;
+ attrs.$observe('placeholder', function(placeholder) {
+ $select.placeholder = placeholder !== undefined ? placeholder : uiSelectConfig.placeholder;
+ });
+
+ function setAllowClear(allow) {
+ $select.allowClear = (angular.isDefined(allow)) ? (allow === '') ? true : (allow.toLowerCase() === 'true') : false;
+ }
+
+ attrs.$observe('allowClear', setAllowClear);
+ setAllowClear(attrs.allowClear);
+
+ if($select.multiple){
+ $select.sizeSearchInput();
+ }
+
+ }
+ };
+
+ function getAttribute(elem, attribute) {
+ if (elem[0].hasAttribute(attribute))
+ return elem.attr(attribute);
+
+ if (elem[0].hasAttribute('data-' + attribute))
+ return elem.attr('data-' + attribute);
+
+ if (elem[0].hasAttribute('x-' + attribute))
+ return elem.attr('x-' + attribute);
+ }
+}]);
+
+uis.directive('uiSelectMultiple', ['uiSelectMinErr','$timeout', function(uiSelectMinErr, $timeout) {
+ return {
+ restrict: 'EA',
+ require: ['^uiSelect', '^ngModel'],
+
+ controller: ['$scope','$timeout', function($scope, $timeout){
+
+ var ctrl = this,
+ $select = $scope.$select,
+ ngModel;
+
+ if (angular.isUndefined($select.selected))
+ $select.selected = [];
+
+ //Wait for link fn to inject it
+ $scope.$evalAsync(function(){ ngModel = $scope.ngModel; });
+
+ ctrl.activeMatchIndex = -1;
+
+ ctrl.updateModel = function(){
+ ngModel.$setViewValue(Date.now()); //Set timestamp as a unique string to force changes
+ ctrl.refreshComponent();
+ };
+
+ ctrl.refreshComponent = function(){
+ //Remove already selected items
+ //e.g. When user clicks on a selection, the selected array changes and
+ //the dropdown should remove that item
+ $select.refreshItems();
+ $select.sizeSearchInput();
+ };
+
+ // Remove item from multiple select
+ ctrl.removeChoice = function(index){
+
+ var removedChoice = $select.selected[index];
+
+ // if the choice is locked, can't remove it
+ if(removedChoice._uiSelectChoiceLocked) return;
+
+ var locals = {};
+ locals[$select.parserResult.itemName] = removedChoice;
+
+ $select.selected.splice(index, 1);
+ ctrl.activeMatchIndex = -1;
+ $select.sizeSearchInput();
+
+ // Give some time for scope propagation.
+ $timeout(function(){
+ $select.onRemoveCallback($scope, {
+ $item: removedChoice,
+ $model: $select.parserResult.modelMapper($scope, locals)
+ });
+ });
+
+ ctrl.updateModel();
+
+ };
+
+ ctrl.getPlaceholder = function(){
+ //Refactor single?
+ if($select.selected && $select.selected.length) return;
+ return $select.placeholder;
+ };
+
+
+ }],
+ controllerAs: '$selectMultiple',
+
+ link: function(scope, element, attrs, ctrls) {
+
+ var $select = ctrls[0];
+ var ngModel = scope.ngModel = ctrls[1];
+ var $selectMultiple = scope.$selectMultiple;
+
+ //$select.selected = raw selected objects (ignoring any property binding)
+
+ $select.multiple = true;
+ $select.removeSelected = true;
+
+ //Input that will handle focus
+ $select.focusInput = $select.searchInput;
+
+ //Properly check for empty if set to multiple
+ ngModel.$isEmpty = function(value) {
+ return !value || value.length === 0;
+ };
+
+ //From view --> model
+ ngModel.$parsers.unshift(function () {
+ var locals = {},
+ result,
+ resultMultiple = [];
+ for (var j = $select.selected.length - 1; j >= 0; j--) {
+ locals = {};
+ locals[$select.parserResult.itemName] = $select.selected[j];
+ result = $select.parserResult.modelMapper(scope, locals);
+ resultMultiple.unshift(result);
+ }
+ return resultMultiple;
+ });
+
+ // From model --> view
+ ngModel.$formatters.unshift(function (inputValue) {
+ var data = $select.parserResult && $select.parserResult.source (scope, { $select : {search:''}}), //Overwrite $search
+ locals = {},
+ result;
+ if (!data) return inputValue;
+ var resultMultiple = [];
+ var checkFnMultiple = function(list, value){
+ if (!list || !list.length) return;
+ for (var p = list.length - 1; p >= 0; p--) {
+ locals[$select.parserResult.itemName] = list[p];
+ result = $select.parserResult.modelMapper(scope, locals);
+ if($select.parserResult.trackByExp){
+ var propsItemNameMatches = /(\w*)\./.exec($select.parserResult.trackByExp);
+ var matches = /\.([^\s]+)/.exec($select.parserResult.trackByExp);
+ if(propsItemNameMatches && propsItemNameMatches.length > 0 && propsItemNameMatches[1] == $select.parserResult.itemName){
+ if(matches && matches.length>0 && result[matches[1]] == value[matches[1]]){
+ resultMultiple.unshift(list[p]);
+ return true;
+ }
+ }
+ }
+ if (angular.equals(result,value)){
+ resultMultiple.unshift(list[p]);
+ return true;
+ }
+ }
+ return false;
+ };
+ if (!inputValue) return resultMultiple; //If ngModel was undefined
+ for (var k = inputValue.length - 1; k >= 0; k--) {
+ //Check model array of currently selected items
+ if (!checkFnMultiple($select.selected, inputValue[k])){
+ //Check model array of all items available
+ if (!checkFnMultiple(data, inputValue[k])){
+ //If not found on previous lists, just add it directly to resultMultiple
+ resultMultiple.unshift(inputValue[k]);
+ }
+ }
+ }
+ return resultMultiple;
+ });
+
+ //Watch for external model changes
+ scope.$watchCollection(function(){ return ngModel.$modelValue; }, function(newValue, oldValue) {
+ if (oldValue != newValue){
+ //update the view value with fresh data from items, if there is a valid model value
+ if(angular.isDefined(ngModel.$modelValue)) {
+ ngModel.$modelValue = null; //Force scope model value and ngModel value to be out of sync to re-run formatters
+ }
+ $selectMultiple.refreshComponent();
+ }
+ });
+
+ ngModel.$render = function() {
+ // Make sure that model value is array
+ if(!angular.isArray(ngModel.$viewValue)){
+ // Have tolerance for null or undefined values
+ if(angular.isUndefined(ngModel.$viewValue) || ngModel.$viewValue === null){
+ $select.selected = [];
+ } else {
+ throw uiSelectMinErr('multiarr', "Expected model value to be array but got '{0}'", ngModel.$viewValue);
+ }
+ }
+ $select.selected = ngModel.$viewValue;
+ $selectMultiple.refreshComponent();
+ scope.$evalAsync(); //To force $digest
+ };
+
+ scope.$on('uis:select', function (event, item) {
+ if($select.selected.length >= $select.limit) {
+ return;
+ }
+ $select.selected.push(item);
+ $selectMultiple.updateModel();
+ });
+
+ scope.$on('uis:activate', function () {
+ $selectMultiple.activeMatchIndex = -1;
+ });
+
+ scope.$watch('$select.disabled', function(newValue, oldValue) {
+ // As the search input field may now become visible, it may be necessary to recompute its size
+ if (oldValue && !newValue) $select.sizeSearchInput();
+ });
+
+ $select.searchInput.on('keydown', function(e) {
+ var key = e.which;
+ scope.$apply(function() {
+ var processed = false;
+ // var tagged = false; //Checkme
+ if(KEY.isHorizontalMovement(key)){
+ processed = _handleMatchSelection(key);
+ }
+ if (processed && key != KEY.TAB) {
+ //TODO Check si el tab selecciona aun correctamente
+ //Crear test
+ e.preventDefault();
+ e.stopPropagation();
+ }
+ });
+ });
+ function _getCaretPosition(el) {
+ if(angular.isNumber(el.selectionStart)) return el.selectionStart;
+ // selectionStart is not supported in IE8 and we don't want hacky workarounds so we compromise
+ else return el.value.length;
+ }
+ // Handles selected options in "multiple" mode
+ function _handleMatchSelection(key){
+ var caretPosition = _getCaretPosition($select.searchInput[0]),
+ length = $select.selected.length,
+ // none = -1,
+ first = 0,
+ last = length-1,
+ curr = $selectMultiple.activeMatchIndex,
+ next = $selectMultiple.activeMatchIndex+1,
+ prev = $selectMultiple.activeMatchIndex-1,
+ newIndex = curr;
+
+ if(caretPosition > 0 || ($select.search.length && key == KEY.RIGHT)) return false;
+
+ $select.close();
+
+ function getNewActiveMatchIndex(){
+ switch(key){
+ case KEY.LEFT:
+ // Select previous/first item
+ if(~$selectMultiple.activeMatchIndex) return prev;
+ // Select last item
+ else return last;
+ break;
+ case KEY.RIGHT:
+ // Open drop-down
+ if(!~$selectMultiple.activeMatchIndex || curr === last){
+ $select.activate();
+ return false;
+ }
+ // Select next/last item
+ else return next;
+ break;
+ case KEY.BACKSPACE:
+ // Remove selected item and select previous/first
+ if(~$selectMultiple.activeMatchIndex){
+ $selectMultiple.removeChoice(curr);
+ return prev;
+ }
+ // Select last item
+ else return last;
+ break;
+ case KEY.DELETE:
+ // Remove selected item and select next item
+ if(~$selectMultiple.activeMatchIndex){
+ $selectMultiple.removeChoice($selectMultiple.activeMatchIndex);
+ return curr;
+ }
+ else return false;
+ }
+ }
+
+ newIndex = getNewActiveMatchIndex();
+
+ if(!$select.selected.length || newIndex === false) $selectMultiple.activeMatchIndex = -1;
+ else $selectMultiple.activeMatchIndex = Math.min(last,Math.max(first,newIndex));
+
+ return true;
+ }
+
+ $select.searchInput.on('keyup', function(e) {
+
+ if ( ! KEY.isVerticalMovement(e.which) ) {
+ scope.$evalAsync( function () {
+ $select.activeIndex = $select.taggingLabel === false ? -1 : 0;
+ });
+ }
+ // Push a "create new" item into array if there is a search string
+ if ( $select.tagging.isActivated && $select.search.length > 0 ) {
+
+ // return early with these keys
+ if (e.which === KEY.TAB || KEY.isControl(e) || KEY.isFunctionKey(e) || e.which === KEY.ESC || KEY.isVerticalMovement(e.which) ) {
+ return;
+ }
+ // always reset the activeIndex to the first item when tagging
+ $select.activeIndex = $select.taggingLabel === false ? -1 : 0;
+ // taggingLabel === false bypasses all of this
+ if ($select.taggingLabel === false) return;
+
+ var items = angular.copy( $select.items );
+ var stashArr = angular.copy( $select.items );
+ var newItem;
+ var item;
+ var hasTag = false;
+ var dupeIndex = -1;
+ var tagItems;
+ var tagItem;
+
+ // case for object tagging via transform `$select.tagging.fct` function
+ if ( $select.tagging.fct !== undefined) {
+ tagItems = $select.$filter('filter')(items,{'isTag': true});
+ if ( tagItems.length > 0 ) {
+ tagItem = tagItems[0];
+ }
+ // remove the first element, if it has the `isTag` prop we generate a new one with each keyup, shaving the previous
+ if ( items.length > 0 && tagItem ) {
+ hasTag = true;
+ items = items.slice(1,items.length);
+ stashArr = stashArr.slice(1,stashArr.length);
+ }
+ newItem = $select.tagging.fct($select.search);
+ // verify the new tag doesn't match the value of a possible selection choice or an already selected item.
+ if (
+ stashArr.some(function (origItem) {
+ return angular.equals(origItem, newItem);
+ }) ||
+ $select.selected.some(function (origItem) {
+ return angular.equals(origItem, newItem);
+ })
+ ) {
+ scope.$evalAsync(function () {
+ $select.activeIndex = 0;
+ $select.items = items;
+ });
+ return;
+ }
+ if (newItem) newItem.isTag = true;
+ // handle newItem string and stripping dupes in tagging string context
+ } else {
+ // find any tagging items already in the $select.items array and store them
+ tagItems = $select.$filter('filter')(items,function (item) {
+ return item.match($select.taggingLabel);
+ });
+ if ( tagItems.length > 0 ) {
+ tagItem = tagItems[0];
+ }
+ item = items[0];
+ // remove existing tag item if found (should only ever be one tag item)
+ if ( item !== undefined && items.length > 0 && tagItem ) {
+ hasTag = true;
+ items = items.slice(1,items.length);
+ stashArr = stashArr.slice(1,stashArr.length);
+ }
+ newItem = $select.search+' '+$select.taggingLabel;
+ if ( _findApproxDupe($select.selected, $select.search) > -1 ) {
+ return;
+ }
+ // verify the the tag doesn't match the value of an existing item from
+ // the searched data set or the items already selected
+ if ( _findCaseInsensitiveDupe(stashArr.concat($select.selected)) ) {
+ // if there is a tag from prev iteration, strip it / queue the change
+ // and return early
+ if ( hasTag ) {
+ items = stashArr;
+ scope.$evalAsync( function () {
+ $select.activeIndex = 0;
+ $select.items = items;
+ });
+ }
+ return;
+ }
+ if ( _findCaseInsensitiveDupe(stashArr) ) {
+ // if there is a tag from prev iteration, strip it
+ if ( hasTag ) {
+ $select.items = stashArr.slice(1,stashArr.length);
+ }
+ return;
+ }
+ }
+ if ( hasTag ) dupeIndex = _findApproxDupe($select.selected, newItem);
+ // dupe found, shave the first item
+ if ( dupeIndex > -1 ) {
+ items = items.slice(dupeIndex+1,items.length-1);
+ } else {
+ items = [];
+ if (newItem) items.push(newItem);
+ items = items.concat(stashArr);
+ }
+ scope.$evalAsync( function () {
+ $select.activeIndex = 0;
+ $select.items = items;
+
+ if ($select.isGrouped) {
+ // update item references in groups, so that indexOf will work after angular.copy
+ var itemsWithoutTag = newItem ? items.slice(1) : items;
+ $select.setItemsFn(itemsWithoutTag);
+ if (newItem) {
+ // add tag item as a new group
+ $select.items.unshift(newItem);
+ $select.groups.unshift({name: '', items: [newItem], tagging: true});
+ }
+ }
+ });
+ }
+ });
+ function _findCaseInsensitiveDupe(arr) {
+ if ( arr === undefined || $select.search === undefined ) {
+ return false;
+ }
+ var hasDupe = arr.filter( function (origItem) {
+ if ( $select.search.toUpperCase() === undefined || origItem === undefined ) {
+ return false;
+ }
+ return origItem.toUpperCase() === $select.search.toUpperCase();
+ }).length > 0;
+
+ return hasDupe;
+ }
+ function _findApproxDupe(haystack, needle) {
+ var dupeIndex = -1;
+ if(angular.isArray(haystack)) {
+ var tempArr = angular.copy(haystack);
+ for (var i = 0; i <tempArr.length; i++) {
+ // handle the simple string version of tagging
+ if ( $select.tagging.fct === undefined ) {
+ // search the array for the match
+ if ( tempArr[i]+' '+$select.taggingLabel === needle ) {
+ dupeIndex = i;
+ }
+ // handle the object tagging implementation
+ } else {
+ var mockObj = tempArr[i];
+ if (angular.isObject(mockObj)) {
+ mockObj.isTag = true;
+ }
+ if ( angular.equals(mockObj, needle) ) {
+ dupeIndex = i;
+ }
+ }
+ }
+ }
+ return dupeIndex;
+ }
+
+ $select.searchInput.on('blur', function() {
+ $timeout(function() {
+ $selectMultiple.activeMatchIndex = -1;
+ });
+ });
+
+ }
+ };
+}]);
+
+uis.directive('uiSelectNoChoice',
+ ['uiSelectConfig', function (uiSelectConfig) {
+ return {
+ restrict: 'EA',
+ require: '^uiSelect',
+ replace: true,
+ transclude: true,
+ templateUrl: function (tElement) {
+ // Gets theme attribute from parent (ui-select)
+ var theme = tElement.parent().attr('theme') || uiSelectConfig.theme;
+ return theme + '/no-choice.tpl.html';
+ }
+ };
+ }]);
+uis.directive('uiSelectSingle', ['$timeout','$compile', function($timeout, $compile) {
+ return {
+ restrict: 'EA',
+ require: ['^uiSelect', '^ngModel'],
+ link: function(scope, element, attrs, ctrls) {
+
+ var $select = ctrls[0];
+ var ngModel = ctrls[1];
+
+ //From view --> model
+ ngModel.$parsers.unshift(function (inputValue) {
+ var locals = {},
+ result;
+ locals[$select.parserResult.itemName] = inputValue;
+ result = $select.parserResult.modelMapper(scope, locals);
+ return result;
+ });
+
+ //From model --> view
+ ngModel.$formatters.unshift(function (inputValue) {
+ var data = $select.parserResult && $select.parserResult.source (scope, { $select : {search:''}}), //Overwrite $search
+ locals = {},
+ result;
+ if (data){
+ var checkFnSingle = function(d){
+ locals[$select.parserResult.itemName] = d;
+ result = $select.parserResult.modelMapper(scope, locals);
+ return result === inputValue;
+ };
+ //If possible pass same object stored in $select.selected
+ if ($select.selected && checkFnSingle($select.selected)) {
+ return $select.selected;
+ }
+ for (var i = data.length - 1; i >= 0; i--) {
+ if (checkFnSingle(data[i])) return data[i];
+ }
+ }
+ return inputValue;
+ });
+
+ //Update viewValue if model change
+ scope.$watch('$select.selected', function(newValue) {
+ if (ngModel.$viewValue !== newValue) {
+ ngModel.$setViewValue(newValue);
+ }
+ });
+
+ ngModel.$render = function() {
+ $select.selected = ngModel.$viewValue;
+ };
+
+ scope.$on('uis:select', function (event, item) {
+ $select.selected = item;
+ });
+
+ scope.$on('uis:close', function (event, skipFocusser) {
+ $timeout(function(){
+ $select.focusser.prop('disabled', false);
+ if (!skipFocusser) $select.focusser[0].focus();
+ },0,false);
+ });
+
+ scope.$on('uis:activate', function () {
+ focusser.prop('disabled', true); //Will reactivate it on .close()
+ });
+
+ //Idea from: https://github.com/ivaynberg/select2/blob/79b5bf6db918d7560bdd959109b7bcfb47edaf43/select2.js#L1954
+ var focusser = angular.element("<input ng-disabled='$select.disabled' class='ui-select-focusser ui-select-offscreen' type='text' id='{{ $select.focusserId }}' aria-label='{{ $select.focusserTitle }}' aria-haspopup='true' role='button' />");
+ $compile(focusser)(scope);
+ $select.focusser = focusser;
+
+ //Input that will handle focus
+ $select.focusInput = focusser;
+
+ element.parent().append(focusser);
+ focusser.bind("focus", function(){
+ scope.$evalAsync(function(){
+ $select.focus = true;
+ });
+ });
+ focusser.bind("blur", function(){
+ scope.$evalAsync(function(){
+ $select.focus = false;
+ });
+ });
+ focusser.bind("keydown", function(e){
+
+ if (e.which === KEY.BACKSPACE) {
+ e.preventDefault();
+ e.stopPropagation();
+ $select.select(undefined);
+ scope.$apply();
+ return;
+ }
+
+ if (e.which === KEY.TAB || KEY.isControl(e) || KEY.isFunctionKey(e) || e.which === KEY.ESC) {
+ return;
+ }
+
+ if (e.which == KEY.DOWN || e.which == KEY.UP || e.which == KEY.ENTER || e.which == KEY.SPACE){
+ e.preventDefault();
+ e.stopPropagation();
+ $select.activate();
+ }
+
+ scope.$digest();
+ });
+
+ focusser.bind("keyup input", function(e){
+
+ if (e.which === KEY.TAB || KEY.isControl(e) || KEY.isFunctionKey(e) || e.which === KEY.ESC || e.which == KEY.ENTER || e.which === KEY.BACKSPACE) {
+ return;
+ }
+
+ $select.activate(focusser.val()); //User pressed some regular key, so we pass it to the search input
+ focusser.val('');
+ scope.$digest();
+
+ });
+
+
+ }
+ };
+}]);
+
+// Make multiple matches sortable
+uis.directive('uiSelectSort', ['$timeout', 'uiSelectConfig', 'uiSelectMinErr', function($timeout, uiSelectConfig, uiSelectMinErr) {
+ return {
+ require: ['^^uiSelect', '^ngModel'],
+ link: function(scope, element, attrs, ctrls) {
+ if (scope[attrs.uiSelectSort] === null) {
+ throw uiSelectMinErr('sort', 'Expected a list to sort');
+ }
+
+ var $select = ctrls[0];
+ var $ngModel = ctrls[1];
+
+ var options = angular.extend({
+ axis: 'horizontal'
+ },
+ scope.$eval(attrs.uiSelectSortOptions));
+
+ var axis = options.axis;
+ var draggingClassName = 'dragging';
+ var droppingClassName = 'dropping';
+ var droppingBeforeClassName = 'dropping-before';
+ var droppingAfterClassName = 'dropping-after';
+
+ scope.$watch(function(){
+ return $select.sortable;
+ }, function(newValue){
+ if (newValue) {
+ element.attr('draggable', true);
+ } else {
+ element.removeAttr('draggable');
+ }
+ });
+
+ element.on('dragstart', function(event) {
+ element.addClass(draggingClassName);
+
+ (event.dataTransfer || event.originalEvent.dataTransfer).setData('text', scope.$index.toString());
+ });
+
+ element.on('dragend', function() {
+ removeClass(draggingClassName);
+ });
+
+ var move = function(from, to) {
+ /*jshint validthis: true */
+ this.splice(to, 0, this.splice(from, 1)[0]);
+ };
+
+ var removeClass = function(className) {
+ angular.forEach($select.$element.querySelectorAll('.' + className), function(el){
+ angular.element(el).removeClass(className);
+ });
+ };
+
+ var dragOverHandler = function(event) {
+ event.preventDefault();
+
+ var offset = axis === 'vertical' ? event.offsetY || event.layerY || (event.originalEvent ? event.originalEvent.offsetY : 0) : event.offsetX || event.layerX || (event.originalEvent ? event.originalEvent.offsetX : 0);
+
+ if (offset < (this[axis === 'vertical' ? 'offsetHeight' : 'offsetWidth'] / 2)) {
+ removeClass(droppingAfterClassName);
+ element.addClass(droppingBeforeClassName);
+
+ } else {
+ removeClass(droppingBeforeClassName);
+ element.addClass(droppingAfterClassName);
+ }
+ };
+
+ var dropTimeout;
+
+ var dropHandler = function(event) {
+ event.preventDefault();
+
+ var droppedItemIndex = parseInt((event.dataTransfer || event.originalEvent.dataTransfer).getData('text'), 10);
+
+ // prevent event firing multiple times in firefox
+ $timeout.cancel(dropTimeout);
+ dropTimeout = $timeout(function() {
+ _dropHandler(droppedItemIndex);
+ }, 20);
+ };
+
+ var _dropHandler = function(droppedItemIndex) {
+ var theList = scope.$eval(attrs.uiSelectSort);
+ var itemToMove = theList[droppedItemIndex];
+ var newIndex = null;
+
+ if (element.hasClass(droppingBeforeClassName)) {
+ if (droppedItemIndex < scope.$index) {
+ newIndex = scope.$index - 1;
+ } else {
+ newIndex = scope.$index;
+ }
+ } else {
+ if (droppedItemIndex < scope.$index) {
+ newIndex = scope.$index;
+ } else {
+ newIndex = scope.$index + 1;
+ }
+ }
+
+ move.apply(theList, [droppedItemIndex, newIndex]);
+
+ $ngModel.$setViewValue(Date.now());
+
+ scope.$apply(function() {
+ scope.$emit('uiSelectSort:change', {
+ array: theList,
+ item: itemToMove,
+ from: droppedItemIndex,
+ to: newIndex
+ });
+ });
+
+ removeClass(droppingClassName);
+ removeClass(droppingBeforeClassName);
+ removeClass(droppingAfterClassName);
+
+ element.off('drop', dropHandler);
+ };
+
+ element.on('dragenter', function() {
+ if (element.hasClass(draggingClassName)) {
+ return;
+ }
+
+ element.addClass(droppingClassName);
+
+ element.on('dragover', dragOverHandler);
+ element.on('drop', dropHandler);
+ });
+
+ element.on('dragleave', function(event) {
+ if (event.target != element) {
+ return;
+ }
+
+ removeClass(droppingClassName);
+ removeClass(droppingBeforeClassName);
+ removeClass(droppingAfterClassName);
+
+ element.off('dragover', dragOverHandler);
+ element.off('drop', dropHandler);
+ });
+ }
+ };
+}]);
+
+/**
+ * Parses "repeat" attribute.
+ *
+ * Taken from AngularJS ngRepeat source code
+ * See https://github.com/angular/angular.js/blob/v1.2.15/src/ng/directive/ngRepeat.js#L211
+ *
+ * Original discussion about parsing "repeat" attribute instead of fully relying on ng-repeat:
+ * https://github.com/angular-ui/ui-select/commit/5dd63ad#commitcomment-5504697
+ */
+
+uis.service('uisRepeatParser', ['uiSelectMinErr','$parse', function(uiSelectMinErr, $parse) {
+ var self = this;
+
+ /**
+ * Example:
+ * expression = "address in addresses | filter: {street: $select.search} track by $index"
+ * itemName = "address",
+ * source = "addresses | filter: {street: $select.search}",
+ * trackByExp = "$index",
+ */
+ self.parse = function(expression) {
+
+
+ var match;
+ //var isObjectCollection = /\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)/.test(expression);
+ // If an array is used as collection
+
+ // if (isObjectCollection){
+ // 000000000000000000000000000000111111111000000000000000222222222222220033333333333333333333330000444444444444444444000000000000000055555555555000000000000000000000066666666600000000
+ match = expression.match(/^\s*(?:([\s\S]+?)\s+as\s+)?(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+(\s*[\s\S]+?)?(?:\s+track\s+by\s+([\s\S]+?))?\s*$/);
+
+ // 1 Alias
+ // 2 Item
+ // 3 Key on (key,value)
+ // 4 Value on (key,value)
+ // 5 Source expression (including filters)
+ // 6 Track by
+
+ if (!match) {
+ throw uiSelectMinErr('iexp', "Expected expression in form of '_item_ in _collection_[ track by _id_]' but got '{0}'.",
+ expression);
+ }
+
+ var source = match[5],
+ filters = '';
+
+ // When using (key,value) ui-select requires filters to be extracted, since the object
+ // is converted to an array for $select.items
+ // (in which case the filters need to be reapplied)
+ if (match[3]) {
+ // Remove any enclosing parenthesis
+ source = match[5].replace(/(^\()|(\)$)/g, '');
+ // match all after | but not after ||
+ var filterMatch = match[5].match(/^\s*(?:[\s\S]+?)(?:[^\|]|\|\|)+([\s\S]*)\s*$/);
+ if(filterMatch && filterMatch[1].trim()) {
+ filters = filterMatch[1];
+ source = source.replace(filters, '');
+ }
+ }
+
+ return {
+ itemName: match[4] || match[2], // (lhs) Left-hand side,
+ keyName: match[3], //for (key, value) syntax
+ source: $parse(source),
+ filters: filters,
+ trackByExp: match[6],
+ modelMapper: $parse(match[1] || match[4] || match[2]),
+ repeatExpression: function (grouped) {
+ var expression = this.itemName + ' in ' + (grouped ? '$group.items' : '$select.items');
+ if (this.trackByExp) {
+ expression += ' track by ' + this.trackByExp;
+ }
+ return expression;
+ }
+ };
+
+ };
+
+ self.getGroupNgRepeatExpression = function() {
+ return '$group in $select.groups';
+ };
+
+}]);
+
+}());
+angular.module("ui.select").run(["$templateCache", function($templateCache) {$templateCache.put("bootstrap/choices.tpl.html","<ul class=\"ui-select-choices ui-select-choices-content ui-select-dropdown dropdown-menu\" role=\"listbox\" ng-show=\"$select.open && $select.items.length > 0\"><li class=\"ui-select-choices-group\" id=\"ui-select-choices-{{ $select.generatedId }}\"><div class=\"divider\" ng-show=\"$select.isGrouped && $index > 0\"></div><div ng-show=\"$select.isGrouped\" class=\"ui-select-choices-group-label dropdown-header\" ng-bind=\"$group.name\"></div><div ng-attr-id=\"ui-select-choices-row-{{ $select.generatedId }}-{{$index}}\" class=\"ui-select-choices-row\" ng-class=\"{active: $select.isActive(this), disabled: $select.isDisabled(this)}\" role=\"option\"><a href=\"\" class=\"ui-select-choices-row-inner\"></a></div></li></ul>");
+$templateCache.put("bootstrap/match-multiple.tpl.html","<span class=\"ui-select-match\"><span ng-repeat=\"$item in $select.selected\"><span class=\"ui-select-match-item btn btn-default btn-xs\" tabindex=\"-1\" type=\"button\" ng-disabled=\"$select.disabled\" ng-click=\"$selectMultiple.activeMatchIndex = $index;\" ng-class=\"{\'btn-primary\':$selectMultiple.activeMatchIndex === $index, \'select-locked\':$select.isLocked(this, $index)}\" ui-select-sort=\"$select.selected\"><span class=\"close ui-select-match-close\" ng-hide=\"$select.disabled\" ng-click=\"$selectMultiple.removeChoice($index)\">&nbsp;&times;</span> <span uis-transclude-append=\"\"></span></span></span></span>");
+$templateCache.put("bootstrap/match.tpl.html","<div class=\"ui-select-match\" ng-hide=\"$select.open && $select.searchEnabled\" ng-disabled=\"$select.disabled\" ng-class=\"{\'btn-default-focus\':$select.focus}\"><span tabindex=\"-1\" class=\"btn btn-default form-control ui-select-toggle\" aria-label=\"{{ $select.baseTitle }} activate\" ng-disabled=\"$select.disabled\" ng-click=\"$select.activate()\" style=\"outline: 0;\"><span ng-show=\"$select.isEmpty()\" class=\"ui-select-placeholder text-muted\">{{$select.placeholder}}</span> <span ng-hide=\"$select.isEmpty()\" class=\"ui-select-match-text pull-left\" ng-class=\"{\'ui-select-allow-clear\': $select.allowClear && !$select.isEmpty()}\" ng-transclude=\"\"></span> <i class=\"caret pull-right\" ng-click=\"$select.toggle($event)\"></i> <a ng-show=\"$select.allowClear && !$select.isEmpty() && ($select.disabled !== true)\" aria-label=\"{{ $select.baseTitle }} clear\" style=\"margin-right: 10px\" ng-click=\"$select.clear($event)\" class=\"btn btn-xs btn-link pull-right\"><i class=\"glyphicon glyphicon-remove\" aria-hidden=\"true\"></i></a></span></div>");
+$templateCache.put("bootstrap/no-choice.tpl.html","<ul class=\"ui-select-no-choice dropdown-menu\" ng-show=\"$select.items.length == 0\"><li ng-transclude=\"\"></li></ul>");
+$templateCache.put("bootstrap/select-multiple.tpl.html","<div class=\"ui-select-container ui-select-multiple ui-select-bootstrap dropdown form-control\" ng-class=\"{open: $select.open}\"><div><div class=\"ui-select-match\"></div><input type=\"search\" autocomplete=\"off\" autocorrect=\"off\" autocapitalize=\"off\" spellcheck=\"false\" class=\"ui-select-search input-xs\" placeholder=\"{{$selectMultiple.getPlaceholder()}}\" ng-disabled=\"$select.disabled\" ng-hide=\"$select.disabled\" ng-click=\"$select.activate()\" ng-model=\"$select.search\" role=\"combobox\" aria-label=\"{{ $select.baseTitle }}\" ondrop=\"return false;\"></div><div class=\"ui-select-choices\"></div></div>");
+$templateCache.put("bootstrap/select.tpl.html","<div class=\"ui-select-container ui-select-bootstrap dropdown\" ng-class=\"{open: $select.open}\"><div class=\"ui-select-match\"></div><input type=\"search\" autocomplete=\"off\" tabindex=\"-1\" aria-expanded=\"true\" aria-label=\"{{ $select.baseTitle }}\" aria-owns=\"ui-select-choices-{{ $select.generatedId }}\" aria-activedescendant=\"ui-select-choices-row-{{ $select.generatedId }}-{{ $select.activeIndex }}\" class=\"form-control ui-select-search\" placeholder=\"{{$select.placeholder}}\" ng-model=\"$select.search\" ng-show=\"$select.searchEnabled && $select.open\"><div class=\"ui-select-choices\"></div><div class=\"ui-select-no-choice\"></div></div>");
+$templateCache.put("select2/choices.tpl.html","<ul tabindex=\"-1\" class=\"ui-select-choices ui-select-choices-content select2-results\"><li class=\"ui-select-choices-group\" ng-class=\"{\'select2-result-with-children\': $select.choiceGrouped($group) }\"><div ng-show=\"$select.choiceGrouped($group)\" class=\"ui-select-choices-group-label select2-result-label\" ng-bind=\"$group.name\"></div><ul role=\"listbox\" id=\"ui-select-choices-{{ $select.generatedId }}\" ng-class=\"{\'select2-result-sub\': $select.choiceGrouped($group), \'select2-result-single\': !$select.choiceGrouped($group) }\"><li role=\"option\" ng-attr-id=\"ui-select-choices-row-{{ $select.generatedId }}-{{$index}}\" class=\"ui-select-choices-row\" ng-class=\"{\'select2-highlighted\': $select.isActive(this), \'select2-disabled\': $select.isDisabled(this)}\"><div class=\"select2-result-label ui-select-choices-row-inner\"></div></li></ul></li></ul>");
+$templateCache.put("select2/match-multiple.tpl.html","<span class=\"ui-select-match\"><li class=\"ui-select-match-item select2-search-choice\" ng-repeat=\"$item in $select.selected\" ng-class=\"{\'select2-search-choice-focus\':$selectMultiple.activeMatchIndex === $index, \'select2-locked\':$select.isLocked(this, $index)}\" ui-select-sort=\"$select.selected\"><span uis-transclude-append=\"\"></span> <a href=\"javascript:;\" class=\"ui-select-match-close select2-search-choice-close\" ng-click=\"$selectMultiple.removeChoice($index)\" tabindex=\"-1\"></a></li></span>");
+$templateCache.put("select2/match.tpl.html","<a class=\"select2-choice ui-select-match\" ng-class=\"{\'select2-default\': $select.isEmpty()}\" ng-click=\"$select.toggle($event)\" aria-label=\"{{ $select.baseTitle }} select\"><span ng-show=\"$select.isEmpty()\" class=\"select2-chosen\">{{$select.placeholder}}</span> <span ng-hide=\"$select.isEmpty()\" class=\"select2-chosen\" ng-transclude=\"\"></span> <abbr ng-if=\"$select.allowClear && !$select.isEmpty()\" class=\"select2-search-choice-close\" ng-click=\"$select.clear($event)\"></abbr> <span class=\"select2-arrow ui-select-toggle\"><b></b></span></a>");
+$templateCache.put("select2/select-multiple.tpl.html","<div class=\"ui-select-container ui-select-multiple select2 select2-container select2-container-multi\" ng-class=\"{\'select2-container-active select2-dropdown-open open\': $select.open, \'select2-container-disabled\': $select.disabled}\"><ul class=\"select2-choices\"><span class=\"ui-select-match\"></span><li class=\"select2-search-field\"><input type=\"search\" autocomplete=\"off\" autocorrect=\"off\" autocapitalize=\"off\" spellcheck=\"false\" role=\"combobox\" aria-expanded=\"true\" aria-owns=\"ui-select-choices-{{ $select.generatedId }}\" aria-label=\"{{ $select.baseTitle }}\" aria-activedescendant=\"ui-select-choices-row-{{ $select.generatedId }}-{{ $select.activeIndex }}\" class=\"select2-input ui-select-search\" placeholder=\"{{$selectMultiple.getPlaceholder()}}\" ng-disabled=\"$select.disabled\" ng-hide=\"$select.disabled\" ng-model=\"$select.search\" ng-click=\"$select.activate()\" style=\"width: 34px;\" ondrop=\"return false;\"></li></ul><div class=\"ui-select-dropdown select2-drop select2-with-searchbox select2-drop-active\" ng-class=\"{\'select2-display-none\': !$select.open || $select.items.length === 0}\"><div class=\"ui-select-choices\"></div></div></div>");
+$templateCache.put("select2/select.tpl.html","<div class=\"ui-select-container select2 select2-container\" ng-class=\"{\'select2-container-active select2-dropdown-open open\': $select.open, \'select2-container-disabled\': $select.disabled, \'select2-container-active\': $select.focus, \'select2-allowclear\': $select.allowClear && !$select.isEmpty()}\"><div class=\"ui-select-match\"></div><div class=\"ui-select-dropdown select2-drop select2-with-searchbox select2-drop-active\" ng-class=\"{\'select2-display-none\': !$select.open}\"><div class=\"select2-search\" ng-show=\"$select.searchEnabled\"><input type=\"search\" autocomplete=\"off\" autocorrect=\"off\" autocapitalize=\"off\" spellcheck=\"false\" role=\"combobox\" aria-expanded=\"true\" aria-owns=\"ui-select-choices-{{ $select.generatedId }}\" aria-label=\"{{ $select.baseTitle }}\" aria-activedescendant=\"ui-select-choices-row-{{ $select.generatedId }}-{{ $select.activeIndex }}\" class=\"ui-select-search select2-input\" ng-model=\"$select.search\"></div><div class=\"ui-select-choices\"></div></div></div>");
+$templateCache.put("selectize/choices.tpl.html","<div ng-show=\"$select.open\" class=\"ui-select-choices ui-select-dropdown selectize-dropdown single\"><div class=\"ui-select-choices-content selectize-dropdown-content\"><div class=\"ui-select-choices-group optgroup\" role=\"listbox\"><div ng-show=\"$select.isGrouped\" class=\"ui-select-choices-group-label optgroup-header\" ng-bind=\"$group.name\"></div><div role=\"option\" class=\"ui-select-choices-row\" ng-class=\"{active: $select.isActive(this), disabled: $select.isDisabled(this)}\"><div class=\"option ui-select-choices-row-inner\" data-selectable=\"\"></div></div></div></div></div>");
+$templateCache.put("selectize/match.tpl.html","<div ng-hide=\"$select.searchEnabled && ($select.open || $select.isEmpty())\" class=\"ui-select-match\" ng-transclude=\"\"></div>");
+$templateCache.put("selectize/select.tpl.html","<div class=\"ui-select-container selectize-control single\" ng-class=\"{\'open\': $select.open}\"><div class=\"selectize-input\" ng-class=\"{\'focus\': $select.open, \'disabled\': $select.disabled, \'selectize-focus\' : $select.focus}\" ng-click=\"$select.open && !$select.searchEnabled ? $select.toggle($event) : $select.activate()\"><div class=\"ui-select-match\"></div><input type=\"search\" autocomplete=\"off\" tabindex=\"-1\" class=\"ui-select-search ui-select-toggle\" ng-click=\"$select.toggle($event)\" placeholder=\"{{$select.placeholder}}\" ng-model=\"$select.search\" ng-hide=\"!$select.searchEnabled || ($select.selected && !$select.open)\" ng-disabled=\"$select.disabled\" aria-label=\"{{ $select.baseTitle }}\"></div><div class=\"ui-select-choices\"></div></div>");}]); \ No newline at end of file
diff --git a/ecomp-portal-FE/client/bower_components/ui-select/dist/select.min.css b/ecomp-portal-FE/client/bower_components/ui-select/dist/select.min.css
new file mode 100644
index 00000000..9161faf3
--- /dev/null
+++ b/ecomp-portal-FE/client/bower_components/ui-select/dist/select.min.css
@@ -0,0 +1,7 @@
+/*!
+ * ui-select
+ * http://github.com/angular-ui/ui-select
+ * Version: 0.17.1 - 2016-05-16T19:31:33.034Z
+ * License: MIT
+ */.ui-select-highlight{font-weight:700}.ui-select-offscreen{clip:rect(0 0 0 0)!important;width:1px!important;height:1px!important;border:0!important;margin:0!important;padding:0!important;overflow:hidden!important;position:absolute!important;outline:0!important;left:0!important;top:0!important}.ui-select-choices-row:hover{background-color:#f5f5f5}.ng-dirty.ng-invalid>a.select2-choice{border-color:#D44950}.select2-result-single{padding-left:0}.select-locked>.ui-select-match-close,.select2-locked>.select2-search-choice-close{display:none}body>.select2-container.open{z-index:9999}.ui-select-container[theme=select2].direction-up .ui-select-match{border-radius:0 0 4px 4px}.ui-select-container[theme=select2].direction-up .ui-select-dropdown{border-radius:4px 4px 0 0;border-top-width:1px;border-top-style:solid;box-shadow:0 -4px 8px rgba(0,0,0,.25);margin-top:-4px}.ui-select-container[theme=select2].direction-up .ui-select-dropdown .select2-search{margin-top:4px}.ui-select-container[theme=select2].direction-up.select2-dropdown-open .ui-select-match{border-bottom-color:#5897fb}.selectize-input.selectize-focus{border-color:#007FBB!important}.selectize-control>.selectize-dropdown,.selectize-control>.selectize-input>input{width:100%}.ng-dirty.ng-invalid>div.selectize-input{border-color:#D44950}.ui-select-container[theme=selectize].direction-up .ui-select-dropdown{box-shadow:0 -4px 8px rgba(0,0,0,.25);margin-top:-2px}.btn-default-focus{color:#333;background-color:#EBEBEB;border-color:#ADADAD;text-decoration:none;outline:-webkit-focus-ring-color auto 5px;outline-offset:-2px;box-shadow:inset 0 1px 1px rgba(0,0,0,.075),0 0 8px rgba(102,175,233,.6)}.ui-select-bootstrap .ui-select-toggle{position:relative}.ui-select-bootstrap .ui-select-toggle>.caret{position:absolute;height:10px;top:50%;right:10px;margin-top:-2px}.input-group>.ui-select-bootstrap.dropdown{position:static}.input-group>.ui-select-bootstrap>input.ui-select-search.form-control{border-radius:4px 0 0 4px}.input-group>.ui-select-bootstrap>input.ui-select-search.form-control.direction-up{border-radius:4px 0 0 4px!important}.ui-select-bootstrap>.ui-select-match>.btn{text-align:left!important}.ui-select-bootstrap>.ui-select-match>.caret{position:absolute;top:45%;right:15px}.ui-select-bootstrap>.ui-select-choices,.ui-select-bootstrap>.ui-select-no-choice{width:100%;height:auto;max-height:200px;overflow-x:hidden;margin-top:-1px}body>.ui-select-bootstrap.open{z-index:1000}.ui-select-multiple.ui-select-bootstrap{height:auto;padding:3px 3px 0}.ui-select-multiple.ui-select-bootstrap input.ui-select-search{background-color:transparent!important;border:none;outline:0;height:1.666666em;margin-bottom:3px}.ui-select-multiple.ui-select-bootstrap .ui-select-match .close{font-size:1.6em;line-height:.75}.ui-select-multiple.ui-select-bootstrap .ui-select-match-item{outline:0;margin:0 3px 3px 0}.ui-select-multiple .ui-select-match-item{position:relative}.ui-select-multiple .ui-select-match-item.dropping .ui-select-match-close{pointer-events:none}.ui-select-multiple:hover .ui-select-match-item.dropping-before:before{content:"";position:absolute;top:0;right:100%;height:100%;margin-right:2px;border-left:1px solid #428bca}.ui-select-multiple:hover .ui-select-match-item.dropping-after:after{content:"";position:absolute;top:0;left:100%;height:100%;margin-left:2px;border-right:1px solid #428bca}.ui-select-bootstrap .ui-select-choices-row>a{display:block;padding:3px 20px;clear:both;font-weight:400;line-height:1.42857143;color:#333;white-space:nowrap}.ui-select-bootstrap .ui-select-choices-row>a:focus,.ui-select-bootstrap .ui-select-choices-row>a:hover{text-decoration:none;color:#262626;background-color:#f5f5f5}.ui-select-bootstrap .ui-select-choices-row.active>a{color:#fff;text-decoration:none;outline:0;background-color:#428bca}.ui-select-bootstrap .ui-select-choices-row.active.disabled>a,.ui-select-bootstrap .ui-select-choices-row.disabled>a{color:#777;cursor:not-allowed;background-color:#fff}.ui-select-match.ng-hide-add,.ui-select-search.ng-hide-add{display:none!important}.ui-select-bootstrap.ng-dirty.ng-invalid>button.btn.ui-select-match{border-color:#D44950}.ui-select-container[theme=bootstrap].direction-up .ui-select-dropdown{box-shadow:0 -4px 8px rgba(0,0,0,.25)}
+/*# sourceMappingURL=select.min.css.map */
diff --git a/ecomp-portal-FE/client/bower_components/ui-select/dist/select.min.js b/ecomp-portal-FE/client/bower_components/ui-select/dist/select.min.js
new file mode 100644
index 00000000..c07bf7d9
--- /dev/null
+++ b/ecomp-portal-FE/client/bower_components/ui-select/dist/select.min.js
@@ -0,0 +1,9 @@
+/*!
+ * ui-select
+ * http://github.com/angular-ui/ui-select
+ * Version: 0.17.1 - 2016-05-16T19:31:32.352Z
+ * License: MIT
+ */
+!function(){"use strict";var e={TAB:9,ENTER:13,ESC:27,SPACE:32,LEFT:37,UP:38,RIGHT:39,DOWN:40,SHIFT:16,CTRL:17,ALT:18,PAGE_UP:33,PAGE_DOWN:34,HOME:36,END:35,BACKSPACE:8,DELETE:46,COMMAND:91,MAP:{91:"COMMAND",8:"BACKSPACE",9:"TAB",13:"ENTER",16:"SHIFT",17:"CTRL",18:"ALT",19:"PAUSEBREAK",20:"CAPSLOCK",27:"ESC",32:"SPACE",33:"PAGE_UP",34:"PAGE_DOWN",35:"END",36:"HOME",37:"LEFT",38:"UP",39:"RIGHT",40:"DOWN",43:"+",44:"PRINTSCREEN",45:"INSERT",46:"DELETE",48:"0",49:"1",50:"2",51:"3",52:"4",53:"5",54:"6",55:"7",56:"8",57:"9",59:";",61:"=",65:"A",66:"B",67:"C",68:"D",69:"E",70:"F",71:"G",72:"H",73:"I",74:"J",75:"K",76:"L",77:"M",78:"N",79:"O",80:"P",81:"Q",82:"R",83:"S",84:"T",85:"U",86:"V",87:"W",88:"X",89:"Y",90:"Z",96:"0",97:"1",98:"2",99:"3",100:"4",101:"5",102:"6",103:"7",104:"8",105:"9",106:"*",107:"+",109:"-",110:".",111:"/",112:"F1",113:"F2",114:"F3",115:"F4",116:"F5",117:"F6",118:"F7",119:"F8",120:"F9",121:"F10",122:"F11",123:"F12",144:"NUMLOCK",145:"SCROLLLOCK",186:";",187:"=",188:",",189:"-",190:".",191:"/",192:"`",219:"[",220:"\\",221:"]",222:"'"},isControl:function(t){var i=t.which;switch(i){case e.COMMAND:case e.SHIFT:case e.CTRL:case e.ALT:return!0}return!!(t.metaKey||t.ctrlKey||t.altKey)},isFunctionKey:function(e){return e=e.which?e.which:e,e>=112&&123>=e},isVerticalMovement:function(t){return~[e.UP,e.DOWN].indexOf(t)},isHorizontalMovement:function(t){return~[e.LEFT,e.RIGHT,e.BACKSPACE,e.DELETE].indexOf(t)},toSeparator:function(t){var i={ENTER:"\n",TAB:" ",SPACE:" "}[t];return i?i:e[t]?void 0:t}};void 0===angular.element.prototype.querySelectorAll&&(angular.element.prototype.querySelectorAll=function(e){return angular.element(this[0].querySelectorAll(e))}),void 0===angular.element.prototype.closest&&(angular.element.prototype.closest=function(e){for(var t=this[0],i=t.matches||t.webkitMatchesSelector||t.mozMatchesSelector||t.msMatchesSelector;t;){if(i.bind(t)(e))return t;t=t.parentElement}return!1});var t=0,i=angular.module("ui.select",[]).constant("uiSelectConfig",{theme:"bootstrap",searchEnabled:!0,sortable:!1,placeholder:"",refreshDelay:1e3,closeOnSelect:!0,skipFocusser:!1,dropdownPosition:"auto",generateId:function(){return t++},appendToBody:!1}).service("uiSelectMinErr",function(){var e=angular.$$minErr("ui.select");return function(){var t=e.apply(this,arguments),i=t.message.replace(new RegExp("\nhttp://errors.angularjs.org/.*"),"");return new Error(i)}}).directive("uisTranscludeAppend",function(){return{link:function(e,t,i,c,s){s(e,function(e){t.append(e)})}}}).filter("highlight",function(){function e(e){return(""+e).replace(/([.?*+^$[\]\\(){}|-])/g,"\\$1")}return function(t,i){return i&&t?(""+t).replace(new RegExp(e(i),"gi"),'<span class="ui-select-highlight">$&</span>'):t}}).factory("uisOffset",["$document","$window",function(e,t){return function(i){var c=i[0].getBoundingClientRect();return{width:c.width||i.prop("offsetWidth"),height:c.height||i.prop("offsetHeight"),top:c.top+(t.pageYOffset||e[0].documentElement.scrollTop),left:c.left+(t.pageXOffset||e[0].documentElement.scrollLeft)}}}]);i.factory("$$uisDebounce",["$timeout",function(e){return function(t,i){var c;return function(){var s=this,l=Array.prototype.slice.call(arguments);c&&e.cancel(c),c=e(function(){t.apply(s,l)},i)}}}]),i.directive("uiSelectChoices",["uiSelectConfig","uisRepeatParser","uiSelectMinErr","$compile","$window",function(e,t,i,c,s){return{restrict:"EA",require:"^uiSelect",replace:!0,transclude:!0,templateUrl:function(t){t.addClass("ui-select-choices");var i=t.parent().attr("theme")||e.theme;return i+"/choices.tpl.html"},compile:function(c,l){if(!l.repeat)throw i("repeat","Expected 'repeat' expression.");var n=l.groupBy,a=l.groupFilter;if(n){var r=c.querySelectorAll(".ui-select-choices-group");if(1!==r.length)throw i("rows","Expected 1 .ui-select-choices-group but got '{0}'.",r.length);r.attr("ng-repeat",t.getGroupNgRepeatExpression())}var o=t.parse(l.repeat),u=c.querySelectorAll(".ui-select-choices-row");if(1!==u.length)throw i("rows","Expected 1 .ui-select-choices-row but got '{0}'.",u.length);u.attr("ng-repeat",o.repeatExpression(n)).attr("ng-if","$select.open");var d=c.querySelectorAll(".ui-select-choices-row-inner");if(1!==d.length)throw i("rows","Expected 1 .ui-select-choices-row-inner but got '{0}'.",d.length);d.attr("uis-transclude-append","");var p=s.document.addEventListener?u:d;return p.attr("ng-click","$select.select("+o.itemName+",$select.skipFocusser,$event)"),function(t,i,c,s){s.parseRepeatAttr(c.repeat,n,a),s.disableChoiceExpression=c.uiDisableChoice,s.onHighlightCallback=c.onHighlight,s.dropdownPosition=c.position?c.position.toLowerCase():e.dropdownPosition,t.$on("$destroy",function(){u.remove()}),t.$watch("$select.search",function(e){e&&!s.open&&s.multiple&&s.activate(!1,!0),s.activeIndex=s.tagging.isActivated?-1:0,!c.minimumInputLength||s.search.length>=c.minimumInputLength?s.refresh(c.refresh):s.items=[]}),c.$observe("refreshDelay",function(){var i=t.$eval(c.refreshDelay);s.refreshDelay=void 0!==i?i:e.refreshDelay})}}}}]),i.controller("uiSelectCtrl",["$scope","$element","$timeout","$filter","$$uisDebounce","uisRepeatParser","uiSelectMinErr","uiSelectConfig","$parse","$injector","$window",function(t,i,c,s,l,n,a,r,o,u,d){function p(e,t,i){if(e.findIndex)return e.findIndex(t,i);for(var c,s=Object(e),l=s.length>>>0,n=0;l>n;n++)if(c=s[n],t.call(i,c,n,s))return n;return-1}function h(){(m.resetSearchInput||void 0===m.resetSearchInput&&r.resetSearchInput)&&(m.search=$,m.selected&&m.items.length&&!m.multiple&&(m.activeIndex=p(m.items,function(e){return angular.equals(this,e)},m.selected)))}function g(e,t){var i,c,s=[];for(i=0;i<t.length;i++)for(c=0;c<e.length;c++)e[c].name==[t[i]]&&s.push(e[c]);return s}function f(t){var i=!0;switch(t){case e.DOWN:!m.open&&m.multiple?m.activate(!1,!0):m.activeIndex<m.items.length-1&&m.activeIndex++;break;case e.UP:!m.open&&m.multiple?m.activate(!1,!0):(m.activeIndex>0||0===m.search.length&&m.tagging.isActivated&&m.activeIndex>-1)&&m.activeIndex--;break;case e.TAB:m.multiple&&!m.open||m.select(m.items[m.activeIndex],!0);break;case e.ENTER:m.open&&(m.tagging.isActivated||m.activeIndex>=0)?m.select(m.items[m.activeIndex],m.skipFocusser):m.activate(!1,!0);break;case e.ESC:m.close();break;default:i=!1}return i}function v(){var e=i.querySelectorAll(".ui-select-choices-content"),t=e.querySelectorAll(".ui-select-choices-row");if(t.length<1)throw a("choices","Expected multiple .ui-select-choices-row but got '{0}'.",t.length);if(!(m.activeIndex<0)){var c=t[m.activeIndex],s=c.offsetTop+c.clientHeight-e[0].scrollTop,l=e[0].offsetHeight;s>l?e[0].scrollTop+=s-l:s<c.clientHeight&&(m.isGrouped&&0===m.activeIndex?e[0].scrollTop=0:e[0].scrollTop-=c.clientHeight-s)}}var m=this,$="";if(m.placeholder=r.placeholder,m.searchEnabled=r.searchEnabled,m.sortable=r.sortable,m.refreshDelay=r.refreshDelay,m.paste=r.paste,m.removeSelected=!1,m.closeOnSelect=!0,m.skipFocusser=!1,m.search=$,m.activeIndex=0,m.items=[],m.open=!1,m.focus=!1,m.disabled=!1,m.selected=void 0,m.dropdownPosition="auto",m.focusser=void 0,m.resetSearchInput=!0,m.multiple=void 0,m.disableChoiceExpression=void 0,m.tagging={isActivated:!1,fct:void 0},m.taggingTokens={isActivated:!1,tokens:void 0},m.lockChoiceExpression=void 0,m.clickTriggeredSelect=!1,m.$filter=s,m.$element=i,m.$animate=function(){try{return u.get("$animate")}catch(e){return null}}(),m.searchInput=i.querySelectorAll("input.ui-select-search"),1!==m.searchInput.length)throw a("searchInput","Expected 1 input.ui-select-search but got '{0}'.",m.searchInput.length);m.isEmpty=function(){return angular.isUndefined(m.selected)||null===m.selected||""===m.selected||m.multiple&&0===m.selected.length},m.activate=function(e,s){if(!m.disabled&&!m.open){s||h(),t.$broadcast("uis:activate"),m.open=!0,m.activeIndex=m.activeIndex>=m.items.length?0:m.activeIndex,-1===m.activeIndex&&m.taggingLabel!==!1&&(m.activeIndex=0);var l=i.querySelectorAll(".ui-select-choices-content"),n=i.querySelectorAll(".ui-select-search");if(m.$animate&&m.$animate.enabled(l[0])){var a=function(t,i){"start"===i&&0===m.items.length?(m.$animate.off("removeClass",n[0],a),c(function(){m.focusSearchInput(e)})):"close"===i&&(m.$animate.off("enter",l[0],a),c(function(){m.focusSearchInput(e)}))};m.items.length>0?m.$animate.on("enter",l[0],a):m.$animate.on("removeClass",n[0],a)}else c(function(){m.focusSearchInput(e),!m.tagging.isActivated&&m.items.length>1&&v()})}},m.focusSearchInput=function(e){m.search=e||m.search,m.searchInput[0].focus()},m.findGroupByName=function(e){return m.groups&&m.groups.filter(function(t){return t.name===e})[0]},m.parseRepeatAttr=function(e,i,c){function s(e){var s=t.$eval(i);if(m.groups=[],angular.forEach(e,function(e){var t=angular.isFunction(s)?s(e):e[s],i=m.findGroupByName(t);i?i.items.push(e):m.groups.push({name:t,items:[e]})}),c){var l=t.$eval(c);angular.isFunction(l)?m.groups=l(m.groups):angular.isArray(l)&&(m.groups=g(m.groups,l))}m.items=[],m.groups.forEach(function(e){m.items=m.items.concat(e.items)})}function l(e){m.items=e}m.setItemsFn=i?s:l,m.parserResult=n.parse(e),m.isGrouped=!!i,m.itemProperty=m.parserResult.itemName;var r=m.parserResult.source,u=function(){var e=r(t);t.$uisSource=Object.keys(e).map(function(t){var i={};return i[m.parserResult.keyName]=t,i.value=e[t],i})};m.parserResult.keyName&&(u(),m.parserResult.source=o("$uisSource"+m.parserResult.filters),t.$watch(r,function(e,t){e!==t&&u()},!0)),m.refreshItems=function(e){e=e||m.parserResult.source(t);var i=m.selected;if(m.isEmpty()||angular.isArray(i)&&!i.length||!m.removeSelected)m.setItemsFn(e);else if(void 0!==e){var c=e.filter(function(e){return i.every(function(t){return!angular.equals(e,t)})});m.setItemsFn(c)}"auto"!==m.dropdownPosition&&"up"!==m.dropdownPosition||t.calculateDropdownPos()},t.$watchCollection(m.parserResult.source,function(e){if(void 0===e||null===e)m.items=[];else{if(!angular.isArray(e))throw a("items","Expected an array but got '{0}'.",e);m.refreshItems(e),angular.isDefined(m.ngModel.$modelValue)&&(m.ngModel.$modelValue=null)}})};var b;m.refresh=function(e){void 0!==e&&(b&&c.cancel(b),b=c(function(){t.$eval(e)},m.refreshDelay))},m.isActive=function(e){if(!m.open)return!1;var t=m.items.indexOf(e[m.itemProperty]),i=t==m.activeIndex;return!i||0>t?!1:(i&&!angular.isUndefined(m.onHighlightCallback)&&e.$eval(m.onHighlightCallback),i)},m.isDisabled=function(e){if(m.open){var t,i=m.items.indexOf(e[m.itemProperty]),c=!1;return i>=0&&!angular.isUndefined(m.disableChoiceExpression)&&(t=m.items[i],c=!!e.$eval(m.disableChoiceExpression),t._uiSelectChoiceDisabled=c),c}},m.select=function(e,i,s){if(void 0===e||!e._uiSelectChoiceDisabled){if(!m.items&&!m.search&&!m.tagging.isActivated)return;if(!e||!e._uiSelectChoiceDisabled){if(m.tagging.isActivated){if(m.taggingLabel===!1)if(m.activeIndex<0){if(e=void 0!==m.tagging.fct?m.tagging.fct(m.search):m.search,!e||angular.equals(m.items[0],e))return}else e=m.items[m.activeIndex];else if(0===m.activeIndex){if(void 0===e)return;if(void 0!==m.tagging.fct&&"string"==typeof e){if(e=m.tagging.fct(e),!e)return}else"string"==typeof e&&(e=e.replace(m.taggingLabel,"").trim())}if(m.selected&&angular.isArray(m.selected)&&m.selected.filter(function(t){return angular.equals(t,e)}).length>0)return void m.close(i)}t.$broadcast("uis:select",e);var l={};l[m.parserResult.itemName]=e,c(function(){m.onSelectCallback(t,{$item:e,$model:m.parserResult.modelMapper(t,l)})}),m.closeOnSelect&&m.close(i),s&&"click"===s.type&&(m.clickTriggeredSelect=!0)}}},m.close=function(e){m.open&&(m.ngModel&&m.ngModel.$setTouched&&m.ngModel.$setTouched(),h(),m.open=!1,t.$broadcast("uis:close",e))},m.setFocus=function(){m.focus||m.focusInput[0].focus()},m.clear=function(e){m.select(void 0),e.stopPropagation(),c(function(){m.focusser[0].focus()},0,!1)},m.toggle=function(e){m.open?(m.close(),e.preventDefault(),e.stopPropagation()):m.activate()},m.isLocked=function(e,t){var i,c=m.selected[t];return c&&!angular.isUndefined(m.lockChoiceExpression)&&(i=!!e.$eval(m.lockChoiceExpression),c._uiSelectChoiceLocked=i),i};var w=null,y=!1;m.sizeSearchInput=function(){var e=m.searchInput[0],i=m.searchInput.parent().parent()[0],s=function(){return i.clientWidth*!!e.offsetParent},l=function(t){if(0===t)return!1;var i=t-e.offsetLeft-10;return 50>i&&(i=t),m.searchInput.css("width",i+"px"),!0};m.searchInput.css("width","10px"),c(function(){null!==w||l(s())||(w=t.$watch(angular.noop,function(){y||(y=!0,t.$$postDigest(function(){y=!1,l(s())&&(w(),w=null)}))}))})},m.searchInput.on("keydown",function(i){var s=i.which;~[e.ENTER,e.ESC].indexOf(s)&&(i.preventDefault(),i.stopPropagation()),t.$apply(function(){var t=!1;if((m.items.length>0||m.tagging.isActivated)&&(f(s),m.taggingTokens.isActivated)){for(var l=0;l<m.taggingTokens.tokens.length;l++)m.taggingTokens.tokens[l]===e.MAP[i.keyCode]&&m.search.length>0&&(t=!0);t&&c(function(){m.searchInput.triggerHandler("tagged");var t=m.search.replace(e.MAP[i.keyCode],"").trim();m.tagging.fct&&(t=m.tagging.fct(t)),t&&m.select(t,!0)})}}),e.isVerticalMovement(s)&&m.items.length>0&&v(),s!==e.ENTER&&s!==e.ESC||(i.preventDefault(),i.stopPropagation())}),m.searchInput.on("paste",function(t){var i;if(i=window.clipboardData&&window.clipboardData.getData?window.clipboardData.getData("Text"):(t.originalEvent||t).clipboardData.getData("text/plain"),i=m.search+i,i&&i.length>0)if(m.taggingTokens.isActivated){for(var c=[],s=0;s<m.taggingTokens.tokens.length;s++){var l=e.toSeparator(m.taggingTokens.tokens[s])||m.taggingTokens.tokens[s];if(i.indexOf(l)>-1){c=i.split(l);break}}if(0===c.length&&(c=[i]),c.length>0){var n=m.search;angular.forEach(c,function(e){var t=m.tagging.fct?m.tagging.fct(e):e;t&&m.select(t,!0)}),m.search=n||$,t.preventDefault(),t.stopPropagation()}}else m.paste&&(m.paste(i),m.search=$,t.preventDefault(),t.stopPropagation())}),m.searchInput.on("tagged",function(){c(function(){h()})});var x=l(function(){m.sizeSearchInput()},50);angular.element(d).bind("resize",x),t.$on("$destroy",function(){m.searchInput.off("keyup keydown tagged blur paste"),angular.element(d).off("resize",x)})}]),i.directive("uiSelect",["$document","uiSelectConfig","uiSelectMinErr","uisOffset","$compile","$parse","$timeout",function(e,t,i,c,s,l,n){return{restrict:"EA",templateUrl:function(e,i){var c=i.theme||t.theme;return c+(angular.isDefined(i.multiple)?"/select-multiple.tpl.html":"/select.tpl.html")},replace:!0,transclude:!0,require:["uiSelect","^ngModel"],scope:!0,controller:"uiSelectCtrl",controllerAs:"$select",compile:function(s,a){var r=/{(.*)}\s*{(.*)}/.exec(a.ngClass);if(r){var o="{"+r[1]+", "+r[2]+"}";a.ngClass=o,s.attr("ng-class",o)}return angular.isDefined(a.multiple)?s.append("<ui-select-multiple/>").removeAttr("multiple"):s.append("<ui-select-single/>"),a.inputId&&(s.querySelectorAll("input.ui-select-search")[0].id=a.inputId),function(s,a,r,o,u){function d(e){if(g.open){var t=!1;if(t=window.jQuery?window.jQuery.contains(a[0],e.target):a[0].contains(e.target),!t&&!g.clickTriggeredSelect){var i;if(g.skipFocusser)i=!0;else{var c=["input","button","textarea","select"],l=angular.element(e.target).controller("uiSelect");i=l&&l!==g,i||(i=~c.indexOf(e.target.tagName.toLowerCase()))}g.close(i),s.$digest()}g.clickTriggeredSelect=!1}}function p(){var t=c(a);m=angular.element('<div class="ui-select-placeholder"></div>'),m[0].style.width=t.width+"px",m[0].style.height=t.height+"px",a.after(m),$=a[0].style.width,e.find("body").append(a),a[0].style.position="absolute",a[0].style.left=t.left+"px",a[0].style.top=t.top+"px",a[0].style.width=t.width+"px"}function h(){null!==m&&(m.replaceWith(a),m=null,a[0].style.position="",a[0].style.left="",a[0].style.top="",a[0].style.width=$,g.setFocus())}var g=o[0],f=o[1];g.generatedId=t.generateId(),g.baseTitle=r.title||"Select box",g.focusserTitle=g.baseTitle+" focus",g.focusserId="focusser-"+g.generatedId,g.closeOnSelect=function(){return angular.isDefined(r.closeOnSelect)?l(r.closeOnSelect)():t.closeOnSelect}(),s.$watch("skipFocusser",function(){var e=s.$eval(r.skipFocusser);g.skipFocusser=void 0!==e?e:t.skipFocusser}),g.onSelectCallback=l(r.onSelect),g.onRemoveCallback=l(r.onRemove),g.limit=angular.isDefined(r.limit)?parseInt(r.limit,10):void 0,g.ngModel=f,g.choiceGrouped=function(e){return g.isGrouped&&e&&e.name},r.tabindex&&r.$observe("tabindex",function(e){g.focusInput.attr("tabindex",e),a.removeAttr("tabindex")}),s.$watch("searchEnabled",function(){var e=s.$eval(r.searchEnabled);g.searchEnabled=void 0!==e?e:t.searchEnabled}),s.$watch("sortable",function(){var e=s.$eval(r.sortable);g.sortable=void 0!==e?e:t.sortable}),r.$observe("disabled",function(){g.disabled=void 0!==r.disabled?r.disabled:!1}),r.$observe("resetSearchInput",function(){var e=s.$eval(r.resetSearchInput);g.resetSearchInput=void 0!==e?e:!0}),r.$observe("paste",function(){g.paste=s.$eval(r.paste)}),r.$observe("tagging",function(){if(void 0!==r.tagging){var e=s.$eval(r.tagging);g.tagging={isActivated:!0,fct:e!==!0?e:void 0}}else g.tagging={isActivated:!1,fct:void 0}}),r.$observe("taggingLabel",function(){void 0!==r.tagging&&("false"===r.taggingLabel?g.taggingLabel=!1:g.taggingLabel=void 0!==r.taggingLabel?r.taggingLabel:"(new)")}),r.$observe("taggingTokens",function(){if(void 0!==r.tagging){var e=void 0!==r.taggingTokens?r.taggingTokens.split("|"):[",","ENTER"];g.taggingTokens={isActivated:!0,tokens:e}}}),angular.isDefined(r.autofocus)&&n(function(){g.setFocus()}),angular.isDefined(r.focusOn)&&s.$on(r.focusOn,function(){n(function(){g.setFocus()})}),e.on("click",d),s.$on("$destroy",function(){e.off("click",d)}),u(s,function(e){var t=angular.element("<div>").append(e),c=t.querySelectorAll(".ui-select-match");if(c.removeAttr("ui-select-match"),c.removeAttr("data-ui-select-match"),1!==c.length)throw i("transcluded","Expected 1 .ui-select-match but got '{0}'.",c.length);a.querySelectorAll(".ui-select-match").replaceWith(c);var s=t.querySelectorAll(".ui-select-choices");if(s.removeAttr("ui-select-choices"),s.removeAttr("data-ui-select-choices"),1!==s.length)throw i("transcluded","Expected 1 .ui-select-choices but got '{0}'.",s.length);a.querySelectorAll(".ui-select-choices").replaceWith(s);var l=t.querySelectorAll(".ui-select-no-choice");l.removeAttr("ui-select-no-choice"),l.removeAttr("data-ui-select-no-choice"),1==l.length&&a.querySelectorAll(".ui-select-no-choice").replaceWith(l)});var v=s.$eval(r.appendToBody);(void 0!==v?v:t.appendToBody)&&(s.$watch("$select.open",function(e){e?p():h()}),s.$on("$destroy",function(){h()}));var m=null,$="",b=null,w="direction-up";s.$watch("$select.open",function(){"auto"!==g.dropdownPosition&&"up"!==g.dropdownPosition||s.calculateDropdownPos()});var y=function(e,t){e=e||c(a),t=t||c(b),b[0].style.position="absolute",b[0].style.top=-1*t.height+"px",a.addClass(w)},x=function(e,t){a.removeClass(w),e=e||c(a),t=t||c(b),b[0].style.position="",b[0].style.top=""};s.calculateDropdownPos=function(){if(g.open){if(b=angular.element(a).querySelectorAll(".ui-select-dropdown"),0===b.length)return;b[0].style.opacity=0,n(function(){if("up"===g.dropdownPosition)y();else{a.removeClass(w);var t=c(a),i=c(b),s=e[0].documentElement.scrollTop||e[0].body.scrollTop;t.top+t.height+i.height>s+e[0].documentElement.clientHeight?y(t,i):x(t,i)}b[0].style.opacity=1})}else{if(null===b||0===b.length)return;b[0].style.position="",b[0].style.top="",a.removeClass(w)}}}}}}]),i.directive("uiSelectMatch",["uiSelectConfig",function(e){function t(e,t){return e[0].hasAttribute(t)?e.attr(t):e[0].hasAttribute("data-"+t)?e.attr("data-"+t):e[0].hasAttribute("x-"+t)?e.attr("x-"+t):void 0}return{restrict:"EA",require:"^uiSelect",replace:!0,transclude:!0,templateUrl:function(i){i.addClass("ui-select-match");var c=i.parent(),s=t(c,"theme")||e.theme,l=angular.isDefined(t(c,"multiple"));return s+(l?"/match-multiple.tpl.html":"/match.tpl.html")},link:function(t,i,c,s){function l(e){s.allowClear=angular.isDefined(e)?""===e?!0:"true"===e.toLowerCase():!1}s.lockChoiceExpression=c.uiLockChoice,c.$observe("placeholder",function(t){s.placeholder=void 0!==t?t:e.placeholder}),c.$observe("allowClear",l),l(c.allowClear),s.multiple&&s.sizeSearchInput()}}}]),i.directive("uiSelectMultiple",["uiSelectMinErr","$timeout",function(t,i){return{restrict:"EA",require:["^uiSelect","^ngModel"],controller:["$scope","$timeout",function(e,t){var i,c=this,s=e.$select;angular.isUndefined(s.selected)&&(s.selected=[]),e.$evalAsync(function(){i=e.ngModel}),c.activeMatchIndex=-1,c.updateModel=function(){i.$setViewValue(Date.now()),c.refreshComponent()},c.refreshComponent=function(){s.refreshItems(),s.sizeSearchInput()},c.removeChoice=function(i){var l=s.selected[i];if(!l._uiSelectChoiceLocked){var n={};n[s.parserResult.itemName]=l,s.selected.splice(i,1),c.activeMatchIndex=-1,s.sizeSearchInput(),t(function(){s.onRemoveCallback(e,{$item:l,$model:s.parserResult.modelMapper(e,n)})}),c.updateModel()}},c.getPlaceholder=function(){return s.selected&&s.selected.length?void 0:s.placeholder}}],controllerAs:"$selectMultiple",link:function(c,s,l,n){function a(e){return angular.isNumber(e.selectionStart)?e.selectionStart:e.value.length}function r(t){function i(){switch(t){case e.LEFT:return~h.activeMatchIndex?u:n;case e.RIGHT:return~h.activeMatchIndex&&r!==n?o:(d.activate(),!1);case e.BACKSPACE:return~h.activeMatchIndex?(h.removeChoice(r),u):n;case e.DELETE:return~h.activeMatchIndex?(h.removeChoice(h.activeMatchIndex),r):!1}}var c=a(d.searchInput[0]),s=d.selected.length,l=0,n=s-1,r=h.activeMatchIndex,o=h.activeMatchIndex+1,u=h.activeMatchIndex-1,p=r;return c>0||d.search.length&&t==e.RIGHT?!1:(d.close(),p=i(),d.selected.length&&p!==!1?h.activeMatchIndex=Math.min(n,Math.max(l,p)):h.activeMatchIndex=-1,!0)}function o(e){if(void 0===e||void 0===d.search)return!1;var t=e.filter(function(e){return void 0===d.search.toUpperCase()||void 0===e?!1:e.toUpperCase()===d.search.toUpperCase()}).length>0;return t}function u(e,t){var i=-1;if(angular.isArray(e))for(var c=angular.copy(e),s=0;s<c.length;s++)if(void 0===d.tagging.fct)c[s]+" "+d.taggingLabel===t&&(i=s);else{var l=c[s];angular.isObject(l)&&(l.isTag=!0),angular.equals(l,t)&&(i=s)}return i}var d=n[0],p=c.ngModel=n[1],h=c.$selectMultiple;d.multiple=!0,d.removeSelected=!0,d.focusInput=d.searchInput,p.$isEmpty=function(e){return!e||0===e.length},p.$parsers.unshift(function(){for(var e,t={},i=[],s=d.selected.length-1;s>=0;s--)t={},t[d.parserResult.itemName]=d.selected[s],e=d.parserResult.modelMapper(c,t),i.unshift(e);return i}),p.$formatters.unshift(function(e){var t,i=d.parserResult&&d.parserResult.source(c,{$select:{search:""}}),s={};if(!i)return e;var l=[],n=function(e,i){if(e&&e.length){for(var n=e.length-1;n>=0;n--){if(s[d.parserResult.itemName]=e[n],t=d.parserResult.modelMapper(c,s),d.parserResult.trackByExp){var a=/(\w*)\./.exec(d.parserResult.trackByExp),r=/\.([^\s]+)/.exec(d.parserResult.trackByExp);if(a&&a.length>0&&a[1]==d.parserResult.itemName&&r&&r.length>0&&t[r[1]]==i[r[1]])return l.unshift(e[n]),!0}if(angular.equals(t,i))return l.unshift(e[n]),!0}return!1}};if(!e)return l;for(var a=e.length-1;a>=0;a--)n(d.selected,e[a])||n(i,e[a])||l.unshift(e[a]);return l}),c.$watchCollection(function(){return p.$modelValue},function(e,t){t!=e&&(angular.isDefined(p.$modelValue)&&(p.$modelValue=null),h.refreshComponent())}),p.$render=function(){if(!angular.isArray(p.$viewValue)){if(!angular.isUndefined(p.$viewValue)&&null!==p.$viewValue)throw t("multiarr","Expected model value to be array but got '{0}'",p.$viewValue);d.selected=[]}d.selected=p.$viewValue,h.refreshComponent(),c.$evalAsync()},c.$on("uis:select",function(e,t){d.selected.length>=d.limit||(d.selected.push(t),h.updateModel())}),c.$on("uis:activate",function(){h.activeMatchIndex=-1}),c.$watch("$select.disabled",function(e,t){t&&!e&&d.sizeSearchInput()}),d.searchInput.on("keydown",function(t){var i=t.which;c.$apply(function(){var c=!1;e.isHorizontalMovement(i)&&(c=r(i)),c&&i!=e.TAB&&(t.preventDefault(),t.stopPropagation())})}),d.searchInput.on("keyup",function(t){if(e.isVerticalMovement(t.which)||c.$evalAsync(function(){d.activeIndex=d.taggingLabel===!1?-1:0}),d.tagging.isActivated&&d.search.length>0){if(t.which===e.TAB||e.isControl(t)||e.isFunctionKey(t)||t.which===e.ESC||e.isVerticalMovement(t.which))return;if(d.activeIndex=d.taggingLabel===!1?-1:0,d.taggingLabel===!1)return;var i,s,l,n,a=angular.copy(d.items),r=angular.copy(d.items),p=!1,h=-1;if(void 0!==d.tagging.fct){if(l=d.$filter("filter")(a,{isTag:!0}),l.length>0&&(n=l[0]),a.length>0&&n&&(p=!0,a=a.slice(1,a.length),r=r.slice(1,r.length)),i=d.tagging.fct(d.search),r.some(function(e){return angular.equals(e,i)})||d.selected.some(function(e){return angular.equals(e,i)}))return void c.$evalAsync(function(){d.activeIndex=0,d.items=a});i&&(i.isTag=!0)}else{if(l=d.$filter("filter")(a,function(e){return e.match(d.taggingLabel)}),l.length>0&&(n=l[0]),s=a[0],void 0!==s&&a.length>0&&n&&(p=!0,a=a.slice(1,a.length),r=r.slice(1,r.length)),i=d.search+" "+d.taggingLabel,u(d.selected,d.search)>-1)return;if(o(r.concat(d.selected)))return void(p&&(a=r,c.$evalAsync(function(){d.activeIndex=0,d.items=a})));if(o(r))return void(p&&(d.items=r.slice(1,r.length)))}p&&(h=u(d.selected,i)),h>-1?a=a.slice(h+1,a.length-1):(a=[],i&&a.push(i),a=a.concat(r)),c.$evalAsync(function(){if(d.activeIndex=0,d.items=a,d.isGrouped){var e=i?a.slice(1):a;d.setItemsFn(e),i&&(d.items.unshift(i),d.groups.unshift({name:"",items:[i],tagging:!0}))}})}}),d.searchInput.on("blur",function(){i(function(){h.activeMatchIndex=-1})})}}}]),i.directive("uiSelectNoChoice",["uiSelectConfig",function(e){return{restrict:"EA",require:"^uiSelect",replace:!0,transclude:!0,templateUrl:function(t){var i=t.parent().attr("theme")||e.theme;return i+"/no-choice.tpl.html"}}}]),i.directive("uiSelectSingle",["$timeout","$compile",function(t,i){return{restrict:"EA",require:["^uiSelect","^ngModel"],link:function(c,s,l,n){var a=n[0],r=n[1];r.$parsers.unshift(function(e){var t,i={};return i[a.parserResult.itemName]=e,t=a.parserResult.modelMapper(c,i)}),r.$formatters.unshift(function(e){var t,i=a.parserResult&&a.parserResult.source(c,{$select:{search:""}}),s={};if(i){var l=function(i){return s[a.parserResult.itemName]=i,t=a.parserResult.modelMapper(c,s),t===e};if(a.selected&&l(a.selected))return a.selected;for(var n=i.length-1;n>=0;n--)if(l(i[n]))return i[n]}return e}),c.$watch("$select.selected",function(e){r.$viewValue!==e&&r.$setViewValue(e)}),r.$render=function(){a.selected=r.$viewValue},c.$on("uis:select",function(e,t){a.selected=t}),c.$on("uis:close",function(e,i){t(function(){a.focusser.prop("disabled",!1),i||a.focusser[0].focus()},0,!1)}),c.$on("uis:activate",function(){o.prop("disabled",!0)});var o=angular.element("<input ng-disabled='$select.disabled' class='ui-select-focusser ui-select-offscreen' type='text' id='{{ $select.focusserId }}' aria-label='{{ $select.focusserTitle }}' aria-haspopup='true' role='button' />");i(o)(c),a.focusser=o,a.focusInput=o,s.parent().append(o),o.bind("focus",function(){c.$evalAsync(function(){a.focus=!0})}),o.bind("blur",function(){c.$evalAsync(function(){a.focus=!1})}),o.bind("keydown",function(t){return t.which===e.BACKSPACE?(t.preventDefault(),t.stopPropagation(),a.select(void 0),void c.$apply()):void(t.which===e.TAB||e.isControl(t)||e.isFunctionKey(t)||t.which===e.ESC||(t.which!=e.DOWN&&t.which!=e.UP&&t.which!=e.ENTER&&t.which!=e.SPACE||(t.preventDefault(),t.stopPropagation(),a.activate()),c.$digest()))}),o.bind("keyup input",function(t){t.which===e.TAB||e.isControl(t)||e.isFunctionKey(t)||t.which===e.ESC||t.which==e.ENTER||t.which===e.BACKSPACE||(a.activate(o.val()),o.val(""),c.$digest())})}}}]),i.directive("uiSelectSort",["$timeout","uiSelectConfig","uiSelectMinErr",function(e,t,i){return{require:["^^uiSelect","^ngModel"],link:function(t,c,s,l){if(null===t[s.uiSelectSort])throw i("sort","Expected a list to sort");var n=l[0],a=l[1],r=angular.extend({axis:"horizontal"},t.$eval(s.uiSelectSortOptions)),o=r.axis,u="dragging",d="dropping",p="dropping-before",h="dropping-after";t.$watch(function(){return n.sortable},function(e){e?c.attr("draggable",!0):c.removeAttr("draggable")}),c.on("dragstart",function(e){c.addClass(u),(e.dataTransfer||e.originalEvent.dataTransfer).setData("text",t.$index.toString())}),c.on("dragend",function(){v(u)});var g,f=function(e,t){this.splice(t,0,this.splice(e,1)[0])},v=function(e){angular.forEach(n.$element.querySelectorAll("."+e),function(t){angular.element(t).removeClass(e)})},m=function(e){e.preventDefault();var t="vertical"===o?e.offsetY||e.layerY||(e.originalEvent?e.originalEvent.offsetY:0):e.offsetX||e.layerX||(e.originalEvent?e.originalEvent.offsetX:0);t<this["vertical"===o?"offsetHeight":"offsetWidth"]/2?(v(h),c.addClass(p)):(v(p),c.addClass(h))},$=function(t){t.preventDefault();var i=parseInt((t.dataTransfer||t.originalEvent.dataTransfer).getData("text"),10);e.cancel(g),g=e(function(){b(i)},20)},b=function(e){var i=t.$eval(s.uiSelectSort),l=i[e],n=null;n=c.hasClass(p)?e<t.$index?t.$index-1:t.$index:e<t.$index?t.$index:t.$index+1,f.apply(i,[e,n]),a.$setViewValue(Date.now()),t.$apply(function(){t.$emit("uiSelectSort:change",{array:i,item:l,from:e,to:n})}),v(d),v(p),v(h),c.off("drop",$)};c.on("dragenter",function(){c.hasClass(u)||(c.addClass(d),c.on("dragover",m),c.on("drop",$))}),c.on("dragleave",function(e){e.target==c&&(v(d),v(p),v(h),c.off("dragover",m),c.off("drop",$))})}}}]),i.service("uisRepeatParser",["uiSelectMinErr","$parse",function(e,t){var i=this;i.parse=function(i){var c;if(c=i.match(/^\s*(?:([\s\S]+?)\s+as\s+)?(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+(\s*[\s\S]+?)?(?:\s+track\s+by\s+([\s\S]+?))?\s*$/),!c)throw e("iexp","Expected expression in form of '_item_ in _collection_[ track by _id_]' but got '{0}'.",i);var s=c[5],l="";if(c[3]){s=c[5].replace(/(^\()|(\)$)/g,"");var n=c[5].match(/^\s*(?:[\s\S]+?)(?:[^\|]|\|\|)+([\s\S]*)\s*$/);n&&n[1].trim()&&(l=n[1],s=s.replace(l,""))}return{itemName:c[4]||c[2],keyName:c[3],source:t(s),filters:l,trackByExp:c[6],modelMapper:t(c[1]||c[4]||c[2]),repeatExpression:function(e){var t=this.itemName+" in "+(e?"$group.items":"$select.items");return this.trackByExp&&(t+=" track by "+this.trackByExp),t}}},i.getGroupNgRepeatExpression=function(){return"$group in $select.groups"}}])}(),angular.module("ui.select").run(["$templateCache",function(e){e.put("bootstrap/choices.tpl.html",'<ul class="ui-select-choices ui-select-choices-content ui-select-dropdown dropdown-menu" role="listbox" ng-show="$select.open && $select.items.length > 0"><li class="ui-select-choices-group" id="ui-select-choices-{{ $select.generatedId }}"><div class="divider" ng-show="$select.isGrouped && $index > 0"></div><div ng-show="$select.isGrouped" class="ui-select-choices-group-label dropdown-header" ng-bind="$group.name"></div><div ng-attr-id="ui-select-choices-row-{{ $select.generatedId }}-{{$index}}" class="ui-select-choices-row" ng-class="{active: $select.isActive(this), disabled: $select.isDisabled(this)}" role="option"><a href="" class="ui-select-choices-row-inner"></a></div></li></ul>'),e.put("bootstrap/match-multiple.tpl.html",'<span class="ui-select-match"><span ng-repeat="$item in $select.selected"><span class="ui-select-match-item btn btn-default btn-xs" tabindex="-1" type="button" ng-disabled="$select.disabled" ng-click="$selectMultiple.activeMatchIndex = $index;" ng-class="{\'btn-primary\':$selectMultiple.activeMatchIndex === $index, \'select-locked\':$select.isLocked(this, $index)}" ui-select-sort="$select.selected"><span class="close ui-select-match-close" ng-hide="$select.disabled" ng-click="$selectMultiple.removeChoice($index)">&nbsp;&times;</span> <span uis-transclude-append=""></span></span></span></span>'),e.put("bootstrap/match.tpl.html",'<div class="ui-select-match" ng-hide="$select.open && $select.searchEnabled" ng-disabled="$select.disabled" ng-class="{\'btn-default-focus\':$select.focus}"><span tabindex="-1" class="btn btn-default form-control ui-select-toggle" aria-label="{{ $select.baseTitle }} activate" ng-disabled="$select.disabled" ng-click="$select.activate()" style="outline: 0;"><span ng-show="$select.isEmpty()" class="ui-select-placeholder text-muted">{{$select.placeholder}}</span> <span ng-hide="$select.isEmpty()" class="ui-select-match-text pull-left" ng-class="{\'ui-select-allow-clear\': $select.allowClear && !$select.isEmpty()}" ng-transclude=""></span> <i class="caret pull-right" ng-click="$select.toggle($event)"></i> <a ng-show="$select.allowClear && !$select.isEmpty() && ($select.disabled !== true)" aria-label="{{ $select.baseTitle }} clear" style="margin-right: 10px" ng-click="$select.clear($event)" class="btn btn-xs btn-link pull-right"><i class="glyphicon glyphicon-remove" aria-hidden="true"></i></a></span></div>'),
+e.put("bootstrap/no-choice.tpl.html",'<ul class="ui-select-no-choice dropdown-menu" ng-show="$select.items.length == 0"><li ng-transclude=""></li></ul>'),e.put("bootstrap/select-multiple.tpl.html",'<div class="ui-select-container ui-select-multiple ui-select-bootstrap dropdown form-control" ng-class="{open: $select.open}"><div><div class="ui-select-match"></div><input type="search" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" class="ui-select-search input-xs" placeholder="{{$selectMultiple.getPlaceholder()}}" ng-disabled="$select.disabled" ng-hide="$select.disabled" ng-click="$select.activate()" ng-model="$select.search" role="combobox" aria-label="{{ $select.baseTitle }}" ondrop="return false;"></div><div class="ui-select-choices"></div></div>'),e.put("bootstrap/select.tpl.html",'<div class="ui-select-container ui-select-bootstrap dropdown" ng-class="{open: $select.open}"><div class="ui-select-match"></div><input type="search" autocomplete="off" tabindex="-1" aria-expanded="true" aria-label="{{ $select.baseTitle }}" aria-owns="ui-select-choices-{{ $select.generatedId }}" aria-activedescendant="ui-select-choices-row-{{ $select.generatedId }}-{{ $select.activeIndex }}" class="form-control ui-select-search" placeholder="{{$select.placeholder}}" ng-model="$select.search" ng-show="$select.searchEnabled && $select.open"><div class="ui-select-choices"></div><div class="ui-select-no-choice"></div></div>'),e.put("select2/choices.tpl.html",'<ul tabindex="-1" class="ui-select-choices ui-select-choices-content select2-results"><li class="ui-select-choices-group" ng-class="{\'select2-result-with-children\': $select.choiceGrouped($group) }"><div ng-show="$select.choiceGrouped($group)" class="ui-select-choices-group-label select2-result-label" ng-bind="$group.name"></div><ul role="listbox" id="ui-select-choices-{{ $select.generatedId }}" ng-class="{\'select2-result-sub\': $select.choiceGrouped($group), \'select2-result-single\': !$select.choiceGrouped($group) }"><li role="option" ng-attr-id="ui-select-choices-row-{{ $select.generatedId }}-{{$index}}" class="ui-select-choices-row" ng-class="{\'select2-highlighted\': $select.isActive(this), \'select2-disabled\': $select.isDisabled(this)}"><div class="select2-result-label ui-select-choices-row-inner"></div></li></ul></li></ul>'),e.put("select2/match-multiple.tpl.html",'<span class="ui-select-match"><li class="ui-select-match-item select2-search-choice" ng-repeat="$item in $select.selected" ng-class="{\'select2-search-choice-focus\':$selectMultiple.activeMatchIndex === $index, \'select2-locked\':$select.isLocked(this, $index)}" ui-select-sort="$select.selected"><span uis-transclude-append=""></span> <a href="javascript:;" class="ui-select-match-close select2-search-choice-close" ng-click="$selectMultiple.removeChoice($index)" tabindex="-1"></a></li></span>'),e.put("select2/match.tpl.html",'<a class="select2-choice ui-select-match" ng-class="{\'select2-default\': $select.isEmpty()}" ng-click="$select.toggle($event)" aria-label="{{ $select.baseTitle }} select"><span ng-show="$select.isEmpty()" class="select2-chosen">{{$select.placeholder}}</span> <span ng-hide="$select.isEmpty()" class="select2-chosen" ng-transclude=""></span> <abbr ng-if="$select.allowClear && !$select.isEmpty()" class="select2-search-choice-close" ng-click="$select.clear($event)"></abbr> <span class="select2-arrow ui-select-toggle"><b></b></span></a>'),e.put("select2/select-multiple.tpl.html",'<div class="ui-select-container ui-select-multiple select2 select2-container select2-container-multi" ng-class="{\'select2-container-active select2-dropdown-open open\': $select.open, \'select2-container-disabled\': $select.disabled}"><ul class="select2-choices"><span class="ui-select-match"></span><li class="select2-search-field"><input type="search" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" role="combobox" aria-expanded="true" aria-owns="ui-select-choices-{{ $select.generatedId }}" aria-label="{{ $select.baseTitle }}" aria-activedescendant="ui-select-choices-row-{{ $select.generatedId }}-{{ $select.activeIndex }}" class="select2-input ui-select-search" placeholder="{{$selectMultiple.getPlaceholder()}}" ng-disabled="$select.disabled" ng-hide="$select.disabled" ng-model="$select.search" ng-click="$select.activate()" style="width: 34px;" ondrop="return false;"></li></ul><div class="ui-select-dropdown select2-drop select2-with-searchbox select2-drop-active" ng-class="{\'select2-display-none\': !$select.open || $select.items.length === 0}"><div class="ui-select-choices"></div></div></div>'),e.put("select2/select.tpl.html",'<div class="ui-select-container select2 select2-container" ng-class="{\'select2-container-active select2-dropdown-open open\': $select.open, \'select2-container-disabled\': $select.disabled, \'select2-container-active\': $select.focus, \'select2-allowclear\': $select.allowClear && !$select.isEmpty()}"><div class="ui-select-match"></div><div class="ui-select-dropdown select2-drop select2-with-searchbox select2-drop-active" ng-class="{\'select2-display-none\': !$select.open}"><div class="select2-search" ng-show="$select.searchEnabled"><input type="search" autocomplete="off" autocorrect="off" autocapitalize="off" spellcheck="false" role="combobox" aria-expanded="true" aria-owns="ui-select-choices-{{ $select.generatedId }}" aria-label="{{ $select.baseTitle }}" aria-activedescendant="ui-select-choices-row-{{ $select.generatedId }}-{{ $select.activeIndex }}" class="ui-select-search select2-input" ng-model="$select.search"></div><div class="ui-select-choices"></div></div></div>'),e.put("selectize/choices.tpl.html",'<div ng-show="$select.open" class="ui-select-choices ui-select-dropdown selectize-dropdown single"><div class="ui-select-choices-content selectize-dropdown-content"><div class="ui-select-choices-group optgroup" role="listbox"><div ng-show="$select.isGrouped" class="ui-select-choices-group-label optgroup-header" ng-bind="$group.name"></div><div role="option" class="ui-select-choices-row" ng-class="{active: $select.isActive(this), disabled: $select.isDisabled(this)}"><div class="option ui-select-choices-row-inner" data-selectable=""></div></div></div></div></div>'),e.put("selectize/match.tpl.html",'<div ng-hide="$select.searchEnabled && ($select.open || $select.isEmpty())" class="ui-select-match" ng-transclude=""></div>'),e.put("selectize/select.tpl.html",'<div class="ui-select-container selectize-control single" ng-class="{\'open\': $select.open}"><div class="selectize-input" ng-class="{\'focus\': $select.open, \'disabled\': $select.disabled, \'selectize-focus\' : $select.focus}" ng-click="$select.open && !$select.searchEnabled ? $select.toggle($event) : $select.activate()"><div class="ui-select-match"></div><input type="search" autocomplete="off" tabindex="-1" class="ui-select-search ui-select-toggle" ng-click="$select.toggle($event)" placeholder="{{$select.placeholder}}" ng-model="$select.search" ng-hide="!$select.searchEnabled || ($select.selected && !$select.open)" ng-disabled="$select.disabled" aria-label="{{ $select.baseTitle }}"></div><div class="ui-select-choices"></div></div>')}]);
+//# sourceMappingURL=select.min.js.map
diff --git a/ecomp-portal-FE/client/bower_components/ui-select/docs/assets/app.js b/ecomp-portal-FE/client/bower_components/ui-select/docs/assets/app.js
new file mode 100644
index 00000000..f51f062d
--- /dev/null
+++ b/ecomp-portal-FE/client/bower_components/ui-select/docs/assets/app.js
@@ -0,0 +1 @@
+var module = angular.module('ui.select.pages', ['plunkr']);
diff --git a/ecomp-portal-FE/client/bower_components/ui-select/docs/assets/demo.js b/ecomp-portal-FE/client/bower_components/ui-select/docs/assets/demo.js
new file mode 100644
index 00000000..7aaf3364
--- /dev/null
+++ b/ecomp-portal-FE/client/bower_components/ui-select/docs/assets/demo.js
@@ -0,0 +1,461 @@
+'use strict';
+
+var app = angular.module('demo', ['ngSanitize', 'ui.select']);
+
+/**
+ * AngularJS default filter with the following expression:
+ * "person in people | filter: {name: $select.search, age: $select.search}"
+ * performs an AND between 'name: $select.search' and 'age: $select.search'.
+ * We want to perform an OR.
+ */
+app.filter('propsFilter', function() {
+ return function(items, props) {
+ var out = [];
+
+ if (angular.isArray(items)) {
+ var keys = Object.keys(props);
+
+ items.forEach(function(item) {
+ var itemMatches = false;
+
+ for (var i = 0; i < keys.length; i++) {
+ var prop = keys[i];
+ var text = props[prop].toLowerCase();
+ if (item[prop].toString().toLowerCase().indexOf(text) !== -1) {
+ itemMatches = true;
+ break;
+ }
+ }
+
+ if (itemMatches) {
+ out.push(item);
+ }
+ });
+ } else {
+ // Let the output be the input untouched
+ out = items;
+ }
+
+ return out;
+ };
+});
+
+app.controller('DemoCtrl', function ($scope, $http, $timeout, $interval) {
+ var vm = this;
+
+ vm.disabled = undefined;
+ vm.searchEnabled = undefined;
+
+ vm.setInputFocus = function (){
+ $scope.$broadcast('UiSelectDemo1');
+ };
+
+ vm.enable = function() {
+ vm.disabled = false;
+ };
+
+ vm.disable = function() {
+ vm.disabled = true;
+ };
+
+ vm.enableSearch = function() {
+ vm.searchEnabled = true;
+ };
+
+ vm.disableSearch = function() {
+ vm.searchEnabled = false;
+ };
+
+ vm.clear = function() {
+ vm.person.selected = undefined;
+ vm.address.selected = undefined;
+ vm.country.selected = undefined;
+ };
+
+ vm.someGroupFn = function (item){
+
+ if (item.name[0] >= 'A' && item.name[0] <= 'M')
+ return 'From A - M';
+
+ if (item.name[0] >= 'N' && item.name[0] <= 'Z')
+ return 'From N - Z';
+
+ };
+
+ vm.firstLetterGroupFn = function (item){
+ return item.name[0];
+ };
+
+ vm.reverseOrderFilterFn = function(groups) {
+ return groups.reverse();
+ };
+
+ vm.personAsync = {selected : "wladimir@email.com"};
+ vm.peopleAsync = [];
+
+ $timeout(function(){
+ vm.peopleAsync = [
+ { name: 'Adam', email: 'adam@email.com', age: 12, country: 'United States' },
+ { name: 'Amalie', email: 'amalie@email.com', age: 12, country: 'Argentina' },
+ { name: 'Estefanía', email: 'estefania@email.com', age: 21, country: 'Argentina' },
+ { name: 'Adrian', email: 'adrian@email.com', age: 21, country: 'Ecuador' },
+ { name: 'Wladimir', email: 'wladimir@email.com', age: 30, country: 'Ecuador' },
+ { name: 'Samantha', email: 'samantha@email.com', age: 30, country: 'United States' },
+ { name: 'Nicole', email: 'nicole@email.com', age: 43, country: 'Colombia' },
+ { name: 'Natasha', email: 'natasha@email.com', age: 54, country: 'Ecuador' },
+ { name: 'Michael', email: 'michael@email.com', age: 15, country: 'Colombia' },
+ { name: 'Nicolás', email: 'nicole@email.com', age: 43, country: 'Colombia' }
+ ];
+ },3000);
+
+ vm.counter = 0;
+ vm.onSelectCallback = function (item, model){
+ vm.counter++;
+ vm.eventResult = {item: item, model: model};
+ };
+
+ vm.removed = function (item, model) {
+ vm.lastRemoved = {
+ item: item,
+ model: model
+ };
+ };
+
+ vm.tagTransform = function (newTag) {
+ var item = {
+ name: newTag,
+ email: newTag.toLowerCase()+'@email.com',
+ age: 'unknown',
+ country: 'unknown'
+ };
+
+ return item;
+ };
+
+ vm.peopleObj = {
+ '1' : { name: 'Adam', email: 'adam@email.com', age: 12, country: 'United States' },
+ '2' : { name: 'Amalie', email: 'amalie@email.com', age: 12, country: 'Argentina' },
+ '3' : { name: 'Estefanía', email: 'estefania@email.com', age: 21, country: 'Argentina' },
+ '4' : { name: 'Adrian', email: 'adrian@email.com', age: 21, country: 'Ecuador' },
+ '5' : { name: 'Wladimir', email: 'wladimir@email.com', age: 30, country: 'Ecuador' },
+ '6' : { name: 'Samantha', email: 'samantha@email.com', age: 30, country: 'United States' },
+ '7' : { name: 'Nicole', email: 'nicole@email.com', age: 43, country: 'Colombia' },
+ '8' : { name: 'Natasha', email: 'natasha@email.com', age: 54, country: 'Ecuador' },
+ '9' : { name: 'Michael', email: 'michael@email.com', age: 15, country: 'Colombia' },
+ '10' : { name: 'Nicolás', email: 'nicolas@email.com', age: 43, country: 'Colombia' }
+ };
+
+ vm.person = {};
+
+ vm.person.selectedValue = vm.peopleObj[3];
+ vm.person.selectedSingle = 'Samantha';
+ vm.person.selectedSingleKey = '5';
+
+ vm.people = [
+ { name: 'Adam', email: 'adam@email.com', age: 12, country: 'United States' },
+ { name: 'Amalie', email: 'amalie@email.com', age: 12, country: 'Argentina' },
+ { name: 'Estefanía', email: 'estefania@email.com', age: 21, country: 'Argentina' },
+ { name: 'Adrian', email: 'adrian@email.com', age: 21, country: 'Ecuador' },
+ { name: 'Wladimir', email: 'wladimir@email.com', age: 30, country: 'Ecuador' },
+ { name: 'Samantha', email: 'samantha@email.com', age: 30, country: 'United States' },
+ { name: 'Nicole', email: 'nicole@email.com', age: 43, country: 'Colombia' },
+ { name: 'Natasha', email: 'natasha@email.com', age: 54, country: 'Ecuador' },
+ { name: 'Michael', email: 'michael@email.com', age: 15, country: 'Colombia' },
+ { name: 'Nicolás', email: 'nicolas@email.com', age: 43, country: 'Colombia' }
+ ];
+
+ vm.availableColors = ['Red','Green','Blue','Yellow','Magenta','Maroon','Umbra','Turquoise'];
+
+ vm.singleDemo = {};
+ vm.singleDemo.color = '';
+ vm.multipleDemo = {};
+ vm.multipleDemo.colors = ['Blue','Red'];
+ vm.multipleDemo.colors2 = ['Blue','Red'];
+ vm.multipleDemo.selectedPeople = [vm.people[5], vm.people[4]];
+ vm.multipleDemo.selectedPeople2 = vm.multipleDemo.selectedPeople;
+ vm.multipleDemo.selectedPeopleWithGroupBy = [vm.people[8], vm.people[6]];
+ vm.multipleDemo.selectedPeopleSimple = ['samantha@email.com','wladimir@email.com'];
+
+ vm.appendToBodyDemo = {
+ remainingToggleTime: 0,
+ present: true,
+ startToggleTimer: function() {
+ var scope = vm.appendToBodyDemo;
+ var promise = $interval(function() {
+ if (scope.remainingTime < 1000) {
+ $interval.cancel(promise);
+ scope.present = !scope.present;
+ scope.remainingTime = 0;
+ } else {
+ scope.remainingTime -= 1000;
+ }
+ }, 1000);
+ scope.remainingTime = 3000;
+ }
+ };
+
+ vm.address = {};
+ vm.refreshAddresses = function(address) {
+ var params = {address: address, sensor: false};
+ return $http.get(
+ 'http://maps.googleapis.com/maps/api/geocode/json',
+ {params: params}
+ ).then(function(response) {
+ vm.addresses = response.data.results;
+ });
+ };
+
+ vm.addPerson = function(item, model){
+ if(item.hasOwnProperty('isTag')) {
+ delete item.isTag;
+ vm.people.push(item);
+ }
+ }
+
+ vm.country = {};
+ vm.countries = [ // Taken from https://gist.github.com/unceus/6501985
+ {name: 'Afghanistan', code: 'AF'},
+ {name: 'Åland Islands', code: 'AX'},
+ {name: 'Albania', code: 'AL'},
+ {name: 'Algeria', code: 'DZ'},
+ {name: 'American Samoa', code: 'AS'},
+ {name: 'Andorra', code: 'AD'},
+ {name: 'Angola', code: 'AO'},
+ {name: 'Anguilla', code: 'AI'},
+ {name: 'Antarctica', code: 'AQ'},
+ {name: 'Antigua and Barbuda', code: 'AG'},
+ {name: 'Argentina', code: 'AR'},
+ {name: 'Armenia', code: 'AM'},
+ {name: 'Aruba', code: 'AW'},
+ {name: 'Australia', code: 'AU'},
+ {name: 'Austria', code: 'AT'},
+ {name: 'Azerbaijan', code: 'AZ'},
+ {name: 'Bahamas', code: 'BS'},
+ {name: 'Bahrain', code: 'BH'},
+ {name: 'Bangladesh', code: 'BD'},
+ {name: 'Barbados', code: 'BB'},
+ {name: 'Belarus', code: 'BY'},
+ {name: 'Belgium', code: 'BE'},
+ {name: 'Belize', code: 'BZ'},
+ {name: 'Benin', code: 'BJ'},
+ {name: 'Bermuda', code: 'BM'},
+ {name: 'Bhutan', code: 'BT'},
+ {name: 'Bolivia', code: 'BO'},
+ {name: 'Bosnia and Herzegovina', code: 'BA'},
+ {name: 'Botswana', code: 'BW'},
+ {name: 'Bouvet Island', code: 'BV'},
+ {name: 'Brazil', code: 'BR'},
+ {name: 'British Indian Ocean Territory', code: 'IO'},
+ {name: 'Brunei Darussalam', code: 'BN'},
+ {name: 'Bulgaria', code: 'BG'},
+ {name: 'Burkina Faso', code: 'BF'},
+ {name: 'Burundi', code: 'BI'},
+ {name: 'Cambodia', code: 'KH'},
+ {name: 'Cameroon', code: 'CM'},
+ {name: 'Canada', code: 'CA'},
+ {name: 'Cape Verde', code: 'CV'},
+ {name: 'Cayman Islands', code: 'KY'},
+ {name: 'Central African Republic', code: 'CF'},
+ {name: 'Chad', code: 'TD'},
+ {name: 'Chile', code: 'CL'},
+ {name: 'China', code: 'CN'},
+ {name: 'Christmas Island', code: 'CX'},
+ {name: 'Cocos (Keeling) Islands', code: 'CC'},
+ {name: 'Colombia', code: 'CO'},
+ {name: 'Comoros', code: 'KM'},
+ {name: 'Congo', code: 'CG'},
+ {name: 'Congo, The Democratic Republic of the', code: 'CD'},
+ {name: 'Cook Islands', code: 'CK'},
+ {name: 'Costa Rica', code: 'CR'},
+ {name: 'Cote D\'Ivoire', code: 'CI'},
+ {name: 'Croatia', code: 'HR'},
+ {name: 'Cuba', code: 'CU'},
+ {name: 'Cyprus', code: 'CY'},
+ {name: 'Czech Republic', code: 'CZ'},
+ {name: 'Denmark', code: 'DK'},
+ {name: 'Djibouti', code: 'DJ'},
+ {name: 'Dominica', code: 'DM'},
+ {name: 'Dominican Republic', code: 'DO'},
+ {name: 'Ecuador', code: 'EC'},
+ {name: 'Egypt', code: 'EG'},
+ {name: 'El Salvador', code: 'SV'},
+ {name: 'Equatorial Guinea', code: 'GQ'},
+ {name: 'Eritrea', code: 'ER'},
+ {name: 'Estonia', code: 'EE'},
+ {name: 'Ethiopia', code: 'ET'},
+ {name: 'Falkland Islands (Malvinas)', code: 'FK'},
+ {name: 'Faroe Islands', code: 'FO'},
+ {name: 'Fiji', code: 'FJ'},
+ {name: 'Finland', code: 'FI'},
+ {name: 'France', code: 'FR'},
+ {name: 'French Guiana', code: 'GF'},
+ {name: 'French Polynesia', code: 'PF'},
+ {name: 'French Southern Territories', code: 'TF'},
+ {name: 'Gabon', code: 'GA'},
+ {name: 'Gambia', code: 'GM'},
+ {name: 'Georgia', code: 'GE'},
+ {name: 'Germany', code: 'DE'},
+ {name: 'Ghana', code: 'GH'},
+ {name: 'Gibraltar', code: 'GI'},
+ {name: 'Greece', code: 'GR'},
+ {name: 'Greenland', code: 'GL'},
+ {name: 'Grenada', code: 'GD'},
+ {name: 'Guadeloupe', code: 'GP'},
+ {name: 'Guam', code: 'GU'},
+ {name: 'Guatemala', code: 'GT'},
+ {name: 'Guernsey', code: 'GG'},
+ {name: 'Guinea', code: 'GN'},
+ {name: 'Guinea-Bissau', code: 'GW'},
+ {name: 'Guyana', code: 'GY'},
+ {name: 'Haiti', code: 'HT'},
+ {name: 'Heard Island and Mcdonald Islands', code: 'HM'},
+ {name: 'Holy See (Vatican City State)', code: 'VA'},
+ {name: 'Honduras', code: 'HN'},
+ {name: 'Hong Kong', code: 'HK'},
+ {name: 'Hungary', code: 'HU'},
+ {name: 'Iceland', code: 'IS'},
+ {name: 'India', code: 'IN'},
+ {name: 'Indonesia', code: 'ID'},
+ {name: 'Iran, Islamic Republic Of', code: 'IR'},
+ {name: 'Iraq', code: 'IQ'},
+ {name: 'Ireland', code: 'IE'},
+ {name: 'Isle of Man', code: 'IM'},
+ {name: 'Israel', code: 'IL'},
+ {name: 'Italy', code: 'IT'},
+ {name: 'Jamaica', code: 'JM'},
+ {name: 'Japan', code: 'JP'},
+ {name: 'Jersey', code: 'JE'},
+ {name: 'Jordan', code: 'JO'},
+ {name: 'Kazakhstan', code: 'KZ'},
+ {name: 'Kenya', code: 'KE'},
+ {name: 'Kiribati', code: 'KI'},
+ {name: 'Korea, Democratic People\'s Republic of', code: 'KP'},
+ {name: 'Korea, Republic of', code: 'KR'},
+ {name: 'Kuwait', code: 'KW'},
+ {name: 'Kyrgyzstan', code: 'KG'},
+ {name: 'Lao People\'s Democratic Republic', code: 'LA'},
+ {name: 'Latvia', code: 'LV'},
+ {name: 'Lebanon', code: 'LB'},
+ {name: 'Lesotho', code: 'LS'},
+ {name: 'Liberia', code: 'LR'},
+ {name: 'Libyan Arab Jamahiriya', code: 'LY'},
+ {name: 'Liechtenstein', code: 'LI'},
+ {name: 'Lithuania', code: 'LT'},
+ {name: 'Luxembourg', code: 'LU'},
+ {name: 'Macao', code: 'MO'},
+ {name: 'Macedonia, The Former Yugoslav Republic of', code: 'MK'},
+ {name: 'Madagascar', code: 'MG'},
+ {name: 'Malawi', code: 'MW'},
+ {name: 'Malaysia', code: 'MY'},
+ {name: 'Maldives', code: 'MV'},
+ {name: 'Mali', code: 'ML'},
+ {name: 'Malta', code: 'MT'},
+ {name: 'Marshall Islands', code: 'MH'},
+ {name: 'Martinique', code: 'MQ'},
+ {name: 'Mauritania', code: 'MR'},
+ {name: 'Mauritius', code: 'MU'},
+ {name: 'Mayotte', code: 'YT'},
+ {name: 'Mexico', code: 'MX'},
+ {name: 'Micronesia, Federated States of', code: 'FM'},
+ {name: 'Moldova, Republic of', code: 'MD'},
+ {name: 'Monaco', code: 'MC'},
+ {name: 'Mongolia', code: 'MN'},
+ {name: 'Montserrat', code: 'MS'},
+ {name: 'Morocco', code: 'MA'},
+ {name: 'Mozambique', code: 'MZ'},
+ {name: 'Myanmar', code: 'MM'},
+ {name: 'Namibia', code: 'NA'},
+ {name: 'Nauru', code: 'NR'},
+ {name: 'Nepal', code: 'NP'},
+ {name: 'Netherlands', code: 'NL'},
+ {name: 'Netherlands Antilles', code: 'AN'},
+ {name: 'New Caledonia', code: 'NC'},
+ {name: 'New Zealand', code: 'NZ'},
+ {name: 'Nicaragua', code: 'NI'},
+ {name: 'Niger', code: 'NE'},
+ {name: 'Nigeria', code: 'NG'},
+ {name: 'Niue', code: 'NU'},
+ {name: 'Norfolk Island', code: 'NF'},
+ {name: 'Northern Mariana Islands', code: 'MP'},
+ {name: 'Norway', code: 'NO'},
+ {name: 'Oman', code: 'OM'},
+ {name: 'Pakistan', code: 'PK'},
+ {name: 'Palau', code: 'PW'},
+ {name: 'Palestinian Territory, Occupied', code: 'PS'},
+ {name: 'Panama', code: 'PA'},
+ {name: 'Papua New Guinea', code: 'PG'},
+ {name: 'Paraguay', code: 'PY'},
+ {name: 'Peru', code: 'PE'},
+ {name: 'Philippines', code: 'PH'},
+ {name: 'Pitcairn', code: 'PN'},
+ {name: 'Poland', code: 'PL'},
+ {name: 'Portugal', code: 'PT'},
+ {name: 'Puerto Rico', code: 'PR'},
+ {name: 'Qatar', code: 'QA'},
+ {name: 'Reunion', code: 'RE'},
+ {name: 'Romania', code: 'RO'},
+ {name: 'Russian Federation', code: 'RU'},
+ {name: 'Rwanda', code: 'RW'},
+ {name: 'Saint Helena', code: 'SH'},
+ {name: 'Saint Kitts and Nevis', code: 'KN'},
+ {name: 'Saint Lucia', code: 'LC'},
+ {name: 'Saint Pierre and Miquelon', code: 'PM'},
+ {name: 'Saint Vincent and the Grenadines', code: 'VC'},
+ {name: 'Samoa', code: 'WS'},
+ {name: 'San Marino', code: 'SM'},
+ {name: 'Sao Tome and Principe', code: 'ST'},
+ {name: 'Saudi Arabia', code: 'SA'},
+ {name: 'Senegal', code: 'SN'},
+ {name: 'Serbia and Montenegro', code: 'CS'},
+ {name: 'Seychelles', code: 'SC'},
+ {name: 'Sierra Leone', code: 'SL'},
+ {name: 'Singapore', code: 'SG'},
+ {name: 'Slovakia', code: 'SK'},
+ {name: 'Slovenia', code: 'SI'},
+ {name: 'Solomon Islands', code: 'SB'},
+ {name: 'Somalia', code: 'SO'},
+ {name: 'South Africa', code: 'ZA'},
+ {name: 'South Georgia and the South Sandwich Islands', code: 'GS'},
+ {name: 'Spain', code: 'ES'},
+ {name: 'Sri Lanka', code: 'LK'},
+ {name: 'Sudan', code: 'SD'},
+ {name: 'Suriname', code: 'SR'},
+ {name: 'Svalbard and Jan Mayen', code: 'SJ'},
+ {name: 'Swaziland', code: 'SZ'},
+ {name: 'Sweden', code: 'SE'},
+ {name: 'Switzerland', code: 'CH'},
+ {name: 'Syrian Arab Republic', code: 'SY'},
+ {name: 'Taiwan, Province of China', code: 'TW'},
+ {name: 'Tajikistan', code: 'TJ'},
+ {name: 'Tanzania, United Republic of', code: 'TZ'},
+ {name: 'Thailand', code: 'TH'},
+ {name: 'Timor-Leste', code: 'TL'},
+ {name: 'Togo', code: 'TG'},
+ {name: 'Tokelau', code: 'TK'},
+ {name: 'Tonga', code: 'TO'},
+ {name: 'Trinidad and Tobago', code: 'TT'},
+ {name: 'Tunisia', code: 'TN'},
+ {name: 'Turkey', code: 'TR'},
+ {name: 'Turkmenistan', code: 'TM'},
+ {name: 'Turks and Caicos Islands', code: 'TC'},
+ {name: 'Tuvalu', code: 'TV'},
+ {name: 'Uganda', code: 'UG'},
+ {name: 'Ukraine', code: 'UA'},
+ {name: 'United Arab Emirates', code: 'AE'},
+ {name: 'United Kingdom', code: 'GB'},
+ {name: 'United States', code: 'US'},
+ {name: 'United States Minor Outlying Islands', code: 'UM'},
+ {name: 'Uruguay', code: 'UY'},
+ {name: 'Uzbekistan', code: 'UZ'},
+ {name: 'Vanuatu', code: 'VU'},
+ {name: 'Venezuela', code: 'VE'},
+ {name: 'Vietnam', code: 'VN'},
+ {name: 'Virgin Islands, British', code: 'VG'},
+ {name: 'Virgin Islands, U.S.', code: 'VI'},
+ {name: 'Wallis and Futuna', code: 'WF'},
+ {name: 'Western Sahara', code: 'EH'},
+ {name: 'Yemen', code: 'YE'},
+ {name: 'Zambia', code: 'ZM'},
+ {name: 'Zimbabwe', code: 'ZW'}
+ ];
+});
diff --git a/ecomp-portal-FE/client/bower_components/ui-select/docs/assets/docs.css b/ecomp-portal-FE/client/bower_components/ui-select/docs/assets/docs.css
new file mode 100644
index 00000000..98ed6173
--- /dev/null
+++ b/ecomp-portal-FE/client/bower_components/ui-select/docs/assets/docs.css
@@ -0,0 +1,339 @@
+/*
+ Taken from angular-ui/bootstrap
+ See https://github.com/angular-ui/bootstrap/blob/master/misc/demo/assets/demo.css
+*/
+
+body {
+ opacity: 1;
+ -webkit-transition: opacity 1s ease;
+ -moz-transition: opacity 1s ease;
+ transition: opacity 1s;
+}
+
+.ng-cloak {
+ opacity: 0;
+}
+
+.ng-invalid {
+ border: 1px solid red !important;
+}
+
+section {
+ padding-top: 30px;
+}
+
+.page-header h1 > small > a {
+ color: #999;
+}
+
+ .page-header h1 > small > a:hover {
+ text-decoration: none;
+ }
+
+.footer {
+ text-align: center;
+ padding: 30px 0;
+ margin-top: 70px;
+ border-top: 1px solid #e5e5e5;
+ background-color: #f5f5f5;
+}
+
+.bs-social {
+ margin-top: 20px;
+ margin-bottom: 20px;
+ text-align: center;
+}
+
+@media (min-width: 768px) {
+
+ .bs-social {
+ text-align: left;
+ }
+}
+
+.nav, .pagination, .carousel, .panel-title a {
+ cursor: pointer;
+}
+
+.bs-social-buttons {
+ display: inline-block;
+ margin-bottom: 0;
+ padding-left: 0;
+ list-style: none;
+}
+
+ .bs-social-buttons li {
+ display: inline-block;
+ padding: 5px 8px;
+ line-height: 1;
+ }
+
+@media (max-width: 767px) {
+
+ .visible-xs.collapse.in {
+ display: block !important;
+ }
+
+ .visible-xs.collapse {
+ display: none !important;
+ }
+}
+
+.navbar .collapse {
+ border-top: 1px solid #e7e7e7;
+ margin-left: -15px;
+ margin-right: -15px;
+ padding-right: 15px;
+ padding-left: 15px;
+}
+
+.show-grid {
+ margin-bottom: 15px;
+}
+
+/*
+ * Container
+ *
+ * Tweak to width of container.
+ */
+
+/*@media (min-width: 1200px) {
+ .container{
+ max-width: 970px;
+ }
+}*/
+
+/*
+ * Tabs
+ *
+ * Tweaks to the Tabs.
+ */
+
+.code .nav-tabs {
+ border-bottom: 1px solid #ccc;
+}
+
+.code pre, .code code {
+ border-top: none;
+ border-top-left-radius: 0;
+ border-top-right-radius: 0;
+}
+
+.code .nav-tabs > li.active > a, .code .nav-tabs > li.active > a:hover, .code .nav-tabs > li.active > a:focus {
+ background-color: #f8f8f8;
+ border: 1px solid #ccc;
+ border-bottom-color: transparent;
+}
+
+/*
+ * Button Inverse
+ *
+ * Buttons in the masthead.
+ */
+
+.btn-outline-inverse {
+ color: #fff;
+ background-color: transparent;
+ border-color: #cdbfe3;
+ margin: 10px;
+}
+
+@media (min-width: 768px) {
+
+ .btn-outline-inverse {
+ width: auto;
+ margin: 20px 5px 20px 0;
+ padding: 18px 24px;
+ font-size: 21px;
+ }
+}
+
+.btn-outline-inverse:hover, .btn-outline-inverse:focus, .btn-outline-inverse:active {
+ color: #563d7c;
+ text-shadow: none;
+ background-color: #fff;
+ border-color: #fff;
+}
+
+
+/* Page headers */
+.bs-header {
+ padding: 30px 15px 40px; /* side padding builds on .container 15px, so 30px */
+ font-size: 16px;
+ text-align: center;
+ text-shadow: 0 1px 0 rgba(0,0,0,.15);
+ color: #cdbfe3;
+ background-color: #563d7c;
+ background-image: url(header.png);
+}
+
+ .bs-header a {
+ color: #fff;
+ font-weight: normal;
+ }
+
+ .bs-header h1 {
+ color: #fff;
+ }
+
+ .bs-header p {
+ font-weight: 200;
+ line-height: 1.4;
+ }
+
+ .bs-header .container {
+ position: relative;
+ }
+
+@media (min-width: 768px) {
+ .bs-header {
+ font-size: 30px;
+ text-align: left;
+ }
+
+ .bs-header h1 {
+ font-size: 100px;
+ line-height: 1;
+ }
+}
+
+@media (min-width: 992px) {
+ .bs-header p {
+ margin-right: 25%;
+ }
+}
+
+.navbar-inner {
+ -webkit-box-shadow: 0 3px 3px rgba(0,0,0,0.175);
+ box-shadow: 0 3px 3px rgba(0,0,0,0.175);
+}
+
+/*
+ * Side navigation
+ *
+ * Scrollspy and affixed enhanced navigation to highlight sections and secondary
+ * sections of docs content.
+ */
+
+/* By default it's not affixed in mobile views, so undo that */
+.bs-sidebar.affix {
+ position: static;
+}
+
+/* First level of nav */
+.bs-sidenav {
+ margin-top: 30px;
+ margin-bottom: 30px;
+ padding-top: 10px;
+ padding-bottom: 10px;
+ text-shadow: 0 1px 0 #fff;
+ background-color: #f7f5fa;
+ border-radius: 5px;
+}
+
+/* All levels of nav */
+.bs-sidebar .nav > li > a {
+ display: block;
+ color: #716b7a;
+ padding: 5px 20px;
+}
+
+ .bs-sidebar .nav > li > a:hover,
+ .bs-sidebar .nav > li > a:focus {
+ text-decoration: none;
+ background-color: #e5e3e9;
+ border-right: 1px solid #dbd8e0;
+ }
+
+.bs-sidebar .nav > .active > a,
+.bs-sidebar .nav > .active:hover > a,
+.bs-sidebar .nav > .active:focus > a {
+ font-weight: bold;
+ color: #563d7c;
+ background-color: transparent;
+ border-right: 1px solid #563d7c;
+}
+
+/* Nav: second level (shown on .active) */
+.bs-sidebar .nav .nav {
+ display: none; /* Hide by default, but at >768px, show it */
+ margin-bottom: 8px;
+}
+
+ .bs-sidebar .nav .nav > li > a {
+ padding-top: 3px;
+ padding-bottom: 3px;
+ padding-left: 30px;
+ font-size: 90%;
+ }
+
+/* Show and affix the side nav when space allows it */
+@media (min-width: 992px) {
+ .bs-sidebar .nav > .active > ul {
+ display: block;
+ }
+ /* Widen the fixed sidebar */
+ .bs-sidebar.affix,
+ .bs-sidebar.affix-bottom {
+ width: 213px;
+ }
+
+ .bs-sidebar.affix {
+ position: fixed; /* Undo the static from mobile first approach */
+ top: 80px;
+ }
+
+ .bs-sidebar.affix-bottom {
+ position: absolute; /* Undo the static from mobile first approach */
+ }
+
+ .bs-sidebar.affix-bottom .bs-sidenav,
+ .bs-sidebar.affix .bs-sidenav {
+ margin-top: 0;
+ margin-bottom: 0;
+ }
+}
+
+@media (min-width: 1200px) {
+ /* Widen the fixed sidebar again */
+ .bs-sidebar.affix-bottom,
+ .bs-sidebar.affix {
+ width: 263px;
+ }
+}
+
+
+/* Not enough room on mobile for markup tab, js tab, and plunk btn.
+ And no one cares about plunk button on a phone anyway */
+@media only screen and (max-device-width: 480px) {
+ #plunk-btn {
+ display: none;
+ }
+}
+
+.navbar-nav .dropdown .navbar-brand {
+ max-width: 100%;
+ margin-right: inherit;
+ margin-left: inherit;
+}
+
+.header-placeholder {
+ height: 50px;
+}
+
+@media screen and (min-width: 768px) {
+
+ .dropdown.open > .navbar-brand + .dropdown-menu {
+ left: 10px;
+ }
+
+ .header-placeholder {
+ height: 50px;
+ }
+
+ .navbar-nav .dropdown .navbar-brand {
+ max-width: 200px;
+ margin-right: 5px;
+ margin-left: 10px;
+ }
+}
diff --git a/ecomp-portal-FE/client/bower_components/ui-select/docs/assets/plunkr.js b/ecomp-portal-FE/client/bower_components/ui-select/docs/assets/plunkr.js
new file mode 100644
index 00000000..deee25ed
--- /dev/null
+++ b/ecomp-portal-FE/client/bower_components/ui-select/docs/assets/plunkr.js
@@ -0,0 +1,110 @@
+angular.module('plunkr', [])
+.factory('formPostData', ['$document', function ($document) {
+ return function (url, newWindow, fields) {
+ /**
+ * If the form posts to target="_blank", pop-up blockers can cause it not to work.
+ * If a user choses to bypass pop-up blocker one time and click the link, they will arrive at
+ * a new default plnkr, not a plnkr with the desired template. Given this undesired behavior,
+ * some may still want to open the plnk in a new window by opting-in via ctrl+click. The
+ * newWindow param allows for this possibility.
+ */
+ var target = newWindow ? '_blank' : '_self';
+ var form = angular.element('<form style="display: none;" method="post" action="' + url + '" target="' + target + '"></form>');
+ angular.forEach(fields, function (value, name) {
+ var input = angular.element('<input type="hidden" name="' + name + '">');
+ input.attr('value', value);
+ form.append(input);
+ });
+ $document.find('body').append(form);
+ form[0].submit();
+ form.remove();
+ };
+}])
+
+
+.directive('plnkrOpener', ['$q', 'getExampleData', 'formPostData', function ($q, getExampleData, formPostData) {
+ return {
+ scope: {},
+ bindToController: {
+ 'examplePath': '@'
+ },
+ controllerAs: 'plnkr',
+ template: '<button ng-click="plnkr.open($event)" class="btn btn-info btn-sm plunk-btn"> <i class="glyphicon glyphicon-edit">&nbsp;</i> Edit in Plunker</button> ',
+ controller: [function () {
+ var ctrl = this;
+
+ ctrl.prepareExampleData = function (examplePath) {
+ if (ctrl.prepared) {
+ return $q.when(ctrl.prepared);
+ } else {
+ return getExampleData(examplePath).then(function (data) {
+ ctrl.prepared = data;
+ });
+ }
+ };
+
+ ctrl.open = function (clickEvent) {
+
+ var newWindow = clickEvent.ctrlKey || clickEvent.metaKey;
+ var postData = {
+ 'tags[0]': "angularjs",
+ 'tags[1]': "ui-select",
+ 'private': true
+ };
+
+ // Make sure the example data is available.
+ // If an XHR must be made, this might break some pop-up blockers when
+ // new window is requested
+ ctrl.prepareExampleData(ctrl.examplePath)
+ .then(function () {
+ angular.forEach(ctrl.prepared, function (file) {
+ postData['files[' + file.name + ']'] = file.content;
+ });
+
+ postData.description = "Angular ui-select http://github.com/angular-ui/ui-select/";
+
+ formPostData('http://plnkr.co/edit/?p=preview', newWindow, postData);
+ });
+ };
+
+ // Initialize the example data, so it's ready when clicking the open button.
+ // Otherwise pop-up blockers will prevent a new window from opening
+ ctrl.prepareExampleData(ctrl.examplePath);
+ }]
+ };
+}])
+
+.factory('getExampleData', ['$http', '$q', function ($http, $q) {
+ return function (exampleFile) {
+ // Load the manifest for the example
+ var defaultFiles = {
+ 'demo.js': './assets/',
+ 'select.css': './dist',
+ 'select.js': './dist'
+ };
+ files = angular.copy(defaultFiles);
+ files[exampleFile] = './';
+
+ var filePromises = [];
+
+ angular.forEach(files, function (folder, filename) {
+ filePromises.push($http.get(folder + '/' + filename, { transformResponse: [], cache: true })
+ .then(function (response) {
+
+ var content = response.data;
+ // Should only be one html (the example)
+ if (filename.match(/.html$/)) {
+ filename = "index.html";
+ content = content.replace(/.\/assets\//g, './').replace(/.\/dist\//g, './');
+ }
+
+ return {
+ name: filename,
+ content: content
+ };
+ }));
+ });
+
+ return $q.all(filePromises);
+ };
+}]);
diff --git a/ecomp-portal-FE/client/bower_components/ui-select/docs/index.html b/ecomp-portal-FE/client/bower_components/ui-select/docs/index.html
new file mode 100644
index 00000000..734486bd
--- /dev/null
+++ b/ecomp-portal-FE/client/bower_components/ui-select/docs/index.html
@@ -0,0 +1,191 @@
+<!DOCTYPE html>
+<html lang="en" ng-app="ui.select.pages">
+<head>
+ <meta charset="utf-8">
+ <title>AngularJS ui-select</title>
+
+ <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.js"></script>
+ <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular-sanitize.js"></script>
+
+ <script src="./assets/app.js" type="text/javascript"></script>
+ <script src="./assets/plunkr.js" type="text/javascript"></script>
+
+ <!-- themes -->
+ <link rel="stylesheet" href="https://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.css">
+ <link rel="stylesheet" href="./assets/docs.css" />
+
+</head>
+
+<body>
+ <header class="navbar navbar-default navbar-fixed-top navbar-inner">
+ <div class="container">
+ <div class="navbar-header">
+ <button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#bs-example-navbar-collapse-3" ng-click="isCollapsed = !isCollapsed">
+ <span class="sr-only">Toggle navigation</span>
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ </button>
+ <a class="navbar-brand visible-xs" href="#">UI Select</a>
+ </div>
+ <nav class="hidden-xs">
+ <ul class="nav navbar-nav">
+ <a href="#top" role="button" class="navbar-brand">
+ UI Select
+ </a>
+ <li><a href="#getting_started">Getting started</a></li>
+ <li><a href="#documenation">Documentation</a></li>
+ <li><a href="#examples">Examples</a></li>
+ <!--<li class="dropdown" uib-dropdown>
+ <a role="button" class="dropdown-toggle" uib-dropdown-toggle>
+ Previous docs <b class="caret"></b>
+ </a>
+ <ul class="dropdown-menu">
+ <li ng-repeat="version in oldDocs">
+ <a ng-href="{{version.url}}">{{version.version}}</a>
+ </li>
+ </ul>
+ </li>-->
+ </ul>
+ </nav>
+ <nav class="visible-xs" uib-collapse="!isCollapsed">
+ <ul class="nav navbar-nav">
+ <li><a href="#getting_started" ng-click="isCollapsed = !isCollapsed">Getting started</a></li>
+ <li><a href="#directives_small" ng-click="isCollapsed = !isCollapsed">Directives</a></li>
+ </ul>
+ </nav>
+ </div>
+ </header>
+ <div class="header-placeholder"></div>
+ <div role="main">
+ <header class="bs-header text-center" id="overview">
+ <div class="container">
+
+ <h1>UI Select</h1>
+ <p>
+ A native <a href="http://angularjs.org">AngularJS</a> implementation of Select2/Selectize by the
+ <a href="http://angular-ui.github.io">AngularUI Team</a>
+ </p>
+
+ <p>
+ <a class="btn btn-outline-inverse btn-lg" href="https://github.com/angular-ui/ui-select"><i class="icon-github"></i>Code on Github</a>
+ <!--<button type="button" class="btn btn-outline-inverse btn-lg" ng-click="showDownloadModal()">
+ <i class="glyphicon glyphicon-download-alt"></i> Download <small>(<%= pkg.version%>)</small>
+ </button>-->
+ </p>
+ </div>
+ <div class="bs-social container">
+ <ul class="bs-social-buttons">
+ <li>
+ <iframe src="//ghbtns.com/github-btn.html?user=angular-ui&repo=ui-select&type=watch&count=true"
+ allowtransparency="true" frameborder="0" scrolling="0" width="110" height="20"></iframe>
+ </li>
+ <li>
+ <iframe src="//ghbtns.com/github-btn.html?user=angular-ui&repo=ui-select&type=fork&count=true"
+ allowtransparency="true" frameborder="0" scrolling="0" width="110" height="20"></iframe>
+ </li>
+ <li>
+ <a href="https://twitter.com/share" class="twitter-share-button"
+ data-hashtags="angularjs">Tweet</a>
+ <script>
+ !function (d, s, id) {
+ var js, fjs = d.getElementsByTagName(s)[0];
+ if (!d.getElementById(id)) {
+ js = d.createElement(s);
+ js.id = id;
+ js.src = "//platform.twitter.com/widgets.js";
+ fjs.parentNode.insertBefore(js, fjs);
+ }
+ }(document, "script", "twitter-wjs");</script>
+ </li>
+ <li>
+ <!-- Place this tag where you want the +1 button to render. -->
+ <div class="g-plusone" data-size="medium"></div>
+
+ <!-- Place this tag after the last +1 button tag. -->
+ <script type="text/javascript">
+ (function () {
+ var po = document.createElement('script');
+ po.type = 'text/javascript';
+ po.async = true;
+ po.src = 'https://apis.google.com/js/plusone.js';
+ var s = document.getElementsByTagName('script')[0];
+ s.parentNode.insertBefore(po, s);
+ })();
+ </script>
+ </li>
+ </ul>
+ </div>
+ </header>
+ <div class="container">
+ <div class="row">
+ <div class="col-md-12">
+ <section id="getting_started">
+ <div class="page-header">
+ <h1>Getting started</h1>
+ </div>
+ <h3>Dependencies</h3>
+ <p>
+ This repository contains a <strong>native AngularJS</strong> select directive based on
+ Bootstrap/Select2/Selectize's CSS. As a result no dependency on jQuery or 3rd-Party
+ JavaScript is required. The only <strong>required</strong> dependencies are:
+ </p>
+ <ul>
+ <li>
+ <a href="http://angularjs.org" target="_blank">AngularJS</a> (requires AngularJS 1.2.x or higher, tested with 1.5.3).
+ </li>
+ <li>
+ <a href="http://angularjs.org" target="_blank">Angular-Sanitze</a> (the version should match your version of angular.js).
+ </li>
+ <li>
+ The matching CSS for your the theme you wish to use:
+ <ul>
+ <li>Bootstrap</li>
+ <li>Select2</li>
+ <li>Selectize</li>
+ </ul>
+ </li>
+ </ul>
+
+ <h3>Installation</h3>
+ <h4>Install via npm</h4>
+ <pre>$ npm install ui-select</pre>
+ <h4>Install via bower</h4>
+ <pre>$ bower install angular-ui-select</pre>
+ <p>
+ As soon as you've got all the files downloaded and included in your page you just need to declare
+ a dependency on the <code>ui.select</code> <a href="http://docs.angularjs.org/guide/module">module</a>:<br>
+ <pre><code>angular.module('myModule', ['ui.select', 'ngSanitize']);</code></pre>
+ </p>
+
+ </section>
+ <section id="documenation">
+ <div class="page-header">
+ <h1>Documentation</h1>
+ </div>
+ <h3>Wiki</h3>
+ For up to date information please refer to the <a href="https://github.com/angular-ui/ui-select/wiki" target="_blank">Wiki</a>
+ <h3>FAQ</h3>
+ <p>Please check <a href="https://github.com/angular-ui/ui-select/wiki/FAQs" target="_blank">our FAQ section</a> for common problems / solutions.</p>
+ </section>
+ <section id="examples">
+ <div class="page-header">
+ <h1>Examples</h1>
+ </div>
+ <p>You can fork one of the plunkers from this page to see a working example of what is described here.</p>
+
+ <!-- INSERT EXAMPLES HERE -->
+ </section>
+ </div>
+ </div>
+ </div><!-- /.container -->
+ </div><!-- /.main -->
+ <footer class="footer">
+ <div class="container">
+ <p>Designed and built by all ui-select <a href="https://github.com/angular-ui/ui-select/graphs/contributors" target="_blank">contributors</a>.</p>
+ <p>Code licensed under <a href="https://github.com/angular-ui/ui-select/blob/master/LICENSE">MIT License</a>.</p>
+ <p><a href="https://github.com/angular-ui/ui-select/issues?state=open">Issues</a></p>
+ </div>
+ </footer>
+</body>
+</html> \ No newline at end of file
diff --git a/ecomp-portal-FE/client/bower_components/ui-select/docs/partials/_footer.html b/ecomp-portal-FE/client/bower_components/ui-select/docs/partials/_footer.html
new file mode 100644
index 00000000..308b1d01
--- /dev/null
+++ b/ecomp-portal-FE/client/bower_components/ui-select/docs/partials/_footer.html
@@ -0,0 +1,2 @@
+</body>
+</html>
diff --git a/ecomp-portal-FE/client/bower_components/ui-select/docs/partials/_header.html b/ecomp-portal-FE/client/bower_components/ui-select/docs/partials/_header.html
new file mode 100644
index 00000000..b6bb1e4b
--- /dev/null
+++ b/ecomp-portal-FE/client/bower_components/ui-select/docs/partials/_header.html
@@ -0,0 +1,64 @@
+<!DOCTYPE html>
+<html lang="en" ng-app="demo">
+<head>
+ <meta charset="utf-8">
+ <title>AngularJS ui-select</title>
+
+ <!--
+ IE8 support, see AngularJS Internet Explorer Compatibility http://docs.angularjs.org/guide/ie
+ For Firefox 3.6, you will also need to include jQuery and ECMAScript 5 shim
+ -->
+ <!--[if lt IE 9]>
+ <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.js"></script>
+ <script src="http://cdnjs.cloudflare.com/ajax/libs/es5-shim/2.2.0/es5-shim.js"></script>
+ <script>
+ document.createElement('ui-select');
+ document.createElement('ui-select-match');
+ document.createElement('ui-select-choices');
+ </script>
+ <![endif]-->
+
+ <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.js"></script>
+ <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular-sanitize.js"></script>
+
+ <!-- ui-select files -->
+ <script src="./dist/select.js"></script>
+ <link rel="stylesheet" href="./dist/select.css">
+
+ <script src="./assets/demo.js"></script>
+
+ <!-- themes -->
+ <link rel="stylesheet" href="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.css">
+ <link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/select2/3.4.5/select2.css">
+ <link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/selectize.js/0.8.5/css/selectize.default.css">
+ <!-- <link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/selectize.js/0.8.5/css/selectize.bootstrap2.css"> -->
+ <!--<link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/selectize.js/0.8.5/css/selectize.bootstrap3.css">-->
+
+ <style>
+ body {
+ padding: 15px;
+ }
+
+ .select2 > .select2-choice.ui-select-match {
+ /* Because of the inclusion of Bootstrap */
+ height: 29px;
+ }
+
+ .selectize-control > .selectize-dropdown {
+ top: 36px;
+ }
+ /* Some additional styling to demonstrate that append-to-body helps achieve the proper z-index layering. */
+ .select-box {
+ background: #fff;
+ position: relative;
+ z-index: 1;
+ }
+ .alert-info.positioned {
+ margin-top: 1em;
+ position: relative;
+ z-index: 10000; /* The select2 dropdown has a z-index of 9999 */
+ }
+ </style>
+</head>
+
+<body class="ng-cloak" ng-controller="DemoCtrl as ctrl">
diff --git a/ecomp-portal-FE/client/bower_components/ui-select/index.js b/ecomp-portal-FE/client/bower_components/ui-select/index.js
new file mode 100644
index 00000000..1625f861
--- /dev/null
+++ b/ecomp-portal-FE/client/bower_components/ui-select/index.js
@@ -0,0 +1,2 @@
+require('./dist/select.js');
+module.exports = 'ui.select';
diff --git a/ecomp-portal-FE/client/bower_components/ui-select/package.json b/ecomp-portal-FE/client/bower_components/ui-select/package.json
new file mode 100644
index 00000000..323e1508
--- /dev/null
+++ b/ecomp-portal-FE/client/bower_components/ui-select/package.json
@@ -0,0 +1,61 @@
+{
+ "name": "ui-select",
+ "main": "./index.js",
+ "author": "http://github.com/angular-ui/ui-select/graphs/contributors",
+ "homepage": "http://github.com/angular-ui/ui-select",
+ "repository": {
+ "url": "git://github.com/angular-ui/ui-select.git"
+ },
+ "style": "dist/select.css",
+ "version": "0.17.1",
+ "devDependencies": {
+ "angular": "^1.2.18",
+ "angular-mocks": "^1.2.18",
+ "angular-sanitize": "^1.2.18",
+ "conventional-changelog": "^0.5.3",
+ "conventional-recommended-bump": "0.0.3",
+ "del": "~0.1.1",
+ "event-stream": "~3.1.0",
+ "gulp": "^3.9.1",
+ "gulp-angular-templatecache": "^1.8.0",
+ "gulp-bump": "^1.0.0",
+ "gulp-conventional-changelog": "^0.7.0",
+ "gulp-concat": "^2.6.0",
+ "gulp-filenames": "^2.0.0",
+ "gulp-git": "^1.4.0",
+ "gulp-header": "^1.7.1",
+ "gulp-footer": "^1.0.5",
+ "gulp-jshint": "^2.0.0",
+ "gulp-load-plugins": "^1.1.0",
+ "gulp-minify-css": "^1.2.4",
+ "gulp-minify-html": "^1.0.6",
+ "gulp-plumber": "^0.6.3",
+ "gulp-replace": "^0.5.4",
+ "gulp-sourcemaps": "^1.6.0",
+ "gulp-tag-version": "^1.3.0",
+ "gulp-uglify": "^1.5.3",
+ "gulp-util": "^2.2.19",
+ "jquery": "~1.11",
+ "jshint": "^2.9.1",
+ "jshint-stylish": "~0.3.0",
+ "karma": "^0.12.16",
+ "karma-chrome-launcher": "^0.1.3",
+ "karma-firefox-launcher": "~0.1",
+ "karma-jasmine": "~0.2",
+ "karma-ng-html2js-preprocessor": "^0.1.0",
+ "karma-phantomjs-launcher": "~0.1.4",
+ "karma-coverage": "~0.2",
+ "run-sequence": "^1.1.5",
+ "title-case": "^1.1.2"
+ },
+ "scripts": {
+ "test": "gulp test"
+ },
+ "spm": {
+ "main": "dist/select.js",
+ "output": [
+ "dist/select.css"
+ ]
+ },
+ "license": "MIT"
+}