Refactor UI Build System (#3203)

* initial build trial, clean up awx/ui

* fix hardcoded refs to ng-toast, add jshint preloader

* remove browserify test

* update grunt-jshint -> jshint module loader, browser-sync, update dev targets to build-docker-machine & build-docker-cid, fix blocking tasks

* less autoprefixer

* sample build commands

* fix release build

* update README

* karma config stub

* webpack config for karma tests

* karma preview for shane

* fix build-docker-machine target

* karma+webpack test pipeline configuration, stub tests

* fix smart/job status icons classes

* fix jquery + jsyaml shims, fix LESS cascade

* fix angular-codemirror dependency, explicitly import style/mode dependencies

* shim jsonlint

* fix angular-scheduler AMD imports, remove jquuery-ui shim, fix release config

* use closed $.fn.datepicker for system-tracking

* remove packaging/node/

* remove old tests

* shrinkwrap fragile dependency sandcastle, update README, lint

* first pass at fixing rrule shim

* update makefile targets

* update gitignore w/ new flag file

* add saucelabs karma config

* add license controller test

* add examples of service and directive tests

* Makefile flubs

* consolidate clean-ui target, compulsively update flag file location

* dep on CJS/AMD/UMD compatible version of rrule lib, fix example tests/config for demo

* boilerplate karma config for saucelabs (should be abstracted to common config after proven to work)

* update docs

* docs feedback

* update Dockerfile with Node 6.x dep
This commit is contained in:
Leigh Johnson 2016-08-17 16:09:54 -04:00 committed by GitHub
parent d51edff8a8
commit ce61fe4a42
3676 changed files with 6254 additions and 663860 deletions

6
.gitignore vendored
View File

@ -45,14 +45,14 @@ __pycache__
/bower.json
/package.json
/testem.yml
/coverage
**/coverage
/.istanbul.yml
node_modules/**
**/node_modules/**
/tmp
npm-debug.log
# UI build debugging
/DEBUG
awx/ui/.deps_built
# Testing
.cache

205
Makefile
View File

@ -5,11 +5,6 @@ OFFICIAL ?= no
PACKER ?= packer
PACKER_BUILD_OPTS ?= -var 'official=$(OFFICIAL)' -var 'aw_repo_url=$(AW_REPO_URL)'
GRUNT ?= $(shell [ -t 0 ] && echo "grunt" || echo "grunt --no-color")
TESTEM ?= ./node_modules/.bin/testem
BROCCOLI_BIN ?= ./node_modules/.bin/broccoli
MOCHA_BIN ?= ./node_modules/.bin/_mocha
ISTANBUL_BIN ?= ./node_modules/.bin/istanbul
BROWSER_SYNC_BIN ?= ./node_modules/.bin/browser-sync
NODE ?= node
NPM_BIN ?= npm
DEPS_SCRIPT ?= packaging/bundle/deps.py
@ -19,8 +14,6 @@ VENV_BASE ?= /tower_devel/venv
SCL_PREFIX ?=
CELERY_SCHEDULE_FILE ?= /celerybeat-schedule
CLIENT_TEST_DIR ?= build_test
# Python packages to install only from source (not from binary wheels)
# Comma separated list
SRC_ONLY_PKGS ?= cffi
@ -177,13 +170,11 @@ endif
develop refresh adduser migrate dbchange dbshell runserver celeryd \
receiver test test_unit test_coverage coverage_html test_jenkins dev_build \
release_build release_clean sdist rpmtar mock-rpm mock-srpm rpm-sign \
build-ui sync-ui test-ui build-ui-for-coverage test-ui-for-coverage \
build-ui-for-browser-tests test-ui-debug jshint ngdocs \
websocket-proxy browser-sync browser-sync-reload brocolli-watcher \
devjs minjs testjs_ci \
deb deb-src debian debsign pbuilder reprepro setup_tarball \
virtualbox-ovf virtualbox-centos-7 virtualbox-centos-6 \
clean-bundle setup_bundle_tarball
clean-bundle setup_bundle_tarball \
ui-docker-machine ui-docker ui-release \
ui-test ui-test-ci ui-test-saucelabs
# Remove setup build files
clean-tar:
@ -197,11 +188,6 @@ clean-rpm:
clean-deb:
rm -rf deb-build reprepro
# Remove grunt build files
clean-grunt:
rm -f package.json Gruntfile.js Brocfile.js bower.json
rm -rf node_modules
# Remove packer artifacts
clean-packer:
rm -rf packer_cache
@ -218,19 +204,15 @@ clean-bundle:
# remove ui build artifacts
clean-ui:
rm -rf DEBUG
clean-static:
rm -rf awx/ui/static/
clean-build-test:
rm -rf awx/ui/build_test/
rm -rf awx/ui/node_modules/
rm -f awx/ui/.deps_built
clean-tmp:
rm -rf tmp/
# Remove temporary build files, compiled Python files.
clean: clean-rpm clean-deb clean-grunt clean-ui clean-static clean-build-test clean-tar clean-packer clean-bundle
clean: clean-rpm clean-deb clean-ui clean-tar clean-packer clean-bundle
rm -rf awx/lib/site-packages
rm -rf awx/lib/.deps_built
rm -rf dist/*
@ -472,170 +454,27 @@ test_jenkins : test_coverage
# UI TASKS
# --------------------------------------
# begin targets that pull ui files from packaging to the root of the app
Gruntfile.js: packaging/node/Gruntfile.js
cp $< $@
ui-deps-built: awx/ui/package.json
$(NPM_BIN) --prefix awx/ui install awx/ui
touch awx/ui/.deps_built
Brocfile.js: packaging/node/Brocfile.js
cp $< $@
ui-docker-machine: ui-deps-built
$(NPM_BIN) --prefix awx/ui run build-docker-machine
bower.json: packaging/node/bower.json
cp $< $@
ui-docker: ui-deps-built
$(NPM_BIN) --prefix awx/ui run build-docker-cid
package.json: packaging/node/package.template
sed -e 's#%NAME%#$(NAME)#;s#%VERSION%#$(VERSION)#;s#%GIT_REMOTE_URL%#$(GIT_REMOTE_URL)#;' $< > $@
ui-release: ui-deps-built
$(NPM_BIN) --prefix awx/ui run build-release
testem.yml: packaging/node/testem.yml
cp $< $@
ui-test: ui-deps-built
$(NPM_BIN) --prefix awx/ui run test
.istanbul.yml: packaging/node/.istanbul.yml
cp $< $@
# end targets that pull ui files from packaging to the root of the app
ui-test-ci: ui-deps-built
$(NPM_BIN) --prefix awx/ui run test:ci
# update package.json and install npm dependencies
node_modules: package.json
$(NPM_BIN) install
touch $@
# helper tasks to run broccoli build process at awx/ui/<destination_dir>,
# to build the ui, use the build-ui target instead:
# UI_FLAGS=<flags as seen in Brocfile.js and
# packaging/node/tower-app.js>: additional parameters to pass broccoli
# for building
awx/ui/static: node_modules clean-ui clean-static Brocfile.js bower.json
$(BROCCOLI_BIN) build awx/ui/static -- $(UI_FLAGS)
awx/ui/build_test: node_modules clean-ui clean-build-test Brocfile.js bower.json
$(BROCCOLI_BIN) build awx/ui/build_test -- $(UI_FLAGS)
# build the ui to awx/ui/static:
# defaults to standard dev build (concatenated, non-minified, sourcemaps, no
# tests)
# PROD=true: standard prod build (concatenated, minified, no sourcemaps,
# compressed, no tests)
# EXTRA_UI_FLAGS=<flags as seen in Brocfile.js and
# packaging/node/tower-app.js>: additional parameters to pass broccoli
# for building
PROD ?= false
# TODO: Remove after 2.4 (alias for devjs/minjs)
devjs: build-ui
minjs: build-ui
ifeq ($(MAKECMDGOALS),minjs)
PROD = true
endif
ifeq ($(PROD),true)
UI_FLAGS=--silent --compress --no-docs --no-debug --no-sourcemaps \
$(EXTRA_UI_FLAGS)
else
UI_FLAGS=$(EXTRA_UI_FLAGS)
endif
build-ui: awx/ui/static
# launch watcher to continuously build the ui to awx/ui/static and run tests
# after changes are made:
# WATCHER_FLAGS: options to be utilized by broccoli timepiece
# UI_FLAGS=<flags as seen in Brocfile.js and
# packaging/node/tower-app.js>: additional parameters to pass broccoli
# for building
# DOCKER_MACHINE_NAME=<name of docker-machine tower is running on>: when
# passed, not only will brocolli rebuild, but browser-sync will proxy
# proxy tower and refresh the ui when a change is made.
DOCKER_MACHINE_NAME ?= none
ifeq ($(DOCKER_MACHINE_NAME),none)
sync-ui: node_modules clean-tmp brocolli-watcher
else
sync-ui: node_modules clean-tmp
tmux new-session -d -s ui_sync 'exec make brocolli-watcher'
tmux rename-window 'UI Sync'
tmux select-window -t ui_sync:0
tmux split-window -v 'exec make browser-sync'
tmux split-window -h 'exec make websocket-proxy'
tmux select-layout main-vertical
tmux attach-session -t ui_sync
endif
websocket-proxy:
docker-machine ssh $(DOCKER_MACHINE_NAME) -L 8080:localhost:8080
browser-sync:
$(BROWSER_SYNC_BIN) start --proxy $(shell docker-machine ip $(DOCKER_MACHINE_NAME)):8013 --ws
browser-sync-reload:
$(BROWSER_SYNC_BIN) reload
brocolli-watcher: Brocfile.js testem.yml
$(NODE) tools/ui/timepiece.js awx/ui/static $(WATCHER_FLAGS) -- $(UI_FLAGS)
# run ui unit-tests:
# defaults to a useful dev testing run. Builds the ui to awx/ui/build_test
# and runs mocha (node.js) tests with istanbul coverage (and an html
# coverage report)
# UI_TESTS_TO_RUN=<file>-test.js: Set this to only run a specific test file
# CI=true: Builds the ui to awx/ui/build_test
# and runs mocha (node.js) tests with istanbul coverage (and a cobertura
# coverage report). Also builds the ui to awx/ui/static and runs the
# testem (phantomjs) tests. Outputs these to XUNIT format to be consumed
# and displayed in jenkins
# DEBUG=true: Builds the ui to awx/ui/static and runs testem tests in Chrome
# so you can breakpoint the tests and underlying code to figure out why
# tests are failing.
# TESTEM_DEBUG_BROWSER: the browser to run tests in, default to Chrome
# TODO: deprecated past 2.4
testjs_ci: test-ui # w var UI_TEST_MODE=CI
UI_TEST_MODE ?= DEV
ifeq ($(UI_TEST_MODE),CI)
# ci testing run
# this used to be testjs_ci, sort-of
REPORTER = xunit
test-ui: .istanbul.yml build-ui-for-coverage test-ui-for-coverage
else
ifeq ($(UI_TEST_MODE),DEV_DEBUG)
# debug (breakpoint) dev testing run
test-ui: build-ui-for-browser-tests test-ui-debug
else
# default dev testing run
test-ui: .istanbul.yml build-ui-for-coverage test-ui-for-coverage
endif
endif
# helper tasks to test ui, don't call directly
build-ui-for-coverage: UI_FLAGS=--node-tests --no-concat --no-styles
build-ui-for-coverage: awx/ui/build_test
REPORTER ?= standard
UI_TESTS_TO_RUN ?= all
ifeq ($(REPORTER), xunit)
test-ui-for-coverage:
XUNIT_FILE=reports/test-results-ui.xml NODE_PATH=awx/ui/build_test $(ISTANBUL_BIN) cover --include-all-sources $(MOCHA_BIN) -- --full-trace --reporter xunit-file $(shell find awx/ui/build_test -name '*-test.js'); cp coverage/ui-coverage-report.xml reports/coverage-report-ui.xml
else
ifeq ($(UI_TESTS_TO_RUN), all)
test-ui-for-coverage:
NODE_PATH=awx/ui/build_test $(ISTANBUL_BIN) cover --include-all-sources $(MOCHA_BIN) -- --full-trace $(shell find awx/ui/build_test -name '*-test.js')
else
test-ui-for-coverage:
NODE_PATH=awx/ui/build_test $(ISTANBUL_BIN) cover $(MOCHA_BIN) -- --full-trace $(shell find awx/ui/build_test -name '$(UI_TESTS_TO_RUN)')
endif
endif
build-ui-for-browser-tests: UI_FLAGS=--no-styles --no-compress --browser-tests --no-node-tests
build-ui-for-browser-tests: awx/ui/static
TESTEM_DEBUG_BROWSER ?= Chrome
test-ui-debug:
PATH=./node_modules/.bin:$(PATH) $(TESTEM) --file testem.yml -l $(TESTEM_DEBUG_BROWSER)
# lint .js files
jshint: node_modules Gruntfile.js
$(GRUNT) $@
# generate ui docs
ngdocs: build-ui Gruntfile.js
$(GRUNT) $@
ui-test-saucelabs: ui-deps-built
$(NPM_BIN) --prefix awx/ui run test:saucelabs
# END UI TASKS
# --------------------------------------
@ -676,7 +515,7 @@ release_clean:
-(rm *.tar)
-(rm -rf ($RELEASE))
dist/$(SDIST_TAR_FILE): minjs
dist/$(SDIST_TAR_FILE): ui-release
BUILD="$(BUILD)" $(PYTHON) setup.py sdist
sdist: dist/$(SDIST_TAR_FILE)

3
awx/ui/.babelrc Normal file
View File

@ -0,0 +1,3 @@
{
"presets": ["es2015"]
}

41
awx/ui/.jshintrc Normal file
View File

@ -0,0 +1,41 @@
{
"browser": true,
"jquery": true,
"esnext": true,
"globalstrict": true,
"curly": true,
"immed": true,
"latedef": "nofunc",
"noarg": true,
"nonew": true,
"maxerr": 10000,
"notypeof": true,
"globals": {
"beforeEach": false,
"inject": false,
"module": false,
"angular":false,
"alert":false,
"$AnsibleConfig":true,
"$basePath":true,
"jsyaml":false,
"_":false,
"d3":false,
"Donut3D":false,
"nv":false,
"it": false,
"xit": false,
"expect": false,
"context": false,
"describe": false,
"moment": false
},
"strict": false,
"quotmark": false,
"trailing": true,
"undef": true,
"unused": true,
"eqeqeq": true,
"indent": 4,
"newcap": false
}

34
awx/ui/Gruntfile.js Normal file
View File

@ -0,0 +1,34 @@
module.exports = function(grunt) {
// Load grunt tasks & configurations automatically from dir grunt/
require('load-grunt-tasks')(grunt);
// display task timings
require('time-grunt')(grunt);
var options = {
config: {
src: './grunt-tasks/*.js'
},
pkg: grunt.file.readJSON('package.json')
};
var configs = require('load-grunt-configs')(grunt, options);
// Project configuration.
grunt.initConfig(configs);
grunt.loadNpmTasks('grunt-newer');
// writes environment variables for development. current manages:
// browser-sync + websocket proxy
grunt.registerTask('dev', [
'clean:static',
'concurrent:dev',
'browserSync:http',
'concurrent:watch'
]);
grunt.registerTask('release', [
'webpack:prod',
'concurrent:prod',
]);
};

View File

@ -1,30 +1,142 @@
Ansible UI
==========
The user interface to Ansible Commander
### Table of Contents
1. [Requirements](#requirements)
2. [Usage](#usage)
3. [Testing](#testing)
4. [Adding new dependencies](#deps)
5. [Using libraries without modular exports/depedency management](#polyfill)
6. [Environment configuration](#environment)
7. [NPM scripts](#scripts)
Installation
------------
### <a name="requirements">Requirements</a>
FIXME: Update the instructions below.
* A supported version of node + npm, constrained in `package.json`.
```json
"engines": {
"node": "^6.3.1",
"npm": "^3.10.3"
}
```
* C/C++ compiler tools, like GCC. Bundled in [Command Line Tools for Xcode](https://developer.apple.com/xcode/)
* [node-gyp](https://github.com/nodejs/node-gyp)
```
npm install -g node-gyp
```
To use the UI you will first need to complete the installation of Ansible Commander. Within
Ansbile Commander you should be able to start the server (make runserver) and log into the
admin console. If that all works, then you are ready to install Ansible UI.
### <a name="usage">Usage</a>
For now the UI runs under the django server installed with Commander. If you are planning to
do development, do NOT pull a copy of UI into the same directory structure as Commander. In
other words, for development the UI should not be insalled as a subdirectory of Commander.
The following Makefile targets are available from the root dir of `ansible-tower`
Once you have obtained a copy of UI, create a symbolic link within the Commander lib/static
directory that points to the app subdirectory under ansible-ui. Call the link web:
**Native Docker**
Specify the container ID of a `tools_tower` instance.
`DOCKER_CID=containerID make ui-docker-cid`
cd ~/ansible-commander/lib/static
ln -s ../../../ansible-ui/app web
**Docker Machine**
Specify the name of a docker-machine.
`DOCKER_MACHINE_NAME=default make ui-docker-machine`
With the Ansible Commander server running, you should now be able to access the UI:
Build a minified/uglified **release candidate**
`make ui-release`
http://127.0.0.1:8013/static/web/index.html
### <a name="testing">Testing</a>
You will be immediately prompted for to log in. User your Commander superuser credientials.
Run unit tests locally, poll for changes to both source and test files, launch tests in supported browser engines:
`make ui-test`
Run unit tests in a CI environment (Jenkins)
`make ui-test-ci`
Run Protractor (E2E) tests in Saucelabs:
`make ui-test-saucelabs`
### <a name="deps">Adding new dependencies</a>
From the root dir of `ansible-tower`:
#### Add/update a bundled vendor dependency
1. `npm install --prefix awx/ui --save some-frontend-package@1.2.3`
2. Add `'some-package'` to `var vendorFiles` in `./grunt-tasks/webpack.js`
3. `npm --prefix awx/ui shrinkwrap` to freeze current dependency resolution
#### Add/update a dependecy in the build/test pipeline:
1. `npm install --prefix awx/ui --save-dev some-toolchain-package@1.2.3`
2. `npm --prefix awx/ui shrinkwrap` to freeze current dependency resolution
### <a name="polyfill">Polyfills, shims, patches</a>
The Webpack pipeline will prefer module patterns in this order: CommonJS, AMD, UMD. For a comparison of supported patterns, refer to [https://webpack.github.io/docs/comparison.html](Webpack's docs).
Some javascript libraries do not export their contents as a module, or depend on other third-party components. If the library maintainer does not wrap their lib in a factory that provides a CommonJS or AMD module, you will need to provide dependencies with a shim.
1. Shim implicit dependencies using Webpack's [ProvidePlugin](https://github.com/webpack/webpack/blob/006d59500de0493c4096d5d4cecd64eb12db2b95/lib/ProvidePlugin.js). Example:
```js
// Tower source code depends on the lodash library being available as _
_.uniq([1,2,3,1]) // will throw error undefined
```
```js
// webpack.config.js
plugins: [
new webpack.ProvidePlugin({
'_': 'lodash',
})
]
```
```js
// the following requirement is inserted by webpack at build time
var _ = require('lodash');
_.uniq([1,2,3,1])
```
2. Use [`imports-loader`](https://webpack.github.io/docs/shimming-modules.html#importing) to inject requirements into the namespace of vendor code at import time. Use [`exports-loader`](https://webpack.github.io/docs/shimming-modules.html#exporting) to conventionally export vendor code lacking a conventional export pattern.
3. [Apply a functional patch](https://gist.github.com/leigh-johnson/070159d3fd780d6d8da6e13625234bb3). A webpack plugin is the correct choice for a functional patch if your patch needs to access events in a build's lifecycle. A webpack loader is preferable if you need to compile and export a custom pattern of library modules.
4. [Submit patches to libraries without modular exports](https://github.com/leigh-johnson/ngToast/commit/fea95bb34d27687e414619b4f72c11735d909f93) - the internet will thank you
Some javascript libraries might only get one module pattern right.
### <a name="environment">Environment configuration</a> - used in development/test builds
Build tasks are parameterized with environment variables.
`package.json` contains default environment configuration. When `npm run myScriptName` is executed, these variables will be exported to your environment with the prefix `npm_package_config_`. For example, `my_variable` will be exported to `npm_package_config_my_variable`.
Environment variables can accessed in a Javascript via `PROCESS.env`.
``` json
"config": {
"django_port": "8013",
"websocket_port": "8080",
"django_host": "0.0.0.0"
}
```
Example usage in `npm run build-docker-machine`:
```bash
docker-machine ssh $DOCKER_MACHINE_NAME -f -N -L ${npm_package_config_websocket_port}:localhost:${npm_package_config_websocket_port}; ip=$(docker-machine ip $DOCKER_MACHINE_NAME); echo npm set ansible-tower:django_host ${ip}; grunt dev
```
Example usage in an `npm test` script target:
```bash
npm_package_config_websocket_port=mock_websocket_port npm_package_config_django_port=mock_api_port npm_package_config_django_host=mock_api_host npm run test:someMockIntegration
```
You'll usually want to pipe and set vars prior to running a script target:
```bash
npm set ansible-tower:websocket_host ${mock_host}; npm run script-name
```
### <a name="scripts">NPM Scripts</a>
Examples:
```json
"scripts": {
"pretest": "echo I run immediately before 'npm test' executes",
"posttest": "echo I run immediately after 'npm test' exits",
"test": "karma start karma.conf.js"
}
```
`npm test` is an alias for `npm run test`. Refer to [script field docs](https://docs.npmjs.com/misc/scripts) for a list of other runtime events.

View File

@ -1,6 +0,0 @@
TODO
====
* mpd - figure out way to mark each object generically with whether it can be edited/administrated/etc
* mpd - enable generic filtering, look into sorting

View File

@ -1,97 +0,0 @@
Mockups
=======
Goals/priority:
Organizations
Inventory
Groups
Hosts
Subgroup
Host variable
Group variable
Jobs and Job Results
Credentials
Projects
Teams
Permissions
Later/Roadmap:
Rich Editing
Just conceptual stuff prior to using Balsamiq.
Login
username:
password:
When log in, menu options:
organizations
projects
teams
credentials
Organization tab:
[if admin, plus sign for add ? ]
org1 [ if admin, delete ]
org2
org3
Organizations detail:
[ see all properties ]
[ click to edit some of them if admin ]
[ if org admin, + project to organization ]
[ + add a user ]
[ + add more admins ]
Projects details:
(projects are created from the organization detail page)
Teams:
add users / remove users
Users:
add remove/users
Credentials:
Permissions:
Jobs:
Inventory View:
| Groups
+--+ Subgroup <----------------- click on this
+----- subgroup
see hosts in group that was selected above, (directly?)
MPD: may need to add a way to see all child hosts of a given group in API
/api/v1/groups/N/all_hosts
if no group is selected, use /api/v1/hosts/
[ Group selector ] [ edit link ] [ delete link (if no kids?) ]
[ Host list ] [ edit link ] [ delete link ]
tree of list of
GROUPS | HOSTS
x | asdf
x | jkl
x | foo
x |
x |

View File

@ -1,18 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="55px" height="42px" viewBox="0 0 55 42" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
<!-- Generator: Sketch 3.2.1 (9971) - http://www.bohemiancoding.com/sketch -->
<title>CloudSync</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Random" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
<g id="CloudSync" sketch:type="MSArtboardGroup">
<path d="M36.5409477,41.6578074 L12.4747864,41.6578074 C6.89348782,41.6461935 3.50985601,33.2876501 3.36842952,27.7211977 C3.26430016,23.6227358 6.26813909,15.5700299 10.0264222,15.5700299 C9.70161873,12.3219956 10.948769,10.0564324 12.3414111,8.65446838 C13.2507957,7.73899662 17.0285665,6.38049299 19.1816026,8.01701681 C21.2839677,1.96620547 25.6993475,5.24541679e-16 30.8987811,0 C35.2156363,0 43.5,7 43.7135366,15.5615059 C43.7181702,15.7472848 43.6975201,15.9215349 43.6941483,16.1073564 C48,14.5 51.7748589,24.4637093 51.9373048,28.8825819 C51.9508956,29.2522799 51.9403411,29.6492134 51.9066002,30.0662646 L35.1799171,30.0662646 C37.1702823,28.1641294 38.4094561,25.4893251 38.4094561,22.5269709 L36.0752456,22.5269709 C36.0752456,25.9348632 33.9567709,28.8595257 30.9621356,30.0662646 L29.3683589,30.0662646 L29.3683589,30.5260875 C28.8936038,30.6118601 28.4047036,30.6566599 27.905509,30.6566599 C23.4004827,30.6566599 19.7357723,27.0099137 19.7357723,22.5269709 C19.7357723,18.0440282 23.4004827,14.397282 27.905509,14.397282 L27.905509,18.6944033 L36.689143,13.6423823 L27.905509,8.59036132 L27.905509,12.0745137 C22.1038288,12.0745137 17.4015618,16.7548918 17.4015618,22.5269709 C17.4015618,28.2990501 22.1038288,32.9794281 27.905509,32.9794281 C28.4019007,32.9794281 28.890272,32.9451378 29.3683589,32.8788075 L29.3683589,41.6578074 L36.5409477,41.6578074 Z" id="CloudSync-cloud" fill="#242424" sketch:type="MSShapeGroup"></path>
<g id="CloudSync-server" sketch:type="MSLayerGroup" transform="translate(29.891633, 31.140060)">
<path d="M20.4481279,7.51656615 C21.0411686,7.51656615 21.5219231,7.03581168 21.5219231,6.44277099 C21.5219231,5.84973029 21.0411686,5.36897582 20.4481279,5.36897582 C19.8550872,5.36897582 19.3743328,5.84973029 19.3743328,6.44277099 C19.3743328,7.03581168 19.8550872,7.51656615 20.4481279,7.51656615 Z M0.0460197928,0.241603912 L23.6695134,0.241603912 L23.6695134,9.58362184 L0.0460197928,9.58362184 L0.0460197928,0.241603912 Z M1.07379516,1.07379516 L22.5496985,1.07379516 L22.5496985,8.59036132 L1.07379516,8.59036132 L1.07379516,1.07379516 Z" id="CloudSync-server-enclosure" fill="#242424" sketch:type="MSShapeGroup"></path>
<rect id="CloudSync-server-light3" fill="#27AB45" sketch:type="MSShapeGroup" x="2.14759033" y="2.14759033" width="2.14759033" height="2.14759033"></rect>
<rect id="CloudSync-server-light2" fill="#E54242" sketch:type="MSShapeGroup" x="5.36897582" y="2.14759033" width="2.14759033" height="2.14759033"></rect>
<rect id="CloudSync-server-light1" fill="#27AB45" sketch:type="MSShapeGroup" x="8.59036132" y="2.14759033" width="2.14759033" height="2.14759033"></rect>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.3 KiB

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="55px" height="42px" viewBox="0 0 55 42" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
<!-- Generator: Sketch 3.2.1 (9971) - http://www.bohemiancoding.com/sketch -->
<title>Credentials</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Credentials">
<path d="M18.425,10.5 C18.425,5.60538462 22.4972,1.61538462 27.50165,1.61538462 C32.505275,1.61538462 36.575,5.60538462 36.575,10.5 L36.575,20.1923077 L18.425,20.1923077 L18.425,10.5 L18.425,10.5 Z M38.225,20.1923077 L38.225,10.5 C38.225,4.70076923 33.4235,0 27.50165,0 C21.57815,0 16.775,4.70076923 16.775,10.5 L16.775,20.1923077 L11,20.1923077 L11,42 L44,42 L44,20.1923077 L38.225,20.1923077 L38.225,20.1923077 Z"></path>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 898 B

View File

@ -1,15 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="55px" height="42px" viewBox="0 0 55 42" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
<!-- Generator: Sketch 3.2.1 (9971) - http://www.bohemiancoding.com/sketch -->
<title>InventoryScripts</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Random" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
<g id="InventoryScripts" sketch:type="MSArtboardGroup" fill="#FFFFFF">
<path d="M18.069332,19.643368 C15.4291803,19.643368 13.289335,17.5029916 13.289335,14.863371 C13.289335,12.2237504 15.4291803,10.0833739 18.069332,10.0833739 L18.069332,8.49004158 L22.0664718,10.8003735 L18.069332,13.1107054 L18.069332,11.1455955 C16.0192444,11.1455955 14.3515566,12.8132834 14.3515566,14.863371 C14.3515566,16.9134586 16.0192444,18.5811465 18.069332,18.5811465 C20.1188886,18.5811465 21.7871075,16.9134586 21.7871075,14.863371 L22.8493291,14.863371 C22.8493291,17.5029916 20.7084215,19.643368 18.069332,19.643368 L18.069332,19.643368 Z M23.1386641,23.3611435 L8.50668238,23.3611435 C4.99019788,23.3611435 2.13866408,20.5090786 2.13866408,16.9878141 C2.13866408,14.1941714 3.9423163,11.8254173 6.44650364,10.9650178 C6.78641455,8.95741907 8.52845792,7.42782001 10.6311255,7.42782001 C11.3162584,7.42782001 11.961558,7.59246435 12.5346266,7.88457528 C13.859748,5.11217699 16.6799462,3.19486706 19.9558375,3.19486706 C24.502677,3.19486706 28.1880547,6.8807759 28.1880547,11.4270842 C28.1880547,11.5120619 28.1779636,11.5970397 28.1758391,11.6767063 C29.6866205,11.6816924 31.0623568,12.2600933 32.0969473,13.2053689 L23.1386641,13.2053689 L23.1386641,23.3611435 Z" id="Fill-87" sketch:type="MSShapeGroup"></path>
<path d="M35.6964491,18.9938144 L33.022193,16 L34.2563702,16 L36.9528193,18.9938144 L34.2563702,22 L33,22 L35.6964491,18.9938144 Z" id="&gt;" sketch:type="MSShapeGroup"></path>
<path d="M26.6964491,18.9938144 L24.022193,16 L25.2563702,16 L27.9528193,18.9938144 L25.2563702,22 L24,22 L26.6964491,18.9938144 Z" id="&gt;-2" sketch:type="MSShapeGroup" transform="translate(25.976410, 19.000000) scale(-1, -1) translate(-25.976410, -19.000000) "></path>
<path d="M32.4528193,15 L29.9528193,23 L28.9528193,23 L31.4528193,15 L32.4528193,15 Z" id="" sketch:type="MSShapeGroup"></path>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -1,16 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="55px" height="42px" viewBox="0 0 55 42" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
<!-- Generator: Sketch 3.2.1 (9971) - http://www.bohemiancoding.com/sketch -->
<title>JobTemplates</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Random" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
<g id="JobTemplates" sketch:type="MSArtboardGroup" fill="#000000">
<path d="M40.2101242,8.2287313 C40.2101242,9.59161492 39.1043885,10.6973507 37.7415048,10.6973507 C36.3786212,10.6973507 35.2728854,9.59161492 35.2728854,8.2287313 C35.2728854,6.86584768 36.3786212,5.76011191 37.7415048,5.76011191 C39.1043885,5.76011191 40.2101242,6.86584768 40.2101242,8.2287313 L40.2101242,8.2287313 Z M30.4233577,36.7724078 L21.6954788,41.8636705 C21.5669049,41.9408148 21.438331,41.9665296 21.2840422,41.9665296 C21.078324,41.9665296 20.8726057,41.8893853 20.6926022,41.7350966 L19.0468559,40.0893503 C18.8411376,39.8579172 18.7639933,39.5493398 18.8411376,39.2664772 L21.0268944,32.1691964 L13.8010397,24.9433417 L6.70375897,27.1290985 C6.62661462,27.1548133 6.54947026,27.1548133 6.47232591,27.1548133 C6.26660762,27.1548133 6.03517456,27.0776689 5.88088584,26.9233802 L4.23513958,25.277634 C3.97799173,24.9947713 3.92656216,24.5833348 4.10656566,24.2747573 L9.86667757,14.4002798 C10.0209663,14.1688467 10.2781141,14.014558 10.535262,13.9888432 L20.2811656,13.4745475 C21.8240527,11.6487977 23.3412251,9.95162191 24.8069678,8.46016437 C31.2356642,2.05718282 36.1471881,0 45.0959334,0 C45.5587996,0 45.9702361,0.360006994 45.9702361,0.82287313 C45.9702361,9.36018185 43.6044759,15.0431494 37.5100718,21.1632683 C36.2836771,22.3685182 34.9181875,23.6085419 33.4564934,24.8690424 L30.4233577,24.8690425 L30.4233577,36.7724078 Z" id="Type-something-2" sketch:type="MSShapeGroup"></path>
<g id="Fill-78-+-Fill-79" sketch:type="MSLayerGroup" transform="translate(31.977673, 26.613090)">
<path d="M5.54883514,0 L5.54883514,4.66294547 L9.95555917,4.66294547 L5.54883514,0" id="Fill-78" sketch:type="MSShapeGroup"></path>
<path d="M5.000198,5.24901943 L5.000198,0 L0.591270607,0 L0.591270607,13.9888364 L10.2309794,13.9888364 L10.2309794,5.24901943 L5.000198,5.24901943" id="Fill-79" sketch:type="MSShapeGroup"></path>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.5 KiB

View File

@ -1,13 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="55px" height="42px" viewBox="0 0 55 42" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
<!-- Generator: Sketch 3.2.1 (9971) - http://www.bohemiancoding.com/sketch -->
<title>Jobs</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Random" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
<g id="Jobs" sketch:type="MSArtboardGroup" fill="#000000">
<path d="M41.8479074,8.1469495 C41.8479074,9.49629019 40.7531593,10.5910383 39.4038186,10.5910383 C38.054478,10.5910383 36.9597298,9.49629019 36.9597298,8.1469495 C36.9597298,6.79760882 38.054478,5.70286072 39.4038186,5.70286072 C40.7531593,5.70286072 41.8479074,6.79760882 41.8479074,8.1469495 L41.8479074,8.1469495 Z M30.6195217,37.3046624 L23.5172415,41.4476592 C23.3899452,41.524037 23.262649,41.5494962 23.1098934,41.5494962 C22.9062193,41.5494962 22.7025453,41.4731185 22.5243305,41.3203629 L20.8949379,39.6909704 C20.6912639,39.4618371 20.6148861,39.156326 20.6912639,38.8762741 L22.8553008,31.8495189 L15.7012493,24.6954673 L8.67449402,26.8595043 C8.59811624,26.8849635 8.52173847,26.8849635 8.44536069,26.8849635 C8.24168663,26.8849635 8.01255331,26.8085857 7.85979776,26.6558302 L6.23040523,25.0264377 C5.97581265,24.7463858 5.92489414,24.3390377 6.10310894,24.0335266 L11.8059828,14.2571715 C11.9587383,14.0280381 12.2133309,13.8752826 12.4679235,13.8498233 L22.1169823,13.3406382 C23.6445378,11.5330308 25.1466341,9.8527198 26.5978118,8.37608283 C32.9626263,2.03672754 37.8253446,-1.31130219e-05 46.6851665,-1.31130219e-05 C47.1434331,-1.31130219e-05 47.5507812,0.356416501 47.5507812,0.814683149 C47.5507812,8.82507352 45.4471323,14.2973656 40.0913338,20.0052965 L30.6195217,20.0052965 L30.6195217,37.3046624 Z" id="Type-something-2" sketch:type="MSShapeGroup"></path>
<path d="M46.9892814,25.2044452 L38.409143,37.8832324 L33.3601481,32.2246949 L35.634673,29.9711887 L38.262012,33.0399206 L44.6517004,23.1190887 L46.9892814,25.2044452 Z" id="✓" sketch:type="MSShapeGroup"></path>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.2 KiB

View File

@ -1,14 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="55px" height="42px" viewBox="0 0 55 42" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
<!-- Generator: Sketch 3.2.1 (9971) - http://www.bohemiancoding.com/sketch -->
<title>MaintenanceJobs</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Random" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
<g id="MaintenanceJobs" sketch:type="MSArtboardGroup" fill="#FFFFFF">
<path d="M22.7780898,23.3397977 L22.7780898,22.3006685 L22.0506329,22.1134422 C21.9919203,21.8918136 21.9063401,21.6817396 21.7977523,21.4867754 L22.1806538,20.8224647 L21.4668592,20.0876761 L20.8235604,20.4849764 C20.634065,20.3734563 20.4298915,20.2855681 20.2144936,20.2253379 L20.0290614,19.4772694 L19.0196215,19.4772694 L18.8377446,20.2261221 C18.6224482,20.2865615 18.4183763,20.3746588 18.2289825,20.486388 L17.5836521,20.0922247 L16.8698575,20.8270133 L17.2558063,21.4892327 C17.1474725,21.6843015 17.0620955,21.8944801 17.0035861,22.1162132 L16.276891,22.3070993 L16.276891,23.3462286 L17.0043479,23.5334548 C17.0630605,23.7550835 17.1486407,23.9651575 17.2572285,24.1601217 L16.874327,24.8244324 L17.5881216,25.559221 L18.2314204,25.1619207 C18.4209158,25.2734408 18.6250893,25.3613289 18.8404872,25.4215592 L19.0259194,26.1696277 L20.0353593,26.1696277 L20.2172362,25.420775 C20.4325326,25.3603355 20.6366045,25.2722383 20.8259983,25.1604567 L21.4712779,25.55462 L22.1850725,24.8198315 L21.7991237,24.1576121 C21.9074575,23.9625433 21.9928345,23.7523647 22.0513439,23.5306315 L22.7780391,23.3397455 L22.7780898,23.3397977 Z M19.5275666,24.6011307 C18.5738427,24.6011307 17.8007261,23.8052754 17.8007261,22.8235008 C17.8007261,21.8417263 18.5738427,21.0458709 19.5275666,21.0458709 C20.4812904,21.0458709 21.2544071,21.8417263 21.2544071,22.8235008 C21.2544071,23.8052754 20.4812904,24.6011307 19.5275666,24.6011307 L19.5275666,24.6011307 Z" id="Shape" sketch:type="MSShapeGroup" transform="translate(19.527490, 22.823449) rotate(-16.000000) translate(-19.527490, -22.823449) "></path>
<path d="M26.2603822,19.2223114 L26.2603822,18.4196181 L25.6984455,18.2749919 C25.653092,18.1037911 25.5869841,17.9415157 25.5031036,17.7909123 L25.7988824,17.277754 L25.2474995,16.7101539 L24.7505722,17.0170554 C24.6041932,16.9309097 24.4464759,16.863019 24.280088,16.8164931 L24.1368477,16.2386347 L23.3570885,16.2386347 L23.2165945,16.8170989 C23.0502851,16.8637864 22.8926462,16.9318386 22.7463458,17.0181458 L22.2478491,16.7136676 L21.6964662,17.2812677 L21.994599,17.7928105 C21.9109147,17.9434947 21.8449637,18.1058508 21.7997671,18.2771324 L21.2384189,18.4245857 L21.2384189,19.227279 L21.8003556,19.3719051 C21.8457091,19.543106 21.911817,19.7053813 21.9956975,19.8559848 L21.6999187,20.3691431 L22.2513016,20.9367432 L22.7482289,20.6298417 C22.8946079,20.7159873 23.0523252,20.783878 23.2187131,20.830404 L23.3619534,21.4082624 L24.1417126,21.4082624 L24.2822066,20.8297982 C24.448516,20.7831107 24.6061549,20.7150584 24.7524554,20.6287109 L25.2509128,20.9331891 L25.8022957,20.365589 L25.5041629,19.8540462 C25.5878472,19.703362 25.6537982,19.5410059 25.6989948,19.3697242 L26.260343,19.222271 L26.2603822,19.2223114 Z M23.7494594,20.1966498 C23.012739,20.1966498 22.4155317,19.5818776 22.4155317,18.8234889 C22.4155317,18.0651002 23.012739,17.450328 23.7494594,17.450328 C24.4861798,17.450328 25.0833871,18.0651002 25.0833871,18.8234889 C25.0833871,19.5818776 24.4861798,20.1966498 23.7494594,20.1966498 L23.7494594,20.1966498 Z" id="Shape-2" sketch:type="MSShapeGroup" transform="translate(23.749401, 18.823449) rotate(-3.000000) translate(-23.749401, -18.823449) "></path>
<path d="M24.2941158,6.29410711 C24.2941158,7.17094577 23.5827184,7.88234317 22.7058798,7.88234317 C21.8290411,7.88234317 21.1176437,7.17094577 21.1176437,6.29410711 C21.1176437,5.41726844 21.8290411,4.70587104 22.7058798,4.70587104 C23.5827184,4.70587104 24.2941158,5.41726844 24.2941158,6.29410711 L24.2941158,6.29410711 Z M14.4988011,26.6992243 L12.3823454,27.9338235 C12.2996247,27.9834559 12.2169041,28 12.1176393,28 C11.9852863,28 11.8529333,27.9503676 11.7371245,27.8511029 L10.6783004,26.7922788 C10.5459474,26.6433817 10.496315,26.4448522 10.5459474,26.2628668 L11.9521981,21.6966881 L7.30329877,17.0477888 L2.73712008,18.4540395 C2.68748771,18.4705836 2.63785533,18.4705836 2.58822295,18.4705836 C2.45586995,18.4705836 2.30697282,18.4209512 2.20770806,18.3216865 L1.14888402,17.2628624 C0.983442761,17.080877 0.95035451,16.816171 1.06616339,16.6176415 L4.77204754,10.2646973 C4.8713123,10.1158001 5.03675355,10.0165354 5.20219481,9.99999126 L11.4724184,9.66910874 C12.465066,8.49447582 13.4411694,7.40256353 14.3841846,6.44300424 C18.520216,2.32351694 21.680144,0.999986887 27.4374997,0.999986887 C27.735294,0.999986887 28,1.23160465 28,1.52939891 C28,7.02204864 26.4779404,10.6783004 22.5569827,14.6158023 C22.4272714,14.7432772 22.2951416,14.8713567 22.160716,14.9999999 L14.4988011,15 L14.4988011,26.6992243 Z" id="Type-something-2" sketch:type="MSShapeGroup"></path>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 5.1 KiB

View File

@ -1,17 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="55px" height="42px" viewBox="0 0 55 42" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
<!-- Generator: Sketch 3.2.1 (9971) - http://www.bohemiancoding.com/sketch -->
<title>Organizations</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Random" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
<g id="Organizations" sketch:type="MSArtboardGroup" fill="#FFFFFF">
<g id="Organizations-back" sketch:type="MSLayerGroup" transform="translate(10.006000, 0.000000)">
<path d="M7.38461538,4.10869565 L9.22707692,4.10869565 L9.22707692,6.45652174 L7.38461538,6.45652174 L7.38461538,4.10869565 Z M11.0732308,4.10869565 L13.5347692,4.10869565 L13.5347692,6.45652174 L11.0732308,6.45652174 L11.0732308,4.10869565 Z M11.0732308,8.80434783 L13.5347692,8.80434783 L13.5347692,11.1521739 L11.0732308,11.1521739 L11.0732308,8.80434783 Z M7.38461538,13.5 L9.22707692,13.5 L9.22707692,15.8478261 L7.38461538,15.8478261 L7.38461538,13.5 Z M11.0732308,13.5 L13.5347692,13.5 L13.5347692,15.8478261 L11.0732308,15.8478261 L11.0732308,13.5 Z M7.38461538,8.80434783 L9.22707692,8.80434783 L9.22707692,11.1521739 L7.38461538,11.1521739 L7.38461538,8.80434783 Z M8.61169231,22.3494391 L11.0769231,22.3494391 L11.0769231,27 L8.61169231,27 L8.61169231,22.3494391 Z M7.38092308,1.76086957 L0,1.76086957 L0,0 L16,0 L16,27 L7.38092308,27 L7.38092308,1.76086957 Z" sketch:type="MSShapeGroup"></path>
</g>
<g id="Organizations-front" sketch:type="MSLayerGroup" transform="translate(0.006000, 3.000000)">
<path d="M2.45784615,4.10869565 L4.91938462,4.10869565 L4.91938462,6.45652174 L2.45784615,6.45652174 L2.45784615,4.10869565 Z M6.76553846,4.10869565 L9.22707692,4.10869565 L9.22707692,6.45652174 L6.76553846,6.45652174 L6.76553846,4.10869565 Z M11.0732308,4.10869565 L13.5347692,4.10869565 L13.5347692,6.45652174 L11.0732308,6.45652174 L11.0732308,4.10869565 Z M11.0732308,8.80434783 L13.5347692,8.80434783 L13.5347692,11.1521739 L11.0732308,11.1521739 L11.0732308,8.80434783 Z M2.45784615,13.5 L4.91938462,13.5 L4.91938462,15.8478261 L2.45784615,15.8478261 L2.45784615,13.5 Z M6.76553846,13.5 L9.22707692,13.5 L9.22707692,15.8478261 L6.76553846,15.8478261 L6.76553846,13.5 Z M11.0732308,13.5 L13.5347692,13.5 L13.5347692,15.8478261 L11.0732308,15.8478261 L11.0732308,13.5 Z M2.45784615,8.80434783 L4.91938462,8.80434783 L4.91938462,11.1521739 L2.45784615,11.1521739 L2.45784615,8.80434783 Z M6.76553846,8.80434783 L9.22707692,8.80434783 L9.22707692,11.1521739 L6.76553846,11.1521739 L6.76553846,8.80434783 Z M8.61169231,22.3494391 L11.0769231,22.3494391 L11.0769231,27 L8.61169231,27 L8.61169231,22.3494391 Z M4.91938462,22.3494391 L7.38461538,22.3494391 L7.38461538,27 L4.91938462,27 L4.91938462,22.3494391 Z M0,0 L16,0 L16,27 L0,27 L0,0 Z" sketch:type="MSShapeGroup"></path>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 3.0 KiB

View File

@ -1,16 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="55px" height="42px" viewBox="0 0 55 42" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
<!-- Generator: Sketch 3.2.1 (9971) - http://www.bohemiancoding.com/sketch -->
<title>PortalMode</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Random" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
<g id="PortalMode--exit" sketch:type="MSArtboardGroup" fill="#000000">
<g id="PortalMode--exit-arrow" sketch:type="MSLayerGroup" transform="translate(2.000000, 8.000000)">
<path d="M11,8.25000041 L32.5589445,8.25 L32.5589445,13.451166 L11,13.4511664 L11,8.25000041 Z" id="Signout-arrow-line" sketch:type="MSShapeGroup"></path>
<path d="M0.66,10.56 L11.22,0.66 L11.22,20.46 L0.66,10.56 L0.66,10.56 Z" id="Signout-arrowhead" sketch:type="MSShapeGroup"></path>
</g>
<path d="M7,8 L38,8 L38,31 L7,31 L7,8 Z M59,36 L59,0 L7,0 L7,36 L32,36 L32,44 L25,44 L25,46 L41,46 L41,44 L34,44 L34,36 L59,36" sketch:type="MSShapeGroup"></path>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.2 KiB

View File

@ -1,12 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="55px" height="42px" viewBox="0 0 55 42" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
<!-- Generator: Sketch 3.2.1 (9971) - http://www.bohemiancoding.com/sketch -->
<title>PortalMode</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Random" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
<g id="PortalMode" sketch:type="MSArtboardGroup" fill="#000000">
<path d="M51,32.8695652 L51,0 L3,0 L3,32.8695652 L26.0769231,32.8695652 L26.0769231,40.173913 L19.6153846,40.173913 L19.6153846,42 L34.3846154,42 L34.3846154,40.173913 L27.9230769,40.173913 L27.9230769,32.8695652 L51,32.8695652" sketch:type="MSShapeGroup"></path>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 905 B

View File

@ -1,13 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="50px" height="48px" viewBox="0 0 50 48" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
<!-- Generator: Sketch 3.2.1 (9971) - http://www.bohemiancoding.com/sketch -->
<title>Projects</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Random" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
<g id="Projects" sketch:type="MSArtboardGroup" fill="#000000">
<path d="M11,5 L37.0087557,5 C38.1084896,5 39,5.89811611 39,7.00199958 L39,45.9980004 C39,47.1036743 38.1001025,48 37.0087557,48 L11,48 L11,5 Z M29.5,25.5 C31.1568542,25.5 32.5,24.1568542 32.5,22.5 C32.5,20.8431458 31.1568542,19.5 29.5,19.5 C27.8431458,19.5 26.5,20.8431458 26.5,22.5 C26.5,24.1568542 27.8431458,25.5 29.5,25.5 Z M20,21.5 C21.6568542,21.5 23,20.1568542 23,18.5 C23,16.8431458 21.6568542,15.5 20,15.5 C18.3431458,15.5 17,16.8431458 17,18.5 C17,20.1568542 18.3431458,21.5 20,21.5 Z M20,39.5 C21.6568542,39.5 23,38.1568542 23,36.5 C23,34.8431458 21.6568542,33.5 20,33.5 C18.3431458,33.5 17,34.8431458 17,36.5 C17,38.1568542 18.3431458,39.5 20,39.5 Z M21,32.1115082 C21.6818613,32.2662308 22.3049134,32.5757914 22.830236,33.00127 L22.8276367,32.9968262 L25.5143157,32.7615076 C27.1632636,32.6170809 28.5065958,31.1651021 28.5148124,29.5021793 L28.5276962,26.894684 C26.5098107,26.4502486 25,24.6514419 25,22.5 C25,20.0147186 27.0147186,18 29.5,18 C31.9852814,18 34,20.0147186 34,22.5 C34,24.6376647 32.5094641,26.427196 30.5110069,26.8859796 L30.5110069,26.8859796 L30.5064583,28.9993706 C30.5028915,30.6565724 29.3608955,32.707252 27.9492244,33.5837365 L24.4439087,35.7601318 L24.4377001,35.7495172 C24.4786728,35.9935757 24.5,36.2442972 24.5,36.5 C24.5,38.9852814 22.4852814,41 20,41 C17.5147186,41 15.5,38.9852814 15.5,36.5 C15.5,34.3584126 16.9960113,32.5662374 19,32.1115082 L19,22.8884918 C16.9960113,22.4337626 15.5,20.6415874 15.5,18.5 C15.5,16.0147186 17.5147186,14 20,14 C22.4852814,14 24.5,16.0147186 24.5,18.5 C24.5,20.6415874 23.0039887,22.4337626 21,22.8884918 L21,32.1115082 Z" id="Rectangle-26" sketch:type="MSShapeGroup"></path>
<path d="M41,5.00526988 C41,3.89778991 40.1050211,3 39.0029953,3 L15,3 L15,1 L41.0087557,1 C42.1084896,1 43,1.89811611 43,3.00199958 L43,41.9980004 C43,43.1036743 42.1052949,44 41,44 L41,44 L41,5.00526988 Z" id="Rectangle-27" sketch:type="MSShapeGroup"></path>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.5 KiB

View File

@ -1,12 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="28px" height="26px" viewBox="0 0 28 26" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
<!-- Generator: Sketch 3.2.1 (9971) - http://www.bohemiancoding.com/sketch -->
<title>Setup</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Random" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
<g id="Setup" sketch:type="MSArtboardGroup" fill="#000000">
<path d="M27.2374467,21.8644068 L21.7059693,16.7312349 L22.4438821,16.0435835 L21.7064908,15.3607748 L19.4948386,17.4140436 L15.8063178,13.9903148 L20.2379662,9.87409201 C20.8282964,10.0677966 21.4452228,10.1646489 22.0783154,10.1646489 C23.5390176,10.1646489 24.9126304,9.63680387 25.9457082,8.6779661 C27.5399127,7.19612591 27.9920472,4.99757869 27.0976865,3.07021792 L26.793656,2.41646489 L24.4166905,4.62469734 L22.5028108,4.64891041 L22.5283639,2.95399516 L24.9517424,0.702179177 L24.2472052,0.421307506 C23.5562268,0.140435835 22.822486,0 22.0668425,0 C20.6056189,0 19.2325275,0.527845036 18.2004927,1.48668281 C16.6881627,2.89104116 16.2021311,4.94430993 16.9176196,6.79418886 L12.4875357,10.905569 L6.21814565,5.08474576 L6.95605839,4.40193705 L2.90144951,0.634382567 L0.686668304,2.68765133 L4.74388465,6.45520581 L5.4807544,5.77239709 L11.7501445,11.5932203 L7.31953908,15.7046005 C6.72764441,15.5108959 6.1081106,15.409201 5.472932,15.409201 C4.01222982,15.409201 2.63913848,15.937046 1.60658214,16.8958838 C0.00924876288,18.377724 -0.442364264,20.5859564 0.456689845,22.5133172 L0.761763311,23.1670702 L3.18462027,20.9152542 L5.00932464,20.8910412 L4.98324998,22.6682809 L2.60628442,24.8765133 L3.31238608,25.157385 C4.00127847,25.433414 4.7318903,25.5738499 5.48492635,25.5738499 C6.94562853,25.5738499 8.31819837,25.0460048 9.35075472,24.0871671 C10.8604773,22.6876513 11.3470303,20.6392252 10.6362352,18.7893462 L15.0689266,14.6731235 L18.7574473,18.0968523 L16.5442306,20.1549637 L17.2816218,20.8377724 L18.0190131,20.1549637 L23.5494474,25.2881356 C24.0422584,25.748184 24.6972538,26 25.393447,26 C26.0896403,26 26.7446357,25.748184 27.2379682,25.2881356 C28.2543582,24.3438257 28.2538367,22.8087167 27.2374467,21.8644068" sketch:type="MSShapeGroup"></path>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.4 KiB

View File

@ -1,18 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="55px" height="42px" viewBox="0 0 55 42" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
<!-- Generator: Sketch 3.2.1 (9971) - http://www.bohemiancoding.com/sketch -->
<title>Signout</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Random" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
<g id="Signout" sketch:type="MSArtboardGroup" fill="#242424">
<g sketch:type="MSLayerGroup">
<path d="M18.3359999,0.00518356419 L18.3359999,4.43876768 L45.0851985,4.43876768 L45.0851985,37.6671922 L18.3281255,37.6671922 L18.3281255,42.1211922 L49.419,42.1211922 L49.419,0 L18.3359999,0.00518356419 Z" id="Signout-entrance" sketch:type="MSShapeGroup"></path>
<g id="Signout-arrow" transform="translate(0.000000, 7.962963)" sketch:type="MSShapeGroup">
<path d="M11.75,9.55555603 L36.7387766,9.55555556 L36.7387766,15.5798016 L11.75,15.5798021 L11.75,9.55555603 Z" id="Signout-arrow-line"></path>
<path d="M0.728571429,12.7407407 L12.3857143,0.796296296 L12.3857143,24.6851852 L0.728571429,12.7407407 L0.728571429,12.7407407 Z" id="Signout-arrowhead"></path>
</g>
</g>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 1.4 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 7.6 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 7.2 KiB

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 6.5 KiB

View File

@ -1,13 +0,0 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg width="54px" height="43px" viewBox="0 0 54 43" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:sketch="http://www.bohemiancoding.com/sketch/ns">
<!-- Generator: Sketch 3.2.1 (9971) - http://www.bohemiancoding.com/sketch -->
<title>Users</title>
<desc>Created with Sketch.</desc>
<defs></defs>
<g id="Random" stroke="none" stroke-width="1" fill="none" fill-rule="evenodd" sketch:type="MSPage">
<g id="Users" sketch:type="MSArtboardGroup" transform="translate(0.000000, 0.940000)" fill="#000000">
<path d="M35.696,32.1 C33.502,31.18 28.291,29.38 25.086,28.44 C24.813,28.35 24.77,28.34 24.77,27.2 C24.77,26.26 25.157,25.31 25.534,24.51 C25.942,23.64 26.426,22.18 26.6,20.87 C27.086,20.3 27.748,19.19 28.174,17.07 C28.547,15.2 28.373,14.52 28.125,13.88 C28.1,13.81 28.073,13.75 28.053,13.68 C27.959,13.24 28.088,10.96 28.409,9.19 C28.629,7.98 28.352,5.4 26.682,3.27 C25.627,1.92 23.61,0.26 19.924,0.03 L17.903,0.04 C14.28,0.26 12.26,1.92 11.205,3.27 C9.536,5.4 9.258,7.98 9.479,9.19 C9.801,10.96 9.928,13.24 9.836,13.67 C9.817,13.75 9.789,13.81 9.762,13.88 C9.516,14.52 9.34,15.2 9.715,17.07 C10.139,19.19 10.801,20.3 11.289,20.87 C11.461,22.18 11.946,23.64 12.356,24.51 C12.655,25.15 12.795,26.02 12.795,27.24 C12.795,28.38 12.752,28.39 12.496,28.47 C9.182,29.45 3.907,31.36 1.94,32.22 C0.381,32.89 0,34.09 0,35.17 L0,40.17 C0,40.88 0.42,42.09 1.94,42.09 L16.707,42.09 L18.801,42.09 L19.166,42.09 L21.291,42.09 L36.061,42.09 C37.578,42.09 38,40.88 38,40.17 L38,35.17 C38,34.09 37.252,32.76 35.696,32.1" id="Users-silhouette" sketch:type="MSShapeGroup"></path>
<path d="M49.979,20.03 L44,20.03 L44,26.01 L42,26.01 L42,20.03 L36.021,20.03 L36.021,18.03 L42,18.03 L42,12.05 L44,12.05 L44,18.03 L49.979,18.03 L49.979,20.03 L49.979,20.03 Z M43,8.03 C36.924,8.03 32,12.95 32,19.03 C32,25.11 36.924,30.03 43,30.03 C49.075,30.03 54,25.11 54,19.03 C54,12.95 49.075,8.03 43,8.03 L43,8.03 Z" id="Users-plus" sketch:type="MSShapeGroup"></path>
</g>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 2.1 KiB

View File

@ -5,12 +5,14 @@
*
*/
/*
/*
#schedules-form-container -inventory group add/edit dialog
*/
@import './client/src/shared/branding/colors.less';
#schedules-tab {
position: relative;
position: relative;
top: 0;
left: 0;
}
@ -20,22 +22,22 @@
position: absolute;
top: 0;
left: 0;
z-index: 100;
z-index: 100;
background-color: @black;
opacity: 0;
opacity: 0;
}
#schedules-list {
overflow-x: hidden;
overflow-y: auto;
overflow-y: auto;
}
#schedules-form-container {
position: absolute;
position: absolute;
top: 0;
left: 0;
display: none;
border: 1px solid #e5e5e5;
border: 1px solid #e5e5e5;
border-radius: 4px;
box-shadow: 3px 3px 6px 0 #666;
padding: 0 10px 15px 8px;
@ -83,15 +85,15 @@
}
#scheduler-modal-dialog, #schedules-form-container {
display: none;
overflow-x: hidden;
display: none;
overflow-x: hidden;
overflow-y: auto;
padding-top: 25px;
form {
width: 100%;
}
.sublabel {
font-weight: normal;
}
@ -101,7 +103,7 @@
}
.occurrence-list {
border: 1px solid @well-border;
border: 1px solid @well-border;
padding: 8px 10px;
border-radius: 4px;
background-color: @well;
@ -113,7 +115,7 @@
display: inline-block;
margin-left: 15px;
font-size: 12px;
.label-inline {
display: inline-block;
vertical-align: middle;
@ -131,7 +133,7 @@
margin-right: 10px;
}
}
.ui-widget input {
font-size: 12px;
font-weight: normal;
@ -162,7 +164,7 @@
color: #999;
padding-left: 10px;
}
.error {
.error {
color: #dd1b16;
font-size: 12px;
margin-bottom: 0;
@ -214,14 +216,14 @@
width: 100%;
}
.occurrence-list {
border: 1px solid @well-border;
border: 1px solid @well-border;
padding: 8px 10px;
border-radius: 4px;
background-color: @well;
list-style: none;
margin-bottom: 5px;
}
#weekdaySelect .btn-default:hover,
#weekdaySelect .btn-default:focus {
background-color: #fff;
@ -232,4 +234,4 @@
#weekdaySelect .btn-default.active:hover {
background-color: #e0e0e0;
}
}
}

View File

@ -21,7 +21,7 @@
src: url(/static/assets/OpenSans-Bold.ttf);
}
@import "src/shared/branding/colors.less";
@import "./client/src/shared/branding/colors.less";
@import "fonts.less";
@import "main-layout.less";
@import "animations.less";
@ -42,9 +42,9 @@
@import "survey-maker.less";
@import "text-label.less";
@import "./bootstrap-datepicker.less";
@import "awx/ui/client/src/shared/branding/colors.default.less";
@import "./client/src/shared/branding/colors.default.less";
// Bootstrap default overrides
@import "awx/ui/client/src/shared/bootstrap-settings.less";
@import "./client/src/shared/bootstrap-settings.less";
/* Bootstrap fix that's causing a right margin to appear
whenver a modal is opened */
body.modal-open {

View File

@ -9,6 +9,8 @@
*
*/
@import "./client/src/shared/branding/colors.less";
.ansible-breadcrumb {
list-style: none;
overflow: hidden;
@ -81,4 +83,4 @@
}
.ansible-breadcrumb li.active a:before {
border-left: 11px solid @grey;
}
}

View File

@ -7,6 +7,8 @@
*
*/
@import "./client/src/shared/branding/colors.less";
.graph-wrapper {
width: 100%;

View File

@ -7,7 +7,7 @@
*
*/
@import "awx/ui/client/src/shared/branding/colors.default.less";
@import "./client/src/shared/branding/colors.default.less";
.noselect {
-webkit-touch-callout: none; /* iOS Safari */

View File

@ -6,6 +6,9 @@
* Custom styles for slideout menu
*
*/
@import "./client/src/shared/branding/colors.less";
.cbp-spmenu {
background: #E8E8E8;
position: fixed;
@ -179,4 +182,4 @@
.cbp-spmenu-push-toright {
left: 190px;
}
}
}

View File

@ -7,6 +7,9 @@
*
*/
@import "./client/src/shared/branding/colors.less";
@failed-hosts-color: @red;
@successful-hosts-color: @green;
@changed-hosts-color: @changed;

View File

@ -7,6 +7,8 @@
*
*/
@import "./client/src/shared/branding/colors.less";
#jobs-page {

View File

@ -8,7 +8,8 @@
*
*/
@import "awx/ui/client/src/shared/branding/colors.default.less";
@import "./client/src/shared/branding/colors.less";
@import "./client/src/shared/branding/colors.default.less";
table.ui-datepicker-calendar {
background-color: @well;

View File

@ -7,7 +7,7 @@
*
*/
@import "awx/ui/client/src/shared/branding/colors.default.less";
@import "./client/src/shared/branding/colors.default.less";
table, tbody {

View File

@ -7,8 +7,8 @@
*
*/
@import "src/shared/branding/colors.less";
@import "src/shared/branding/colors.default.less";
@import "./client/src/shared/branding/colors.less";
@import "./client/src/shared/branding/colors.default.less";
html { height: 100%; }

View File

@ -5,7 +5,8 @@
*
*/
@import "awx/ui/client/src/shared/branding/colors.default.less";
@import "./client/src/shared/branding/colors.default.less";
@import "./client/src/shared/branding/colors.less";
#jobs-stdout {
margin-bottom: 20px;

View File

@ -1,4 +1,4 @@
@import "src/shared/branding/colors.default.less";
@import "./client/src/shared/branding/colors.default.less";
.host-disabled-label {
&:after {

View File

@ -1,19 +0,0 @@
{
"name": "angular-animate",
"version": "1.4.8",
"main": "./angular-animate.js",
"ignore": [],
"dependencies": {
"angular": "1.4.8"
},
"homepage": "https://github.com/angular/bower-angular-animate",
"_release": "1.4.8",
"_resolution": {
"type": "version",
"tag": "v1.4.8",
"commit": "cc1d9740059f5e8fd43abf0e2e80695d43b3b6b1"
},
"_source": "git://github.com/angular/bower-angular-animate.git",
"_target": "~1.4.8",
"_originalSource": "angular-animate"
}

View File

@ -1,68 +0,0 @@
# packaged angular-animate
This repo is for distribution on `npm` and `bower`. The source for this module is in the
[main AngularJS repo](https://github.com/angular/angular.js/tree/master/src/ngAnimate).
Please file issues and pull requests against that repo.
## Install
You can install this package either with `npm` or with `bower`.
### npm
```shell
npm install angular-animate
```
Then add `ngAnimate` as a dependency for your app:
```javascript
angular.module('myApp', [require('angular-animate')]);
```
### bower
```shell
bower install angular-animate
```
Then add a `<script>` to your `index.html`:
```html
<script src="/bower_components/angular-animate/angular-animate.js"></script>
```
Then add `ngAnimate` as a dependency for your app:
```javascript
angular.module('myApp', ['ngAnimate']);
```
## Documentation
Documentation is available on the
[AngularJS docs site](http://docs.angularjs.org/api/ngAnimate).
## License
The MIT License
Copyright (c) 2010-2015 Google, Inc. http://angularjs.org
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.

File diff suppressed because it is too large Load Diff

View File

@ -1,56 +0,0 @@
/*
AngularJS v1.4.8
(c) 2010-2015 Google, Inc. http://angularjs.org
License: MIT
*/
(function(H,u,Sa){'use strict';function wa(a,b,c){if(!a)throw ngMinErr("areq",b||"?",c||"required");return a}function xa(a,b){if(!a&&!b)return"";if(!a)return b;if(!b)return a;X(a)&&(a=a.join(" "));X(b)&&(b=b.join(" "));return a+" "+b}function Ia(a){var b={};a&&(a.to||a.from)&&(b.to=a.to,b.from=a.from);return b}function T(a,b,c){var d="";a=X(a)?a:a&&I(a)&&a.length?a.split(/\s+/):[];q(a,function(a,s){a&&0<a.length&&(d+=0<s?" ":"",d+=c?b+a:a+b)});return d}function Ja(a){if(a instanceof L)switch(a.length){case 0:return[];
case 1:if(1===a[0].nodeType)return a;break;default:return L(ma(a))}if(1===a.nodeType)return L(a)}function ma(a){if(!a[0])return a;for(var b=0;b<a.length;b++){var c=a[b];if(1==c.nodeType)return c}}function Ka(a,b,c){q(b,function(b){a.addClass(b,c)})}function La(a,b,c){q(b,function(b){a.removeClass(b,c)})}function N(a){return function(b,c){c.addClass&&(Ka(a,b,c.addClass),c.addClass=null);c.removeClass&&(La(a,b,c.removeClass),c.removeClass=null)}}function ia(a){a=a||{};if(!a.$$prepared){var b=a.domOperation||
M;a.domOperation=function(){a.$$domOperationFired=!0;b();b=M};a.$$prepared=!0}return a}function da(a,b){ya(a,b);za(a,b)}function ya(a,b){b.from&&(a.css(b.from),b.from=null)}function za(a,b){b.to&&(a.css(b.to),b.to=null)}function Q(a,b,c){var d=(b.addClass||"")+" "+(c.addClass||""),e=(b.removeClass||"")+" "+(c.removeClass||"");a=Ma(a.attr("class"),d,e);c.preparationClasses&&(b.preparationClasses=Y(c.preparationClasses,b.preparationClasses),delete c.preparationClasses);d=b.domOperation!==M?b.domOperation:
null;Aa(b,c);d&&(b.domOperation=d);b.addClass=a.addClass?a.addClass:null;b.removeClass=a.removeClass?a.removeClass:null;return b}function Ma(a,b,c){function d(a){I(a)&&(a=a.split(" "));var b={};q(a,function(a){a.length&&(b[a]=!0)});return b}var e={};a=d(a);b=d(b);q(b,function(a,b){e[b]=1});c=d(c);q(c,function(a,b){e[b]=1===e[b]?null:-1});var s={addClass:"",removeClass:""};q(e,function(b,c){var e,d;1===b?(e="addClass",d=!a[c]):-1===b&&(e="removeClass",d=a[c]);d&&(s[e].length&&(s[e]+=" "),s[e]+=c)});
return s}function B(a){return a instanceof u.element?a[0]:a}function Na(a,b,c){var d="";b&&(d=T(b,"ng-",!0));c.addClass&&(d=Y(d,T(c.addClass,"-add")));c.removeClass&&(d=Y(d,T(c.removeClass,"-remove")));d.length&&(c.preparationClasses=d,a.addClass(d))}function ja(a,b){var c=b?"-"+b+"s":"";ea(a,[fa,c]);return[fa,c]}function na(a,b){var c=b?"paused":"",d=U+"PlayState";ea(a,[d,c]);return[d,c]}function ea(a,b){a.style[b[0]]=b[1]}function Y(a,b){return a?b?a+" "+b:a:b}function Ba(a,b,c){var d=Object.create(null),
e=a.getComputedStyle(b)||{};q(c,function(a,b){var c=e[a];if(c){var v=c.charAt(0);if("-"===v||"+"===v||0<=v)c=Oa(c);0===c&&(c=null);d[b]=c}});return d}function Oa(a){var b=0;a=a.split(/\s*,\s*/);q(a,function(a){"s"==a.charAt(a.length-1)&&(a=a.substring(0,a.length-1));a=parseFloat(a)||0;b=b?Math.max(a,b):a});return b}function oa(a){return 0===a||null!=a}function Ca(a,b){var c=O,d=a+"s";b?c+="Duration":d+=" linear all";return[c,d]}function Da(){var a=Object.create(null);return{flush:function(){a=Object.create(null)},
count:function(b){return(b=a[b])?b.total:0},get:function(b){return(b=a[b])&&b.value},put:function(b,c){a[b]?a[b].total++:a[b]={total:1,value:c}}}}function Ea(a,b,c){q(c,function(c){a[c]=V(a[c])?a[c]:b.style.getPropertyValue(c)})}var M=u.noop,Aa=u.extend,L=u.element,q=u.forEach,X=u.isArray,I=u.isString,pa=u.isObject,qa=u.isUndefined,V=u.isDefined,Fa=u.isFunction,ra=u.isElement,O,sa,U,ta;qa(H.ontransitionend)&&V(H.onwebkittransitionend)?(O="WebkitTransition",sa="webkitTransitionEnd transitionend"):
(O="transition",sa="transitionend");qa(H.onanimationend)&&V(H.onwebkitanimationend)?(U="WebkitAnimation",ta="webkitAnimationEnd animationend"):(U="animation",ta="animationend");var ka=U+"Delay",ua=U+"Duration",fa=O+"Delay";H=O+"Duration";var Pa={transitionDuration:H,transitionDelay:fa,transitionProperty:O+"Property",animationDuration:ua,animationDelay:ka,animationIterationCount:U+"IterationCount"},Qa={transitionDuration:H,transitionDelay:fa,animationDuration:ua,animationDelay:ka};u.module("ngAnimate",
[]).directive("ngAnimateChildren",[function(){return function(a,b,c){a=c.ngAnimateChildren;u.isString(a)&&0===a.length?b.data("$$ngAnimateChildren",!0):c.$observe("ngAnimateChildren",function(a){b.data("$$ngAnimateChildren","on"===a||"true"===a)})}}]).factory("$$rAFScheduler",["$$rAF",function(a){function b(a){d=d.concat(a);c()}function c(){if(d.length){for(var b=d.shift(),h=0;h<b.length;h++)b[h]();e||a(function(){e||c()})}}var d,e;d=b.queue=[];b.waitUntilQuiet=function(b){e&&e();e=a(function(){e=
null;b();c()})};return b}]).factory("$$AnimateRunner",["$q","$sniffer","$$animateAsyncRun",function(a,b,c){function d(a){this.setHost(a);this._doneCallbacks=[];this._runInAnimationFrame=c();this._state=0}d.chain=function(a,b){function c(){if(d===a.length)b(!0);else a[d](function(a){!1===a?b(!1):(d++,c())})}var d=0;c()};d.all=function(a,b){function c(h){v=v&&h;++d===a.length&&b(v)}var d=0,v=!0;q(a,function(a){a.done(c)})};d.prototype={setHost:function(a){this.host=a||{}},done:function(a){2===this._state?
a():this._doneCallbacks.push(a)},progress:M,getPromise:function(){if(!this.promise){var b=this;this.promise=a(function(a,c){b.done(function(b){!1===b?c():a()})})}return this.promise},then:function(a,b){return this.getPromise().then(a,b)},"catch":function(a){return this.getPromise()["catch"](a)},"finally":function(a){return this.getPromise()["finally"](a)},pause:function(){this.host.pause&&this.host.pause()},resume:function(){this.host.resume&&this.host.resume()},end:function(){this.host.end&&this.host.end();
this._resolve(!0)},cancel:function(){this.host.cancel&&this.host.cancel();this._resolve(!1)},complete:function(a){var b=this;0===b._state&&(b._state=1,b._runInAnimationFrame(function(){b._resolve(a)}))},_resolve:function(a){2!==this._state&&(q(this._doneCallbacks,function(b){b(a)}),this._doneCallbacks.length=0,this._state=2)}};return d}]).factory("$$animateAsyncRun",["$$rAF",function(a){function b(b){c.push(b);1<c.length||a(function(){for(var a=0;a<c.length;a++)c[a]();c=[]})}var c=[];return function(){var a=
!1;b(function(){a=!0});return function(c){a?c():b(c)}}}]).provider("$$animateQueue",["$animateProvider",function(a){function b(a,b,c,q){return d[a].some(function(a){return a(b,c,q)})}function c(a,b){a=a||{};var c=0<(a.addClass||"").length,d=0<(a.removeClass||"").length;return b?c&&d:c||d}var d=this.rules={skip:[],cancel:[],join:[]};d.join.push(function(a,b,d){return!b.structural&&c(b.options)});d.skip.push(function(a,b,d){return!b.structural&&!c(b.options)});d.skip.push(function(a,b,c){return"leave"==
c.event&&b.structural});d.skip.push(function(a,b,c){return c.structural&&2===c.state&&!b.structural});d.cancel.push(function(a,b,c){return c.structural&&b.structural});d.cancel.push(function(a,b,c){return 2===c.state&&b.structural});d.cancel.push(function(a,b,c){a=b.options;c=c.options;return a.addClass&&a.addClass===c.removeClass||a.removeClass&&a.removeClass===c.addClass});this.$get=["$$rAF","$rootScope","$rootElement","$document","$$HashMap","$$animation","$$AnimateRunner","$templateRequest","$$jqLite",
"$$forceReflow",function(d,s,h,g,v,r,$,u,R,C){function D(){var a=!1;return function(b){a?b():s.$$postDigest(function(){a=!0;b()})}}function K(a,b,c){var f=B(b),d=B(a),n=[];(a=t[c])&&q(a,function(a){a.node.contains(f)?n.push(a.callback):"leave"===c&&a.node.contains(d)&&n.push(a.callback)});return n}function l(a,f,k){function n(b,c,f,t){R(function(){var b=K(v,a,c);b.length&&d(function(){q(b,function(b){b(a,f,t)})})});b.progress(c,f,t)}function t(b){var c=a,f=k;f.preparationClasses&&(c.removeClass(f.preparationClasses),
f.preparationClasses=null);f.activeClasses&&(c.removeClass(f.activeClasses),f.activeClasses=null);Ha(a,k);da(a,k);k.domOperation();h.complete(!b)}var A,v;if(a=Ja(a))A=B(a),v=a.parent();k=ia(k);var h=new $,R=D();X(k.addClass)&&(k.addClass=k.addClass.join(" "));k.addClass&&!I(k.addClass)&&(k.addClass=null);X(k.removeClass)&&(k.removeClass=k.removeClass.join(" "));k.removeClass&&!I(k.removeClass)&&(k.removeClass=null);k.from&&!pa(k.from)&&(k.from=null);k.to&&!pa(k.to)&&(k.to=null);if(!A)return t(),h;
var z=[A.className,k.addClass,k.removeClass].join(" ");if(!Ra(z))return t(),h;var l=0<=["enter","move","leave"].indexOf(f),g=!G||F.get(A),z=!g&&m.get(A)||{},C=!!z.state;g||C&&1==z.state||(g=!la(a,v,f));if(g)return t(),h;l&&y(a);g={structural:l,element:a,event:f,close:t,options:k,runner:h};if(C){if(b("skip",a,g,z)){if(2===z.state)return t(),h;Q(a,z.options,k);return z.runner}if(b("cancel",a,g,z))if(2===z.state)z.runner.end();else if(z.structural)z.close();else return Q(a,z.options,g.options),z.runner;
else if(b("join",a,g,z))if(2===z.state)Q(a,k,{});else return Na(a,l?f:null,k),f=g.event=z.event,k=Q(a,z.options,g.options),z.runner}else Q(a,k,{});(C=g.structural)||(C="animate"===g.event&&0<Object.keys(g.options.to||{}).length||c(g.options));if(!C)return t(),w(a),h;var u=(z.counter||0)+1;g.counter=u;x(a,1,g);s.$$postDigest(function(){var b=m.get(A),d=!b,b=b||{},K=0<(a.parent()||[]).length&&("animate"===b.event||b.structural||c(b.options));if(d||b.counter!==u||!K){d&&(Ha(a,k),da(a,k));if(d||l&&b.event!==
f)k.domOperation(),h.end();K||w(a)}else f=!b.structural&&c(b.options,!0)?"setClass":b.event,x(a,2),b=r(a,f,b.options),b.done(function(b){t(!b);(b=m.get(A))&&b.counter===u&&w(B(a));n(h,f,"close",{})}),h.setHost(b),n(h,f,"start",{})});return h}function y(a){a=B(a).querySelectorAll("[data-ng-animate]");q(a,function(a){var b=parseInt(a.getAttribute("data-ng-animate")),c=m.get(a);switch(b){case 2:c.runner.end();case 1:c&&m.remove(a)}})}function w(a){a=B(a);a.removeAttribute("data-ng-animate");m.remove(a)}
function f(a,b){return B(a)===B(b)}function la(a,b,c){c=L(g[0].body);var d=f(a,c)||"HTML"===a[0].nodeName,t=f(a,h),n=!1,w;for((a=a.data("$ngAnimatePin"))&&(b=a);b&&b.length;){t||(t=f(b,h));a=b[0];if(1!==a.nodeType)break;var x=m.get(a)||{};n||(n=x.structural||F.get(a));if(qa(w)||!0===w)a=b.data("$$ngAnimateChildren"),V(a)&&(w=a);if(n&&!1===w)break;t||(t=f(b,h),t||(a=b.data("$ngAnimatePin"))&&(b=a));d||(d=f(b,c));b=b.parent()}return(!n||w)&&t&&d}function x(a,b,c){c=c||{};c.state=b;a=B(a);a.setAttribute("data-ng-animate",
b);c=(b=m.get(a))?Aa(b,c):c;m.put(a,c)}var m=new v,F=new v,G=null,A=s.$watch(function(){return 0===u.totalPendingRequests},function(a){a&&(A(),s.$$postDigest(function(){s.$$postDigest(function(){null===G&&(G=!0)})}))}),t={},n=a.classNameFilter(),Ra=n?function(a){return n.test(a)}:function(){return!0},Ha=N(R);return{on:function(a,b,c){b=ma(b);t[a]=t[a]||[];t[a].push({node:b,callback:c})},off:function(a,b,c){function f(a,b,c){var d=ma(b);return a.filter(function(a){return!(a.node===d&&(!c||a.callback===
c))})}var d=t[a];d&&(t[a]=1===arguments.length?null:f(d,b,c))},pin:function(a,b){wa(ra(a),"element","not an element");wa(ra(b),"parentElement","not an element");a.data("$ngAnimatePin",b)},push:function(a,b,c,f){c=c||{};c.domOperation=f;return l(a,b,c)},enabled:function(a,b){var c=arguments.length;if(0===c)b=!!G;else if(ra(a)){var f=B(a),d=F.get(f);1===c?b=!d:(b=!!b)?d&&F.remove(f):F.put(f,!0)}else b=G=!!a;return b}}}]}]).provider("$$animation",["$animateProvider",function(a){function b(a){return a.data("$$animationRunner")}
var c=this.drivers=[];this.$get=["$$jqLite","$rootScope","$injector","$$AnimateRunner","$$HashMap","$$rAFScheduler",function(a,e,s,h,g,v){function r(a){function b(a){if(a.processed)return a;a.processed=!0;var f=a.domNode,d=f.parentNode;e.put(f,a);for(var x;d;){if(x=e.get(d)){x.processed||(x=b(x));break}d=d.parentNode}(x||c).children.push(a);return a}var c={children:[]},d,e=new g;for(d=0;d<a.length;d++){var h=a[d];e.put(h.domNode,a[d]={domNode:h.domNode,fn:h.fn,children:[]})}for(d=0;d<a.length;d++)b(a[d]);
return function(a){var b=[],c=[],d;for(d=0;d<a.children.length;d++)c.push(a.children[d]);a=c.length;var m=0,e=[];for(d=0;d<c.length;d++){var h=c[d];0>=a&&(a=m,m=0,b.push(e),e=[]);e.push(h.fn);h.children.forEach(function(a){m++;c.push(a)});a--}e.length&&b.push(e);return b}(c)}var $=[],u=N(a);return function(g,C,D){function K(a){a=a.hasAttribute("ng-animate-ref")?[a]:a.querySelectorAll("[ng-animate-ref]");var b=[];q(a,function(a){var c=a.getAttribute("ng-animate-ref");c&&c.length&&b.push(a)});return b}
function l(a){var b=[],c={};q(a,function(a,f){var d=B(a.element),t=0<=["enter","move"].indexOf(a.event),d=a.structural?K(d):[];if(d.length){var m=t?"to":"from";q(d,function(a){var b=a.getAttribute("ng-animate-ref");c[b]=c[b]||{};c[b][m]={animationID:f,element:L(a)}})}else b.push(a)});var f={},d={};q(c,function(c,m){var w=c.from,e=c.to;if(w&&e){var h=a[w.animationID],g=a[e.animationID],x=w.animationID.toString();if(!d[x]){var A=d[x]={structural:!0,beforeStart:function(){h.beforeStart();g.beforeStart()},
close:function(){h.close();g.close()},classes:y(h.classes,g.classes),from:h,to:g,anchors:[]};A.classes.length?b.push(A):(b.push(h),b.push(g))}d[x].anchors.push({out:w.element,"in":e.element})}else w=w?w.animationID:e.animationID,e=w.toString(),f[e]||(f[e]=!0,b.push(a[w]))});return b}function y(a,b){a=a.split(" ");b=b.split(" ");for(var c=[],f=0;f<a.length;f++){var d=a[f];if("ng-"!==d.substring(0,3))for(var m=0;m<b.length;m++)if(d===b[m]){c.push(d);break}}return c.join(" ")}function w(a){for(var b=
c.length-1;0<=b;b--){var f=c[b];if(s.has(f)&&(f=s.get(f)(a)))return f}}function f(a,c){a.from&&a.to?(b(a.from.element).setHost(c),b(a.to.element).setHost(c)):b(a.element).setHost(c)}function la(){var a=b(g);!a||"leave"===C&&D.$$domOperationFired||a.end()}function x(b){g.off("$destroy",la);g.removeData("$$animationRunner");u(g,D);da(g,D);D.domOperation();A&&a.removeClass(g,A);g.removeClass("ng-animate");F.complete(!b)}D=ia(D);var m=0<=["enter","move","leave"].indexOf(C),F=new h({end:function(){x()},
cancel:function(){x(!0)}});if(!c.length)return x(),F;g.data("$$animationRunner",F);var G=xa(g.attr("class"),xa(D.addClass,D.removeClass)),A=D.tempClasses;A&&(G+=" "+A,D.tempClasses=null);$.push({element:g,classes:G,event:C,structural:m,options:D,beforeStart:function(){g.addClass("ng-animate");A&&a.addClass(g,A)},close:x});g.on("$destroy",la);if(1<$.length)return F;e.$$postDigest(function(){var a=[];q($,function(c){b(c.element)?a.push(c):c.close()});$.length=0;var c=l(a),d=[];q(c,function(a){d.push({domNode:B(a.from?
a.from.element:a.element),fn:function(){a.beforeStart();var c,d=a.close;if(b(a.anchors?a.from.element||a.to.element:a.element)){var m=w(a);m&&(c=m.start)}c?(c=c(),c.done(function(a){d(!a)}),f(a,c)):d()}})});v(r(d))});return F}}]}]).provider("$animateCss",["$animateProvider",function(a){var b=Da(),c=Da();this.$get=["$window","$$jqLite","$$AnimateRunner","$timeout","$$forceReflow","$sniffer","$$rAFScheduler","$animate",function(a,e,s,h,g,v,r,u){function Ga(a,b){var c=a.parentNode;return(c.$$ngAnimateParentKey||
(c.$$ngAnimateParentKey=++l))+"-"+a.getAttribute("class")+"-"+b}function R(w,f,h,g){var m;0<b.count(h)&&(m=c.get(h),m||(f=T(f,"-stagger"),e.addClass(w,f),m=Ba(a,w,g),m.animationDuration=Math.max(m.animationDuration,0),m.transitionDuration=Math.max(m.transitionDuration,0),e.removeClass(w,f),c.put(h,m)));return m||{}}function C(a){y.push(a);r.waitUntilQuiet(function(){b.flush();c.flush();for(var a=g(),d=0;d<y.length;d++)y[d](a);y.length=0})}function D(c,f,e){f=b.get(e);f||(f=Ba(a,c,Pa),"infinite"===
f.animationIterationCount&&(f.animationIterationCount=1));b.put(e,f);c=f;e=c.animationDelay;f=c.transitionDelay;c.maxDelay=e&&f?Math.max(e,f):e||f;c.maxDuration=Math.max(c.animationDuration*c.animationIterationCount,c.transitionDuration);return c}var K=N(e),l=0,y=[];return function(a,c){function d(){m()}function g(){m(!0)}function m(b){if(!(ga||va&&k)){ga=!0;k=!1;c.$$skipPreparationClasses||e.removeClass(a,Z);e.removeClass(a,Y);na(n,!1);ja(n,!1);q(y,function(a){n.style[a[0]]=""});K(a,c);da(a,c);Object.keys(t).length&&
q(t,function(a,b){a?n.style.setProperty(b,a):n.style.removeProperty(b)});if(c.onDone)c.onDone();H&&H.complete(!b)}}function F(a){p.blockTransition&&ja(n,a);p.blockKeyframeAnimation&&na(n,!!a)}function G(){H=new s({end:d,cancel:g});C(M);m();return{$$willAnimate:!1,start:function(){return H},end:d}}function A(){function b(){if(!ga){F(!1);q(y,function(a){n.style[a[0]]=a[1]});K(a,c);e.addClass(a,Y);if(p.recalculateTimingStyles){ha=n.className+" "+Z;aa=Ga(n,ha);E=D(n,ha,aa);W=E.maxDelay;I=Math.max(W,0);
J=E.maxDuration;if(0===J){m();return}p.hasTransitions=0<E.transitionDuration;p.hasAnimations=0<E.animationDuration}p.applyAnimationDelay&&(W="boolean"!==typeof c.delay&&oa(c.delay)?parseFloat(c.delay):W,I=Math.max(W,0),E.animationDelay=W,ca=[ka,W+"s"],y.push(ca),n.style[ca[0]]=ca[1]);N=1E3*I;z=1E3*J;if(c.easing){var k,l=c.easing;p.hasTransitions&&(k=O+"TimingFunction",y.push([k,l]),n.style[k]=l);p.hasAnimations&&(k=U+"TimingFunction",y.push([k,l]),n.style[k]=l)}E.transitionDuration&&x.push(sa);E.animationDuration&&
x.push(ta);A=Date.now();var v=N+1.5*z;k=A+v;var l=a.data("$$animateCss")||[],r=!0;if(l.length){var G=l[0];(r=k>G.expectedEndTime)?h.cancel(G.timer):l.push(m)}r&&(v=h(d,v,!1),l[0]={timer:v,expectedEndTime:k},l.push(m),a.data("$$animateCss",l));a.on(x.join(" "),g);c.to&&(c.cleanupStyles&&Ea(t,n,Object.keys(c.to)),za(a,c))}}function d(){var b=a.data("$$animateCss");if(b){for(var c=1;c<b.length;c++)b[c]();a.removeData("$$animateCss")}}function g(a){a.stopPropagation();var b=a.originalEvent||a;a=b.$manualTimeStamp||
b.timeStamp||Date.now();b=parseFloat(b.elapsedTime.toFixed(3));Math.max(a-A,0)>=N&&b>=J&&(va=!0,m())}if(!ga)if(n.parentNode){var A,x=[],l=function(a){if(va)k&&a&&(k=!1,m());else if(k=!a,E.animationDuration)if(a=na(n,k),k)y.push(a);else{var b=y,c=b.indexOf(a);0<=a&&b.splice(c,1)}},v=0<V&&(E.transitionDuration&&0===S.transitionDuration||E.animationDuration&&0===S.animationDuration)&&Math.max(S.animationDelay,S.transitionDelay);v?h(b,Math.floor(v*V*1E3),!1):b();L.resume=function(){l(!0)};L.pause=function(){l(!1)}}else m()}
var t={},n=B(a);if(!n||!n.parentNode||!u.enabled())return G();c=ia(c);var y=[],r=a.attr("class"),l=Ia(c),ga,k,va,H,L,I,N,J,z;if(0===c.duration||!v.animations&&!v.transitions)return G();var ba=c.event&&X(c.event)?c.event.join(" "):c.event,Q="",P="";ba&&c.structural?Q=T(ba,"ng-",!0):ba&&(Q=ba);c.addClass&&(P+=T(c.addClass,"-add"));c.removeClass&&(P.length&&(P+=" "),P+=T(c.removeClass,"-remove"));c.applyClassesEarly&&P.length&&K(a,c);var Z=[Q,P].join(" ").trim(),ha=r+" "+Z,Y=T(Z,"-active"),r=l.to&&0<
Object.keys(l.to).length;if(!(0<(c.keyframeStyle||"").length||r||Z))return G();var aa,S;0<c.stagger?(l=parseFloat(c.stagger),S={transitionDelay:l,animationDelay:l,transitionDuration:0,animationDuration:0}):(aa=Ga(n,ha),S=R(n,Z,aa,Qa));c.$$skipPreparationClasses||e.addClass(a,Z);c.transitionStyle&&(l=[O,c.transitionStyle],ea(n,l),y.push(l));0<=c.duration&&(l=0<n.style[O].length,l=Ca(c.duration,l),ea(n,l),y.push(l));c.keyframeStyle&&(l=[U,c.keyframeStyle],ea(n,l),y.push(l));var V=S?0<=c.staggerIndex?
c.staggerIndex:b.count(aa):0;(ba=0===V)&&!c.skipBlocking&&ja(n,9999);var E=D(n,ha,aa),W=E.maxDelay;I=Math.max(W,0);J=E.maxDuration;var p={};p.hasTransitions=0<E.transitionDuration;p.hasAnimations=0<E.animationDuration;p.hasTransitionAll=p.hasTransitions&&"all"==E.transitionProperty;p.applyTransitionDuration=r&&(p.hasTransitions&&!p.hasTransitionAll||p.hasAnimations&&!p.hasTransitions);p.applyAnimationDuration=c.duration&&p.hasAnimations;p.applyTransitionDelay=oa(c.delay)&&(p.applyTransitionDuration||
p.hasTransitions);p.applyAnimationDelay=oa(c.delay)&&p.hasAnimations;p.recalculateTimingStyles=0<P.length;if(p.applyTransitionDuration||p.applyAnimationDuration)J=c.duration?parseFloat(c.duration):J,p.applyTransitionDuration&&(p.hasTransitions=!0,E.transitionDuration=J,l=0<n.style[O+"Property"].length,y.push(Ca(J,l))),p.applyAnimationDuration&&(p.hasAnimations=!0,E.animationDuration=J,y.push([ua,J+"s"]));if(0===J&&!p.recalculateTimingStyles)return G();if(null!=c.delay){var ca=parseFloat(c.delay);
p.applyTransitionDelay&&y.push([fa,ca+"s"]);p.applyAnimationDelay&&y.push([ka,ca+"s"])}null==c.duration&&0<E.transitionDuration&&(p.recalculateTimingStyles=p.recalculateTimingStyles||ba);N=1E3*I;z=1E3*J;c.skipBlocking||(p.blockTransition=0<E.transitionDuration,p.blockKeyframeAnimation=0<E.animationDuration&&0<S.animationDelay&&0===S.animationDuration);c.from&&(c.cleanupStyles&&Ea(t,n,Object.keys(c.from)),ya(a,c));p.blockTransition||p.blockKeyframeAnimation?F(J):c.skipBlocking||ja(n,!1);return{$$willAnimate:!0,
end:d,start:function(){if(!ga)return L={end:d,cancel:g,resume:null,pause:null},H=new s(L),C(A),H}}}}]}]).provider("$$animateCssDriver",["$$animationProvider",function(a){a.drivers.push("$$animateCssDriver");this.$get=["$animateCss","$rootScope","$$AnimateRunner","$rootElement","$sniffer","$$jqLite","$document",function(a,c,d,e,s,h,g){function v(a){return a.replace(/\bng-\S+\b/g,"")}function r(a,b){I(a)&&(a=a.split(" "));I(b)&&(b=b.split(" "));return a.filter(function(a){return-1===b.indexOf(a)}).join(" ")}
function u(c,e,g){function h(a){var b={},c=B(a).getBoundingClientRect();q(["width","height","top","left"],function(a){var d=c[a];switch(a){case "top":d+=C.scrollTop;break;case "left":d+=C.scrollLeft}b[a]=Math.floor(d)+"px"});return b}function f(){var c=v(g.attr("class")||""),d=r(c,m),c=r(m,c),d=a(x,{to:h(g),addClass:"ng-anchor-in "+d,removeClass:"ng-anchor-out "+c,delay:!0});return d.$$willAnimate?d:null}function s(){x.remove();e.removeClass("ng-animate-shim");g.removeClass("ng-animate-shim")}var x=
L(B(e).cloneNode(!0)),m=v(x.attr("class")||"");e.addClass("ng-animate-shim");g.addClass("ng-animate-shim");x.addClass("ng-anchor");D.append(x);var F;c=function(){var c=a(x,{addClass:"ng-anchor-out",delay:!0,from:h(e)});return c.$$willAnimate?c:null}();if(!c&&(F=f(),!F))return s();var G=c||F;return{start:function(){function a(){c&&c.end()}var b,c=G.start();c.done(function(){c=null;if(!F&&(F=f()))return c=F.start(),c.done(function(){c=null;s();b.complete()}),c;s();b.complete()});return b=new d({end:a,
cancel:a})}}}function H(a,b,c,e){var f=R(a,M),g=R(b,M),h=[];q(e,function(a){(a=u(c,a.out,a["in"]))&&h.push(a)});if(f||g||0!==h.length)return{start:function(){function a(){q(b,function(a){a.end()})}var b=[];f&&b.push(f.start());g&&b.push(g.start());q(h,function(a){b.push(a.start())});var c=new d({end:a,cancel:a});d.all(b,function(a){c.complete(a)});return c}}}function R(c){var d=c.element,e=c.options||{};c.structural&&(e.event=c.event,e.structural=!0,e.applyClassesEarly=!0,"leave"===c.event&&(e.onDone=
e.domOperation));e.preparationClasses&&(e.event=Y(e.event,e.preparationClasses));c=a(d,e);return c.$$willAnimate?c:null}if(!s.animations&&!s.transitions)return M;var C=g[0].body;c=B(e);var D=L(c.parentNode&&11===c.parentNode.nodeType||C.contains(c)?c:C);N(h);return function(a){return a.from&&a.to?H(a.from,a.to,a.classes,a.anchors):R(a)}}]}]).provider("$$animateJs",["$animateProvider",function(a){this.$get=["$injector","$$AnimateRunner","$$jqLite",function(b,c,d){function e(c){c=X(c)?c:c.split(" ");
for(var d=[],e={},r=0;r<c.length;r++){var q=c[r],s=a.$$registeredAnimations[q];s&&!e[q]&&(d.push(b.get(s)),e[q]=!0)}return d}var s=N(d);return function(a,b,d,r){function u(){r.domOperation();s(a,r)}function H(a,b,d,e,f){switch(d){case "animate":b=[b,e.from,e.to,f];break;case "setClass":b=[b,D,K,f];break;case "addClass":b=[b,D,f];break;case "removeClass":b=[b,K,f];break;default:b=[b,f]}b.push(e);if(a=a.apply(a,b))if(Fa(a.start)&&(a=a.start()),a instanceof c)a.done(f);else if(Fa(a))return a;return M}
function B(a,b,d,e,f){var g=[];q(e,function(e){var h=e[f];h&&g.push(function(){var e,f,g=!1,k=function(a){g||(g=!0,(f||M)(a),e.complete(!a))};e=new c({end:function(){k()},cancel:function(){k(!0)}});f=H(h,a,b,d,function(a){k(!1===a)});return e})});return g}function C(a,b,d,e,f){var g=B(a,b,d,e,f);if(0===g.length){var h,l;"beforeSetClass"===f?(h=B(a,"removeClass",d,e,"beforeRemoveClass"),l=B(a,"addClass",d,e,"beforeAddClass")):"setClass"===f&&(h=B(a,"removeClass",d,e,"removeClass"),l=B(a,"addClass",
d,e,"addClass"));h&&(g=g.concat(h));l&&(g=g.concat(l))}if(0!==g.length)return function(a){var b=[];g.length&&q(g,function(a){b.push(a())});b.length?c.all(b,a):a();return function(a){q(b,function(b){a?b.cancel():b.end()})}}}3===arguments.length&&pa(d)&&(r=d,d=null);r=ia(r);d||(d=a.attr("class")||"",r.addClass&&(d+=" "+r.addClass),r.removeClass&&(d+=" "+r.removeClass));var D=r.addClass,K=r.removeClass,l=e(d),y,w;if(l.length){var f,I;"leave"==b?(I="leave",f="afterLeave"):(I="before"+b.charAt(0).toUpperCase()+
b.substr(1),f=b);"enter"!==b&&"move"!==b&&(y=C(a,b,r,l,I));w=C(a,b,r,l,f)}if(y||w)return{start:function(){function b(c){f=!0;u();da(a,r);g.complete(c)}var d,e=[];y&&e.push(function(a){d=y(a)});e.length?e.push(function(a){u();a(!0)}):u();w&&e.push(function(a){d=w(a)});var f=!1,g=new c({end:function(){f||((d||M)(void 0),b(void 0))},cancel:function(){f||((d||M)(!0),b(!0))}});c.chain(e,b);return g}}}}]}]).provider("$$animateJsDriver",["$$animationProvider",function(a){a.drivers.push("$$animateJsDriver");
this.$get=["$$animateJs","$$AnimateRunner",function(a,c){function d(c){return a(c.element,c.event,c.classes,c.options)}return function(a){if(a.from&&a.to){var b=d(a.from),h=d(a.to);if(b||h)return{start:function(){function a(){return function(){q(d,function(a){a.end()})}}var d=[];b&&d.push(b.start());h&&d.push(h.start());c.all(d,function(a){e.complete(a)});var e=new c({end:a(),cancel:a()});return e}}}else return d(a)}}]}])})(window,window.angular);
//# sourceMappingURL=angular-animate.min.js.map

File diff suppressed because one or more lines are too long

View File

@ -1,9 +0,0 @@
{
"name": "angular-animate",
"version": "1.4.8",
"main": "./angular-animate.js",
"ignore": [],
"dependencies": {
"angular": "1.4.8"
}
}

View File

@ -1,2 +0,0 @@
require('./angular-animate');
module.exports = 'ngAnimate';

View File

@ -1,26 +0,0 @@
{
"name": "angular-animate",
"version": "1.4.8",
"description": "AngularJS module for animations",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "https://github.com/angular/angular.js.git"
},
"keywords": [
"angular",
"framework",
"browser",
"animation",
"client-side"
],
"author": "Angular Core Team <angular-core+npm@google.com>",
"license": "MIT",
"bugs": {
"url": "https://github.com/angular/angular.js/issues"
},
"homepage": "http://angularjs.org"
}

View File

@ -1,44 +0,0 @@
{
"name": "angular-breadcrumb",
"description": "AngularJS module that generates a breadcrumb from ui-router's states",
"version": "0.4.1",
"main": "release/angular-breadcrumb.js",
"ignore": [
"sample",
"src",
"test",
".bowerrc",
".coveralls.yml",
".gitignore",
".jshintrc",
".travis.yml",
"gruntfile.js",
"bower.json",
"karma.conf.js",
"libpeerconnection.log",
"package.json",
"README.md"
],
"dependencies": {
"angular": ">=1.0.8",
"angular-ui-router": ">=0.2.0"
},
"devDependencies": {
"bootstrap": "~2.3.2",
"angular-ui-bootstrap-bower": "~0.8.0",
"underscore": "~1.5.1",
"angular-mocks": ">=1.0.8",
"angular-sanitize": ">=1.0.8"
},
"homepage": "https://github.com/ncuillery/angular-breadcrumb",
"_release": "0.4.1",
"_resolution": {
"type": "version",
"tag": "v0.4.1",
"commit": "b291e06f4010ebebbb41ea2c14e73e236aa70930"
},
"_source": "git://github.com/ncuillery/angular-breadcrumb.git",
"_target": "~0.4.1",
"_originalSource": "angular-breadcrumb",
"_direct": true
}

View File

@ -1,16 +0,0 @@
# EditorConfig helps developers define and maintain consistent
# coding styles between different editors and IDEs
# editorconfig.org
root = true
[*]
indent_style = space
indent_size = 4
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
[*.md]
trim_trailing_whitespace = false

View File

@ -1,15 +0,0 @@
sample
src
test
.idea
bower_components
coverage
testDependencies
.bowerrc
.coveralls.yml
.gitignore
.jshintrc
.travis.yml
gruntfile.js
karma.conf.js
libpeerconnection.log

View File

@ -1,151 +0,0 @@
<a name="0.4.1"></a>
### 0.4.1 (2015-08-09)
#### Features
* add the scope-based ncyBreadcrumbIgnore flag ([934c5523](http://github.com/ncuillery/angular-breadcrumb/commit/934c5523208a9615d7cfa3abcb397bbe131332ac), closes [#42](http://github.com/ncuillery/angular-breadcrumb/issues/42), [#62](http://github.com/ncuillery/angular-breadcrumb/issues/42))
<a name="0.4.0"></a>
### 0.4.0 (2015-05-17)
#### Bug Fixes
* **$breadcrumb:** Handle parents provided by StateObject references ([f4288d37](http://github.com/ncuillery/angular-breadcrumb/commit/f4288d375fd1090ffec1d67e85c6300d74d86d37), closes [#82](http://github.com/ncuillery/angular-breadcrumb/issues/82))
* **ncyBreadcrumb:**
* Prevent memory leak when label is a binding ([264e10f6](http://github.com/ncuillery/angular-breadcrumb/commit/264e10f680e1bbb8d1e00cf500de39cac4222cfd), closes [#88](http://github.com/ncuillery/angular-breadcrumb/issues/88))
* Removed trailing spaces from breadcrumb items([bc276ed5](http://github.com/ncuillery/angular-breadcrumb/commit/bc276ed5351a586d4a6dc83ada0687e6ca485344), closes [#77](http://github.com/ncuillery/angular-breadcrumb/issues/77))
#### Features
* Add force to ncyBreadcrumb options ([31125a38](http://github.com/ncuillery/angular-breadcrumb/commit/31125a386d706dd76df807b3b02e1fccea38fb59), closes [#77](http://github.com/ncuillery/angular-breadcrumb/issues/78))
* **ncyBreadcrumbText:** Add ncyBreadcrumbText directive ([82b2b443](http://github.com/ncuillery/angular-breadcrumb/commit/82b2b443fab220cd9ac7d3a8c90c1edc4291e54a), closes [#71](http://github.com/ncuillery/angular-breadcrumb/issues/71), [#83](http://github.com/ncuillery/angular-breadcrumb/issues/83))
<a name="0.3.3"></a>
### 0.3.3 (2014-12-16)
#### Bug Fixes
* **ncyBreadcrumb:** define `$$templates` with var instead of attaching it to `window` ([c35c9d25](http://github.com/ncuillery/angular-breadcrumb/commit/c35c9d255b5e2585d225a961d1efdb51d18f6a55), closes [#55](http://github.com/ncuillery/angular-breadcrumb/issues/55))
<a name="0.3.2"></a>
### 0.3.2 (2014-11-15)
* **npm:** nothing, it's only a blank release due to a network problem during the last `npm publish` (f...ing npm doesn't allow a republish with the same version number [npm-registry-couchapp#148](https://github.com/npm/npm-registry-couchapp/issues/148)).
<a name="0.3.1"></a>
### 0.3.1 (2014-11-15)
#### Bug Fixes
* **npm:** update package.json after (unclean) npm publish ([ab8161c2](http://github.com/ncuillery/angular-breadcrumb/commit/ab8161c25f98613f725b5e5ff8fe147acd60b365), closes [#52](http://github.com/ncuillery/angular-breadcrumb/issues/52))
* **sample:** Send correct url params for the room link in booking view ([876de49a](http://github.com/ncuillery/angular-breadcrumb/commit/876de49a9c5d6e2d75714a606238e9041ed49baf))
<a name="0.3.0"></a>
## 0.3.0 (2014-10-29)
#### Bug Fixes
* organize state-level options in `ncyBreadcrumb` key instead of `data` ([1ea436d3](http://github.com/ncuillery/angular-breadcrumb/commit/1ea436d3f6d5470b7ae3e71e71259dbd2422bc00), closes [#30](http://github.com/ncuillery/angular-breadcrumb/issues/30))
* curly braces appearing on title of sample app ([855e76cb](http://github.com/ncuillery/angular-breadcrumb/commit/855e76cb33fda607fa3caa230564b77b48262c40))
#### Features
* Add a global option to include abstract states ([6f0461ea](http://github.com/ncuillery/angular-breadcrumb/commit/6f0461ea7db36d8e10c29ed10de1f1c08d215a19), closes [#35](http://github.com/ncuillery/angular-breadcrumb/issues/35), [#28](http://github.com/ncuillery/angular-breadcrumb/issues/28))
* **$breadcrumb:**
* Support url params when using `ncyBreadcrumb.parent` property ([55730045](http://github.com/ncuillery/angular-breadcrumb/commit/55730045dcf3b4fb1048c67f1e18953505563ed4), closes [#46](http://github.com/ncuillery/angular-breadcrumb/issues/46))
* add the customization of the parent state with a function ([ada09015](http://github.com/ncuillery/angular-breadcrumb/commit/ada09015c49f05a94349dabf078f1ed621811aaa), closes [#32](http://github.com/ncuillery/angular-breadcrumb/issues/32))
* **ncyBreadcrumbLast:** Add a new directive rendering the last step ([1eef24fb](http://github.com/ncuillery/angular-breadcrumb/commit/1eef24fbe862a1e3308181c38f50755843cf4426), closes [#37](http://github.com/ncuillery/angular-breadcrumb/issues/37))
#### Breaking Changes
* state-level options has been moved under the custom key
`ncyBreadcrumb` in state's configuration.
To migrate the code follow the example below:
```
// Before
$stateProvider.state('A', {
url: '/a',
data: {
ncyBreadcrumbLabel: 'State A'
}
});
```
```
// After
$stateProvider.state('A', {
url: '/a',
ncyBreadcrumb: {
label: 'State A'
}
});
```
See [API reference](https://github.com/ncuillery/angular-breadcrumb/wiki/API-Reference) for more informations.
([1ea436d3](http://github.com/ncuillery/angular-breadcrumb/commit/1ea436d3f6d5470b7ae3e71e71259dbd2422bc00))
<a name="0.2.3"></a>
### 0.2.3 (2014-07-26)
#### Bug Fixes
* **$breadcrumb:** use `$stateParams` in case of unhierarchical states ([1c3c05e0](http://github.com/ncuillery/angular-breadcrumb/commit/1c3c05e0acac191fe2e76db2ef18da339caefaaa), closes [#29](http://github.com/ncuillery/angular-breadcrumb/issues/29))
<a name="0.2.2"></a>
### 0.2.2 (2014-06-23)
#### Bug Fixes
* catch the `$viewContentLoaded` earlier ([bb47dd54](http://github.com/ncuillery/angular-breadcrumb/commit/bb47dd54deb5efc579ccb9b1575e686803dee1c5), closes [#14](http://github.com/ncuillery/angular-breadcrumb/issues/14))
* **sample:**
* make the CRU(D) about rooms working ([3ca89ec7](http://github.com/ncuillery/angular-breadcrumb/commit/3ca89ec771fd20dc4ab2d733612bdcfb96ced703))
* prevent direct URL access to a day disabled in the datepicker ([95236916](http://github.com/ncuillery/angular-breadcrumb/commit/95236916e00b19464a3dfe3584ef1b18da9ffb25), closes [#17](http://github.com/ncuillery/angular-breadcrumb/issues/17))
* use the same variable in the datepicker and from url params for state `booking.day` ([646f7060](http://github.com/ncuillery/angular-breadcrumb/commit/646f70607e494f0e5e3c2483ed69f689684b2742), closes [#16](http://github.com/ncuillery/angular-breadcrumb/issues/16))
#### Features
* **ncyBreadcrumb:** watch every expression founded in labels ([1363515e](http://github.com/ncuillery/angular-breadcrumb/commit/1363515e20977ce2f39a1f5e5e1d701f0d7af296), closes [#20](http://github.com/ncuillery/angular-breadcrumb/issues/20))
<a name="0.2.1"></a>
### 0.2.1 (2014-05-16)
#### Bug Fixes
* **$breadcrumb:** check if a state has a parent when looking for an inheritated property ([77e668b5](http://github.com/ncuillery/angular-breadcrumb/commit/77e668b5eb759570a64c2a885e81580953af3201), closes [#11](http://github.com/ncuillery/angular-breadcrumb/issues/11))
<a name="0.2.0"></a>
### 0.2.0 (2014-05-08)
#### Bug Fixes
* **$breadcrumb:** remove abstract states from breadcrumb ([8a06c5ab](http://github.com/ncuillery/angular-breadcrumb/commit/8a06c5abce749027d48f7309d1aabea1e447dfd5), closes [#8](http://github.com/ncuillery/angular-breadcrumb/issues/8))
* **ncyBreadcrumb:** display the correct breadcrumb in case of direct access ([e1f455ba](http://github.com/ncuillery/angular-breadcrumb/commit/e1f455ba4def97d3fc76b53772867b5f9daf4232), closes [#10](http://github.com/ncuillery/angular-breadcrumb/issues/10))
#### Features
* **$breadcrumb:**
* add a configuration property for skipping a state in the breadcrumb ([dd255d90](http://github.com/ncuillery/angular-breadcrumb/commit/dd255d906c4231f44b48f066d4db197a9c6b9e27), closes [#9](http://github.com/ncuillery/angular-breadcrumb/issues/9))
* allow chain of states customization ([028e493a](http://github.com/ncuillery/angular-breadcrumb/commit/028e493a1ebcae5ae60b8a9d42b949262000d7df), closes [#7](http://github.com/ncuillery/angular-breadcrumb/issues/7))
* **ncyBreadcrumb:** add 'Element' declaration style '<ncy-breadcrumb />' ([b51441ea](http://github.com/ncuillery/angular-breadcrumb/commit/b51441eafb1659b782fea1f8668c7f455e1d6b4d))

View File

@ -1,52 +0,0 @@
# Contributing to angular-breadcrumb
I am very glad to see this project living with PR from contributors who trust in it. Here is some guidelines to keep the contributions useful and efficient.
## Development hints
### Installation
- Checkout the repository
- Run `npm install`
- Run `bower install`
### Test running
This module uses the classic AngularJS stack with:
- Karma (test runner)
- Jasmine (assertion framework)
- angular-mocks (AngularJS module for testing)
Run the test with the grunt task `grunt test`. It runs the tests with different versions of AngularJS.
### Test developing
Tests are build around modules with a specific `$stateProvider` configuration:
- [Basic configuration](https://github.com/ncuillery/angular-breadcrumb/blob/master/test/mock/test-modules.js#L6): Basic definitions (no template, no controller)
- [Interpolation configuration](https://github.com/ncuillery/angular-breadcrumb/blob/master/test/mock/test-modules.js#L21): States with bindings in `ncyBreadcrumbLabel`
- [HTML configuration](https://github.com/ncuillery/angular-breadcrumb/blob/master/test/mock/test-modules.js#L36): States with HTML in `ncyBreadcrumbLabel`
- [Sample configuration](https://github.com/ncuillery/angular-breadcrumb/blob/master/test/mock/test-modules.js#L41): Bridge towards the sample app configuration for using in tests
- [UI-router's configuration](https://github.com/ncuillery/angular-breadcrumb/blob/master/test/mock/test-ui-router-sample.js#L9): Clone of the UI-router sample app (complemented with breadcrumb configuration)
Theses modules are loaded by Karma and they are available in test specifications.
Specifications are generally related to the directive `ncyBreadcrumb` or the service `$breadcrumb`.
### Sample
If you are not familiar with JS testing. You can run the [sample](http://ncuillery.github.io/angular-breadcrumb/#/sample) locally for testing purposes by using `grunt sample`. Sources are live-reloaded after each changes.
## Submitting a Pull Request
- Fork the [repository](https://github.com/ncuillery/angular-breadcrumb/)
- Make your changes in a new git branch following the coding rules below.
- Run the grunt default task (by typing `grunt` or `grunt default`): it will run the tests and build the module in `dist` directory)
- Commit the changes (including the `dist` directory) by using the commit conventions explained below.
- Push and make the PR
## Coding rules
- When making changes on the source file, please check that your changes are covered by the tests. If not, create a new test case.
## Commit conventions
angular-breadcrumb uses the same strict conventions as AngularJS and UI-router. These conventions are explained [here](https://github.com/angular/angular.js/blob/master/CONTRIBUTING.md#-git-commit-guidelines).
It is very important to fit these conventions especially for types `fix` and `feature` which are used by the CHANGELOG.md generation (it uses the [grunt-conventional-changelog](https://github.com/btford/grunt-conventional-changelog)).

View File

@ -1,258 +0,0 @@
'use strict';
var LIVERELOAD_PORT = 35729;
var lrSnippet = require('connect-livereload')({ port: LIVERELOAD_PORT });
var mountFolder = function (connect, dir) {
return connect.static(require('path').resolve(dir));
};
module.exports = function (grunt) {
// Project configuration.
grunt.initConfig({
// Metadata.
pkg: grunt.file.readJSON('package.json'),
headerDev: '/*! <%= pkg.name %> - v<%= pkg.version %>-dev-<%= grunt.template.today("yyyy-mm-dd") %>\n',
headerRelease: '/*! <%= pkg.name %> - v<%= pkg.version %>\n',
banner: '<%= pkg.homepage ? "* " + pkg.homepage + "\\n" : "" %>' +
'* Copyright (c) <%= grunt.template.today("yyyy") %> <%= pkg.author.name %>;' +
' Licensed <%= _.pluck(pkg.licenses, "type").join(", ") %> */\n',
// Task configuration.
concat: {
dev: {
options: {
banner: '<%= headerDev %><%= banner %>\n(function (window, angular, undefined) {\n',
footer: '})(window, window.angular);\n',
stripBanners: true
},
src: ['src/<%= pkg.name %>.js'],
dest: 'dist/<%= pkg.name %>.js'
},
release: {
options: {
banner: '<%= headerRelease %><%= banner %>\n(function (window, angular, undefined) {\n',
footer: '})(window, window.angular);\n',
stripBanners: true
},
src: ['src/<%= pkg.name %>.js'],
dest: 'release/<%= pkg.name %>.js'
}
},
uglify: {
dev: {
options: {
banner: '<%= headerDev %><%= banner %>'
},
src: '<%= concat.dev.dest %>',
dest: 'dist/<%= pkg.name %>.min.js'
},
release: {
options: {
banner: '<%= headerRelease %><%= banner %>'
},
src: '<%= concat.release.dest %>',
dest: 'release/<%= pkg.name %>.min.js'
}
},
karma: {
unit: {
configFile: 'karma.conf.js'
}
},
jshint: {
options: {
jshintrc: '.jshintrc'
},
gruntfile: {
src: 'Gruntfile.js'
},
sources: {
options: {
jshintrc: 'src/.jshintrc'
},
src: ['src/**/*.js']
},
test: {
src: ['test/**/*.js']
}
},
watch: {
gruntfile: {
files: '<%= jshint.gruntfile.src %>',
tasks: ['jshint:gruntfile']
},
sources: {
files: '<%= jshint.sources.src %>',
tasks: ['jshint:sources', 'karma']
},
test: {
files: '<%= jshint.test.src %>',
tasks: ['jshint:test', 'karma']
},
sample: {
options: {
livereload: LIVERELOAD_PORT
},
tasks: 'copy:breadcrumb',
files: [
'sample/*.{css,js,html}',
'sample/controllers/*.{css,js,html}',
'sample/views/*.{css,js,html}',
'src/*.js'
]
}
},
copy: {
breadcrumb: {
files: [
{
flatten: true,
expand: true,
src: [
'src/angular-breadcrumb.js'
],
dest: 'sample/asset/'
}
]
},
asset: {
files: [
{
flatten: true,
expand: true,
src: [
'dist/angular-breadcrumb.js',
'bower_components/angular/angular.js',
'bower_components/angular-ui-router/release/angular-ui-router.js',
'bower_components/angular-ui-bootstrap-bower/ui-bootstrap-tpls.js',
'bower_components/bootstrap/docs/assets/css/bootstrap.css',
'bower_components/underscore/underscore.js'
],
dest: 'sample/asset/'
}
]
},
img: {
files: [
{
flatten: true,
expand: true,
src: [
'bower_components/bootstrap.css/img/glyphicons-halflings.png'
],
dest: 'sample/img/'
}
]
}
},
connect: {
options: {
port: 9000,
hostname: 'localhost'
},
livereload: {
options: {
middleware: function (connect) {
return [
lrSnippet,
mountFolder(connect, 'sample')
];
}
}
}
},
open: {
server: {
url: 'http://localhost:<%= connect.options.port %>/index.html'
}
},
bump: {
options: {
files: ['package.json', 'bower.json'],
updateConfigs: ['pkg']
}
},
clean: {
release: ["sample/*.zip"],
test: ["testDependencies/*"]
},
compress: {
release: {
options: {
archive: 'sample/<%= pkg.name %>-<%= pkg.version %>.zip'
},
files: [
{expand: true, cwd: 'release/', src: ['*.js']}
]
}
},
replace: {
release: {
src: ['sample/views/home.html'],
overwrite: true,
replacements: [{
from: /angular-breadcrumb-[0-9]+\.[0-9]+\.[0-9]+\.zip/g,
to: "angular-breadcrumb-<%= pkg.version %>.zip"
},
{
from: /\([0-9]+\.[0-9]+\.[0-9]+\)/g,
to: "(<%= pkg.version %>)"
}]
}
},
shell: {
testMinimal: {
command: 'bower install angular#=1.0.8 angular-mocks#=1.0.8 angular-sanitize#=1.0.8 angular-ui-router#=0.2.0 --config.directory=. --config.cwd=testDependencies'
},
test1dot2: {
command: 'bower install angular#=1.2.18 angular-mocks#=1.2.18 angular-sanitize#=1.2.18 angular-ui-router#=0.2.15 --config.directory=. --config.cwd=testDependencies'
},
testLatest: {
command: 'bower install angular angular-mocks angular-sanitize angular-ui-router --config.directory=. --config.cwd=testDependencies'
}
}
});
// These plugins provide necessary tasks.
grunt.loadNpmTasks('grunt-bump');
grunt.loadNpmTasks('grunt-contrib-clean');
grunt.loadNpmTasks('grunt-contrib-compress');
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.loadNpmTasks('grunt-contrib-copy');
grunt.loadNpmTasks('grunt-contrib-connect');
grunt.loadNpmTasks('grunt-conventional-changelog');
grunt.loadNpmTasks('grunt-karma');
grunt.loadNpmTasks('grunt-open');
grunt.loadNpmTasks('grunt-shell');
grunt.loadNpmTasks('grunt-text-replace');
grunt.registerTask('test', ['jshint', 'testMin', 'test1dot2', 'testLatest']);
grunt.registerTask('testMin', ['clean:test', 'shell:testMinimal', 'karma']);
grunt.registerTask('test1dot2', ['clean:test', 'shell:test1dot2', 'karma']);
grunt.registerTask('testLatest', ['clean:test', 'shell:testLatest', 'karma']);
grunt.registerTask('default', ['test', 'concat:dev', 'uglify:dev']);
grunt.registerTask('sample', ['concat:dev', 'copy:asset', 'copy:img', 'connect:livereload', 'open', 'watch']);
grunt.registerTask('release-prepare', 'Update all files for a release', function(target) {
if(!target) {
target = 'patch';
}
grunt.task.run(
'bump-only:' + target, // Version update
'test', // Tests
'concat:release', // Concat with release banner
'uglify:release', // Minify with release banner
'changelog', // Changelog update
'clean:release', // Delete old version download file
'compress:release', // New version download file
'replace:release' // Update version in download button (link & label)
);
});
};

View File

@ -1,24 +0,0 @@
The MIT License
Copyright (c) 2013 Nicolas Cuillery
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.

View File

@ -1,33 +0,0 @@
{
"name": "angular-breadcrumb",
"description": "AngularJS module that generates a breadcrumb from ui-router's states",
"version": "0.4.1",
"main": "release/angular-breadcrumb.js",
"ignore": [
"sample",
"src",
"test",
".bowerrc",
".coveralls.yml",
".gitignore",
".jshintrc",
".travis.yml",
"gruntfile.js",
"bower.json",
"karma.conf.js",
"libpeerconnection.log",
"package.json",
"README.md"
],
"dependencies": {
"angular": ">=1.0.8",
"angular-ui-router": ">=0.2.0"
},
"devDependencies": {
"bootstrap": "~2.3.2",
"angular-ui-bootstrap-bower": "~0.8.0",
"underscore": "~1.5.1",
"angular-mocks": ">=1.0.8",
"angular-sanitize": ">=1.0.8"
}
}

View File

@ -1,369 +0,0 @@
/*! angular-breadcrumb - v0.4.0-dev-2015-08-07
* http://ncuillery.github.io/angular-breadcrumb
* Copyright (c) 2015 Nicolas Cuillery; Licensed MIT */
(function (window, angular, undefined) {
'use strict';
function isAOlderThanB(scopeA, scopeB) {
if(angular.equals(scopeA.length, scopeB.length)) {
return scopeA > scopeB;
} else {
return scopeA.length > scopeB.length;
}
}
function parseStateRef(ref) {
var parsed = ref.replace(/\n/g, " ").match(/^([^(]+?)\s*(\((.*)\))?$/);
if (!parsed || parsed.length !== 4) { throw new Error("Invalid state ref '" + ref + "'"); }
return { state: parsed[1], paramExpr: parsed[3] || null };
}
function $Breadcrumb() {
var $$options = {
prefixStateName: null,
template: 'bootstrap3',
templateUrl: null,
includeAbstract : false
};
this.setOptions = function(options) {
angular.extend($$options, options);
};
this.$get = ['$state', '$stateParams', '$rootScope', function($state, $stateParams, $rootScope) {
var $lastViewScope = $rootScope;
// Early catch of $viewContentLoaded event
$rootScope.$on('$viewContentLoaded', function (event) {
// With nested views, the event occur several times, in "wrong" order
if(!event.targetScope.ncyBreadcrumbIgnore &&
isAOlderThanB(event.targetScope.$id, $lastViewScope.$id)) {
$lastViewScope = event.targetScope;
}
});
// Get the parent state
var $$parentState = function(state) {
// Check if state has explicit parent OR we try guess parent from its name
var parent = state.parent || (/^(.+)\.[^.]+$/.exec(state.name) || [])[1];
var isObjectParent = typeof parent === "object";
// if parent is a object reference, then extract the name
return isObjectParent ? parent.name : parent;
};
// Add the state in the chain if not already in and if not abstract
var $$addStateInChain = function(chain, stateRef) {
var conf,
parentParams,
ref = parseStateRef(stateRef),
force = false,
skip = false;
for(var i=0, l=chain.length; i<l; i+=1) {
if (chain[i].name === ref.state) {
return;
}
}
conf = $state.get(ref.state);
// Get breadcrumb options
if(conf.ncyBreadcrumb) {
if(conf.ncyBreadcrumb.force){ force = true; }
if(conf.ncyBreadcrumb.skip){ skip = true; }
}
if((!conf.abstract || $$options.includeAbstract || force) && !skip) {
if(ref.paramExpr) {
parentParams = $lastViewScope.$eval(ref.paramExpr);
}
conf.ncyBreadcrumbLink = $state.href(ref.state, parentParams || $stateParams || {});
chain.unshift(conf);
}
};
// Get the state for the parent step in the breadcrumb
var $$breadcrumbParentState = function(stateRef) {
var ref = parseStateRef(stateRef),
conf = $state.get(ref.state);
if(conf.ncyBreadcrumb && conf.ncyBreadcrumb.parent) {
// Handle the "parent" property of the breadcrumb, override the parent/child relation of the state
var isFunction = typeof conf.ncyBreadcrumb.parent === 'function';
var parentStateRef = isFunction ? conf.ncyBreadcrumb.parent($lastViewScope) : conf.ncyBreadcrumb.parent;
if(parentStateRef) {
return parentStateRef;
}
}
return $$parentState(conf);
};
return {
getTemplate: function(templates) {
if($$options.templateUrl) {
// templateUrl takes precedence over template
return null;
} else if(templates[$$options.template]) {
// Predefined templates (bootstrap, ...)
return templates[$$options.template];
} else {
return $$options.template;
}
},
getTemplateUrl: function() {
return $$options.templateUrl;
},
getStatesChain: function(exitOnFirst) { // Deliberately undocumented param, see getLastStep
var chain = [];
// From current state to the root
for(var stateRef = $state.$current.self.name; stateRef; stateRef=$$breadcrumbParentState(stateRef)) {
$$addStateInChain(chain, stateRef);
if(exitOnFirst && chain.length) {
return chain;
}
}
// Prefix state treatment
if($$options.prefixStateName) {
$$addStateInChain(chain, $$options.prefixStateName);
}
return chain;
},
getLastStep: function() {
var chain = this.getStatesChain(true);
return chain.length ? chain[0] : undefined;
},
$getLastViewScope: function() {
return $lastViewScope;
}
};
}];
}
var getExpression = function(interpolationFunction) {
if(interpolationFunction.expressions) {
return interpolationFunction.expressions;
} else {
var expressions = [];
angular.forEach(interpolationFunction.parts, function(part) {
if(angular.isFunction(part)) {
expressions.push(part.exp);
}
});
return expressions;
}
};
var registerWatchers = function(labelWatcherArray, interpolationFunction, viewScope, step) {
angular.forEach(getExpression(interpolationFunction), function(expression) {
var watcher = viewScope.$watch(expression, function() {
step.ncyBreadcrumbLabel = interpolationFunction(viewScope);
});
labelWatcherArray.push(watcher);
});
};
var deregisterWatchers = function(labelWatcherArray) {
angular.forEach(labelWatcherArray, function(deregisterWatch) {
deregisterWatch();
});
};
function BreadcrumbDirective($interpolate, $breadcrumb, $rootScope) {
var $$templates = {
bootstrap2: '<ul class="breadcrumb">' +
'<li ng-repeat="step in steps" ng-switch="$last || !!step.abstract" ng-class="{active: $last}">' +
'<a ng-switch-when="false" href="{{step.ncyBreadcrumbLink}}">{{step.ncyBreadcrumbLabel}}</a>' +
'<span ng-switch-when="true">{{step.ncyBreadcrumbLabel}}</span>' +
'<span class="divider" ng-hide="$last">/</span>' +
'</li>' +
'</ul>',
bootstrap3: '<ol class="breadcrumb">' +
'<li ng-repeat="step in steps" ng-class="{active: $last}" ng-switch="$last || !!step.abstract">' +
'<a ng-switch-when="false" href="{{step.ncyBreadcrumbLink}}">{{step.ncyBreadcrumbLabel}}</a>' +
'<span ng-switch-when="true">{{step.ncyBreadcrumbLabel}}</span>' +
'</li>' +
'</ol>'
};
return {
restrict: 'AE',
replace: true,
scope: {},
template: $breadcrumb.getTemplate($$templates),
templateUrl: $breadcrumb.getTemplateUrl(),
link: {
post: function postLink(scope) {
var labelWatchers = [];
var renderBreadcrumb = function() {
deregisterWatchers(labelWatchers);
labelWatchers = [];
var viewScope = $breadcrumb.$getLastViewScope();
scope.steps = $breadcrumb.getStatesChain();
angular.forEach(scope.steps, function (step) {
if (step.ncyBreadcrumb && step.ncyBreadcrumb.label) {
var parseLabel = $interpolate(step.ncyBreadcrumb.label);
step.ncyBreadcrumbLabel = parseLabel(viewScope);
// Watcher for further viewScope updates
registerWatchers(labelWatchers, parseLabel, viewScope, step);
} else {
step.ncyBreadcrumbLabel = step.name;
}
});
};
$rootScope.$on('$viewContentLoaded', function (event) {
if(!event.targetScope.ncyBreadcrumbIgnore) {
renderBreadcrumb();
}
});
// View(s) may be already loaded while the directive's linking
renderBreadcrumb();
}
}
};
}
BreadcrumbDirective.$inject = ['$interpolate', '$breadcrumb', '$rootScope'];
function BreadcrumbLastDirective($interpolate, $breadcrumb, $rootScope) {
return {
restrict: 'A',
scope: {},
template: '{{ncyBreadcrumbLabel}}',
compile: function(cElement, cAttrs) {
// Override the default template if ncyBreadcrumbLast has a value
var template = cElement.attr(cAttrs.$attr.ncyBreadcrumbLast);
if(template) {
cElement.html(template);
}
return {
post: function postLink(scope) {
var labelWatchers = [];
var renderLabel = function() {
deregisterWatchers(labelWatchers);
labelWatchers = [];
var viewScope = $breadcrumb.$getLastViewScope();
var lastStep = $breadcrumb.getLastStep();
if(lastStep) {
scope.ncyBreadcrumbLink = lastStep.ncyBreadcrumbLink;
if (lastStep.ncyBreadcrumb && lastStep.ncyBreadcrumb.label) {
var parseLabel = $interpolate(lastStep.ncyBreadcrumb.label);
scope.ncyBreadcrumbLabel = parseLabel(viewScope);
// Watcher for further viewScope updates
// Tricky last arg: the last step is the entire scope of the directive !
registerWatchers(labelWatchers, parseLabel, viewScope, scope);
} else {
scope.ncyBreadcrumbLabel = lastStep.name;
}
}
};
$rootScope.$on('$viewContentLoaded', function (event) {
if(!event.targetScope.ncyBreadcrumbIgnore) {
renderLabel();
}
});
// View(s) may be already loaded while the directive's linking
renderLabel();
}
};
}
};
}
BreadcrumbLastDirective.$inject = ['$interpolate', '$breadcrumb', '$rootScope'];
function BreadcrumbTextDirective($interpolate, $breadcrumb, $rootScope) {
return {
restrict: 'A',
scope: {},
template: '{{ncyBreadcrumbChain}}',
compile: function(cElement, cAttrs) {
// Override the default template if ncyBreadcrumbText has a value
var template = cElement.attr(cAttrs.$attr.ncyBreadcrumbText);
if(template) {
cElement.html(template);
}
var separator = cElement.attr(cAttrs.$attr.ncyBreadcrumbTextSeparator) || ' / ';
return {
post: function postLink(scope) {
var labelWatchers = [];
var registerWatchersText = function(labelWatcherArray, interpolationFunction, viewScope) {
angular.forEach(getExpression(interpolationFunction), function(expression) {
var watcher = viewScope.$watch(expression, function(newValue, oldValue) {
if (newValue !== oldValue) {
renderLabel();
}
});
labelWatcherArray.push(watcher);
});
};
var renderLabel = function() {
deregisterWatchers(labelWatchers);
labelWatchers = [];
var viewScope = $breadcrumb.$getLastViewScope();
var steps = $breadcrumb.getStatesChain();
var combinedLabels = [];
angular.forEach(steps, function (step) {
if (step.ncyBreadcrumb && step.ncyBreadcrumb.label) {
var parseLabel = $interpolate(step.ncyBreadcrumb.label);
combinedLabels.push(parseLabel(viewScope));
// Watcher for further viewScope updates
registerWatchersText(labelWatchers, parseLabel, viewScope);
} else {
combinedLabels.push(step.name);
}
});
scope.ncyBreadcrumbChain = combinedLabels.join(separator);
};
$rootScope.$on('$viewContentLoaded', function (event) {
if(!event.targetScope.ncyBreadcrumbIgnore) {
renderLabel();
}
});
// View(s) may be already loaded while the directive's linking
renderLabel();
}
};
}
};
}
BreadcrumbTextDirective.$inject = ['$interpolate', '$breadcrumb', '$rootScope'];
angular.module('ncy-angular-breadcrumb', ['ui.router.state'])
.provider('$breadcrumb', $Breadcrumb)
.directive('ncyBreadcrumb', BreadcrumbDirective)
.directive('ncyBreadcrumbLast', BreadcrumbLastDirective)
.directive('ncyBreadcrumbText', BreadcrumbTextDirective);
})(window, window.angular);

View File

@ -1,4 +0,0 @@
/*! angular-breadcrumb - v0.4.0-dev-2015-08-07
* http://ncuillery.github.io/angular-breadcrumb
* Copyright (c) 2015 Nicolas Cuillery; Licensed MIT */
!function(a,b,c){"use strict";function d(a,c){return b.equals(a.length,c.length)?a>c:a.length>c.length}function e(a){var b=a.replace(/\n/g," ").match(/^([^(]+?)\s*(\((.*)\))?$/);if(!b||4!==b.length)throw new Error("Invalid state ref '"+a+"'");return{state:b[1],paramExpr:b[3]||null}}function f(){var a={prefixStateName:null,template:"bootstrap3",templateUrl:null,includeAbstract:!1};this.setOptions=function(c){b.extend(a,c)},this.$get=["$state","$stateParams","$rootScope",function(b,f,g){var h=g;g.$on("$viewContentLoaded",function(a){!a.targetScope.ncyBreadcrumbIgnore&&d(a.targetScope.$id,h.$id)&&(h=a.targetScope)});var i=function(a){var b=a.parent||(/^(.+)\.[^.]+$/.exec(a.name)||[])[1],c="object"==typeof b;return c?b.name:b},j=function(c,d){for(var g,i,j=e(d),k=!1,l=!1,m=0,n=c.length;n>m;m+=1)if(c[m].name===j.state)return;g=b.get(j.state),g.ncyBreadcrumb&&(g.ncyBreadcrumb.force&&(k=!0),g.ncyBreadcrumb.skip&&(l=!0)),g["abstract"]&&!a.includeAbstract&&!k||l||(j.paramExpr&&(i=h.$eval(j.paramExpr)),g.ncyBreadcrumbLink=b.href(j.state,i||f||{}),c.unshift(g))},k=function(a){var c=e(a),d=b.get(c.state);if(d.ncyBreadcrumb&&d.ncyBreadcrumb.parent){var f="function"==typeof d.ncyBreadcrumb.parent,g=f?d.ncyBreadcrumb.parent(h):d.ncyBreadcrumb.parent;if(g)return g}return i(d)};return{getTemplate:function(b){return a.templateUrl?null:b[a.template]?b[a.template]:a.template},getTemplateUrl:function(){return a.templateUrl},getStatesChain:function(c){for(var d=[],e=b.$current.self.name;e;e=k(e))if(j(d,e),c&&d.length)return d;return a.prefixStateName&&j(d,a.prefixStateName),d},getLastStep:function(){var a=this.getStatesChain(!0);return a.length?a[0]:c},$getLastViewScope:function(){return h}}}]}function g(a,c,d){var e={bootstrap2:'<ul class="breadcrumb"><li ng-repeat="step in steps" ng-switch="$last || !!step.abstract" ng-class="{active: $last}"><a ng-switch-when="false" href="{{step.ncyBreadcrumbLink}}">{{step.ncyBreadcrumbLabel}}</a><span ng-switch-when="true">{{step.ncyBreadcrumbLabel}}</span><span class="divider" ng-hide="$last">/</span></li></ul>',bootstrap3:'<ol class="breadcrumb"><li ng-repeat="step in steps" ng-class="{active: $last}" ng-switch="$last || !!step.abstract"><a ng-switch-when="false" href="{{step.ncyBreadcrumbLink}}">{{step.ncyBreadcrumbLabel}}</a><span ng-switch-when="true">{{step.ncyBreadcrumbLabel}}</span></li></ol>'};return{restrict:"AE",replace:!0,scope:{},template:c.getTemplate(e),templateUrl:c.getTemplateUrl(),link:{post:function(e){var f=[],g=function(){l(f),f=[];var d=c.$getLastViewScope();e.steps=c.getStatesChain(),b.forEach(e.steps,function(b){if(b.ncyBreadcrumb&&b.ncyBreadcrumb.label){var c=a(b.ncyBreadcrumb.label);b.ncyBreadcrumbLabel=c(d),k(f,c,d,b)}else b.ncyBreadcrumbLabel=b.name})};d.$on("$viewContentLoaded",function(a){a.targetScope.ncyBreadcrumbIgnore||g()}),g()}}}}function h(a,b,c){return{restrict:"A",scope:{},template:"{{ncyBreadcrumbLabel}}",compile:function(d,e){var f=d.attr(e.$attr.ncyBreadcrumbLast);return f&&d.html(f),{post:function(d){var e=[],f=function(){l(e),e=[];var c=b.$getLastViewScope(),f=b.getLastStep();if(f)if(d.ncyBreadcrumbLink=f.ncyBreadcrumbLink,f.ncyBreadcrumb&&f.ncyBreadcrumb.label){var g=a(f.ncyBreadcrumb.label);d.ncyBreadcrumbLabel=g(c),k(e,g,c,d)}else d.ncyBreadcrumbLabel=f.name};c.$on("$viewContentLoaded",function(a){a.targetScope.ncyBreadcrumbIgnore||f()}),f()}}}}}function i(a,c,d){return{restrict:"A",scope:{},template:"{{ncyBreadcrumbChain}}",compile:function(e,f){var g=e.attr(f.$attr.ncyBreadcrumbText);g&&e.html(g);var h=e.attr(f.$attr.ncyBreadcrumbTextSeparator)||" / ";return{post:function(e){var f=[],g=function(a,c,d){b.forEach(j(c),function(b){var c=d.$watch(b,function(a,b){a!==b&&i()});a.push(c)})},i=function(){l(f),f=[];var d=c.$getLastViewScope(),i=c.getStatesChain(),j=[];b.forEach(i,function(b){if(b.ncyBreadcrumb&&b.ncyBreadcrumb.label){var c=a(b.ncyBreadcrumb.label);j.push(c(d)),g(f,c,d)}else j.push(b.name)}),e.ncyBreadcrumbChain=j.join(h)};d.$on("$viewContentLoaded",function(a){a.targetScope.ncyBreadcrumbIgnore||i()}),i()}}}}}var j=function(a){if(a.expressions)return a.expressions;var c=[];return b.forEach(a.parts,function(a){b.isFunction(a)&&c.push(a.exp)}),c},k=function(a,c,d,e){b.forEach(j(c),function(b){var f=d.$watch(b,function(){e.ncyBreadcrumbLabel=c(d)});a.push(f)})},l=function(a){b.forEach(a,function(a){a()})};g.$inject=["$interpolate","$breadcrumb","$rootScope"],h.$inject=["$interpolate","$breadcrumb","$rootScope"],i.$inject=["$interpolate","$breadcrumb","$rootScope"],b.module("ncy-angular-breadcrumb",["ui.router.state"]).provider("$breadcrumb",f).directive("ncyBreadcrumb",g).directive("ncyBreadcrumbLast",h).directive("ncyBreadcrumbText",i)}(window,window.angular);

View File

@ -1,369 +0,0 @@
/*! angular-breadcrumb - v0.4.1
* http://ncuillery.github.io/angular-breadcrumb
* Copyright (c) 2015 Nicolas Cuillery; Licensed MIT */
(function (window, angular, undefined) {
'use strict';
function isAOlderThanB(scopeA, scopeB) {
if(angular.equals(scopeA.length, scopeB.length)) {
return scopeA > scopeB;
} else {
return scopeA.length > scopeB.length;
}
}
function parseStateRef(ref) {
var parsed = ref.replace(/\n/g, " ").match(/^([^(]+?)\s*(\((.*)\))?$/);
if (!parsed || parsed.length !== 4) { throw new Error("Invalid state ref '" + ref + "'"); }
return { state: parsed[1], paramExpr: parsed[3] || null };
}
function $Breadcrumb() {
var $$options = {
prefixStateName: null,
template: 'bootstrap3',
templateUrl: null,
includeAbstract : false
};
this.setOptions = function(options) {
angular.extend($$options, options);
};
this.$get = ['$state', '$stateParams', '$rootScope', function($state, $stateParams, $rootScope) {
var $lastViewScope = $rootScope;
// Early catch of $viewContentLoaded event
$rootScope.$on('$viewContentLoaded', function (event) {
// With nested views, the event occur several times, in "wrong" order
if(!event.targetScope.ncyBreadcrumbIgnore &&
isAOlderThanB(event.targetScope.$id, $lastViewScope.$id)) {
$lastViewScope = event.targetScope;
}
});
// Get the parent state
var $$parentState = function(state) {
// Check if state has explicit parent OR we try guess parent from its name
var parent = state.parent || (/^(.+)\.[^.]+$/.exec(state.name) || [])[1];
var isObjectParent = typeof parent === "object";
// if parent is a object reference, then extract the name
return isObjectParent ? parent.name : parent;
};
// Add the state in the chain if not already in and if not abstract
var $$addStateInChain = function(chain, stateRef) {
var conf,
parentParams,
ref = parseStateRef(stateRef),
force = false,
skip = false;
for(var i=0, l=chain.length; i<l; i+=1) {
if (chain[i].name === ref.state) {
return;
}
}
conf = $state.get(ref.state);
// Get breadcrumb options
if(conf.ncyBreadcrumb) {
if(conf.ncyBreadcrumb.force){ force = true; }
if(conf.ncyBreadcrumb.skip){ skip = true; }
}
if((!conf.abstract || $$options.includeAbstract || force) && !skip) {
if(ref.paramExpr) {
parentParams = $lastViewScope.$eval(ref.paramExpr);
}
conf.ncyBreadcrumbLink = $state.href(ref.state, parentParams || $stateParams || {});
chain.unshift(conf);
}
};
// Get the state for the parent step in the breadcrumb
var $$breadcrumbParentState = function(stateRef) {
var ref = parseStateRef(stateRef),
conf = $state.get(ref.state);
if(conf.ncyBreadcrumb && conf.ncyBreadcrumb.parent) {
// Handle the "parent" property of the breadcrumb, override the parent/child relation of the state
var isFunction = typeof conf.ncyBreadcrumb.parent === 'function';
var parentStateRef = isFunction ? conf.ncyBreadcrumb.parent($lastViewScope) : conf.ncyBreadcrumb.parent;
if(parentStateRef) {
return parentStateRef;
}
}
return $$parentState(conf);
};
return {
getTemplate: function(templates) {
if($$options.templateUrl) {
// templateUrl takes precedence over template
return null;
} else if(templates[$$options.template]) {
// Predefined templates (bootstrap, ...)
return templates[$$options.template];
} else {
return $$options.template;
}
},
getTemplateUrl: function() {
return $$options.templateUrl;
},
getStatesChain: function(exitOnFirst) { // Deliberately undocumented param, see getLastStep
var chain = [];
// From current state to the root
for(var stateRef = $state.$current.self.name; stateRef; stateRef=$$breadcrumbParentState(stateRef)) {
$$addStateInChain(chain, stateRef);
if(exitOnFirst && chain.length) {
return chain;
}
}
// Prefix state treatment
if($$options.prefixStateName) {
$$addStateInChain(chain, $$options.prefixStateName);
}
return chain;
},
getLastStep: function() {
var chain = this.getStatesChain(true);
return chain.length ? chain[0] : undefined;
},
$getLastViewScope: function() {
return $lastViewScope;
}
};
}];
}
var getExpression = function(interpolationFunction) {
if(interpolationFunction.expressions) {
return interpolationFunction.expressions;
} else {
var expressions = [];
angular.forEach(interpolationFunction.parts, function(part) {
if(angular.isFunction(part)) {
expressions.push(part.exp);
}
});
return expressions;
}
};
var registerWatchers = function(labelWatcherArray, interpolationFunction, viewScope, step) {
angular.forEach(getExpression(interpolationFunction), function(expression) {
var watcher = viewScope.$watch(expression, function() {
step.ncyBreadcrumbLabel = interpolationFunction(viewScope);
});
labelWatcherArray.push(watcher);
});
};
var deregisterWatchers = function(labelWatcherArray) {
angular.forEach(labelWatcherArray, function(deregisterWatch) {
deregisterWatch();
});
};
function BreadcrumbDirective($interpolate, $breadcrumb, $rootScope) {
var $$templates = {
bootstrap2: '<ul class="breadcrumb">' +
'<li ng-repeat="step in steps" ng-switch="$last || !!step.abstract" ng-class="{active: $last}">' +
'<a ng-switch-when="false" href="{{step.ncyBreadcrumbLink}}">{{step.ncyBreadcrumbLabel}}</a>' +
'<span ng-switch-when="true">{{step.ncyBreadcrumbLabel}}</span>' +
'<span class="divider" ng-hide="$last">/</span>' +
'</li>' +
'</ul>',
bootstrap3: '<ol class="breadcrumb">' +
'<li ng-repeat="step in steps" ng-class="{active: $last}" ng-switch="$last || !!step.abstract">' +
'<a ng-switch-when="false" href="{{step.ncyBreadcrumbLink}}">{{step.ncyBreadcrumbLabel}}</a>' +
'<span ng-switch-when="true">{{step.ncyBreadcrumbLabel}}</span>' +
'</li>' +
'</ol>'
};
return {
restrict: 'AE',
replace: true,
scope: {},
template: $breadcrumb.getTemplate($$templates),
templateUrl: $breadcrumb.getTemplateUrl(),
link: {
post: function postLink(scope) {
var labelWatchers = [];
var renderBreadcrumb = function() {
deregisterWatchers(labelWatchers);
labelWatchers = [];
var viewScope = $breadcrumb.$getLastViewScope();
scope.steps = $breadcrumb.getStatesChain();
angular.forEach(scope.steps, function (step) {
if (step.ncyBreadcrumb && step.ncyBreadcrumb.label) {
var parseLabel = $interpolate(step.ncyBreadcrumb.label);
step.ncyBreadcrumbLabel = parseLabel(viewScope);
// Watcher for further viewScope updates
registerWatchers(labelWatchers, parseLabel, viewScope, step);
} else {
step.ncyBreadcrumbLabel = step.name;
}
});
};
$rootScope.$on('$viewContentLoaded', function (event) {
if(!event.targetScope.ncyBreadcrumbIgnore) {
renderBreadcrumb();
}
});
// View(s) may be already loaded while the directive's linking
renderBreadcrumb();
}
}
};
}
BreadcrumbDirective.$inject = ['$interpolate', '$breadcrumb', '$rootScope'];
function BreadcrumbLastDirective($interpolate, $breadcrumb, $rootScope) {
return {
restrict: 'A',
scope: {},
template: '{{ncyBreadcrumbLabel}}',
compile: function(cElement, cAttrs) {
// Override the default template if ncyBreadcrumbLast has a value
var template = cElement.attr(cAttrs.$attr.ncyBreadcrumbLast);
if(template) {
cElement.html(template);
}
return {
post: function postLink(scope) {
var labelWatchers = [];
var renderLabel = function() {
deregisterWatchers(labelWatchers);
labelWatchers = [];
var viewScope = $breadcrumb.$getLastViewScope();
var lastStep = $breadcrumb.getLastStep();
if(lastStep) {
scope.ncyBreadcrumbLink = lastStep.ncyBreadcrumbLink;
if (lastStep.ncyBreadcrumb && lastStep.ncyBreadcrumb.label) {
var parseLabel = $interpolate(lastStep.ncyBreadcrumb.label);
scope.ncyBreadcrumbLabel = parseLabel(viewScope);
// Watcher for further viewScope updates
// Tricky last arg: the last step is the entire scope of the directive !
registerWatchers(labelWatchers, parseLabel, viewScope, scope);
} else {
scope.ncyBreadcrumbLabel = lastStep.name;
}
}
};
$rootScope.$on('$viewContentLoaded', function (event) {
if(!event.targetScope.ncyBreadcrumbIgnore) {
renderLabel();
}
});
// View(s) may be already loaded while the directive's linking
renderLabel();
}
};
}
};
}
BreadcrumbLastDirective.$inject = ['$interpolate', '$breadcrumb', '$rootScope'];
function BreadcrumbTextDirective($interpolate, $breadcrumb, $rootScope) {
return {
restrict: 'A',
scope: {},
template: '{{ncyBreadcrumbChain}}',
compile: function(cElement, cAttrs) {
// Override the default template if ncyBreadcrumbText has a value
var template = cElement.attr(cAttrs.$attr.ncyBreadcrumbText);
if(template) {
cElement.html(template);
}
var separator = cElement.attr(cAttrs.$attr.ncyBreadcrumbTextSeparator) || ' / ';
return {
post: function postLink(scope) {
var labelWatchers = [];
var registerWatchersText = function(labelWatcherArray, interpolationFunction, viewScope) {
angular.forEach(getExpression(interpolationFunction), function(expression) {
var watcher = viewScope.$watch(expression, function(newValue, oldValue) {
if (newValue !== oldValue) {
renderLabel();
}
});
labelWatcherArray.push(watcher);
});
};
var renderLabel = function() {
deregisterWatchers(labelWatchers);
labelWatchers = [];
var viewScope = $breadcrumb.$getLastViewScope();
var steps = $breadcrumb.getStatesChain();
var combinedLabels = [];
angular.forEach(steps, function (step) {
if (step.ncyBreadcrumb && step.ncyBreadcrumb.label) {
var parseLabel = $interpolate(step.ncyBreadcrumb.label);
combinedLabels.push(parseLabel(viewScope));
// Watcher for further viewScope updates
registerWatchersText(labelWatchers, parseLabel, viewScope);
} else {
combinedLabels.push(step.name);
}
});
scope.ncyBreadcrumbChain = combinedLabels.join(separator);
};
$rootScope.$on('$viewContentLoaded', function (event) {
if(!event.targetScope.ncyBreadcrumbIgnore) {
renderLabel();
}
});
// View(s) may be already loaded while the directive's linking
renderLabel();
}
};
}
};
}
BreadcrumbTextDirective.$inject = ['$interpolate', '$breadcrumb', '$rootScope'];
angular.module('ncy-angular-breadcrumb', ['ui.router.state'])
.provider('$breadcrumb', $Breadcrumb)
.directive('ncyBreadcrumb', BreadcrumbDirective)
.directive('ncyBreadcrumbLast', BreadcrumbLastDirective)
.directive('ncyBreadcrumbText', BreadcrumbTextDirective);
})(window, window.angular);

View File

@ -1,4 +0,0 @@
/*! angular-breadcrumb - v0.4.1
* http://ncuillery.github.io/angular-breadcrumb
* Copyright (c) 2015 Nicolas Cuillery; Licensed MIT */
!function(a,b,c){"use strict";function d(a,c){return b.equals(a.length,c.length)?a>c:a.length>c.length}function e(a){var b=a.replace(/\n/g," ").match(/^([^(]+?)\s*(\((.*)\))?$/);if(!b||4!==b.length)throw new Error("Invalid state ref '"+a+"'");return{state:b[1],paramExpr:b[3]||null}}function f(){var a={prefixStateName:null,template:"bootstrap3",templateUrl:null,includeAbstract:!1};this.setOptions=function(c){b.extend(a,c)},this.$get=["$state","$stateParams","$rootScope",function(b,f,g){var h=g;g.$on("$viewContentLoaded",function(a){!a.targetScope.ncyBreadcrumbIgnore&&d(a.targetScope.$id,h.$id)&&(h=a.targetScope)});var i=function(a){var b=a.parent||(/^(.+)\.[^.]+$/.exec(a.name)||[])[1],c="object"==typeof b;return c?b.name:b},j=function(c,d){for(var g,i,j=e(d),k=!1,l=!1,m=0,n=c.length;n>m;m+=1)if(c[m].name===j.state)return;g=b.get(j.state),g.ncyBreadcrumb&&(g.ncyBreadcrumb.force&&(k=!0),g.ncyBreadcrumb.skip&&(l=!0)),g["abstract"]&&!a.includeAbstract&&!k||l||(j.paramExpr&&(i=h.$eval(j.paramExpr)),g.ncyBreadcrumbLink=b.href(j.state,i||f||{}),c.unshift(g))},k=function(a){var c=e(a),d=b.get(c.state);if(d.ncyBreadcrumb&&d.ncyBreadcrumb.parent){var f="function"==typeof d.ncyBreadcrumb.parent,g=f?d.ncyBreadcrumb.parent(h):d.ncyBreadcrumb.parent;if(g)return g}return i(d)};return{getTemplate:function(b){return a.templateUrl?null:b[a.template]?b[a.template]:a.template},getTemplateUrl:function(){return a.templateUrl},getStatesChain:function(c){for(var d=[],e=b.$current.self.name;e;e=k(e))if(j(d,e),c&&d.length)return d;return a.prefixStateName&&j(d,a.prefixStateName),d},getLastStep:function(){var a=this.getStatesChain(!0);return a.length?a[0]:c},$getLastViewScope:function(){return h}}}]}function g(a,c,d){var e={bootstrap2:'<ul class="breadcrumb"><li ng-repeat="step in steps" ng-switch="$last || !!step.abstract" ng-class="{active: $last}"><a ng-switch-when="false" href="{{step.ncyBreadcrumbLink}}">{{step.ncyBreadcrumbLabel}}</a><span ng-switch-when="true">{{step.ncyBreadcrumbLabel}}</span><span class="divider" ng-hide="$last">/</span></li></ul>',bootstrap3:'<ol class="breadcrumb"><li ng-repeat="step in steps" ng-class="{active: $last}" ng-switch="$last || !!step.abstract"><a ng-switch-when="false" href="{{step.ncyBreadcrumbLink}}">{{step.ncyBreadcrumbLabel}}</a><span ng-switch-when="true">{{step.ncyBreadcrumbLabel}}</span></li></ol>'};return{restrict:"AE",replace:!0,scope:{},template:c.getTemplate(e),templateUrl:c.getTemplateUrl(),link:{post:function(e){var f=[],g=function(){l(f),f=[];var d=c.$getLastViewScope();e.steps=c.getStatesChain(),b.forEach(e.steps,function(b){if(b.ncyBreadcrumb&&b.ncyBreadcrumb.label){var c=a(b.ncyBreadcrumb.label);b.ncyBreadcrumbLabel=c(d),k(f,c,d,b)}else b.ncyBreadcrumbLabel=b.name})};d.$on("$viewContentLoaded",function(a){a.targetScope.ncyBreadcrumbIgnore||g()}),g()}}}}function h(a,b,c){return{restrict:"A",scope:{},template:"{{ncyBreadcrumbLabel}}",compile:function(d,e){var f=d.attr(e.$attr.ncyBreadcrumbLast);return f&&d.html(f),{post:function(d){var e=[],f=function(){l(e),e=[];var c=b.$getLastViewScope(),f=b.getLastStep();if(f)if(d.ncyBreadcrumbLink=f.ncyBreadcrumbLink,f.ncyBreadcrumb&&f.ncyBreadcrumb.label){var g=a(f.ncyBreadcrumb.label);d.ncyBreadcrumbLabel=g(c),k(e,g,c,d)}else d.ncyBreadcrumbLabel=f.name};c.$on("$viewContentLoaded",function(a){a.targetScope.ncyBreadcrumbIgnore||f()}),f()}}}}}function i(a,c,d){return{restrict:"A",scope:{},template:"{{ncyBreadcrumbChain}}",compile:function(e,f){var g=e.attr(f.$attr.ncyBreadcrumbText);g&&e.html(g);var h=e.attr(f.$attr.ncyBreadcrumbTextSeparator)||" / ";return{post:function(e){var f=[],g=function(a,c,d){b.forEach(j(c),function(b){var c=d.$watch(b,function(a,b){a!==b&&i()});a.push(c)})},i=function(){l(f),f=[];var d=c.$getLastViewScope(),i=c.getStatesChain(),j=[];b.forEach(i,function(b){if(b.ncyBreadcrumb&&b.ncyBreadcrumb.label){var c=a(b.ncyBreadcrumb.label);j.push(c(d)),g(f,c,d)}else j.push(b.name)}),e.ncyBreadcrumbChain=j.join(h)};d.$on("$viewContentLoaded",function(a){a.targetScope.ncyBreadcrumbIgnore||i()}),i()}}}}}var j=function(a){if(a.expressions)return a.expressions;var c=[];return b.forEach(a.parts,function(a){b.isFunction(a)&&c.push(a.exp)}),c},k=function(a,c,d,e){b.forEach(j(c),function(b){var f=d.$watch(b,function(){e.ncyBreadcrumbLabel=c(d)});a.push(f)})},l=function(a){b.forEach(a,function(a){a()})};g.$inject=["$interpolate","$breadcrumb","$rootScope"],h.$inject=["$interpolate","$breadcrumb","$rootScope"],i.$inject=["$interpolate","$breadcrumb","$rootScope"],b.module("ncy-angular-breadcrumb",["ui.router.state"]).provider("$breadcrumb",f).directive("ncyBreadcrumb",g).directive("ncyBreadcrumbLast",h).directive("ncyBreadcrumbText",i)}(window,window.angular);

View File

@ -1,26 +0,0 @@
{
"name": "angular-codemirror",
"version": "1.0.2",
"dependencies": {
"angular": "latest",
"angular-route": "latest",
"jquery": "latest",
"jqueryui": "latest",
"components-font-awesome": "latest",
"twitter": "latest",
"js-yaml": "latest",
"jsonlint": "latest",
"codemirror": "latest"
},
"homepage": "https://github.com/chouseknecht/angular-codemirror",
"_release": "1.0.2",
"_resolution": {
"type": "version",
"tag": "v1.0.2",
"commit": "94b7aac548b036f4fbd94e56129ed9574e472616"
},
"_source": "git://github.com/chouseknecht/angular-codemirror.git",
"_target": "~1.0.2",
"_originalSource": "angular-codemirror",
"_direct": true
}

View File

@ -1,2 +0,0 @@
bower_components/
node_modules/

View File

@ -1,21 +0,0 @@
{
// Details: https://github.com/victorporof/Sublime-JSHint#using-your-own-jshintrc-options
// Example: https://github.com/jshint/jshint/blob/master/examples/.jshintrc
// Documentation: http://www.jshint.com/docs/
"browser": true,
"jquery": true,
"esnext": true,
"globalstrict": true,
"globals": { "angular":false, "alert":true, "CodeMirror":false, "jsyaml":false },
"strict": false,
"quotmark": false,
"smarttabs": true,
"trailing": true,
"undef": true,
"unused": true,
"eqeqeq": true,
"indent": 4,
"onevar": true,
"newcap": false
}

View File

@ -1,24 +0,0 @@
AngularCodeMirror
================
Copyright (c) 2014 Chris Houseknecht
The MIT License (MIT)
Permission is hereby granted, free of charge, to any person obtaining a copy
of angular-codemirror 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.

View File

@ -1,29 +0,0 @@
AngularCodeMirror
=================
Incorporate [CodeMirror](http://www.codemirror.net) into your AngularJS app. Presents the editor in a resizable, draggable modal dialog styled with Twitter Bootstrap. Pass in any valid CodeMirror options to make the editor fit your app needs.
Installation:
-------------
bower install angular-codemirror
Example App:
------------
With [Node.js](http://nodejs.org) installed, you can run the sample app locally. Clone the repo to a local projects directory, install package dependencies, and then run with the included server:
cd projects
git clone git@github.com:chouseknecht/angular-codemirror.git
cd angular-codemirror
bower install
node ./scripts/web-server.js
Point your browser to http://localhost:8000/app/index.html. Click the code editor link.
How To:
-------
If you installed with Bower, then all the dependencies will exist in bower_components. See app/index.html for a template of how to include all the needed .js and .css files. If you want to install dependencies manually, review bower.json for a list of what's needed.
Check the CodeMirror documentation to see what needs to be included for the mode and options you choose. Again, if you installed with Bower, then everything you need should be found under bower_components.
Incorporate into your Angular app by following the example in app/js/sampleApp.js.

View File

@ -1,68 +0,0 @@
/*********************************************
* Copyright (c) 2013-2014 Chris Houseknecht
*
* SampleForm.js
*
* Demonstrate some of the things you can do with angular-forms.js to
* generate clean, consistent forms in your app.
*
*/
body {
padding-bottom: 80px;
}
#parse-type-group {
margin: 15px 0;
}
#parse-type-label {
display: inline-block;
padding-right: 10px;
font-weight: bold;
}
textarea {
resize: none;
}
a,
a:active,
a:link,
a:hover {
text-decoration: none;
}
.external-editor-link {
display: inline-block;
margin-left: 20px;
}
/*.ui-dialog-titlebar-close {
color: #000;
border: none;
background-color: transparent;
}*/
.red-txt {
color: #dd1b16;
}
.navbar-default .navbar-brand {
font-size: 24px;
color: #000;
}
.navigation {
margin-top: 20px;
padding-right: 15px;
}
.footer {
margin-top: 30px;
}
.footer .navbar-brand {
margin-bottom: 20px;
padding-right: 0;
}

View File

@ -1,70 +0,0 @@
<!doctype html>
<html lang="en" ng-app="sampleApp">
<head>
<meta charset="utf-8">
<title>AngularCodeMirror | Sample application</title>
<link rel="stylesheet" href="/bower_components/twitter/dist/css/bootstrap.min.css" >
<link rel="stylesheet" href="/bower_components/components-font-awesome/css/font-awesome.min.css" >
<link rel="stylesheet" href="/bower_components/jqueryui/themes/redmond/jquery-ui.min.css" >
<link rel="stylesheet" href="/bower_components/codemirror/lib/codemirror.css" >
<link rel="stylesheet" href="/bower_components/codemirror/theme/elegant.css" >
<link rel="stylesheet" href="/bower_components/codemirror/addon/lint/lint.css" >
<link rel="stylesheet" href="/lib/AngularCodeMirror.css" >
<link rel="stylesheet" href="/app/css/sampleApp.css" >
<script src="/bower_components/angular/angular.min.js"></script>
<script src="/bower_components/angular-route/angular-route.min.js"></script>
<script src="/app/js/sampleApp.js"></script>
<script src="/lib/AngularCodeMirror.js"></script>
</head>
<body>
<nav class="navbar navbar-default" role="navigation">
<div class="container">
<!-- Brand and toggle get grouped for better mobile display -->
<div class="navbar-header">
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target="#nb-collapse-1">
<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" href="/">Angular CodeMirror</a>
</div>
</div>
</nav>
<div class="container">
<div id="main-view" ng-view></div>
</div>
<div class="footer navbar-default navbar-fixed-bottom">
<div class="container">
<div class="row">
<div class="col-lg-12">
<a class="navbar-brand pull-right" href="/">Angular CodeMirror</a>
</div>
</div>
</div>
</div>
<script src="/bower_components/jquery/dist/jquery.min.js"></script>
<script src="/bower_components/jqueryui/ui/minified/jquery-ui.min.js"></script>
<script src="/bower_components/twitter/dist/js/bootstrap.min.js"></script>
<!-- bits to support code mirror -->
<script src="/bower_components/js-yaml/js-yaml.min.js"></script>
<script src="/bower_components/jsonlint/lib/jsonlint.js"></script>
<script src="/bower_components/codemirror/lib/codemirror.js"></script>
<script src="/bower_components/codemirror/mode/javascript/javascript.js"></script>
<script src="/bower_components/codemirror/mode/yaml/yaml.js"></script>
<script src="/bower_components/codemirror/addon/lint/lint.js"></script>
<script src="/bower_components/codemirror/addon/lint/json-lint.js"></script>
<script src="/lib/yaml-lint.js"></script>
<script src="/bower_components/codemirror/addon/edit/closebrackets.js"></script>
<script src="/bower_components/codemirror/addon/edit/matchbrackets.js"></script>
<script src="/bower_components/codemirror/addon/selection/active-line.js"></script>
</body>
</html>

View File

@ -1,135 +0,0 @@
/**********************************************
* sampleApp.js
*
* Copyright (c) 2013-2014 Chris Houseknecht
*
* Distributed under The MIT License (MIT)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
'use strict';
angular.module('sampleApp', ['ngRoute', 'AngularCodeMirrorModule'])
.config(['$routeProvider', function($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'partials/main.html',
controller: 'sampleController'
})
.otherwise({
redirectTo: '/'
});
}])
.controller('sampleController', ['$scope', 'AngularCodeMirror', function($scope, AngularCodeMirror) {
$scope.parseType = 'json';
$scope.codeValue = '{}';
var container = document.getElementById('main-view'),
modes = {
yaml: {
mode:"text/x-yaml",
matchBrackets: true,
autoCloseBrackets: true,
styleActiveLine: true,
lineNumbers: true,
gutters: ["CodeMirror-lint-markers"],
lint: true
},
json: {
mode: "application/json",
styleActiveLine: true,
matchBrackets: true,
autoCloseBrackets: true,
lineNumbers: true,
gutters: ["CodeMirror-lint-markers"],
lint: true
}
},
codeMirror = AngularCodeMirror();
codeMirror.addModes(modes);
$scope.parseTypeChange = function() {
var json_obj;
if ($scope.parseType === 'json') {
// converting yaml to json
try {
json_obj = jsyaml.load($scope.codeValue);
if ($.isEmptyObject(json_obj)) {
$scope.codeValue = "{}";
}
else {
$scope.codeValue = JSON.stringify(json_obj, null, " ");
}
}
catch (e) {
alert('Failed to parse valid YAML. ' + e.message);
setTimeout( function() { $scope.$apply( function() { $scope.parseType = 'yaml'; }); }, 500);
}
}
else {
// convert json to yaml
try {
json_obj = JSON.parse($scope.codeValue);
if ($.isEmptyObject(json_obj)) {
$scope.codeValue = '---';
}
else {
$scope.codeValue = jsyaml.safeDump(json_obj);
}
}
catch (e) {
alert('Failed to parse valid JSON. ' + e.message);
setTimeout( function() { $scope.$apply( function() { $scope.parseType = 'json'; }); }, 500 );
}
}
};
$scope.showCodeEditor = function() {
var title = 'Edit ' + $scope.parseType.toUpperCase();
codeMirror.show({
scope: $scope,
container: container,
mode: $scope.parseType,
model: 'codeValue',
title: title
});
};
}])
.directive('afTooltip', [ function() {
return {
link: function(scope, element, attrs) {
var placement = (attrs.placement) ? attrs.placement : 'top';
$(element).tooltip({
html: true,
placement: placement,
title: attrs.afTooltip,
trigger: 'hover',
container: 'body'
});
}
};
}]);

View File

@ -1,20 +0,0 @@
<div class="row">
<div class="col-lg-12">
<h4>CodeMirror Example</h4>
<div id="parse-type-group">
<div id="parse-type-label">Parse Type:</div>
<label class="radio-inline"><input type="radio" name="parsetype" value="json" ng-model="parseType"
ng-change="parseTypeChange()">JSON</label>
<label class="radio-inline"><input type="radio" name="parsetype" value="yaml" ng-model="parseType"
ng-change="parseTypeChange()">YAML</label>
<a class="external-editor-link" ng-click="showCodeEditor('code')" data-placement="top"
af-tooltip="View in code editor" href=""><i class="fa fa-external-link"></i> Code Editor</a>
</div>
<form>
<div class="form-group">
<textarea rows="10" name="code" id="code_textarea" class="form-control" ng-model="codeValue"></textarea>
</div>
</form>
</div><!-- col-lg-12 -->
</div><!-- row -->

View File

@ -1,15 +0,0 @@
{
"name": "angular-codemirror",
"version": "0.0.3",
"dependencies": {
"angular": "latest",
"angular-route": "latest",
"jquery": "latest",
"jqueryui": "latest",
"components-font-awesome": "latest",
"twitter": "latest",
"js-yaml": "latest",
"jsonlint": "latest",
"codemirror": "latest"
}
}

View File

@ -1,110 +0,0 @@
/**********************************************
* AngularCodeMirror.css
*
* CodeMirror.css overrides
*
* Copyright (c) 2014 Chris Houseknecht
*
* The MIT License (MIT)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of angular-codemirror and associated files and documentation (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.
*
*/
.CodeMirror {
height: auto;
}
.CodeMirror-activeline-background {
background-color: #f7f7f7;
}
/* Modal dialog overrides to make jqueryui dialog blend in with Twitter.
Why? Twitter's modal is not draggable or resizable, which is not very
useful for a code editor */
.ui-dialog-title {
font-size: 22px;
color: #1778c3;
font-weight: bold;
line-height: normal;
}
.ui-dialog .close {
font-size: 18px;
font-weight: bold;
font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;
line-height: 1;
opacity: .7;
text-shadow: 0 1px 0 #ffffff;
}
.ui-dialog .ui-widget-header {
border-radius: 0;
border: none;
border-bottom: 1px solid #A9A9A9;
height: 55px;
}
.ui-dialog .ui-dialog-titlebar {
padding-bottom: 0;
padding-top: 12px;
}
.ui-dialog .ui-dialog-titlebar {
background-image: none;
background-color: #ffffff;
border-color: #ffffff;
color: #A9A9A9;
}
.ui-dialog .ui-resizable-se {
right: 5px;
bottom: 5px;
background-position: -80px -224px;
color: #171717;
}
.ui-dialog-buttonset button.btn.btn-default.ui-state-hover,
.ui-dialog-buttonset button.btn.btn-default.ui-state-active,
.ui-dialog-buttonset button.btn.btn-default.ui-state-focus {
font-weight: normal;
}
.ui-dialog-buttonset button.btn.btn-primary.ui-state-hover,
.ui-dialog-buttonset button.btn.btn-primary.ui-state-active,
.ui-dialog-buttonset button.btn.btn-primary.ui-state-focus {
background-image: none;
color: #ffffff;
background-color: #2a6496;
border-color: #285e8e;
text-decoration: none;
font-weight: normal;
}
/* Bring the overlay above any TB fixed navs and darken it to match */
.ui-widget-overlay.ui-front {
background-image: none;
background-color: #000;
opacity: .6;
z-index: 1040;
}
/* Make sure code editor dialog is always at top of stack */
[aria-describedby=af-code-editor-modal].ui-front {
z-index: 2050;
}
.CodeMirror-lint-tooltip {
z-index: 2060;
}

View File

@ -1,188 +0,0 @@
/**********************************************
* AngularCodeMirror.js
*
* Copyright (c) 2014 Chris Houseknecht
*
* The MIT License (MIT)
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of angular-codemirror and associated files and documentation (the "Software"),
* to deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
'use strict';
angular.module('AngularCodeMirrorModule', [])
.factory('AngularCodeMirror', [ function() {
return function() {
var fn = function() {
this.myCodeMirror = null;
this.element = null;
this.showTextArea = function(params) {
var self = this,
element = (typeof params.element === "object") ? params.element : document.getElementById(params.element),
scope = params.scope,
model = params.model,
mode = params.mode,
onReady = params.onReady,
onChange = params.onChange,
height = 0;
self.element = $(element);
// We don't want to touch the original textarea. Angular likely has a model and other listeners
// attached to it. In prior iterations attaching CodeMirror to it seemed to go bad, so we'll insert a
// <div> under it, hide the textarea and let CodeMirror attach to the <div>.
if ($('#cm-' + model + '-container').length > 0) {
$('#cm-' + model + '-container').empty();
}
else {
self.element.after("<div id=\"cm-" + model + "-container\"></div>");
}
// Calc the height of the text area- our CodeMirror should match.
height += self.element.attr('rows') * parseInt($(self.element).css('line-height').replace(/px/,''),10);
height += parseInt(self.element.css('padding-top').replace(/px|%/,''),10) +
parseInt(self.element.css('padding-bottom').replace(/px|%/,''),10);
height += 2; //for the border
// hide
self.element.hide();
// Initialize CodeMirror
self.modes[mode].value = scope[model];
self.myCodeMirror = CodeMirror(document.getElementById('cm-' + model + '-container'), self.modes[mode]);
// Adjust the height
$('.CodeMirror').css({ 'min-height': height, 'max-height': height });
self.myCodeMirror.setSize(null, height);
// This doesn't work without a setTimeout
setTimeout(function() {
self.myCodeMirror.refresh();
if (onReady) {
onReady();
}
}, 500);
// Update the model on change
self.myCodeMirror.on('change', function() {
setTimeout(function() {
scope.$apply(function(){
scope[model] = self.myCodeMirror.getValue();
if (onChange) {
onChange();
}
});
}, 500);
});
};
this.getValue = function() {
var self = this;
return self.myCodeMirror.getValue();
};
this.destroy = function() {
// Intended for use with showTextArea. This will get ride of CM and put the
// textarea back to normal
var self = this;
$('.CodeMirror').empty().remove();
if (self.element) {
self.element.show();
}
};
this.showModal = function(params) {
var self = this,
scope = params.scope,
target = (typeof params.container === "string") ? document.getElementById(params.container) : params.container,
mode = params.mode,
model = params.model,
title = params.title || 'Code Editor',
modes = self.modes;
this.html = "<div id=\"af-code-editor-modal\"><div id=\"af-code\"></div>\n</div>\n";
if ($('#af-code-editor-modal').length === 0) {
$(target).append(this.html);
}
else {
$('#af-code-editor-modal').remove();
$(target).append(this.html);
}
$('#af-code-editor-modal').dialog({
title: title,
resizable: true,
width: Math.ceil($(window).width() * 0.9),
height: Math.ceil($(window).height() * 0.8),
position: "center",
show: true,
closeOnEscape: true,
modal: true,
autoOpen: true,
buttons: [
{ text: "Cancel", id: "af-code-edit-cancel", click: function() { $(this).dialog('close'); } },
{ text: "OK", id: "af-code-edit-ok", click:
function() {
scope.$apply(function() { scope[model] = self.myCodeMirror.getValue(); });
$(this).dialog('close');
}
}
],
open: function() {
var self = $('.ui-dialog[aria-describedby="af-code-editor-modal"]'),
idx, options;
// bring the overlay up to just below the new window
idx = self.css('z-index');
$('.ui-widget-overlay').css({ 'z-index': idx - 1});
// fix buttons- make them more twittery
self.find('.ui-dialog-titlebar button').empty().attr({'class': 'close'}).text('x');
$('#af-code-edit-cancel').attr({ "class": "btn btn-default" }).empty().html("<i class=\"fa fa-times\"></i> Cancel");
$('#af-code-edit-ok').attr({ "class": "btn btn-primary" }).empty().html("<i class=\"fa fa-check\"></i> Save");
// initialize CodeMirror
options = modes[mode];
options.value = scope[model];
self.myCodeMirror = CodeMirror(document.getElementById('af-code'), options);
}
});
};
// Don't maintain modes here. Use this.addModes() to set/override available modes
this.modes = {};
// Add or override available modes.
this.addModes = function(obj) {
for (var key in obj) {
if (this.modes[key]) {
delete this.modes[key];
}
this.modes[key] = angular.copy(obj[key]);
}
};
};
return new fn();
};
}]);

View File

@ -1,15 +0,0 @@
// Add YAML lint support to CodeMirror. Submitted pull request #2266
// Depends on js-yaml.js from https://github.com/nodeca/js-yaml
// declare global: jsyaml
CodeMirror.registerHelper("lint", "yaml", function(text) {
var found = [];
try { jsyaml.load(text); }
catch(e) {
var loc = e.mark;
found.push({ from: CodeMirror.Pos(loc.line, loc.column), to: CodeMirror.Pos(loc.line, loc.column), message: e.message });
}
return found;
});
CodeMirror.yamlValidator = CodeMirror.lint.yaml; // deprecated

View File

@ -1,12 +0,0 @@
#!/bin/bash
#
# Minify angular-forms.js
#
# ./compile.sh
#
if [ -f ../angular-forms.min.js ]; then
rm ../angular-forms.min.js
fi
java -jar ../bower_components/closure-compiler/compiler.jar --js ../angular-forms.js --js_output_file ../angular-forms.min.js

View File

@ -1,244 +0,0 @@
#!/usr/bin/env node
var util = require('util'),
http = require('http'),
fs = require('fs'),
url = require('url'),
events = require('events');
var DEFAULT_PORT = 8000;
function main(argv) {
new HttpServer({
'GET': createServlet(StaticServlet),
'HEAD': createServlet(StaticServlet)
}).start(Number(argv[2]) || DEFAULT_PORT);
}
function escapeHtml(value) {
return value.toString().
replace('<', '&lt;').
replace('>', '&gt;').
replace('"', '&quot;');
}
function createServlet(Class) {
var servlet = new Class();
return servlet.handleRequest.bind(servlet);
}
/**
* An Http server implementation that uses a map of methods to decide
* action routing.
*
* @param {Object} Map of method => Handler function
*/
function HttpServer(handlers) {
this.handlers = handlers;
this.server = http.createServer(this.handleRequest_.bind(this));
}
HttpServer.prototype.start = function(port) {
this.port = port;
this.server.listen(port);
util.puts('Http Server running at http://localhost:' + port + '/');
};
HttpServer.prototype.parseUrl_ = function(urlString) {
var parsed = url.parse(urlString);
parsed.pathname = url.resolve('/', parsed.pathname);
return url.parse(url.format(parsed), true);
};
HttpServer.prototype.handleRequest_ = function(req, res) {
var logEntry = req.method + ' ' + req.url;
if (req.headers['user-agent']) {
logEntry += ' ' + req.headers['user-agent'];
}
util.puts(logEntry);
req.url = this.parseUrl_(req.url);
var handler = this.handlers[req.method];
if (!handler) {
res.writeHead(501);
res.end();
} else {
handler.call(this, req, res);
}
};
/**
* Handles static content.
*/
function StaticServlet() {}
StaticServlet.MimeMap = {
'txt': 'text/plain',
'html': 'text/html',
'css': 'text/css',
'xml': 'application/xml',
'json': 'application/json',
'js': 'application/javascript',
'jpg': 'image/jpeg',
'jpeg': 'image/jpeg',
'gif': 'image/gif',
'png': 'image/png',
  'svg': 'image/svg+xml'
};
StaticServlet.prototype.handleRequest = function(req, res) {
var self = this;
var path = ('./' + req.url.pathname).replace('//','/').replace(/%(..)/g, function(match, hex){
return String.fromCharCode(parseInt(hex, 16));
});
var parts = path.split('/');
if (parts[parts.length-1].charAt(0) === '.')
return self.sendForbidden_(req, res, path);
fs.stat(path, function(err, stat) {
if (err)
return self.sendMissing_(req, res, path);
if (stat.isDirectory())
return self.sendDirectory_(req, res, path);
return self.sendFile_(req, res, path);
});
}
StaticServlet.prototype.sendError_ = function(req, res, error) {
res.writeHead(500, {
'Content-Type': 'text/html'
});
res.write('<!doctype html>\n');
res.write('<title>Internal Server Error</title>\n');
res.write('<h1>Internal Server Error</h1>');
res.write('<pre>' + escapeHtml(util.inspect(error)) + '</pre>');
util.puts('500 Internal Server Error');
util.puts(util.inspect(error));
};
StaticServlet.prototype.sendMissing_ = function(req, res, path) {
path = path.substring(1);
res.writeHead(404, {
'Content-Type': 'text/html'
});
res.write('<!doctype html>\n');
res.write('<title>404 Not Found</title>\n');
res.write('<h1>Not Found</h1>');
res.write(
'<p>The requested URL ' +
escapeHtml(path) +
' was not found on this server.</p>'
);
res.end();
util.puts('404 Not Found: ' + path);
};
StaticServlet.prototype.sendForbidden_ = function(req, res, path) {
path = path.substring(1);
res.writeHead(403, {
'Content-Type': 'text/html'
});
res.write('<!doctype html>\n');
res.write('<title>403 Forbidden</title>\n');
res.write('<h1>Forbidden</h1>');
res.write(
'<p>You do not have permission to access ' +
escapeHtml(path) + ' on this server.</p>'
);
res.end();
util.puts('403 Forbidden: ' + path);
};
StaticServlet.prototype.sendRedirect_ = function(req, res, redirectUrl) {
res.writeHead(301, {
'Content-Type': 'text/html',
'Location': redirectUrl
});
res.write('<!doctype html>\n');
res.write('<title>301 Moved Permanently</title>\n');
res.write('<h1>Moved Permanently</h1>');
res.write(
'<p>The document has moved <a href="' +
redirectUrl +
'">here</a>.</p>'
);
res.end();
util.puts('301 Moved Permanently: ' + redirectUrl);
};
StaticServlet.prototype.sendFile_ = function(req, res, path) {
var self = this;
var file = fs.createReadStream(path);
res.writeHead(200, {
'Content-Type': StaticServlet.
MimeMap[path.split('.').pop()] || 'text/plain'
});
if (req.method === 'HEAD') {
res.end();
} else {
file.on('data', res.write.bind(res));
file.on('close', function() {
res.end();
});
file.on('error', function(error) {
self.sendError_(req, res, error);
});
}
};
StaticServlet.prototype.sendDirectory_ = function(req, res, path) {
var self = this;
if (path.match(/[^\/]$/)) {
req.url.pathname += '/';
var redirectUrl = url.format(url.parse(url.format(req.url)));
return self.sendRedirect_(req, res, redirectUrl);
}
fs.readdir(path, function(err, files) {
if (err)
return self.sendError_(req, res, error);
if (!files.length)
return self.writeDirectoryIndex_(req, res, path, []);
var remaining = files.length;
files.forEach(function(fileName, index) {
fs.stat(path + '/' + fileName, function(err, stat) {
if (err)
return self.sendError_(req, res, err);
if (stat.isDirectory()) {
files[index] = fileName + '/';
}
if (!(--remaining))
return self.writeDirectoryIndex_(req, res, path, files);
});
});
});
};
StaticServlet.prototype.writeDirectoryIndex_ = function(req, res, path, files) {
path = path.substring(1);
res.writeHead(200, {
'Content-Type': 'text/html'
});
if (req.method === 'HEAD') {
res.end();
return;
}
res.write('<!doctype html>\n');
res.write('<title>' + escapeHtml(path) + '</title>\n');
res.write('<style>\n');
res.write(' ol { list-style-type: none; font-size: 1.2em; }\n');
res.write('</style>\n');
res.write('<h1>Directory: ' + escapeHtml(path) + '</h1>');
res.write('<ol>');
files.forEach(function(fileName) {
if (fileName.charAt(0) !== '.') {
res.write('<li><a href="' +
escapeHtml(fileName) + '">' +
escapeHtml(fileName) + '</a></li>');
}
});
res.write('</ol>');
res.end();
};
// Must be last,
main(process.argv);

View File

@ -1,19 +0,0 @@
{
"name": "angular-cookies",
"version": "1.4.3",
"main": "./angular-cookies.js",
"ignore": [],
"dependencies": {
"angular": "1.4.3"
},
"homepage": "https://github.com/angular/bower-angular-cookies",
"_release": "1.4.3",
"_resolution": {
"type": "version",
"tag": "v1.4.3",
"commit": "1ef7a87fc52ed419322aefe14890bdb24e717fc9"
},
"_source": "git://github.com/angular/bower-angular-cookies.git",
"_target": "~1.4.3",
"_originalSource": "angular-cookies"
}

View File

@ -1,68 +0,0 @@
# packaged angular-cookies
This repo is for distribution on `npm` and `bower`. The source for this module is in the
[main AngularJS repo](https://github.com/angular/angular.js/tree/master/src/ngCookies).
Please file issues and pull requests against that repo.
## Install
You can install this package either with `npm` or with `bower`.
### npm
```shell
npm install angular-cookies
```
Then add `ngCookies` as a dependency for your app:
```javascript
angular.module('myApp', [require('angular-cookies')]);
```
### bower
```shell
bower install angular-cookies
```
Add a `<script>` to your `index.html`:
```html
<script src="/bower_components/angular-cookies/angular-cookies.js"></script>
```
Then add `ngCookies` as a dependency for your app:
```javascript
angular.module('myApp', ['ngCookies']);
```
## Documentation
Documentation is available on the
[AngularJS docs site](http://docs.angularjs.org/api/ngCookies).
## License
The MIT License
Copyright (c) 2010-2015 Google, Inc. http://angularjs.org
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.

View File

@ -1,321 +0,0 @@
/**
* @license AngularJS v1.4.3
* (c) 2010-2015 Google, Inc. http://angularjs.org
* License: MIT
*/
(function(window, angular, undefined) {'use strict';
/**
* @ngdoc module
* @name ngCookies
* @description
*
* # ngCookies
*
* The `ngCookies` module provides a convenient wrapper for reading and writing browser cookies.
*
*
* <div doc-module-components="ngCookies"></div>
*
* See {@link ngCookies.$cookies `$cookies`} for usage.
*/
angular.module('ngCookies', ['ng']).
/**
* @ngdoc provider
* @name $cookiesProvider
* @description
* Use `$cookiesProvider` to change the default behavior of the {@link ngCookies.$cookies $cookies} service.
* */
provider('$cookies', [function $CookiesProvider() {
/**
* @ngdoc property
* @name $cookiesProvider#defaults
* @description
*
* Object containing default options to pass when setting cookies.
*
* The object may have following properties:
*
* - **path** - `{string}` - The cookie will be available only for this path and its
* sub-paths. By default, this would be the URL that appears in your base tag.
* - **domain** - `{string}` - The cookie will be available only for this domain and
* its sub-domains. For obvious security reasons the user agent will not accept the
* cookie if the current domain is not a sub domain or equals to the requested domain.
* - **expires** - `{string|Date}` - String of the form "Wdy, DD Mon YYYY HH:MM:SS GMT"
* or a Date object indicating the exact date/time this cookie will expire.
* - **secure** - `{boolean}` - The cookie will be available only in secured connection.
*
* Note: by default the address that appears in your `<base>` tag will be used as path.
* This is import so that cookies will be visible for all routes in case html5mode is enabled
*
**/
var defaults = this.defaults = {};
function calcOptions(options) {
return options ? angular.extend({}, defaults, options) : defaults;
}
/**
* @ngdoc service
* @name $cookies
*
* @description
* Provides read/write access to browser's cookies.
*
* <div class="alert alert-info">
* Up until Angular 1.3, `$cookies` exposed properties that represented the
* current browser cookie values. In version 1.4, this behavior has changed, and
* `$cookies` now provides a standard api of getters, setters etc.
* </div>
*
* Requires the {@link ngCookies `ngCookies`} module to be installed.
*
* @example
*
* ```js
* angular.module('cookiesExample', ['ngCookies'])
* .controller('ExampleController', ['$cookies', function($cookies) {
* // Retrieving a cookie
* var favoriteCookie = $cookies.get('myFavorite');
* // Setting a cookie
* $cookies.put('myFavorite', 'oatmeal');
* }]);
* ```
*/
this.$get = ['$$cookieReader', '$$cookieWriter', function($$cookieReader, $$cookieWriter) {
return {
/**
* @ngdoc method
* @name $cookies#get
*
* @description
* Returns the value of given cookie key
*
* @param {string} key Id to use for lookup.
* @returns {string} Raw cookie value.
*/
get: function(key) {
return $$cookieReader()[key];
},
/**
* @ngdoc method
* @name $cookies#getObject
*
* @description
* Returns the deserialized value of given cookie key
*
* @param {string} key Id to use for lookup.
* @returns {Object} Deserialized cookie value.
*/
getObject: function(key) {
var value = this.get(key);
return value ? angular.fromJson(value) : value;
},
/**
* @ngdoc method
* @name $cookies#getAll
*
* @description
* Returns a key value object with all the cookies
*
* @returns {Object} All cookies
*/
getAll: function() {
return $$cookieReader();
},
/**
* @ngdoc method
* @name $cookies#put
*
* @description
* Sets a value for given cookie key
*
* @param {string} key Id for the `value`.
* @param {string} value Raw value to be stored.
* @param {Object=} options Options object.
* See {@link ngCookies.$cookiesProvider#defaults $cookiesProvider.defaults}
*/
put: function(key, value, options) {
$$cookieWriter(key, value, calcOptions(options));
},
/**
* @ngdoc method
* @name $cookies#putObject
*
* @description
* Serializes and sets a value for given cookie key
*
* @param {string} key Id for the `value`.
* @param {Object} value Value to be stored.
* @param {Object=} options Options object.
* See {@link ngCookies.$cookiesProvider#defaults $cookiesProvider.defaults}
*/
putObject: function(key, value, options) {
this.put(key, angular.toJson(value), options);
},
/**
* @ngdoc method
* @name $cookies#remove
*
* @description
* Remove given cookie
*
* @param {string} key Id of the key-value pair to delete.
* @param {Object=} options Options object.
* See {@link ngCookies.$cookiesProvider#defaults $cookiesProvider.defaults}
*/
remove: function(key, options) {
$$cookieWriter(key, undefined, calcOptions(options));
}
};
}];
}]);
angular.module('ngCookies').
/**
* @ngdoc service
* @name $cookieStore
* @deprecated
* @requires $cookies
*
* @description
* Provides a key-value (string-object) storage, that is backed by session cookies.
* Objects put or retrieved from this storage are automatically serialized or
* deserialized by angular's toJson/fromJson.
*
* Requires the {@link ngCookies `ngCookies`} module to be installed.
*
* <div class="alert alert-danger">
* **Note:** The $cookieStore service is **deprecated**.
* Please use the {@link ngCookies.$cookies `$cookies`} service instead.
* </div>
*
* @example
*
* ```js
* angular.module('cookieStoreExample', ['ngCookies'])
* .controller('ExampleController', ['$cookieStore', function($cookieStore) {
* // Put cookie
* $cookieStore.put('myFavorite','oatmeal');
* // Get cookie
* var favoriteCookie = $cookieStore.get('myFavorite');
* // Removing a cookie
* $cookieStore.remove('myFavorite');
* }]);
* ```
*/
factory('$cookieStore', ['$cookies', function($cookies) {
return {
/**
* @ngdoc method
* @name $cookieStore#get
*
* @description
* Returns the value of given cookie key
*
* @param {string} key Id to use for lookup.
* @returns {Object} Deserialized cookie value, undefined if the cookie does not exist.
*/
get: function(key) {
return $cookies.getObject(key);
},
/**
* @ngdoc method
* @name $cookieStore#put
*
* @description
* Sets a value for given cookie key
*
* @param {string} key Id for the `value`.
* @param {Object} value Value to be stored.
*/
put: function(key, value) {
$cookies.putObject(key, value);
},
/**
* @ngdoc method
* @name $cookieStore#remove
*
* @description
* Remove given cookie
*
* @param {string} key Id of the key-value pair to delete.
*/
remove: function(key) {
$cookies.remove(key);
}
};
}]);
/**
* @name $$cookieWriter
* @requires $document
*
* @description
* This is a private service for writing cookies
*
* @param {string} name Cookie name
* @param {string=} value Cookie value (if undefined, cookie will be deleted)
* @param {Object=} options Object with options that need to be stored for the cookie.
*/
function $$CookieWriter($document, $log, $browser) {
var cookiePath = $browser.baseHref();
var rawDocument = $document[0];
function buildCookieString(name, value, options) {
var path, expires;
options = options || {};
expires = options.expires;
path = angular.isDefined(options.path) ? options.path : cookiePath;
if (value === undefined) {
expires = 'Thu, 01 Jan 1970 00:00:00 GMT';
value = '';
}
if (angular.isString(expires)) {
expires = new Date(expires);
}
var str = encodeURIComponent(name) + '=' + encodeURIComponent(value);
str += path ? ';path=' + path : '';
str += options.domain ? ';domain=' + options.domain : '';
str += expires ? ';expires=' + expires.toUTCString() : '';
str += options.secure ? ';secure' : '';
// per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum:
// - 300 cookies
// - 20 cookies per unique domain
// - 4096 bytes per cookie
var cookieLength = str.length + 1;
if (cookieLength > 4096) {
$log.warn("Cookie '" + name +
"' possibly not set or overflowed because it was too large (" +
cookieLength + " > 4096 bytes)!");
}
return str;
}
return function(name, value, options) {
rawDocument.cookie = buildCookieString(name, value, options);
};
}
$$CookieWriter.$inject = ['$document', '$log', '$browser'];
angular.module('ngCookies').provider('$$cookieWriter', function $$CookieWriterProvider() {
this.$get = $$CookieWriter;
});
})(window, window.angular);

View File

@ -1,9 +0,0 @@
/*
AngularJS v1.4.3
(c) 2010-2015 Google, Inc. http://angularjs.org
License: MIT
*/
(function(p,g,l){'use strict';function m(b,a,f){var c=f.baseHref(),k=b[0];return function(b,d,e){var f,h;e=e||{};h=e.expires;f=g.isDefined(e.path)?e.path:c;d===l&&(h="Thu, 01 Jan 1970 00:00:00 GMT",d="");g.isString(h)&&(h=new Date(h));d=encodeURIComponent(b)+"="+encodeURIComponent(d);d=d+(f?";path="+f:"")+(e.domain?";domain="+e.domain:"");d+=h?";expires="+h.toUTCString():"";d+=e.secure?";secure":"";e=d.length+1;4096<e&&a.warn("Cookie '"+b+"' possibly not set or overflowed because it was too large ("+
e+" > 4096 bytes)!");k.cookie=d}}g.module("ngCookies",["ng"]).provider("$cookies",[function(){var b=this.defaults={};this.$get=["$$cookieReader","$$cookieWriter",function(a,f){return{get:function(c){return a()[c]},getObject:function(c){return(c=this.get(c))?g.fromJson(c):c},getAll:function(){return a()},put:function(c,a,n){f(c,a,n?g.extend({},b,n):b)},putObject:function(c,b,a){this.put(c,g.toJson(b),a)},remove:function(a,k){f(a,l,k?g.extend({},b,k):b)}}}]}]);g.module("ngCookies").factory("$cookieStore",
["$cookies",function(b){return{get:function(a){return b.getObject(a)},put:function(a,f){b.putObject(a,f)},remove:function(a){b.remove(a)}}}]);m.$inject=["$document","$log","$browser"];g.module("ngCookies").provider("$$cookieWriter",function(){this.$get=m})})(window,window.angular);
//# sourceMappingURL=angular-cookies.min.js.map

View File

@ -1,8 +0,0 @@
{
"version":3,
"file":"angular-cookies.min.js",
"lineCount":8,
"mappings":"A;;;;;aAKC,SAAQ,CAACA,CAAD,CAASC,CAAT,CAAkBC,CAAlB,CAA6B,CA0QtCC,QAASA,EAAc,CAACC,CAAD,CAAYC,CAAZ,CAAkBC,CAAlB,CAA4B,CACjD,IAAIC,EAAaD,CAAAE,SAAA,EAAjB,CACIC,EAAcL,CAAA,CAAU,CAAV,CAmClB,OAAO,SAAQ,CAACM,CAAD,CAAOC,CAAP,CAAcC,CAAd,CAAuB,CAjCW,IAC3CC,CAD2C,CACrCC,CACVF,EAAA,CAgCoDA,CAhCpD,EAAqB,EACrBE,EAAA,CAAUF,CAAAE,QACVD,EAAA,CAAOZ,CAAAc,UAAA,CAAkBH,CAAAC,KAAlB,CAAA,CAAkCD,CAAAC,KAAlC,CAAiDN,CACpDI,EAAJ,GAAcT,CAAd,GACEY,CACA,CADU,+BACV,CAAAH,CAAA,CAAQ,EAFV,CAIIV,EAAAe,SAAA,CAAiBF,CAAjB,CAAJ,GACEA,CADF,CACY,IAAIG,IAAJ,CAASH,CAAT,CADZ,CAIII,EAAAA,CAAMC,kBAAA,CAqB6BT,CArB7B,CAANQ,CAAiC,GAAjCA,CAAuCC,kBAAA,CAAmBR,CAAnB,CAE3CO,EAAA,CADAA,CACA,EADOL,CAAA,CAAO,QAAP,CAAkBA,CAAlB,CAAyB,EAChC,GAAOD,CAAAQ,OAAA,CAAiB,UAAjB,CAA8BR,CAAAQ,OAA9B,CAA+C,EAAtD,CACAF,EAAA,EAAOJ,CAAA,CAAU,WAAV,CAAwBA,CAAAO,YAAA,EAAxB,CAAgD,EACvDH,EAAA,EAAON,CAAAU,OAAA,CAAiB,SAAjB,CAA6B,EAMhCC,EAAAA,CAAeL,CAAAM,OAAfD,CAA4B,CACb,KAAnB,CAAIA,CAAJ,EACElB,CAAAoB,KAAA,CAAU,UAAV,CASqCf,CATrC,CACE,6DADF;AAEEa,CAFF,CAEiB,iBAFjB,CASFd,EAAAiB,OAAA,CAJOR,CAG6B,CArCW,CAxPnDjB,CAAA0B,OAAA,CAAe,WAAf,CAA4B,CAAC,IAAD,CAA5B,CAAAC,SAAA,CAOY,UAPZ,CAOwB,CAACC,QAAyB,EAAG,CAuBjD,IAAIC,EAAW,IAAAA,SAAXA,CAA2B,EAiC/B,KAAAC,KAAA,CAAY,CAAC,gBAAD,CAAmB,gBAAnB,CAAqC,QAAQ,CAACC,CAAD,CAAiBC,CAAjB,CAAiC,CACxF,MAAO,CAWLC,IAAKA,QAAQ,CAACC,CAAD,CAAM,CACjB,MAAOH,EAAA,EAAA,CAAiBG,CAAjB,CADU,CAXd,CAyBLC,UAAWA,QAAQ,CAACD,CAAD,CAAM,CAEvB,MAAO,CADHxB,CACG,CADK,IAAAuB,IAAA,CAASC,CAAT,CACL,EAAQlC,CAAAoC,SAAA,CAAiB1B,CAAjB,CAAR,CAAkCA,CAFlB,CAzBpB,CAuCL2B,OAAQA,QAAQ,EAAG,CACjB,MAAON,EAAA,EADU,CAvCd,CAuDLO,IAAKA,QAAQ,CAACJ,CAAD,CAAMxB,CAAN,CAAaC,CAAb,CAAsB,CACjCqB,CAAA,CAAeE,CAAf,CAAoBxB,CAApB,CAAuCC,CAvFpC,CAAUX,CAAAuC,OAAA,CAAe,EAAf,CAAmBV,CAAnB,CAuF0BlB,CAvF1B,CAAV,CAAkDkB,CAuFrD,CADiC,CAvD9B,CAuELW,UAAWA,QAAQ,CAACN,CAAD,CAAMxB,CAAN,CAAaC,CAAb,CAAsB,CACvC,IAAA2B,IAAA,CAASJ,CAAT,CAAclC,CAAAyC,OAAA,CAAe/B,CAAf,CAAd,CAAqCC,CAArC,CADuC,CAvEpC,CAsFL+B,OAAQA,QAAQ,CAACR,CAAD,CAAMvB,CAAN,CAAe,CAC7BqB,CAAA,CAAeE,CAAf,CAAoBjC,CAApB,CAA2CU,CAtHxC,CAAUX,CAAAuC,OAAA,CAAe,EAAf,CAAmBV,CAAnB,CAsH8BlB,CAtH9B,CAAV,CAAkDkB,CAsHrD,CAD6B,CAtF1B,CADiF,CAA9E,CAxDqC,CAA7B,CAPxB,CA6JA7B,EAAA0B,OAAA,CAAe,WAAf,CAAAiB,QAAA,CAiCS,cAjCT;AAiCyB,CAAC,UAAD,CAAa,QAAQ,CAACC,CAAD,CAAW,CAErD,MAAO,CAWLX,IAAKA,QAAQ,CAACC,CAAD,CAAM,CACjB,MAAOU,EAAAT,UAAA,CAAmBD,CAAnB,CADU,CAXd,CAyBLI,IAAKA,QAAQ,CAACJ,CAAD,CAAMxB,CAAN,CAAa,CACxBkC,CAAAJ,UAAA,CAAmBN,CAAnB,CAAwBxB,CAAxB,CADwB,CAzBrB,CAsCLgC,OAAQA,QAAQ,CAACR,CAAD,CAAM,CACpBU,CAAAF,OAAA,CAAgBR,CAAhB,CADoB,CAtCjB,CAF8C,CAAhC,CAjCzB,CAqIAhC,EAAA2C,QAAA,CAAyB,CAAC,WAAD,CAAc,MAAd,CAAsB,UAAtB,CAEzB7C,EAAA0B,OAAA,CAAe,WAAf,CAAAC,SAAA,CAAqC,gBAArC,CAAuDmB,QAA+B,EAAG,CACvF,IAAAhB,KAAA,CAAY5B,CAD2E,CAAzF,CAtTsC,CAArC,CAAD,CA2TGH,MA3TH,CA2TWA,MAAAC,QA3TX;",
"sources":["angular-cookies.js"],
"names":["window","angular","undefined","$$CookieWriter","$document","$log","$browser","cookiePath","baseHref","rawDocument","name","value","options","path","expires","isDefined","isString","Date","str","encodeURIComponent","domain","toUTCString","secure","cookieLength","length","warn","cookie","module","provider","$CookiesProvider","defaults","$get","$$cookieReader","$$cookieWriter","get","key","getObject","fromJson","getAll","put","extend","putObject","toJson","remove","factory","$cookies","$inject","$$CookieWriterProvider"]
}

View File

@ -1,9 +0,0 @@
{
"name": "angular-cookies",
"version": "1.4.3",
"main": "./angular-cookies.js",
"ignore": [],
"dependencies": {
"angular": "1.4.3"
}
}

View File

@ -1,2 +0,0 @@
require('./angular-cookies');
module.exports = 'ngCookies';

View File

@ -1,26 +0,0 @@
{
"name": "angular-cookies",
"version": "1.4.3",
"description": "AngularJS module for cookies",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "https://github.com/angular/angular.js.git"
},
"keywords": [
"angular",
"framework",
"browser",
"cookies",
"client-side"
],
"author": "Angular Core Team <angular-core+npm@google.com>",
"license": "MIT",
"bugs": {
"url": "https://github.com/angular/angular.js/issues"
},
"homepage": "http://angularjs.org"
}

View File

@ -1,40 +0,0 @@
{
"name": "angular-drag-and-drop-lists",
"main": "angular-drag-and-drop-lists.js",
"version": "1.4.0",
"homepage": "https://github.com/marceljuenemann/angular-drag-and-drop-lists",
"authors": [
"Marcel Juenemann <mail@marcel-juenemann.de>"
],
"description": "Angular directives for sorting nested lists using the HTML5 Drag & Drop API",
"keywords": [
"angular",
"drag",
"drop",
"dnd",
"nested",
"sortable",
"lists",
"html5"
],
"license": "MIT",
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"demo",
"*.json",
"test",
"tests"
],
"_release": "1.4.0",
"_resolution": {
"type": "version",
"tag": "v1.4.0",
"commit": "141e13919b30578ed53d079bdd269fb99b20f78f"
},
"_source": "git://github.com/marceljuenemann/angular-drag-and-drop-lists.git",
"_target": "~1.4.0",
"_originalSource": "angular-drag-and-drop-lists",
"_direct": true
}

View File

@ -1,107 +0,0 @@
# 1.4.0 (2016-02-06)
## Features
- **dnd-handle directive**: This directive can be used in combination with `dnd-nodrag`, so that a `dnd-draggable` can only be dragged by using certain handle elements. [Demo](http://marceljuenemann.github.io/angular-drag-and-drop-lists/demo/#/types)
- **dnd-drop can handle insertion**: The `dnd-drop` callback can now return true to signalize that it will take care of inserting the dropped element itself. `dnd-list` will then no longer insert any elements into the list, but will still call the `dnd-inserted` callback.
## Bug Fixes
- **Fix dnd-disable-if on dnd-draggable**: When you disabled a `dnd-draggable` with `dnd-disable-if`, the user was still able to trigger a drag of that element by selecting some text inside the element. (issue #159)
- **dnd-list now handles the dragenter event**: According to the HTML5 standard dropzones need to handle the `dragenter` event, although there doesn't seem to be any browser that enforces this. (issue #118)
## Tested browsers
- Chrome 48 (Mac, Ubuntu & Windows 10)
- Firefox 44 (Ubuntu)
- Safari 9 (Mac)
- Microsoft Edge 20 (Windows 10)
- Internet Explorer 11 (Windows 10)
- Internet Explorer 10 & 9 in compatibility mode (Windows 10)
# 1.3.0 (2015-08-20)
## Features
- **New callbacks**: `dnd-dragend`, `dnd-canceled` and `dnd-inserted`.
- **Custom placeholder elements**: `dnd-list` elements can have custom elements by creating a child element with `dnd-placeholder` class. This is useful for cases where a simple `li` element is not sufficient.
- **dnd-nodrag directive**: This directive can be used inside `dnd-draggable` to prevent dragging certain areas. This is useful for input elements inside the draggable or creating handle elements.
## Bug Fixes
- **Fix user selection inside dnd-draggable**: The `selectstart` event is no longer cancelled.
- **Fix click handler compatibility**: Propagation of click events is now only stopped if the `dnd-selected` attribute is present.
- **Fix IE9 glitch**: Double clicks in IE9 previously would trigger the `dnd-moved` callback, and therefore remove items accidentially. (issue #21)
## Tested browsers
- Chrome 43 (Win7)
- Chrome 44 (Ubuntu)
- Chrome 44 (Mac)
- Firefox 40 (Win7)
- Firefox 39 (Ubuntu)
- Safari 8.0.8 (Mac)
- Internet Explorer 11 (IE9 & 10 in compatibility mode)
# 1.2.0 (2014-11-30)
## Bug Fixes
- **Fix glitches in Chrome**: When aborting a drag operation or dragging an element on itself, Chrome on Linux sometimes sends `move` as dropEffect instead of `none`. This lead to elements sometimes disappearing. Can be reproduced by dragging an element over itself and aborting with Esc key. (issue #14)
- **Fix dnd-allowed-types in nested lists**: When a drop was not allowed due to the wrong element type, the event was correctly propagated to the parent list. Nevertheless, the drop was still executed, because the drop handler didn't check the type again. (issue #16)
## Features
- **New callbacks**: The `dnd-draggable` directive now has a new `dnd-dragstart` callback besides the existing `dnd-moved` and `dnd-copied`. The `dnd-list` directive got the callbacks `dnd-dragover` and `dnd-drag` added, which are also able to abort a drop. (issue #11)
- **dnd-horizontal-list**: Lists can be marked as horizontal with this new attribute. The positioning algorithm then positions the placeholder left or right of other list items, instead of above or below. (issue #19)
- **dnd-external-sources**: This attribute allows drag and drop accross browser windows. See documentation for details. (issue #9)
- **pointer-events: none no longer required**: The dragover handler now traverses the DOM until it finds the list item node, therefore it's child elements no longer require the pointer-events: none style.
## Tested browsers
- Chrome 38 (Ubuntu)
- Chrome 38 (Win7)
- Chrome 39 (Mac)
- Firefox 31 (Win7)
- Firefox 33 (Ubuntu)
- Safari 7.1 (Mac)
- Internet Explorer 11 (IE9 & 10 in compatibility mode)
# 1.1.0 (2014-08-31)
## Bug Fixes
- **jQuery compatibility**: jQuery wraps browser events in event.originalEvent
## Features
- **dnd-disable-if attribute**: allows to dynamically disable the drag and drop functionality
- **dnd-type and dnd-allowed-types**: allows to restrict an item to specifc lists depending on it's type
## Tested browsers
- Chrome 34 (Ubuntu)
- Chrome 37 (Mac)
- Chrome 37 (Win7)
- Firefox 28 (Win7)
- Firefox 31 (Ubuntu)
- Safari 7.0.6 (Mac)
- Internet Explorer 11 (IE9 & 10 in compatibility mode)
# 1.0.0 (2014-04-11)
Initial release
# Release checklist
- Bump versions
- bower.json
- package.json
- JS files
- Minify and test (npm run-script minify)
- Test different OS & browsers (npm start)
- Update README and CHANGELOG
- Merge to master
- Tag release
- Merge to gh-pages
- Publish to npm

View File

@ -1,22 +0,0 @@
The MIT License (MIT)
Copyright (c) 2014 Marcel Juenemann <marcel@juenemann.cc>
Copyright (c) 2014-2016 Google Inc.
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.

View File

@ -1,135 +0,0 @@
angular-drag-and-drop-lists
===========================
Angular directives that allow you to build sortable lists with the native HTML5 drag & drop API. The directives can also be nested to bring drag & drop to your WYSIWYG editor, your tree, or whatever fancy structure you are building.
## Demo
* [Nested Lists](http://marceljuenemann.github.io/angular-drag-and-drop-lists/demo/#/nested)
* [Simple Lists](http://marceljuenemann.github.io/angular-drag-and-drop-lists/demo/#/simple)
* [Typed Lists](http://marceljuenemann.github.io/angular-drag-and-drop-lists/demo/#/types)
* [Advanced Features](http://marceljuenemann.github.io/angular-drag-and-drop-lists/demo/#/advanced)
* [Multiselection Demo](http://marceljuenemann.github.io/angular-drag-and-drop-lists/demo/#/multi)
## Supported browsers
**Touch devices are not supported**, because they do not implement the HTML5 drag & drop standard. However, you can use a [shim](https://github.com/timruffles/ios-html5-drag-drop-shim) to make it work on touch devices as well.
Internet Explorer 8 or lower is *not supported*, but all modern browsers are (see changelog for list of tested browsers).
## Download & Installation
Download `angular-drag-and-drop-lists.js` (or the minified version) and include it in your application. If you use bower, you can of course just add it via bower. Add the `dndLists` module as dependency to your angular app.
## dnd-draggable directive
Use the dnd-draggable directive to make your element draggable
**Attributes**
* `dnd-draggable` Required attribute. The value has to be an object that represents the data of the element. In case of a drag and drop operation the object will be serialized and unserialized on the receiving end.
* `dnd-effect-allowed` Use this attribute to limit the operations that can be performed. Options are:
* `move` The drag operation will move the element. This is the default
* `copy` The drag operation will copy the element. There will be a copy cursor.
* `copyMove` The user can choose between copy and move by pressing the ctrl or shift key.
* *Not supported in IE:* In Internet Explorer this option will be the same as `copy`.
* *Not fully supported in Chrome on Windows:* In the Windows version of Chrome the cursor will always be the move cursor. However, when the user drops an element and has the ctrl key pressed, we will perform a copy anyways.
* HTML5 also specifies the `link` option, but this library does not actively support it yet, so use it at your own risk.
* [Demo](http://marceljuenemann.github.io/angular-drag-and-drop-lists/demo/#/advanced)
* `dnd-type` Use this attribute if you have different kinds of items in your application and you want to limit which items can be dropped into which lists. Combine with dnd-allowed-types on the dnd-list(s). This attribute should evaluate to a string, although this restriction is not enforced (at the moment). [Demo](http://marceljuenemann.github.io/angular-drag-and-drop-lists/demo/#/types)
* `dnd-disable-if` You can use this attribute to dynamically disable the draggability of the element. This is useful if you have certain list items that you don't want to be draggable, or if you want to disable drag & drop completely without having two different code branches (e.g. only allow for admins). *Note*: If your element is not draggable, the user is probably able to select text or images inside of it. Since a selection is always draggable, this breaks your UI. You most likely want to disable user selection via CSS (see [user-select](http://stackoverflow.com/a/4407335)). [Demo](http://marceljuenemann.github.io/angular-drag-and-drop-lists/demo/#/types)
**Callbacks**
* `dnd-moved` Callback that is invoked when the element was moved. Usually you will remove your element from the original list in this callback, since the directive is not doing that for you automatically. The original dragend event will be provided in the local `event` variable. [Demo](http://marceljuenemann.github.io/angular-drag-and-drop-lists/demo/#/advanced)
* `dnd-copied` Same as dnd-moved, just that it is called when the element was copied instead of moved. The original dragend event will be provided in the local `event` variable. [Demo](http://marceljuenemann.github.io/angular-drag-and-drop-lists/demo/#/advanced)
* `dnd-canceled` Callback that is invoked if the element was dragged, but the operation was canceled and the element was not dropped. The original dragend event will be provided in the local event variable. [Demo](http://marceljuenemann.github.io/angular-drag-and-drop-lists/demo/#/advanced)
* `dnd-dragstart` Callback that is invoked when the element was dragged. The original dragstart event will be provided in the local `event` variable. [Demo](http://marceljuenemann.github.io/angular-drag-and-drop-lists/demo/#/advanced)
* `dnd-dragend` Callback that is invoked when the drag operation ended. Available local variables are `event` and `dropEffect`. [Demo](http://marceljuenemann.github.io/angular-drag-and-drop-lists/demo/#/advanced)
* `dnd-selected` Callback that is invoked when the element was clicked but not dragged. The original click event will be provided in the local `event` variable. [Demo](http://marceljuenemann.github.io/angular-drag-and-drop-lists/demo/#/nested)
**CSS classes**
* `dndDragging` This class will be added to the element while the element is being dragged. It will affect both the element you see while dragging and the source element that stays at it's position. Do not try to hide the source element with this class, because that will abort the drag operation.
* `dndDraggingSource` This class will be added to the element after the drag operation was started, meaning it only affects the original element that is still at it's source position, and not the "element" that the user is dragging with his mouse pointer
## dnd-list directive
Use the dnd-list attribute to make your list element a dropzone. Usually you will add a single li element as child with the ng-repeat directive. If you don't do that, we will not be able to position the dropped element correctly. If you want your list to be sortable, also add the dnd-draggable directive to your li element(s). Both the dnd-list and it's direct children must have position: relative CSS style, otherwise the positioning algorithm will not be able to determine the correct placeholder position in all browsers.
**Attributes**
* `dnd-list` Required attribute. The value has to be the array in which the data of the dropped element should be inserted.
* `dnd-allowed-types` Optional array of allowed item types. When used, only items that had a matching dnd-type attribute will be dropable. [Demo](http://marceljuenemann.github.io/angular-drag-and-drop-lists/demo/#/types)
* `dnd-disable-if` Optional boolean expression. When it evaluates to true, no dropping into the list is possible. Note that this also disables rearranging items inside the list. [Demo](http://marceljuenemann.github.io/angular-drag-and-drop-lists/demo/#/types)
* `dnd-horizontal-list` Optional boolean expression. When it evaluates to true, the positioning algorithm will use the left and right halfs of the list items instead of the upper and lower halfs. [Demo](http://marceljuenemann.github.io/angular-drag-and-drop-lists/demo/#/advanced)
* `dnd-external-sources` Optional boolean expression. When it evaluates to true, the list accepts drops from sources outside of the current browser tab. This allows to drag and drop accross different browser tabs. Note that this will allow to drop arbitrary text into the list, thus it is highly recommended to implement the dnd-drop callback to check the incoming element for sanity. Furthermore, the dnd-type of external sources can not be determined, therefore do not rely on restrictions of dnd-allowed-type. Also note that this feature does not work very well in Internet Explorer. [Demo](http://marceljuenemann.github.io/angular-drag-and-drop-lists/demo/#/advanced)
**Callbacks**
* `dnd-dragover` Optional expression that is invoked when an element is dragged over the list. If the expression is set, but does not return true, the element is not allowed to be dropped. The following variables will be available:
* `event` The original dragover event sent by the browser.
* `index` The position in the list at which the element would be dropped.
* `type` The `dnd-type` set on the dnd-draggable, or undefined if unset.
* `external` Whether the element was dragged from an external source. See `dnd-external-sources`.
* [Demo](http://marceljuenemann.github.io/angular-drag-and-drop-lists/demo/#/advanced)
* `dnd-drop` Optional expression that is invoked when an element is dropped on the list.
* The following variables will be available:
* `event` The original drop event sent by the browser.
* `index` The position in the list at which the element would be dropped.
* `item` The transferred object.
* `type` The dnd-type set on the dnd-draggable, or undefined if unset.
* `external` Whether the element was dragged from an external source. See `dnd-external-sources`.
* The return value determines the further handling of the drop:
* `false` The drop will be canceled and the element won't be inserted.
* `true` Signalises that the drop is allowed, but the dnd-drop callback will take care of inserting the element.
* Otherwise: All other return values will be treated as the object to insert into the array. In most cases you simply want to return the `item` parameter, but there are no restrictions on what you can return.
* `dnd-inserted` Optional expression that is invoked after a drop if the element was actually inserted into the list. The same local variables as for `dnd-drop` will be available. Note that for reorderings inside the same list the old element will still be in the list due to the fact that `dnd-moved` was not called yet. [Demo](http://marceljuenemann.github.io/angular-drag-and-drop-lists/demo/#/advanced)
**CSS classes**
* `dndPlaceholder` When an element is dragged over the list, a new placeholder child element will be added. This element is of type `li` and has the class `dndPlaceholder` set. Alternatively, you can define your own placeholder by creating a child element with `dndPlaceholder` class.
* `dndDragover` This class will be added to the list while an element is being dragged over the list.
## dnd-nodrag directive
Use the `dnd-nodrag` attribute inside of `dnd-draggable` elements to prevent them from starting drag operations. This is especially useful if you want to use input elements inside of `dnd-draggable` elements or create specific handle elements.
**Note:** This directive does not work in Internet Explorer 9.
[Demo](http://marceljuenemann.github.io/angular-drag-and-drop-lists/demo/#/types)
## dnd-handle directive
Use the `dnd-handle` directive within a `dnd-nodrag` element in order to allow dragging of that element after all. Therefore, by combining `dnd-nodrag` and `dnd-handle` you can allow `dnd-draggable` elements to only be dragged via specific *handle* elements.
**Note:** Internet Explorer will show the handle element as drag image instead of the `dnd-draggable` element. You can work around this by styling the handle element differently when it is being dragged. Use the CSS selector `.dndDragging:not(.dndDraggingSource) [dnd-handle]` for that.
[Demo](http://marceljuenemann.github.io/angular-drag-and-drop-lists/demo/#/types)
## Required CSS styles
Both the dnd-list and it's children require relative positioning, so that the directive can determine the mouse position relative to the list and thus calculate the correct drop position.
<pre>
ul[dnd-list], ul[dnd-list] > li {
position: relative;
}
</pre>
## Why another drag & drop library?
There are tons of other drag & drop libraries out there, but none of them met my three requirements:
* **Angular:** If you use angular.js, you really don't want to throw a bunch of jQuery into your app. Instead you want to use libraries that were build the "angular way" and support **two-way data binding** to update your data model automatically.
* **Nested lists:** If you want to build a **WYSIWYG editor** or have some fancy **tree structure**, the library has to support nested lists.
* **HTML5 drag & drop:** Most drag & drop applications you'll find on the internet use pure JavaScript drag & drop. But with the arrival of HTML5 we can delegate most of the work to the browser. For example: If you want to show the user what he's currently dragging, you'll have to update the position of the element all the time and set it below the mouse pointer. In HTML5 the browser will do that for you! But you can not only save code lines, you can also offer a more **native user experience**: If you click on an element in a pure JavaScript drag & drop implementation, it will usually start the drag operation. But remember what happens when you click an icon on your desktop: The icon will be selected, not dragged! This is the native behaviour you can bring to your web application with HTML5.
If this doesn't fit your requirements, check out one of the other awesome drag & drop libraries:
* [angular-ui-tree](https://github.com/JimLiu/angular-ui-tree): Very similar to this library, but does not use the HTML5 API. Therefore you need to write some more markup to see what you are dragging and it will create another DOM node that you have to style. However, if you plan to support touch devices this is probably your best choice.
* [angular-dragdrop](https://github.com/ganarajpr/angular-dragdrop): One of many libraries with the same name. This one uses the HTML5 API, but if you want to build (nested) sortable lists, you're on your own, because it does not calculate the correct element position for you.
* [more...](https://www.google.de/search?q=angular+drag+and+drop)
## License
Copyright (c) 2014 [Marcel Juenemann](mailto:marcel@juenemann.cc)
Copyright (c) 2014-2016 Google Inc.
This is not an official Google product (experimental or otherwise), it is just code that happens to be owned by Google.
[MIT License](https://raw.githubusercontent.com/marceljuenemann/angular-drag-and-drop-lists/master/LICENSE)

View File

@ -1,590 +0,0 @@
/**
* angular-drag-and-drop-lists v1.4.0
*
* Copyright (c) 2014 Marcel Juenemann marcel@juenemann.cc
* Copyright (c) 2014-2016 Google Inc.
* https://github.com/marceljuenemann/angular-drag-and-drop-lists
*
* License: MIT
*/
angular.module('dndLists', [])
/**
* Use the dnd-draggable attribute to make your element draggable
*
* Attributes:
* - dnd-draggable Required attribute. The value has to be an object that represents the data
* of the element. In case of a drag and drop operation the object will be
* serialized and unserialized on the receiving end.
* - dnd-selected Callback that is invoked when the element was clicked but not dragged.
* The original click event will be provided in the local event variable.
* - dnd-effect-allowed Use this attribute to limit the operations that can be performed. Options:
* - "move": The drag operation will move the element. This is the default.
* - "copy": The drag operation will copy the element. Shows a copy cursor.
* - "copyMove": The user can choose between copy and move by pressing the
* ctrl or shift key. *Not supported in IE:* In Internet Explorer this
* option will be the same as "copy". *Not fully supported in Chrome on
* Windows:* In the Windows version of Chrome the cursor will always be the
* move cursor. However, when the user drops an element and has the ctrl
* key pressed, we will perform a copy anyways.
* - HTML5 also specifies the "link" option, but this library does not
* actively support it yet, so use it at your own risk.
* - dnd-moved Callback that is invoked when the element was moved. Usually you will
* remove your element from the original list in this callback, since the
* directive is not doing that for you automatically. The original dragend
* event will be provided in the local event variable.
* - dnd-canceled Callback that is invoked if the element was dragged, but the operation was
* canceled and the element was not dropped. The original dragend event will
* be provided in the local event variable.
* - dnd-copied Same as dnd-moved, just that it is called when the element was copied
* instead of moved. The original dragend event will be provided in the local
* event variable.
* - dnd-dragstart Callback that is invoked when the element was dragged. The original
* dragstart event will be provided in the local event variable.
* - dnd-dragend Callback that is invoked when the drag operation ended. Available local
* variables are event and dropEffect.
* - dnd-type Use this attribute if you have different kinds of items in your
* application and you want to limit which items can be dropped into which
* lists. Combine with dnd-allowed-types on the dnd-list(s). This attribute
* should evaluate to a string, although this restriction is not enforced.
* - dnd-disable-if You can use this attribute to dynamically disable the draggability of the
* element. This is useful if you have certain list items that you don't want
* to be draggable, or if you want to disable drag & drop completely without
* having two different code branches (e.g. only allow for admins).
* **Note**: If your element is not draggable, the user is probably able to
* select text or images inside of it. Since a selection is always draggable,
* this breaks your UI. You most likely want to disable user selection via
* CSS (see user-select).
*
* CSS classes:
* - dndDragging This class will be added to the element while the element is being
* dragged. It will affect both the element you see while dragging and the
* source element that stays at it's position. Do not try to hide the source
* element with this class, because that will abort the drag operation.
* - dndDraggingSource This class will be added to the element after the drag operation was
* started, meaning it only affects the original element that is still at
* it's source position, and not the "element" that the user is dragging with
* his mouse pointer.
*/
.directive('dndDraggable', ['$parse', '$timeout', 'dndDropEffectWorkaround', 'dndDragTypeWorkaround',
function($parse, $timeout, dndDropEffectWorkaround, dndDragTypeWorkaround) {
return function(scope, element, attr) {
// Set the HTML5 draggable attribute on the element
element.attr("draggable", "true");
// If the dnd-disable-if attribute is set, we have to watch that
if (attr.dndDisableIf) {
scope.$watch(attr.dndDisableIf, function(disabled) {
element.attr("draggable", !disabled);
});
}
/**
* When the drag operation is started we have to prepare the dataTransfer object,
* which is the primary way we communicate with the target element
*/
element.on('dragstart', function(event) {
event = event.originalEvent || event;
// Check whether the element is draggable, since dragstart might be triggered on a child.
if (element.attr('draggable') == 'false') return true;
// Serialize the data associated with this element. IE only supports the Text drag type
event.dataTransfer.setData("Text", angular.toJson(scope.$eval(attr.dndDraggable)));
// Only allow actions specified in dnd-effect-allowed attribute
event.dataTransfer.effectAllowed = attr.dndEffectAllowed || "move";
// Add CSS classes. See documentation above
element.addClass("dndDragging");
$timeout(function() { element.addClass("dndDraggingSource"); }, 0);
// Workarounds for stupid browsers, see description below
dndDropEffectWorkaround.dropEffect = "none";
dndDragTypeWorkaround.isDragging = true;
// Save type of item in global state. Usually, this would go into the dataTransfer
// typename, but we have to use "Text" there to support IE
dndDragTypeWorkaround.dragType = attr.dndType ? scope.$eval(attr.dndType) : undefined;
// Try setting a proper drag image if triggered on a dnd-handle (won't work in IE).
if (event._dndHandle && event.dataTransfer.setDragImage) {
event.dataTransfer.setDragImage(element[0], 0, 0);
}
// Invoke callback
$parse(attr.dndDragstart)(scope, {event: event});
event.stopPropagation();
});
/**
* The dragend event is triggered when the element was dropped or when the drag
* operation was aborted (e.g. hit escape button). Depending on the executed action
* we will invoke the callbacks specified with the dnd-moved or dnd-copied attribute.
*/
element.on('dragend', function(event) {
event = event.originalEvent || event;
// Invoke callbacks. Usually we would use event.dataTransfer.dropEffect to determine
// the used effect, but Chrome has not implemented that field correctly. On Windows
// it always sets it to 'none', while Chrome on Linux sometimes sets it to something
// else when it's supposed to send 'none' (drag operation aborted).
var dropEffect = dndDropEffectWorkaround.dropEffect;
scope.$apply(function() {
switch (dropEffect) {
case "move":
$parse(attr.dndMoved)(scope, {event: event});
break;
case "copy":
$parse(attr.dndCopied)(scope, {event: event});
break;
case "none":
$parse(attr.dndCanceled)(scope, {event: event});
break;
}
$parse(attr.dndDragend)(scope, {event: event, dropEffect: dropEffect});
});
// Clean up
element.removeClass("dndDragging");
$timeout(function() { element.removeClass("dndDraggingSource"); }, 0);
dndDragTypeWorkaround.isDragging = false;
event.stopPropagation();
});
/**
* When the element is clicked we invoke the callback function
* specified with the dnd-selected attribute.
*/
element.on('click', function(event) {
if (!attr.dndSelected) return;
event = event.originalEvent || event;
scope.$apply(function() {
$parse(attr.dndSelected)(scope, {event: event});
});
// Prevent triggering dndSelected in parent elements.
event.stopPropagation();
});
/**
* Workaround to make element draggable in IE9
*/
element.on('selectstart', function() {
if (this.dragDrop) this.dragDrop();
});
};
}])
/**
* Use the dnd-list attribute to make your list element a dropzone. Usually you will add a single
* li element as child with the ng-repeat directive. If you don't do that, we will not be able to
* position the dropped element correctly. If you want your list to be sortable, also add the
* dnd-draggable directive to your li element(s). Both the dnd-list and it's direct children must
* have position: relative CSS style, otherwise the positioning algorithm will not be able to
* determine the correct placeholder position in all browsers.
*
* Attributes:
* - dnd-list Required attribute. The value has to be the array in which the data of
* the dropped element should be inserted.
* - dnd-allowed-types Optional array of allowed item types. When used, only items that had a
* matching dnd-type attribute will be dropable.
* - dnd-disable-if Optional boolean expresssion. When it evaluates to true, no dropping
* into the list is possible. Note that this also disables rearranging
* items inside the list.
* - dnd-horizontal-list Optional boolean expresssion. When it evaluates to true, the positioning
* algorithm will use the left and right halfs of the list items instead of
* the upper and lower halfs.
* - dnd-dragover Optional expression that is invoked when an element is dragged over the
* list. If the expression is set, but does not return true, the element is
* not allowed to be dropped. The following variables will be available:
* - event: The original dragover event sent by the browser.
* - index: The position in the list at which the element would be dropped.
* - type: The dnd-type set on the dnd-draggable, or undefined if unset.
* - external: Whether the element was dragged from an external source.
* - dnd-drop Optional expression that is invoked when an element is dropped on the
* list. The following variables will be available:
* - event: The original drop event sent by the browser.
* - index: The position in the list at which the element would be dropped.
* - item: The transferred object.
* - type: The dnd-type set on the dnd-draggable, or undefined if unset.
* - external: Whether the element was dragged from an external source.
* The return value determines the further handling of the drop:
* - false: The drop will be canceled and the element won't be inserted.
* - true: Signalises that the drop is allowed, but the dnd-drop
* callback already took care of inserting the element.
* - otherwise: All other return values will be treated as the object to
* insert into the array. In most cases you want to simply return the
* item parameter, but there are no restrictions on what you can return.
* - dnd-inserted Optional expression that is invoked after a drop if the element was
* actually inserted into the list. The same local variables as for
* dnd-drop will be available. Note that for reorderings inside the same
* list the old element will still be in the list due to the fact that
* dnd-moved was not called yet.
* - dnd-external-sources Optional boolean expression. When it evaluates to true, the list accepts
* drops from sources outside of the current browser tab. This allows to
* drag and drop accross different browser tabs. Note that this will allow
* to drop arbitrary text into the list, thus it is highly recommended to
* implement the dnd-drop callback to check the incoming element for
* sanity. Furthermore, the dnd-type of external sources can not be
* determined, therefore do not rely on restrictions of dnd-allowed-type.
*
* CSS classes:
* - dndPlaceholder When an element is dragged over the list, a new placeholder child
* element will be added. This element is of type li and has the class
* dndPlaceholder set. Alternatively, you can define your own placeholder
* by creating a child element with dndPlaceholder class.
* - dndDragover Will be added to the list while an element is dragged over the list.
*/
.directive('dndList', ['$parse', '$timeout', 'dndDropEffectWorkaround', 'dndDragTypeWorkaround',
function($parse, $timeout, dndDropEffectWorkaround, dndDragTypeWorkaround) {
return function(scope, element, attr) {
// While an element is dragged over the list, this placeholder element is inserted
// at the location where the element would be inserted after dropping
var placeholder = getPlaceholderElement();
var placeholderNode = placeholder[0];
var listNode = element[0];
placeholder.remove();
var horizontal = attr.dndHorizontalList && scope.$eval(attr.dndHorizontalList);
var externalSources = attr.dndExternalSources && scope.$eval(attr.dndExternalSources);
/**
* The dragenter event is fired when a dragged element or text selection enters a valid drop
* target. According to the spec, we either need to have a dropzone attribute or listen on
* dragenter events and call preventDefault(). It should be noted though that no browser seems
* to enforce this behaviour.
*/
element.on('dragenter', function (event) {
event = event.originalEvent || event;
if (!isDropAllowed(event)) return true;
event.preventDefault();
});
/**
* The dragover event is triggered "every few hundred milliseconds" while an element
* is being dragged over our list, or over an child element.
*/
element.on('dragover', function(event) {
event = event.originalEvent || event;
if (!isDropAllowed(event)) return true;
// First of all, make sure that the placeholder is shown
// This is especially important if the list is empty
if (placeholderNode.parentNode != listNode) {
element.append(placeholder);
}
if (event.target !== listNode) {
// Try to find the node direct directly below the list node.
var listItemNode = event.target;
while (listItemNode.parentNode !== listNode && listItemNode.parentNode) {
listItemNode = listItemNode.parentNode;
}
if (listItemNode.parentNode === listNode && listItemNode !== placeholderNode) {
// If the mouse pointer is in the upper half of the child element,
// we place it before the child element, otherwise below it.
if (isMouseInFirstHalf(event, listItemNode)) {
listNode.insertBefore(placeholderNode, listItemNode);
} else {
listNode.insertBefore(placeholderNode, listItemNode.nextSibling);
}
}
} else {
// This branch is reached when we are dragging directly over the list element.
// Usually we wouldn't need to do anything here, but the IE does not fire it's
// events for the child element, only for the list directly. Therefore, we repeat
// the positioning algorithm for IE here.
if (isMouseInFirstHalf(event, placeholderNode, true)) {
// Check if we should move the placeholder element one spot towards the top.
// Note that display none elements will have offsetTop and offsetHeight set to
// zero, therefore we need a special check for them.
while (placeholderNode.previousElementSibling
&& (isMouseInFirstHalf(event, placeholderNode.previousElementSibling, true)
|| placeholderNode.previousElementSibling.offsetHeight === 0)) {
listNode.insertBefore(placeholderNode, placeholderNode.previousElementSibling);
}
} else {
// Check if we should move the placeholder element one spot towards the bottom
while (placeholderNode.nextElementSibling &&
!isMouseInFirstHalf(event, placeholderNode.nextElementSibling, true)) {
listNode.insertBefore(placeholderNode,
placeholderNode.nextElementSibling.nextElementSibling);
}
}
}
// At this point we invoke the callback, which still can disallow the drop.
// We can't do this earlier because we want to pass the index of the placeholder.
if (attr.dndDragover && !invokeCallback(attr.dndDragover, event, getPlaceholderIndex())) {
return stopDragover();
}
element.addClass("dndDragover");
event.preventDefault();
event.stopPropagation();
return false;
});
/**
* When the element is dropped, we use the position of the placeholder element as the
* position where we insert the transferred data. This assumes that the list has exactly
* one child element per array element.
*/
element.on('drop', function(event) {
event = event.originalEvent || event;
if (!isDropAllowed(event)) return true;
// The default behavior in Firefox is to interpret the dropped element as URL and
// forward to it. We want to prevent that even if our drop is aborted.
event.preventDefault();
// Unserialize the data that was serialized in dragstart. According to the HTML5 specs,
// the "Text" drag type will be converted to text/plain, but IE does not do that.
var data = event.dataTransfer.getData("Text") || event.dataTransfer.getData("text/plain");
var transferredObject;
try {
transferredObject = JSON.parse(data);
} catch(e) {
return stopDragover();
}
// Invoke the callback, which can transform the transferredObject and even abort the drop.
var index = getPlaceholderIndex();
if (attr.dndDrop) {
transferredObject = invokeCallback(attr.dndDrop, event, index, transferredObject);
if (!transferredObject) {
return stopDragover();
}
}
// Insert the object into the array, unless dnd-drop took care of that (returned true).
if (transferredObject !== true) {
scope.$apply(function() {
scope.$eval(attr.dndList).splice(index, 0, transferredObject);
});
}
invokeCallback(attr.dndInserted, event, index, transferredObject);
// In Chrome on Windows the dropEffect will always be none...
// We have to determine the actual effect manually from the allowed effects
if (event.dataTransfer.dropEffect === "none") {
if (event.dataTransfer.effectAllowed === "copy" ||
event.dataTransfer.effectAllowed === "move") {
dndDropEffectWorkaround.dropEffect = event.dataTransfer.effectAllowed;
} else {
dndDropEffectWorkaround.dropEffect = event.ctrlKey ? "copy" : "move";
}
} else {
dndDropEffectWorkaround.dropEffect = event.dataTransfer.dropEffect;
}
// Clean up
stopDragover();
event.stopPropagation();
return false;
});
/**
* We have to remove the placeholder when the element is no longer dragged over our list. The
* problem is that the dragleave event is not only fired when the element leaves our list,
* but also when it leaves a child element -- so practically it's fired all the time. As a
* workaround we wait a few milliseconds and then check if the dndDragover class was added
* again. If it is there, dragover must have been called in the meantime, i.e. the element
* is still dragging over the list. If you know a better way of doing this, please tell me!
*/
element.on('dragleave', function(event) {
event = event.originalEvent || event;
element.removeClass("dndDragover");
$timeout(function() {
if (!element.hasClass("dndDragover")) {
placeholder.remove();
}
}, 100);
});
/**
* Checks whether the mouse pointer is in the first half of the given target element.
*
* In Chrome we can just use offsetY, but in Firefox we have to use layerY, which only
* works if the child element has position relative. In IE the events are only triggered
* on the listNode instead of the listNodeItem, therefore the mouse positions are
* relative to the parent element of targetNode.
*/
function isMouseInFirstHalf(event, targetNode, relativeToParent) {
var mousePointer = horizontal ? (event.offsetX || event.layerX)
: (event.offsetY || event.layerY);
var targetSize = horizontal ? targetNode.offsetWidth : targetNode.offsetHeight;
var targetPosition = horizontal ? targetNode.offsetLeft : targetNode.offsetTop;
targetPosition = relativeToParent ? targetPosition : 0;
return mousePointer < targetPosition + targetSize / 2;
}
/**
* Tries to find a child element that has the dndPlaceholder class set. If none was found, a
* new li element is created.
*/
function getPlaceholderElement() {
var placeholder;
angular.forEach(element.children(), function(childNode) {
var child = angular.element(childNode);
if (child.hasClass('dndPlaceholder')) {
placeholder = child;
}
});
return placeholder || angular.element("<li class='dndPlaceholder'></li>");
}
/**
* We use the position of the placeholder node to determine at which position of the array the
* object needs to be inserted
*/
function getPlaceholderIndex() {
return Array.prototype.indexOf.call(listNode.children, placeholderNode);
}
/**
* Checks various conditions that must be fulfilled for a drop to be allowed
*/
function isDropAllowed(event) {
// Disallow drop from external source unless it's allowed explicitly.
if (!dndDragTypeWorkaround.isDragging && !externalSources) return false;
// Check mimetype. Usually we would use a custom drag type instead of Text, but IE doesn't
// support that.
if (!hasTextMimetype(event.dataTransfer.types)) return false;
// Now check the dnd-allowed-types against the type of the incoming element. For drops from
// external sources we don't know the type, so it will need to be checked via dnd-drop.
if (attr.dndAllowedTypes && dndDragTypeWorkaround.isDragging) {
var allowed = scope.$eval(attr.dndAllowedTypes);
if (angular.isArray(allowed) && allowed.indexOf(dndDragTypeWorkaround.dragType) === -1) {
return false;
}
}
// Check whether droping is disabled completely
if (attr.dndDisableIf && scope.$eval(attr.dndDisableIf)) return false;
return true;
}
/**
* Small helper function that cleans up if we aborted a drop.
*/
function stopDragover() {
placeholder.remove();
element.removeClass("dndDragover");
return true;
}
/**
* Invokes a callback with some interesting parameters and returns the callbacks return value.
*/
function invokeCallback(expression, event, index, item) {
return $parse(expression)(scope, {
event: event,
index: index,
item: item || undefined,
external: !dndDragTypeWorkaround.isDragging,
type: dndDragTypeWorkaround.isDragging ? dndDragTypeWorkaround.dragType : undefined
});
}
/**
* Check if the dataTransfer object contains a drag type that we can handle. In old versions
* of IE the types collection will not even be there, so we just assume a drop is possible.
*/
function hasTextMimetype(types) {
if (!types) return true;
for (var i = 0; i < types.length; i++) {
if (types[i] === "Text" || types[i] === "text/plain") return true;
}
return false;
}
};
}])
/**
* Use the dnd-nodrag attribute inside of dnd-draggable elements to prevent them from starting
* drag operations. This is especially useful if you want to use input elements inside of
* dnd-draggable elements or create specific handle elements. Note: This directive does not work
* in Internet Explorer 9.
*/
.directive('dndNodrag', function() {
return function(scope, element, attr) {
// Set as draggable so that we can cancel the events explicitly
element.attr("draggable", "true");
/**
* Since the element is draggable, the browser's default operation is to drag it on dragstart.
* We will prevent that and also stop the event from bubbling up.
*/
element.on('dragstart', function(event) {
event = event.originalEvent || event;
if (!event._dndHandle) {
// If a child element already reacted to dragstart and set a dataTransfer object, we will
// allow that. For example, this is the case for user selections inside of input elements.
if (!(event.dataTransfer.types && event.dataTransfer.types.length)) {
event.preventDefault();
}
event.stopPropagation();
}
});
/**
* Stop propagation of dragend events, otherwise dnd-moved might be triggered and the element
* would be removed.
*/
element.on('dragend', function(event) {
event = event.originalEvent || event;
if (!event._dndHandle) {
event.stopPropagation();
}
});
};
})
/**
* Use the dnd-handle directive within a dnd-nodrag element in order to allow dragging with that
* element after all. Therefore, by combining dnd-nodrag and dnd-handle you can allow
* dnd-draggable elements to only be dragged via specific "handle" elements. Note that Internet
* Explorer will show the handle element as drag image instead of the dnd-draggable element. You
* can work around this by styling the handle element differently when it is being dragged. Use
* the CSS selector .dndDragging:not(.dndDraggingSource) [dnd-handle] for that.
*/
.directive('dndHandle', function() {
return function(scope, element, attr) {
element.attr("draggable", "true");
element.on('dragstart dragend', function(event) {
event = event.originalEvent || event;
event._dndHandle = true;
});
};
})
/**
* This workaround handles the fact that Internet Explorer does not support drag types other than
* "Text" and "URL". That means we can not know whether the data comes from one of our elements or
* is just some other data like a text selection. As a workaround we save the isDragging flag in
* here. When a dropover event occurs, we only allow the drop if we are already dragging, because
* that means the element is ours.
*/
.factory('dndDragTypeWorkaround', function(){ return {} })
/**
* Chrome on Windows does not set the dropEffect field, which we need in dragend to determine
* whether a drag operation was successful. Therefore we have to maintain it in this global
* variable. The bug report for that has been open for years:
* https://code.google.com/p/chromium/issues/detail?id=39399
*/
.factory('dndDropEffectWorkaround', function(){ return {} });

View File

@ -1,35 +0,0 @@
/**
* angular-drag-and-drop-lists v1.4.0
*
* Copyright (c) 2014 Marcel Juenemann marcel@juenemann.cc
* Copyright (c) 2014-2016 Google Inc.
* https://github.com/marceljuenemann/angular-drag-and-drop-lists
*
* License: MIT
*/
angular.module("dndLists",[]).directive("dndDraggable",["$parse","$timeout","dndDropEffectWorkaround","dndDragTypeWorkaround",function(e,n,r,t){return function(a,d,o){d.attr("draggable","true"),o.dndDisableIf&&a.$watch(o.dndDisableIf,function(e){d.attr("draggable",!e)}),d.on("dragstart",function(i){return i=i.originalEvent||i,"false"==d.attr("draggable")?!0:(i.dataTransfer.setData("Text",angular.toJson(a.$eval(o.dndDraggable))),i.dataTransfer.effectAllowed=o.dndEffectAllowed||"move",d.addClass("dndDragging"),n(function(){d.addClass("dndDraggingSource")},0),r.dropEffect="none",t.isDragging=!0,t.dragType=o.dndType?a.$eval(o.dndType):void 0,i._dndHandle&&i.dataTransfer.setDragImage&&i.dataTransfer.setDragImage(d[0],0,0),e(o.dndDragstart)(a,{event:i}),void i.stopPropagation())}),d.on("dragend",function(i){i=i.originalEvent||i
var f=r.dropEffect
a.$apply(function(){switch(f){case"move":e(o.dndMoved)(a,{event:i})
break
case"copy":e(o.dndCopied)(a,{event:i})
break
case"none":e(o.dndCanceled)(a,{event:i})}e(o.dndDragend)(a,{event:i,dropEffect:f})}),d.removeClass("dndDragging"),n(function(){d.removeClass("dndDraggingSource")},0),t.isDragging=!1,i.stopPropagation()}),d.on("click",function(n){o.dndSelected&&(n=n.originalEvent||n,a.$apply(function(){e(o.dndSelected)(a,{event:n})}),n.stopPropagation())}),d.on("selectstart",function(){this.dragDrop&&this.dragDrop()})}}]).directive("dndList",["$parse","$timeout","dndDropEffectWorkaround","dndDragTypeWorkaround",function(e,n,r,t){return function(a,d,o){function i(e,n,r){var t=E?e.offsetX||e.layerX:e.offsetY||e.layerY,a=E?n.offsetWidth:n.offsetHeight,d=E?n.offsetLeft:n.offsetTop
return d=r?d:0,d+a/2>t}function f(){var e
return angular.forEach(d.children(),function(n){var r=angular.element(n)
r.hasClass("dndPlaceholder")&&(e=r)}),e||angular.element("<li class='dndPlaceholder'></li>")}function l(){return Array.prototype.indexOf.call(D.children,v)}function g(e){if(!t.isDragging&&!y)return!1
if(!c(e.dataTransfer.types))return!1
if(o.dndAllowedTypes&&t.isDragging){var n=a.$eval(o.dndAllowedTypes)
if(angular.isArray(n)&&-1===n.indexOf(t.dragType))return!1}return o.dndDisableIf&&a.$eval(o.dndDisableIf)?!1:!0}function s(){return p.remove(),d.removeClass("dndDragover"),!0}function u(n,r,d,o){return e(n)(a,{event:r,index:d,item:o||void 0,external:!t.isDragging,type:t.isDragging?t.dragType:void 0})}function c(e){if(!e)return!0
for(var n=0;n<e.length;n++)if("Text"===e[n]||"text/plain"===e[n])return!0
return!1}var p=f(),v=p[0],D=d[0]
p.remove()
var E=o.dndHorizontalList&&a.$eval(o.dndHorizontalList),y=o.dndExternalSources&&a.$eval(o.dndExternalSources)
d.on("dragenter",function(e){return e=e.originalEvent||e,g(e)?void e.preventDefault():!0}),d.on("dragover",function(e){if(e=e.originalEvent||e,!g(e))return!0
if(v.parentNode!=D&&d.append(p),e.target!==D){for(var n=e.target;n.parentNode!==D&&n.parentNode;)n=n.parentNode
n.parentNode===D&&n!==v&&(i(e,n)?D.insertBefore(v,n):D.insertBefore(v,n.nextSibling))}else if(i(e,v,!0))for(;v.previousElementSibling&&(i(e,v.previousElementSibling,!0)||0===v.previousElementSibling.offsetHeight);)D.insertBefore(v,v.previousElementSibling)
else for(;v.nextElementSibling&&!i(e,v.nextElementSibling,!0);)D.insertBefore(v,v.nextElementSibling.nextElementSibling)
return o.dndDragover&&!u(o.dndDragover,e,l())?s():(d.addClass("dndDragover"),e.preventDefault(),e.stopPropagation(),!1)}),d.on("drop",function(e){if(e=e.originalEvent||e,!g(e))return!0
e.preventDefault()
var n,t=e.dataTransfer.getData("Text")||e.dataTransfer.getData("text/plain")
try{n=JSON.parse(t)}catch(d){return s()}var i=l()
return o.dndDrop&&(n=u(o.dndDrop,e,i,n),!n)?s():(n!==!0&&a.$apply(function(){a.$eval(o.dndList).splice(i,0,n)}),u(o.dndInserted,e,i,n),"none"===e.dataTransfer.dropEffect?"copy"===e.dataTransfer.effectAllowed||"move"===e.dataTransfer.effectAllowed?r.dropEffect=e.dataTransfer.effectAllowed:r.dropEffect=e.ctrlKey?"copy":"move":r.dropEffect=e.dataTransfer.dropEffect,s(),e.stopPropagation(),!1)}),d.on("dragleave",function(e){e=e.originalEvent||e,d.removeClass("dndDragover"),n(function(){d.hasClass("dndDragover")||p.remove()},100)})}}]).directive("dndNodrag",function(){return function(e,n,r){n.attr("draggable","true"),n.on("dragstart",function(e){e=e.originalEvent||e,e._dndHandle||(e.dataTransfer.types&&e.dataTransfer.types.length||e.preventDefault(),e.stopPropagation())}),n.on("dragend",function(e){e=e.originalEvent||e,e._dndHandle||e.stopPropagation()})}}).directive("dndHandle",function(){return function(e,n,r){n.attr("draggable","true"),n.on("dragstart dragend",function(e){e=e.originalEvent||e,e._dndHandle=!0})}}).factory("dndDragTypeWorkaround",function(){return{}}).factory("dndDropEffectWorkaround",function(){return{}})

View File

@ -1,30 +0,0 @@
{
"name": "angular-drag-and-drop-lists",
"main": "angular-drag-and-drop-lists.js",
"version": "1.4.0",
"homepage": "https://github.com/marceljuenemann/angular-drag-and-drop-lists",
"authors": [
"Marcel Juenemann <mail@marcel-juenemann.de>"
],
"description": "Angular directives for sorting nested lists using the HTML5 Drag & Drop API",
"keywords": [
"angular",
"drag",
"drop",
"dnd",
"nested",
"sortable",
"lists",
"html5"
],
"license": "MIT",
"ignore": [
"**/.*",
"node_modules",
"bower_components",
"demo",
"*.json",
"test",
"tests"
]
}

View File

@ -1,27 +0,0 @@
{
"author": "Francesco Pontillo",
"name": "angular-filters",
"description": "A collection of filters for AngularJS.",
"version": "1.1.2",
"homepage": "https://github.com/frapontillo/angular-filters",
"repository": {
"type": "git",
"url": "git://github.com/frapontillo/angular-filters.git"
},
"main": "./dist/angular-filters.js",
"dependencies": {
"angular": "~1.4.0"
},
"devDependencies": {
"angular-mocks": "~1.4.0"
},
"_release": "1.1.2",
"_resolution": {
"type": "version",
"tag": "1.1.2",
"commit": "61c1501beb057ff75fbc4953e32623104c6cd8ad"
},
"_source": "git://github.com/frapontillo/angular-filters.git",
"_target": "~1.1.2",
"_originalSource": "angular-filters"
}

View File

@ -1,3 +0,0 @@
.idea
node_modules
bower_components

View File

@ -1,26 +0,0 @@
{
"node": true,
"browser": true,
"esnext": true,
"bitwise": true,
"camelcase": true,
"curly": true,
"eqeqeq": true,
"immed": true,
"indent": 2,
"latedef": true,
"newcap": true,
"noarg": true,
"quotmark": "single",
"regexp": true,
"undef": true,
"unused": true,
"strict": true,
"trailing": true,
"smarttabs": true,
"globals": {
"angular": false,
"$": false,
"jQuery": false
}
}

View File

@ -1,16 +0,0 @@
language: node_js
node_js:
- '0.10'
before_script:
- export DISPLAY=:99.0
- export PHANTOMJS_BIN=/usr/local/phantomjs/bin/phantomjs
- sh -e /etc/init.d/xvfb start
- sleep 3 # give xvfb some time to start
- 'npm install -g bower grunt-cli'
- 'npm install'
- 'bower install'
script:
- grunt

View File

@ -1,40 +0,0 @@
CHANGELOG
=========
#### v1.1.2 (2015-06-13)
- Updated to angular 1.4.0
#### v1.1.1
- Treat `NaN` as an invalid value for the `default` filter
#### v1.1.0
- Added `property` filter
- Added `join` filter
- Updated to angular 1.2.10
#### v1.0.1
- Improved tests and stability
- Rewritten build process
#### v1.0.0
- Main module renamed to `frapontillo.ex.filters` in order to adhere with the [Angular Component Specification draft](https://github.com/PascalPrecht/angular-component-spec).
- Added `bool` filter.
- Upgraded bower information, node packages and Karma test runner.
#### v0.0.2
- Added `firstNotNull`, `lastNotNull`, `max`, `min`.
- Test set complete.
- TravisCI is working.
#### v0.0.1
- First release.
- `default` filter is the only filter at the moment.
- Unit testing with grunt, testacular and gruntacular configured.
- `defaultSpec` test written.

View File

@ -1,109 +0,0 @@
'use strict';
module.exports = function(grunt) {
require('matchdep').filterDev('grunt-*').forEach(grunt.loadNpmTasks);
// configurable paths
var yeomanConfig = {
src: 'src',
dist: 'dist',
test: 'test'
};
grunt.initConfig({
yeoman: yeomanConfig,
pkg: grunt.file.readJSON('package.json'),
dev: {
reporters: 'dots'
},
karma : {
options: {
configFile: 'karma.conf.js',
singleRun: true
},
travis: {
browsers: ['PhantomJS']
},
local: {
browsers: ['Chrome']
},
dev: {
singleRun: false
}
},
jshint: {
options: {
jshintrc: '.jshintrc'
},
src: [
'Gruntfile.js',
'<%= yeoman.src %>/**/*.js'
],
test: {
src: ['<%= yeoman.test %>/**/*.js'],
options: {
jshintrc: 'test/.jshintrc'
}
}
},
meta: {
banner: '/**\n' + ' * <%= pkg.description %>\n' +
' * @version v<%= pkg.version %> - <%= grunt.template.today("yyyy-mm-dd") %>\n' +
' * @author <%= pkg.author.name %>\n' +
' * @link <%= pkg.homepage %>\n' +
' * @license <%= _.pluck(pkg.licenses, "type").join(", ") %>\n**/\n\n'
},
clean: {
dist: {
files: [{
dot: true,
src: [
'<%= yeoman.dist %>/*',
'!<%= yeoman.dist %>/.git*'
]
}]
},
temp: {
src: ['<%= yeoman.dist %>/.temp']
}
},
ngmin: {
dist: {
expand: true,
cwd: '<%= yeoman.src %>',
src: ['**/*.js'],
dest: '<%= yeoman.dist %>/.temp'
}
},
concat: {
options: {
banner: '<%= meta.banner %>\'use strict\';\n',
process: function(src, filepath) {
return '// Source: ' + filepath + '\n' +
src.replace(/(^|\n)[ \t]*('use strict'|"use strict");?\s*/g, '$1');
}
},
build: {
src: ['common/*.js', '<%= yeoman.dist %>/.temp/**/*.js'],
dest: '<%= yeoman.dist %>/<%= pkg.name %>.js'
}
},
uglify: {
options: {
banner: '<%= meta.banner %>'
},
build: {
src: ['<%= yeoman.dist %>/<%= pkg.name %>.js'],
dest: '<%= yeoman.dist %>/<%= pkg.name %>.min.js'
}
}
});
grunt.registerTask('test', ['jshint', 'karma:local']);
grunt.registerTask('test-travis', ['jshint', 'karma:travis']);
grunt.registerTask('build', ['clean', 'ngmin', 'concat', 'uglify', 'clean:temp']);
grunt.registerTask('travis', ['test-travis', 'build']);
grunt.registerTask('default', ['test-travis', 'build']);
};

View File

@ -1,202 +0,0 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.

View File

@ -1,201 +0,0 @@
angular-filters [![Build Status](https://travis-ci.org/frapontillo/angular-filters.png?branch=master)](https://travis-ci.org/frapontillo/angular-filters)
===============
A collection of useful filters for [AngularJS](http://angularjs.org/).
You can install the latest version of `angular-filters` with `bower`:
```bash
$ bower install angular-filters
```
Then, simply include `./dist/angular-filters.js` or `./dist/angular-filters.min.js` in your Web app and inject the module `frapontillo.ex.filters` in your application.
## Filters specs
The included filters are:
- [`bool:trueValue:falseValue`](#bool)
- [`default:defaultValue`](#default)
- [`firstNotNull`](#firstnotnull)
- [`lastNotNull`](#lastnotnull)
- [`max`](#max)
- [`min`](#min)
- [`property`](#property)
- [`join`](#join)
### bool
The `bool` filter allows to **specify true and false values** to show depending on the input value. The second parameter will be returned if and only if the first parameter is `true`; the third parameter will be returned if and only if the first parameter is `false`.
This filter can be used to print a specific message depending on a boolean value.
Use it as follows:
```html
<p>{{ someBoolValue | bool:'Candies!':'No candies :(' }}</p>
```
```javascript
$scope.returnValue = $filter('bool')($scope.someBoolValue, 'Candies!', 'No candies :(');
```
### default
The `default` filter allows to **specify a default fallback value** if an object is one of the following:
- `null`
- `undefined`
- empty string, `''`
- `NaN`
Please notice that if a value equals to `0`, the default value won't be returned, as `0` is accepted.
This filter is useful when another filter return is not safe and when you want to display a fallback value.
Use it as follows:
```html
<p>{{ someValue | number:2 | default:'No value is available.' }}</p>
```
```javascript
$scope.returnValue = $filter('default')
($filter('number')($scope.someValue, 2), 'No value is available.');
```
### firstNotNull
The `firstNotNull` filter returns the **first element from an array** that is neither `null` or `undefined`. This means it returns all numbers and strings, even if empty. It returns `undefined` if all values aren't set or if the array is empty.
Use it as follows:
```html
<p>{{ myValues | firstNotNull }}</p>
```
```javascript
$scope.firstValue = $filter('firstNotNull')($scope.myValues);
```
### lastNotNull
The `lastNotNull` filter returns the **last element from an array** that is neither `null` or `undefined`. This means it returns all numbers and strings, even if empty. It returns `undefined` if all values aren't set or if the array is empty.
Use it as follows:
```html
<p>{{ myValues | lastNotNull }}</p>
```
```javascript
$scope.firstValue = $filter('lastNotNull')($scope.myValues);
```
### max
The `max` filter returns the **maximum value from an array** that is neither `null` or `undefined`. It returns `undefined` if all values aren't set or if the array is empty.
Use it as follows:
```html
<p>{{ myValues | max }}</p>
```
```javascript
$scope.maxValue = $filter('max')($scope.myValues);
```
### min
The `min` filter returns the **minimum value from an array** that is neither `null` or `undefined`. It returns `undefined` if all values aren't set or if the array is empty.
Use it as follows:
```html
<p>{{ myValues | min }}</p>
```
```javascript
$scope.minValue = $filter('min')($scope.myValues);
```
### property
The `property` filter returns an **array with only the specified property from the original objects**, not altering the `null` or `undefined` values.
Use it as follows:
```html
<p>{{ myObjects | property:'myText' }}</p>
```
```javascript
$scope.allTheTexts = $filter('property')($scope.myObjects, 'myText');
```
### join
The `join` filter returns **the original array as a string, with its elements joined with the specified separator**, if any, otherwise defaulting to the comma `,`.
Use it as follows:
```html
<p>{{ myValues | join:', ' }}</p>
```
```javascript
$scope.joinedValues = $filter('join')($scope.myValues, ', ');
```
## Development
### Test and build
To test and build the distribution files yourself, do the following:
```shell
npm install -g grunt-cli karma bower
npm install
bower install
grunt
```
These are the available grunt task:
* `karma:travis`, run karma tests once, on PhantomJS
* `karma:local`, run karma tests once, on Chrome
* `karma:dev`, run karma tests indefinitely after every file change, on Chrome
* `jshint:src`, run jshint on every source file
* `jshint:test`, run jshint on every test file
* `clean:dist`, clean the distribution directory
* `clean:temp`, clean the temporary directory
* `ngmin`, prepares every angular file into the `dist/.temp` directory
* `concat`, concatenates the module declaration and the `ngmin`-ified file from the `dist/.temp` into the `dist` directory, adding the banner
* `uglify`, minifies the output file in the `dist` directory, adding the banner
* `build`, builds the regular and minified file
* `test-travis`, runs `jshint` and `karma:travis`
Use the default task by calling `grunt` to run tests on PhantomJS and builds the regular and minified file.
### Contribute
To contribute, please follow the generic [AngularJS Contributing Guidelines](https://github.com/angular/angular.js/blob/master/CONTRIBUTING.md), with the only exception to send the PR to the `develop` branch instead of `master`.
## License
```
Copyright 2014-2015 Francesco Pontillo
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
```

View File

@ -1,18 +0,0 @@
{
"author": "Francesco Pontillo",
"name": "angular-filters",
"description": "A collection of filters for AngularJS.",
"version": "1.1.2",
"homepage": "https://github.com/frapontillo/angular-filters",
"repository": {
"type": "git",
"url": "git://github.com/frapontillo/angular-filters.git"
},
"main": "./dist/angular-filters.js",
"dependencies": {
"angular": "~1.4.0"
},
"devDependencies": {
"angular-mocks": "~1.4.0"
}
}

View File

@ -1,2 +0,0 @@
angular.module('frapontillo.ex.filters', []);
angular.module('frapontillo', ['ex.filters']);

View File

@ -1,101 +0,0 @@
/**
* A collection of filters for AngularJS.
* @version v1.1.2 - 2015-06-13
* @author Francesco Pontillo
* @link https://github.com/frapontillo/angular-filters
* @license Apache License 2.0
**/
'use strict';
// Source: common/module.js
angular.module('frapontillo.ex.filters', []);
angular.module('frapontillo', ['ex.filters']);
// Source: dist/.temp/filters/bool/bool.js
angular.module('frapontillo.ex.filters').filter('bool', function () {
return function (input, valueTrue, valueFalse) {
return input !== true ? valueFalse : valueTrue;
};
});
// Source: dist/.temp/filters/default/default.js
angular.module('frapontillo.ex.filters').filter('default', function () {
return function (input, value) {
if (!isNaN(input) && input !== null && input !== undefined && (input !== '' || angular.isNumber(input))) {
return input;
}
return value || '';
};
});
// Source: dist/.temp/filters/firstNotNull/firstNotNull.js
angular.module('frapontillo.ex.filters').filter('firstNotNull', function () {
return function (input) {
if (input) {
var l = input.length - 1;
for (var i = 0; i <= l; i++) {
if (input[i] !== undefined && input[i] !== null) {
return input[i];
}
}
}
};
});
// Source: dist/.temp/filters/join/join.js
angular.module('frapontillo.ex.filters').filter('join', function () {
return function (array, separator) {
if (!array) {
return '';
}
return array.join(separator);
};
});
// Source: dist/.temp/filters/lastNotNull/lastNotNull.js
angular.module('frapontillo.ex.filters').filter('lastNotNull', function () {
return function (input) {
if (input) {
var l = input.length - 1;
for (var i = l; i >= 0; i--) {
if (input[i] !== undefined) {
return input[i];
}
}
}
};
});
// Source: dist/.temp/filters/max/max.js
angular.module('frapontillo.ex.filters').filter('max', function () {
return function (input) {
var out;
if (input) {
for (var i in input) {
if (input[i] > out || out === undefined || out === null) {
out = input[i];
}
}
}
return out;
};
});
// Source: dist/.temp/filters/min/min.js
angular.module('frapontillo.ex.filters').filter('min', function () {
return function (input) {
var out;
if (input) {
for (var i in input) {
if (input[i] < out || out === undefined || out === null) {
out = input[i];
}
}
}
return out;
};
});
// Source: dist/.temp/filters/property/property.js
angular.module('frapontillo.ex.filters').filter('property', function () {
return function (array, property) {
var newArray = [];
angular.forEach(array, function (element) {
var evalProperty = element[property];
newArray.push(evalProperty);
});
return newArray;
};
});

View File

@ -1,9 +0,0 @@
/**
* A collection of filters for AngularJS.
* @version v1.1.2 - 2015-06-13
* @author Francesco Pontillo
* @link https://github.com/frapontillo/angular-filters
* @license Apache License 2.0
**/
"use strict";angular.module("frapontillo.ex.filters",[]),angular.module("frapontillo",["ex.filters"]),angular.module("frapontillo.ex.filters").filter("bool",function(){return function(a,b,c){return a!==!0?c:b}}),angular.module("frapontillo.ex.filters").filter("default",function(){return function(a,b){return isNaN(a)||null===a||void 0===a||""===a&&!angular.isNumber(a)?b||"":a}}),angular.module("frapontillo.ex.filters").filter("firstNotNull",function(){return function(a){if(a)for(var b=a.length-1,c=0;b>=c;c++)if(void 0!==a[c]&&null!==a[c])return a[c]}}),angular.module("frapontillo.ex.filters").filter("join",function(){return function(a,b){return a?a.join(b):""}}),angular.module("frapontillo.ex.filters").filter("lastNotNull",function(){return function(a){if(a)for(var b=a.length-1,c=b;c>=0;c--)if(void 0!==a[c])return a[c]}}),angular.module("frapontillo.ex.filters").filter("max",function(){return function(a){var b;if(a)for(var c in a)(a[c]>b||void 0===b||null===b)&&(b=a[c]);return b}}),angular.module("frapontillo.ex.filters").filter("min",function(){return function(a){var b;if(a)for(var c in a)(a[c]<b||void 0===b||null===b)&&(b=a[c]);return b}}),angular.module("frapontillo.ex.filters").filter("property",function(){return function(a,b){var c=[];return angular.forEach(a,function(a){var d=a[b];c.push(d)}),c}});

Some files were not shown because too many files have changed in this diff Show More