From 1cd231fdb902a8046064f60f7750c62190fd8b5e Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 28 May 2018 20:47:54 +0200 Subject: [PATCH 001/115] upgrade angular version + load new dependencies --- src/Umbraco.Web.UI.Client/bower.json | 7 +- src/Umbraco.Web.UI.Client/package-lock.json | 3352 ++++++----------- src/Umbraco.Web.UI.Client/src/app.js | 4 +- src/Umbraco.Web/UI/JavaScript/JsInitialize.js | 10 +- 4 files changed, 1235 insertions(+), 2138 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/bower.json b/src/Umbraco.Web.UI.Client/bower.json index ac8a79ca26..e8fb7d78fa 100644 --- a/src/Umbraco.Web.UI.Client/bower.json +++ b/src/Umbraco.Web.UI.Client/bower.json @@ -16,6 +16,12 @@ "tests" ], "dependencies": { + "angular": "1.7.0", + "angular-cookies": "1.7.0", + "angular-sanitize": "1.7.0", + "angular-touch": "1.7.0", + "angular-route": "1.7.0", + "angular-animate": "1.7.0", "signalr": "^2.2.1", "typeahead.js": "~0.10.5", "underscore": "~1.7.0", @@ -39,7 +45,6 @@ "path": "lib-bower", "ignore": [ "font-awesome", - "angular", "bootstrap", "codemirror" ], diff --git a/src/Umbraco.Web.UI.Client/package-lock.json b/src/Umbraco.Web.UI.Client/package-lock.json index 6ffaa55d68..79aab79300 100644 --- a/src/Umbraco.Web.UI.Client/package-lock.json +++ b/src/Umbraco.Web.UI.Client/package-lock.json @@ -16,7 +16,7 @@ "integrity": "sha1-5fHzkoxtlf2WVYw27D2dDeSm7Oo=", "dev": true, "requires": { - "mime-types": "~2.1.6", + "mime-types": "2.1.18", "negotiator": "0.5.3" } }, @@ -26,20 +26,20 @@ "integrity": "sha1-vsUWovci59UPX59C+Bt387lUSLo=", "dev": true, "requires": { - "convert-source-map": "^1.5.0", - "glob": "^7.0.5", - "indx": "^0.2.3", - "lodash.clone": "^4.3.2", - "lodash.defaults": "^4.0.1", - "lodash.flatten": "^4.2.0", - "lodash.merge": "^4.4.0", - "lodash.partialright": "^4.1.4", - "lodash.pick": "^4.2.1", - "lodash.uniq": "^4.3.0", - "resolve": "^1.5.0", - "semver": "^5.3.0", - "uglify-js": "^2.8.22", - "when": "^3.7.8" + "convert-source-map": "1.5.1", + "glob": "7.1.2", + "indx": "0.2.3", + "lodash.clone": "4.5.0", + "lodash.defaults": "4.2.0", + "lodash.flatten": "4.4.0", + "lodash.merge": "4.6.1", + "lodash.partialright": "4.2.1", + "lodash.pick": "4.4.0", + "lodash.uniq": "4.5.0", + "resolve": "1.6.0", + "semver": "5.5.0", + "uglify-js": "2.8.29", + "when": "3.7.8" }, "dependencies": { "semver": { @@ -62,8 +62,8 @@ "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", "dev": true, "requires": { - "co": "^4.6.0", - "json-stable-stringify": "^1.0.1" + "co": "4.6.0", + "json-stable-stringify": "1.0.1" } }, "align-text": { @@ -72,9 +72,9 @@ "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", "dev": true, "requires": { - "kind-of": "^3.0.2", - "longest": "^1.0.1", - "repeat-string": "^1.5.2" + "kind-of": "3.2.2", + "longest": "1.0.1", + "repeat-string": "1.6.1" }, "dependencies": { "kind-of": { @@ -83,7 +83,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.6" } } } @@ -163,8 +163,8 @@ "integrity": "sha1-VT3Lj5HjyImEXf26NMd3IbkLnXo=", "dev": true, "requires": { - "micromatch": "^2.1.5", - "normalize-path": "^2.0.0" + "micromatch": "2.3.11", + "normalize-path": "2.1.1" }, "dependencies": { "arr-diff": { @@ -173,7 +173,7 @@ "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", "dev": true, "requires": { - "arr-flatten": "^1.0.1" + "arr-flatten": "1.1.0" } }, "array-unique": { @@ -188,9 +188,9 @@ "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", "dev": true, "requires": { - "expand-range": "^1.8.1", - "preserve": "^0.2.0", - "repeat-element": "^1.1.2" + "expand-range": "1.8.2", + "preserve": "0.2.0", + "repeat-element": "1.1.2" } }, "expand-brackets": { @@ -199,7 +199,7 @@ "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", "dev": true, "requires": { - "is-posix-bracket": "^0.1.0" + "is-posix-bracket": "0.1.1" } }, "extglob": { @@ -208,7 +208,7 @@ "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", "dev": true, "requires": { - "is-extglob": "^1.0.0" + "is-extglob": "1.0.0" } }, "is-extglob": { @@ -223,7 +223,7 @@ "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", "dev": true, "requires": { - "is-extglob": "^1.0.0" + "is-extglob": "1.0.0" } }, "kind-of": { @@ -232,7 +232,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.6" } }, "micromatch": { @@ -241,19 +241,19 @@ "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", "dev": true, "requires": { - "arr-diff": "^2.0.0", - "array-unique": "^0.2.1", - "braces": "^1.8.2", - "expand-brackets": "^0.1.4", - "extglob": "^0.3.1", - "filename-regex": "^2.0.0", - "is-extglob": "^1.0.0", - "is-glob": "^2.0.1", - "kind-of": "^3.0.2", - "normalize-path": "^2.0.1", - "object.omit": "^2.0.0", - "parse-glob": "^3.0.4", - "regex-cache": "^0.4.2" + "arr-diff": "2.0.0", + "array-unique": "0.2.1", + "braces": "1.8.5", + "expand-brackets": "0.1.5", + "extglob": "0.3.2", + "filename-regex": "2.0.1", + "is-extglob": "1.0.0", + "is-glob": "2.0.1", + "kind-of": "3.2.2", + "normalize-path": "2.1.1", + "object.omit": "2.0.1", + "parse-glob": "3.0.4", + "regex-cache": "0.4.4" } } } @@ -270,7 +270,7 @@ "integrity": "sha1-vNZ5HqWuCXJeF+WtmIE0zUCz2RE=", "dev": true, "requires": { - "sprintf-js": "~1.0.2" + "sprintf-js": "1.0.3" } }, "arr-diff": { @@ -364,7 +364,7 @@ "integrity": "sha1-YaKau2/MAm/qd+VtHG7FOnlZUfQ=", "dev": true, "requires": { - "lodash": "^4.14.0" + "lodash": "4.17.5" } }, "async-each": { @@ -391,12 +391,12 @@ "integrity": "sha1-Hb0cg1ZY41zj+ZhAmdsAWFx4IBQ=", "dev": true, "requires": { - "browserslist": "^1.7.6", - "caniuse-db": "^1.0.30000634", - "normalize-range": "^0.1.2", - "num2fraction": "^1.2.2", - "postcss": "^5.2.16", - "postcss-value-parser": "^3.2.3" + "browserslist": "1.7.7", + "caniuse-db": "1.0.30000821", + "normalize-range": "0.1.2", + "num2fraction": "1.2.2", + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" } }, "aws-sign2": { @@ -429,13 +429,13 @@ "integrity": "sha1-e95c7RRbbVUakNuH+DxVi060io8=", "dev": true, "requires": { - "cache-base": "^1.0.1", - "class-utils": "^0.3.5", - "component-emitter": "^1.2.1", - "define-property": "^1.0.0", - "isobject": "^3.0.1", - "mixin-deep": "^1.2.0", - "pascalcase": "^0.1.1" + "cache-base": "1.0.1", + "class-utils": "0.3.6", + "component-emitter": "1.2.1", + "define-property": "1.0.0", + "isobject": "3.0.1", + "mixin-deep": "1.3.1", + "pascalcase": "0.1.1" }, "dependencies": { "define-property": { @@ -444,7 +444,7 @@ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", "dev": true, "requires": { - "is-descriptor": "^1.0.0" + "is-descriptor": "1.0.2" } } } @@ -492,7 +492,7 @@ "dev": true, "optional": true, "requires": { - "tweetnacl": "^0.14.3" + "tweetnacl": "0.14.5" } }, "beeper": { @@ -535,15 +535,15 @@ "dev": true, "requires": { "bytes": "2.1.0", - "content-type": "~1.0.1", - "debug": "~2.2.0", - "depd": "~1.0.1", - "http-errors": "~1.3.1", + "content-type": "1.0.4", + "debug": "2.2.0", + "depd": "1.0.1", + "http-errors": "1.3.1", "iconv-lite": "0.4.11", - "on-finished": "~2.3.0", + "on-finished": "2.3.0", "qs": "4.0.0", - "raw-body": "~2.1.2", - "type-is": "~1.6.6" + "raw-body": "2.1.7", + "type-is": "1.6.16" }, "dependencies": { "debug": { @@ -569,7 +569,7 @@ "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", "dev": true, "requires": { - "hoek": "2.x.x" + "hoek": "2.16.3" } }, "bower": { @@ -584,14 +584,14 @@ "integrity": "sha1-z3g5tlQh0rJwqyLHT8hYpV46E3A=", "dev": true, "requires": { - "async": "^2.1.4", - "bower": "^1.8.0", - "colors": "^1.1.2", - "glob": "^7.1.1", - "lodash": "^4.17.2", - "mkdirp": "^0.5.1", - "node-fs": "~0.1.7", - "nopt": "^3.0.6" + "async": "2.6.0", + "bower": "1.8.4", + "colors": "1.2.1", + "glob": "7.1.2", + "lodash": "4.17.5", + "mkdirp": "0.5.1", + "node-fs": "0.1.7", + "nopt": "3.0.6" } }, "brace-expansion": { @@ -600,7 +600,7 @@ "integrity": "sha1-PH/L9SnYcibz0vUrlm/1Jx60Qd0=", "dev": true, "requires": { - "balanced-match": "^1.0.0", + "balanced-match": "1.0.0", "concat-map": "0.0.1" } }, @@ -610,18 +610,18 @@ "integrity": "sha1-cIbJE7TloI2+N6wO5qJQDEumkbs=", "dev": true, "requires": { - "arr-flatten": "^1.1.0", - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "extend-shallow": "^2.0.1", - "fill-range": "^4.0.0", - "isobject": "^3.0.1", - "kind-of": "^6.0.2", - "repeat-element": "^1.1.2", - "snapdragon": "^0.8.1", - "snapdragon-node": "^2.0.1", - "split-string": "^3.0.2", - "to-regex": "^3.0.1" + "arr-flatten": "1.1.0", + "array-unique": "0.3.2", + "define-property": "1.0.0", + "extend-shallow": "2.0.1", + "fill-range": "4.0.0", + "isobject": "3.0.1", + "kind-of": "6.0.2", + "repeat-element": "1.1.2", + "snapdragon": "0.8.2", + "snapdragon-node": "2.1.1", + "split-string": "3.1.0", + "to-regex": "3.0.2" }, "dependencies": { "define-property": { @@ -630,7 +630,7 @@ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", "dev": true, "requires": { - "is-descriptor": "^1.0.0" + "is-descriptor": "1.0.2" } }, "extend-shallow": { @@ -639,7 +639,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "^0.1.0" + "is-extendable": "0.1.1" } } } @@ -650,8 +650,8 @@ "integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=", "dev": true, "requires": { - "caniuse-db": "^1.0.30000639", - "electron-to-chromium": "^1.2.7" + "caniuse-db": "1.0.30000821", + "electron-to-chromium": "1.3.41" } }, "bufferstreams": { @@ -660,7 +660,7 @@ "integrity": "sha1-z7GtlWjTujz+k1upq92VLeiKqyo=", "dev": true, "requires": { - "readable-stream": "^1.0.33" + "readable-stream": "1.1.14" } }, "builtin-modules": { @@ -681,15 +681,15 @@ "integrity": "sha1-Cn9GQWgxyLZi7jb+TnxZ129marI=", "dev": true, "requires": { - "collection-visit": "^1.0.0", - "component-emitter": "^1.2.1", - "get-value": "^2.0.6", - "has-value": "^1.0.0", - "isobject": "^3.0.1", - "set-value": "^2.0.0", - "to-object-path": "^0.3.0", - "union-value": "^1.0.0", - "unset-value": "^1.0.0" + "collection-visit": "1.0.0", + "component-emitter": "1.2.1", + "get-value": "2.0.6", + "has-value": "1.0.0", + "isobject": "3.0.1", + "set-value": "2.0.0", + "to-object-path": "0.3.0", + "union-value": "1.0.0", + "unset-value": "1.0.0" } }, "callsite": { @@ -710,8 +710,8 @@ "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", "dev": true, "requires": { - "camelcase": "^2.0.0", - "map-obj": "^1.0.0" + "camelcase": "2.1.1", + "map-obj": "1.0.1" }, "dependencies": { "camelcase": { @@ -728,10 +728,10 @@ "integrity": "sha1-tTTnxzTE+B7F++isoq0kNUuWLGw=", "dev": true, "requires": { - "browserslist": "^1.3.6", - "caniuse-db": "^1.0.30000529", - "lodash.memoize": "^4.1.2", - "lodash.uniq": "^4.5.0" + "browserslist": "1.7.7", + "caniuse-db": "1.0.30000821", + "lodash.memoize": "4.1.2", + "lodash.uniq": "4.5.0" } }, "caniuse-db": { @@ -758,8 +758,8 @@ "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", "dev": true, "requires": { - "align-text": "^0.1.3", - "lazy-cache": "^1.0.3" + "align-text": "0.1.4", + "lazy-cache": "1.0.4" } }, "chalk": { @@ -768,11 +768,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "^2.2.1", - "escape-string-regexp": "^1.0.2", - "has-ansi": "^2.0.0", - "strip-ansi": "^3.0.0", - "supports-color": "^2.0.0" + "ansi-styles": "2.2.1", + "escape-string-regexp": "1.0.5", + "has-ansi": "2.0.0", + "strip-ansi": "3.0.1", + "supports-color": "2.0.0" }, "dependencies": { "supports-color": { @@ -789,15 +789,14 @@ "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", "dev": true, "requires": { - "anymatch": "^1.3.0", - "async-each": "^1.0.0", - "fsevents": "^1.0.0", - "glob-parent": "^2.0.0", - "inherits": "^2.0.1", - "is-binary-path": "^1.0.0", - "is-glob": "^2.0.0", - "path-is-absolute": "^1.0.0", - "readdirp": "^2.0.0" + "anymatch": "1.3.2", + "async-each": "1.0.1", + "glob-parent": "2.0.0", + "inherits": "2.0.3", + "is-binary-path": "1.0.1", + "is-glob": "2.0.1", + "path-is-absolute": "1.0.1", + "readdirp": "2.1.0" }, "dependencies": { "glob-parent": { @@ -806,7 +805,7 @@ "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", "dev": true, "requires": { - "is-glob": "^2.0.0" + "is-glob": "2.0.1" } }, "is-extglob": { @@ -821,7 +820,7 @@ "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", "dev": true, "requires": { - "is-extglob": "^1.0.0" + "is-extglob": "1.0.0" } } } @@ -832,7 +831,7 @@ "integrity": "sha1-TzZ0WzIAhJJVf0ZBLWbVDLmbzlE=", "dev": true, "requires": { - "chalk": "^1.1.3" + "chalk": "1.1.3" } }, "class-utils": { @@ -841,10 +840,10 @@ "integrity": "sha1-+TNprouafOAv1B+q0MqDAzGQxGM=", "dev": true, "requires": { - "arr-union": "^3.1.0", - "define-property": "^0.2.5", - "isobject": "^3.0.0", - "static-extend": "^0.1.1" + "arr-union": "3.1.0", + "define-property": "0.2.5", + "isobject": "3.0.1", + "static-extend": "0.1.2" }, "dependencies": { "define-property": { @@ -853,7 +852,7 @@ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "^0.1.0" + "is-descriptor": "0.1.6" } }, "is-accessor-descriptor": { @@ -862,7 +861,7 @@ "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", "dev": true, "requires": { - "kind-of": "^3.0.2" + "kind-of": "3.2.2" }, "dependencies": { "kind-of": { @@ -871,7 +870,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.6" } } } @@ -882,7 +881,7 @@ "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", "dev": true, "requires": { - "kind-of": "^3.0.2" + "kind-of": "3.2.2" }, "dependencies": { "kind-of": { @@ -891,7 +890,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.6" } } } @@ -902,9 +901,9 @@ "integrity": "sha1-Nm2CQN3kh8pRgjsaufB6EKeCUco=", "dev": true, "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" } }, "kind-of": { @@ -921,8 +920,8 @@ "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", "dev": true, "requires": { - "center-align": "^0.1.1", - "right-align": "^0.1.1", + "center-align": "0.1.3", + "right-align": "0.1.3", "wordwrap": "0.0.2" } }, @@ -950,9 +949,9 @@ "integrity": "sha1-1ZHe5Kj4vBXaQ86X3O66E9Q+KmU=", "dev": true, "requires": { - "inherits": "^2.0.1", - "process-nextick-args": "^2.0.0", - "readable-stream": "^2.3.5" + "inherits": "2.0.3", + "process-nextick-args": "2.0.0", + "readable-stream": "2.3.5" }, "dependencies": { "isarray": { @@ -967,13 +966,13 @@ "integrity": "sha1-tPhQA6k4y7bsvOKhJPsQEr0ag40=", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.0.3", - "util-deprecate": "~1.0.1" + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" } }, "string_decoder": { @@ -982,7 +981,7 @@ "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", "dev": true, "requires": { - "safe-buffer": "~5.1.0" + "safe-buffer": "5.1.1" } } } @@ -999,7 +998,7 @@ "integrity": "sha1-qe8VNmDWqGqL3sAomlxoTSF0Mv0=", "dev": true, "requires": { - "q": "^1.1.2" + "q": "1.5.1" } }, "collection-visit": { @@ -1008,8 +1007,8 @@ "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", "dev": true, "requires": { - "map-visit": "^1.0.0", - "object-visit": "^1.0.0" + "map-visit": "1.0.0", + "object-visit": "1.0.1" } }, "color": { @@ -1018,9 +1017,9 @@ "integrity": "sha1-bXtcdPtl6EHNSHkq0e1eB7kE12Q=", "dev": true, "requires": { - "clone": "^1.0.2", - "color-convert": "^1.3.0", - "color-string": "^0.3.0" + "clone": "1.0.4", + "color-convert": "1.9.1", + "color-string": "0.3.0" } }, "color-convert": { @@ -1029,7 +1028,7 @@ "integrity": "sha1-wSYRB66y8pTr/+ye2eytUppgl+0=", "dev": true, "requires": { - "color-name": "^1.1.1" + "color-name": "1.1.3" } }, "color-name": { @@ -1044,7 +1043,7 @@ "integrity": "sha1-J9RvtnAlxcL6JZk7+/V55HhBuZE=", "dev": true, "requires": { - "color-name": "^1.0.0" + "color-name": "1.1.3" } }, "color-support": { @@ -1059,9 +1058,9 @@ "integrity": "sha1-6i90IKcrlogaOKrlnsEkpvcpgTM=", "dev": true, "requires": { - "color": "^0.11.0", + "color": "0.11.4", "css-color-names": "0.0.4", - "has": "^1.0.1" + "has": "1.0.1" } }, "colors": { @@ -1076,7 +1075,7 @@ "integrity": "sha1-RYwH4J4NkA/Ci3Cj/sLazR0st/Y=", "dev": true, "requires": { - "lodash": "^4.5.0" + "lodash": "4.17.5" } }, "combined-stream": { @@ -1085,7 +1084,7 @@ "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", "dev": true, "requires": { - "delayed-stream": "~1.0.0" + "delayed-stream": "1.0.0" } }, "component-bind": { @@ -1112,7 +1111,7 @@ "integrity": "sha1-DRAgq5JLL9tNYnmHXH1tq6a6p6k=", "dev": true, "requires": { - "mime-db": ">= 1.33.0 < 2" + "mime-db": "1.33.0" } }, "compression": { @@ -1121,12 +1120,12 @@ "integrity": "sha1-sDuNhub4rSloPLqN+R3cb/x3s5U=", "dev": true, "requires": { - "accepts": "~1.2.12", + "accepts": "1.2.13", "bytes": "2.1.0", - "compressible": "~2.0.5", - "debug": "~2.2.0", - "on-headers": "~1.0.0", - "vary": "~1.0.1" + "compressible": "2.0.13", + "debug": "2.2.0", + "on-headers": "1.0.1", + "vary": "1.0.1" }, "dependencies": { "debug": { @@ -1158,9 +1157,9 @@ "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", "dev": true, "requires": { - "inherits": "^2.0.3", - "readable-stream": "^2.2.2", - "typedarray": "^0.0.6" + "inherits": "2.0.3", + "readable-stream": "2.3.5", + "typedarray": "0.0.6" }, "dependencies": { "isarray": { @@ -1175,13 +1174,13 @@ "integrity": "sha1-tPhQA6k4y7bsvOKhJPsQEr0ag40=", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.0.3", - "util-deprecate": "~1.0.1" + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" } }, "string_decoder": { @@ -1190,7 +1189,7 @@ "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", "dev": true, "requires": { - "safe-buffer": "~5.1.0" + "safe-buffer": "5.1.1" } } } @@ -1201,7 +1200,7 @@ "integrity": "sha1-iWS8I0fQWBm2N5gQTYfW4AG+2NA=", "dev": true, "requires": { - "source-map": "^0.6.1" + "source-map": "0.6.1" }, "dependencies": { "source-map": { @@ -1219,36 +1218,36 @@ "dev": true, "requires": { "basic-auth-connect": "1.0.0", - "body-parser": "~1.13.3", + "body-parser": "1.13.3", "bytes": "2.1.0", - "compression": "~1.5.2", - "connect-timeout": "~1.6.2", - "content-type": "~1.0.1", + "compression": "1.5.2", + "connect-timeout": "1.6.2", + "content-type": "1.0.4", "cookie": "0.1.3", - "cookie-parser": "~1.3.5", + "cookie-parser": "1.3.5", "cookie-signature": "1.0.6", - "csurf": "~1.8.3", - "debug": "~2.2.0", - "depd": "~1.0.1", - "errorhandler": "~1.4.2", - "express-session": "~1.11.3", + "csurf": "1.8.3", + "debug": "2.2.0", + "depd": "1.0.1", + "errorhandler": "1.4.3", + "express-session": "1.11.3", "finalhandler": "0.4.0", "fresh": "0.3.0", - "http-errors": "~1.3.1", - "method-override": "~2.3.5", - "morgan": "~1.6.1", + "http-errors": "1.3.1", + "method-override": "2.3.10", + "morgan": "1.6.1", "multiparty": "3.3.2", - "on-headers": "~1.0.0", - "parseurl": "~1.3.0", + "on-headers": "1.0.1", + "parseurl": "1.3.2", "pause": "0.1.0", "qs": "4.0.0", - "response-time": "~2.3.1", - "serve-favicon": "~2.3.0", - "serve-index": "~1.7.2", - "serve-static": "~1.10.0", - "type-is": "~1.6.6", + "response-time": "2.3.2", + "serve-favicon": "2.3.2", + "serve-index": "1.7.3", + "serve-static": "1.10.3", + "type-is": "1.6.16", "utils-merge": "1.0.0", - "vhost": "~3.0.1" + "vhost": "3.0.2" }, "dependencies": { "debug": { @@ -1280,10 +1279,10 @@ "integrity": "sha1-3ppexh4zoStu2qt7XwYumMWZuI4=", "dev": true, "requires": { - "debug": "~2.2.0", - "http-errors": "~1.3.1", + "debug": "2.2.0", + "http-errors": "1.3.1", "ms": "0.7.1", - "on-headers": "~1.0.0" + "on-headers": "1.0.1" }, "dependencies": { "debug": { @@ -1309,7 +1308,7 @@ "integrity": "sha1-WiUEe8dvcwcmZ8jLUsmJiI9JTGM=", "dev": true, "requires": { - "bluebird": "^3.1.1" + "bluebird": "3.5.1" } }, "content-type": { @@ -1370,13 +1369,13 @@ "integrity": "sha1-YXPOvVb6wELB9DkO33r2wHx8uJI=", "dev": true, "requires": { - "is-directory": "^0.3.1", - "js-yaml": "^3.4.3", - "minimist": "^1.2.0", - "object-assign": "^4.1.0", - "os-homedir": "^1.0.1", - "parse-json": "^2.2.0", - "require-from-string": "^1.1.0" + "is-directory": "0.3.1", + "js-yaml": "3.7.0", + "minimist": "1.2.0", + "object-assign": "4.1.1", + "os-homedir": "1.0.2", + "parse-json": "2.2.0", + "require-from-string": "1.2.1" }, "dependencies": { "minimist": { @@ -1399,7 +1398,7 @@ "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", "dev": true, "requires": { - "boom": "2.x.x" + "boom": "2.10.1" } }, "csrf": { @@ -1425,38 +1424,38 @@ "integrity": "sha1-Tzj2zqK5sX+gFJDyPx3GjqZcHDg=", "dev": true, "requires": { - "autoprefixer": "^6.3.1", - "decamelize": "^1.1.2", - "defined": "^1.0.0", - "has": "^1.0.1", - "object-assign": "^4.0.1", - "postcss": "^5.0.14", - "postcss-calc": "^5.2.0", - "postcss-colormin": "^2.1.8", - "postcss-convert-values": "^2.3.4", - "postcss-discard-comments": "^2.0.4", - "postcss-discard-duplicates": "^2.0.1", - "postcss-discard-empty": "^2.0.1", - "postcss-discard-overridden": "^0.1.1", - "postcss-discard-unused": "^2.2.1", - "postcss-filter-plugins": "^2.0.0", - "postcss-merge-idents": "^2.1.5", - "postcss-merge-longhand": "^2.0.1", - "postcss-merge-rules": "^2.0.3", - "postcss-minify-font-values": "^1.0.2", - "postcss-minify-gradients": "^1.0.1", - "postcss-minify-params": "^1.0.4", - "postcss-minify-selectors": "^2.0.4", - "postcss-normalize-charset": "^1.1.0", - "postcss-normalize-url": "^3.0.7", - "postcss-ordered-values": "^2.1.0", - "postcss-reduce-idents": "^2.2.2", - "postcss-reduce-initial": "^1.0.0", - "postcss-reduce-transforms": "^1.0.3", - "postcss-svgo": "^2.1.1", - "postcss-unique-selectors": "^2.0.2", - "postcss-value-parser": "^3.2.3", - "postcss-zindex": "^2.0.1" + "autoprefixer": "6.7.7", + "decamelize": "1.2.0", + "defined": "1.0.0", + "has": "1.0.1", + "object-assign": "4.1.1", + "postcss": "5.2.18", + "postcss-calc": "5.3.1", + "postcss-colormin": "2.2.2", + "postcss-convert-values": "2.6.1", + "postcss-discard-comments": "2.0.4", + "postcss-discard-duplicates": "2.1.0", + "postcss-discard-empty": "2.1.0", + "postcss-discard-overridden": "0.1.1", + "postcss-discard-unused": "2.2.3", + "postcss-filter-plugins": "2.0.2", + "postcss-merge-idents": "2.1.7", + "postcss-merge-longhand": "2.0.2", + "postcss-merge-rules": "2.1.2", + "postcss-minify-font-values": "1.0.5", + "postcss-minify-gradients": "1.0.5", + "postcss-minify-params": "1.2.2", + "postcss-minify-selectors": "2.1.1", + "postcss-normalize-charset": "1.1.1", + "postcss-normalize-url": "3.0.8", + "postcss-ordered-values": "2.2.3", + "postcss-reduce-idents": "2.4.0", + "postcss-reduce-initial": "1.0.1", + "postcss-reduce-transforms": "1.0.4", + "postcss-svgo": "2.1.6", + "postcss-unique-selectors": "2.0.2", + "postcss-value-parser": "3.3.0", + "postcss-zindex": "2.2.0" } }, "csso": { @@ -1465,8 +1464,8 @@ "integrity": "sha1-3dUsWHAz9J6Utx/FVWnyUuj/X4U=", "dev": true, "requires": { - "clap": "^1.0.9", - "source-map": "^0.5.3" + "clap": "1.2.3", + "source-map": "0.5.7" } }, "csurf": { @@ -1477,8 +1476,8 @@ "requires": { "cookie": "0.1.3", "cookie-signature": "1.0.6", - "csrf": "~3.0.0", - "http-errors": "~1.3.1" + "csrf": "3.0.6", + "http-errors": "1.3.1" } }, "currently-unhandled": { @@ -1487,7 +1486,7 @@ "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", "dev": true, "requires": { - "array-find-index": "^1.0.1" + "array-find-index": "1.0.2" } }, "custom-event": { @@ -1502,7 +1501,7 @@ "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", "dev": true, "requires": { - "assert-plus": "^1.0.0" + "assert-plus": "1.0.0" }, "dependencies": { "assert-plus": { @@ -1552,7 +1551,7 @@ "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", "dev": true, "requires": { - "clone": "^1.0.2" + "clone": "1.0.4" } }, "define-property": { @@ -1561,8 +1560,8 @@ "integrity": "sha1-1Flono1lS6d+AqgX+HENcCyxbp0=", "dev": true, "requires": { - "is-descriptor": "^1.0.2", - "isobject": "^3.0.1" + "is-descriptor": "1.0.2", + "isobject": "3.0.1" } }, "defined": { @@ -1613,10 +1612,10 @@ "integrity": "sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs=", "dev": true, "requires": { - "custom-event": "~1.0.0", - "ent": "~2.2.0", - "extend": "^3.0.0", - "void-elements": "^2.0.0" + "custom-event": "1.0.1", + "ent": "2.2.0", + "extend": "3.0.1", + "void-elements": "2.0.1" } }, "duplexer": { @@ -1631,7 +1630,7 @@ "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", "dev": true, "requires": { - "readable-stream": "~1.1.9" + "readable-stream": "1.1.14" } }, "ecc-jsbn": { @@ -1641,7 +1640,7 @@ "dev": true, "optional": true, "requires": { - "jsbn": "~0.1.0" + "jsbn": "0.1.1" } }, "ee-first": { @@ -1668,7 +1667,7 @@ "integrity": "sha1-jhdyBsPICDfYVjLouTWd/osvbq8=", "dev": true, "requires": { - "once": "~1.3.0" + "once": "1.3.3" }, "dependencies": { "once": { @@ -1677,7 +1676,7 @@ "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", "dev": true, "requires": { - "wrappy": "1" + "wrappy": "1.0.2" } } } @@ -1702,7 +1701,7 @@ "integrity": "sha1-w8p0NJOGSMPg2cHjKN1otiLChMo=", "dev": true, "requires": { - "mime-types": "~2.1.11", + "mime-types": "2.1.18", "negotiator": "0.6.1" } }, @@ -1799,7 +1798,7 @@ "dev": true, "optional": true, "requires": { - "prr": "~1.0.1" + "prr": "1.0.1" } }, "error-ex": { @@ -1808,7 +1807,7 @@ "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", "dev": true, "requires": { - "is-arrayish": "^0.2.1" + "is-arrayish": "0.2.1" } }, "errorhandler": { @@ -1817,8 +1816,8 @@ "integrity": "sha1-t7cO2PNZ6duICS8tIMD4MUIK2D8=", "dev": true, "requires": { - "accepts": "~1.3.0", - "escape-html": "~1.0.3" + "accepts": "1.3.5", + "escape-html": "1.0.3" }, "dependencies": { "accepts": { @@ -1827,7 +1826,7 @@ "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", "dev": true, "requires": { - "mime-types": "~2.1.18", + "mime-types": "2.1.18", "negotiator": "0.6.1" } }, @@ -1863,11 +1862,11 @@ "integrity": "sha1-264X75bI5L7bE1b0UE+kzC98t+I=", "dev": true, "requires": { - "esprima": "^3.1.3", - "estraverse": "^4.2.0", - "esutils": "^2.0.2", - "optionator": "^0.8.1", - "source-map": "~0.6.1" + "esprima": "3.1.3", + "estraverse": "4.2.0", + "esutils": "2.0.2", + "optionator": "0.8.2", + "source-map": "0.6.1" }, "dependencies": { "esprima": { @@ -1897,8 +1896,8 @@ "integrity": "sha1-FxSp1GGQc4rJWLyv1J4CnNpWo54=", "dev": true, "requires": { - "esprima": "^2.7.2", - "estraverse": "^4.1.1" + "esprima": "2.7.3", + "estraverse": "4.2.0" } }, "estraverse": { @@ -1925,13 +1924,13 @@ "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", "dev": true, "requires": { - "duplexer": "~0.1.1", - "from": "~0", - "map-stream": "~0.1.0", + "duplexer": "0.1.1", + "from": "0.1.7", + "map-stream": "0.1.0", "pause-stream": "0.0.11", - "split": "0.3", - "stream-combiner": "~0.0.4", - "through": "~2.3.1" + "split": "0.3.3", + "stream-combiner": "0.0.4", + "through": "2.3.8" } }, "eventemitter3": { @@ -1946,9 +1945,9 @@ "integrity": "sha1-SIsdHSRRyz06axks/AMPRMWFX+o=", "dev": true, "requires": { - "array-slice": "^0.2.3", - "array-unique": "^0.2.1", - "braces": "^0.1.2" + "array-slice": "0.2.3", + "array-unique": "0.2.1", + "braces": "0.1.5" }, "dependencies": { "array-slice": { @@ -1969,7 +1968,7 @@ "integrity": "sha1-wIVxEIUpHYt1/ddOqw+FlygHEeY=", "dev": true, "requires": { - "expand-range": "^0.1.0" + "expand-range": "0.1.1" } }, "expand-range": { @@ -1978,8 +1977,8 @@ "integrity": "sha1-TLjtoJk8pW+k9B/ELzy7TMrf8EQ=", "dev": true, "requires": { - "is-number": "^0.1.1", - "repeat-string": "^0.2.2" + "is-number": "0.1.1", + "repeat-string": "0.2.2" } }, "is-number": { @@ -2002,13 +2001,13 @@ "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", "dev": true, "requires": { - "debug": "^2.3.3", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "posix-character-classes": "^0.1.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "posix-character-classes": "0.1.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" }, "dependencies": { "define-property": { @@ -2017,7 +2016,7 @@ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "^0.1.0" + "is-descriptor": "0.1.6" } }, "extend-shallow": { @@ -2026,7 +2025,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "^0.1.0" + "is-extendable": "0.1.1" } }, "is-accessor-descriptor": { @@ -2035,7 +2034,7 @@ "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", "dev": true, "requires": { - "kind-of": "^3.0.2" + "kind-of": "3.2.2" }, "dependencies": { "kind-of": { @@ -2044,7 +2043,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.6" } } } @@ -2055,7 +2054,7 @@ "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", "dev": true, "requires": { - "kind-of": "^3.0.2" + "kind-of": "3.2.2" }, "dependencies": { "kind-of": { @@ -2064,7 +2063,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.6" } } } @@ -2075,9 +2074,9 @@ "integrity": "sha1-Nm2CQN3kh8pRgjsaufB6EKeCUco=", "dev": true, "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" } }, "kind-of": { @@ -2094,7 +2093,7 @@ "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", "dev": true, "requires": { - "fill-range": "^2.1.0" + "fill-range": "2.2.3" }, "dependencies": { "fill-range": { @@ -2103,11 +2102,11 @@ "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", "dev": true, "requires": { - "is-number": "^2.1.0", - "isobject": "^2.0.0", - "randomatic": "^1.1.3", - "repeat-element": "^1.1.2", - "repeat-string": "^1.5.2" + "is-number": "2.1.0", + "isobject": "2.1.0", + "randomatic": "1.1.7", + "repeat-element": "1.1.2", + "repeat-string": "1.6.1" } }, "is-number": { @@ -2116,7 +2115,7 @@ "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", "dev": true, "requires": { - "kind-of": "^3.0.2" + "kind-of": "3.2.2" } }, "isarray": { @@ -2140,7 +2139,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.6" } } } @@ -2151,7 +2150,7 @@ "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", "dev": true, "requires": { - "homedir-polyfill": "^1.0.1" + "homedir-polyfill": "1.0.1" } }, "express-session": { @@ -2163,11 +2162,11 @@ "cookie": "0.1.3", "cookie-signature": "1.0.6", "crc": "3.3.0", - "debug": "~2.2.0", - "depd": "~1.0.1", - "on-headers": "~1.0.0", - "parseurl": "~1.3.0", - "uid-safe": "~2.0.0", + "debug": "2.2.0", + "depd": "1.0.1", + "on-headers": "1.0.1", + "parseurl": "1.3.2", + "uid-safe": "2.0.0", "utils-merge": "1.0.0" }, "dependencies": { @@ -2209,8 +2208,8 @@ "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", "dev": true, "requires": { - "assign-symbols": "^1.0.0", - "is-extendable": "^1.0.1" + "assign-symbols": "1.0.0", + "is-extendable": "1.0.1" }, "dependencies": { "is-extendable": { @@ -2219,7 +2218,7 @@ "integrity": "sha1-p0cPnkJnM9gb2B4RVSZOOjUHyrQ=", "dev": true, "requires": { - "is-plain-object": "^2.0.4" + "is-plain-object": "2.0.4" } } } @@ -2230,14 +2229,14 @@ "integrity": "sha1-rQD+TcYSqSMuhxhxHcXLWrAoVUM=", "dev": true, "requires": { - "array-unique": "^0.3.2", - "define-property": "^1.0.0", - "expand-brackets": "^2.1.4", - "extend-shallow": "^2.0.1", - "fragment-cache": "^0.2.1", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" + "array-unique": "0.3.2", + "define-property": "1.0.0", + "expand-brackets": "2.1.4", + "extend-shallow": "2.0.1", + "fragment-cache": "0.2.1", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" }, "dependencies": { "define-property": { @@ -2246,7 +2245,7 @@ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", "dev": true, "requires": { - "is-descriptor": "^1.0.0" + "is-descriptor": "1.0.2" } }, "extend-shallow": { @@ -2255,7 +2254,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "^0.1.0" + "is-extendable": "0.1.1" } } } @@ -2295,9 +2294,9 @@ "integrity": "sha1-9BEl49hPLn2JpD0G2VjI94vha+E=", "dev": true, "requires": { - "ansi-gray": "^0.1.1", - "color-support": "^1.1.3", - "time-stamp": "^1.0.0" + "ansi-gray": "0.1.1", + "color-support": "1.1.3", + "time-stamp": "1.1.0" } }, "fast-levenshtein": { @@ -2312,7 +2311,7 @@ "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", "dev": true, "requires": { - "websocket-driver": ">=0.5.1" + "websocket-driver": "0.7.0" } }, "fd-slicer": { @@ -2321,7 +2320,7 @@ "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=", "dev": true, "requires": { - "pend": "~1.2.0" + "pend": "1.2.0" } }, "filename-regex": { @@ -2336,10 +2335,10 @@ "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", "dev": true, "requires": { - "extend-shallow": "^2.0.1", - "is-number": "^3.0.0", - "repeat-string": "^1.6.1", - "to-regex-range": "^2.1.0" + "extend-shallow": "2.0.1", + "is-number": "3.0.0", + "repeat-string": "1.6.1", + "to-regex-range": "2.1.1" }, "dependencies": { "extend-shallow": { @@ -2348,7 +2347,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "^0.1.0" + "is-extendable": "0.1.1" } } } @@ -2359,10 +2358,10 @@ "integrity": "sha1-llpS2ejQXSuFdUhUH7ibU6JJfZs=", "dev": true, "requires": { - "debug": "~2.2.0", + "debug": "2.2.0", "escape-html": "1.0.2", - "on-finished": "~2.3.0", - "unpipe": "~1.0.0" + "on-finished": "2.3.0", + "unpipe": "1.0.0" }, "dependencies": { "debug": { @@ -2400,8 +2399,8 @@ "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", "dev": true, "requires": { - "path-exists": "^2.0.0", - "pinkie-promise": "^2.0.0" + "path-exists": "2.1.0", + "pinkie-promise": "2.0.1" } }, "findup-sync": { @@ -2410,10 +2409,10 @@ "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", "dev": true, "requires": { - "detect-file": "^1.0.0", - "is-glob": "^3.1.0", - "micromatch": "^3.0.4", - "resolve-dir": "^1.0.1" + "detect-file": "1.0.0", + "is-glob": "3.1.0", + "micromatch": "3.1.10", + "resolve-dir": "1.0.1" } }, "fined": { @@ -2422,11 +2421,11 @@ "integrity": "sha1-s33IRLdqL15wgeiE98CuNE8VNHY=", "dev": true, "requires": { - "expand-tilde": "^2.0.2", - "is-plain-object": "^2.0.3", - "object.defaults": "^1.1.0", - "object.pick": "^1.2.0", - "parse-filepath": "^1.0.1" + "expand-tilde": "2.0.2", + "is-plain-object": "2.0.4", + "object.defaults": "1.1.0", + "object.pick": "1.3.0", + "parse-filepath": "1.0.2" } }, "first-chunk-stream": { @@ -2459,7 +2458,7 @@ "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", "dev": true, "requires": { - "for-in": "^1.0.1" + "for-in": "1.0.2" } }, "forever-agent": { @@ -2474,9 +2473,9 @@ "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", "dev": true, "requires": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.5", - "mime-types": "^2.1.12" + "asynckit": "0.4.0", + "combined-stream": "1.0.6", + "mime-types": "2.1.18" } }, "fragment-cache": { @@ -2485,7 +2484,7 @@ "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", "dev": true, "requires": { - "map-cache": "^0.2.2" + "map-cache": "0.2.2" } }, "fresh": { @@ -2506,9 +2505,9 @@ "integrity": "sha1-zTzl9+fLYUWIP8rjGR6Yd/hYeVA=", "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "jsonfile": "^2.1.0", - "klaw": "^1.0.0" + "graceful-fs": "4.1.11", + "jsonfile": "2.4.0", + "klaw": "1.3.1" }, "dependencies": { "graceful-fs": { @@ -2525,7 +2524,7 @@ "integrity": "sha1-gAI4I5gfn//+AWCei+Zo9prknnA=", "dev": true, "requires": { - "graceful-fs": "^4.1.2" + "graceful-fs": "4.1.11" }, "dependencies": { "graceful-fs": { @@ -2542,910 +2541,6 @@ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true }, - "fsevents": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.1.3.tgz", - "integrity": "sha512-WIr7iDkdmdbxu/Gh6eKEZJL6KPE74/5MEsf2whTOFNxbIoIixogroLdKYqB6FDav4Wavh/lZdzzd3b2KxIXC5Q==", - "dev": true, - "optional": true, - "requires": { - "nan": "^2.3.0", - "node-pre-gyp": "^0.6.39" - }, - "dependencies": { - "abbrev": { - "version": "1.1.0", - "bundled": true, - "dev": true, - "optional": true - }, - "ajv": { - "version": "4.11.8", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "co": "4.6.0", - "json-stable-stringify": "1.0.1" - } - }, - "ansi-regex": { - "version": "2.1.1", - "bundled": true, - "dev": true - }, - "aproba": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "are-we-there-yet": { - "version": "1.1.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "delegates": "1.0.0", - "readable-stream": "2.2.9" - } - }, - "asn1": { - "version": "0.2.3", - "bundled": true, - "dev": true, - "optional": true - }, - "assert-plus": { - "version": "0.2.0", - "bundled": true, - "dev": true, - "optional": true - }, - "asynckit": { - "version": "0.4.0", - "bundled": true, - "dev": true, - "optional": true - }, - "aws-sign2": { - "version": "0.6.0", - "bundled": true, - "dev": true, - "optional": true - }, - "aws4": { - "version": "1.6.0", - "bundled": true, - "dev": true, - "optional": true - }, - "balanced-match": { - "version": "0.4.2", - "bundled": true, - "dev": true - }, - "bcrypt-pbkdf": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "tweetnacl": "0.14.5" - } - }, - "block-stream": { - "version": "0.0.9", - "bundled": true, - "dev": true, - "requires": { - "inherits": "2.0.3" - } - }, - "boom": { - "version": "2.10.1", - "bundled": true, - "dev": true, - "requires": { - "hoek": "2.16.3" - } - }, - "brace-expansion": { - "version": "1.1.7", - "bundled": true, - "dev": true, - "requires": { - "balanced-match": "0.4.2", - "concat-map": "0.0.1" - } - }, - "buffer-shims": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "caseless": { - "version": "0.12.0", - "bundled": true, - "dev": true, - "optional": true - }, - "co": { - "version": "4.6.0", - "bundled": true, - "dev": true, - "optional": true - }, - "code-point-at": { - "version": "1.1.0", - "bundled": true, - "dev": true - }, - "combined-stream": { - "version": "1.0.5", - "bundled": true, - "dev": true, - "requires": { - "delayed-stream": "1.0.0" - } - }, - "concat-map": { - "version": "0.0.1", - "bundled": true, - "dev": true - }, - "console-control-strings": { - "version": "1.1.0", - "bundled": true, - "dev": true - }, - "core-util-is": { - "version": "1.0.2", - "bundled": true, - "dev": true - }, - "cryptiles": { - "version": "2.0.5", - "bundled": true, - "dev": true, - "requires": { - "boom": "2.10.1" - } - }, - "dashdash": { - "version": "1.14.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "assert-plus": "1.0.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - } - } - }, - "debug": { - "version": "2.6.8", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ms": "2.0.0" - } - }, - "deep-extend": { - "version": "0.4.2", - "bundled": true, - "dev": true, - "optional": true - }, - "delayed-stream": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "delegates": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "detect-libc": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "ecc-jsbn": { - "version": "0.1.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "jsbn": "0.1.1" - } - }, - "extend": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "extsprintf": { - "version": "1.0.2", - "bundled": true, - "dev": true - }, - "forever-agent": { - "version": "0.6.1", - "bundled": true, - "dev": true, - "optional": true - }, - "form-data": { - "version": "2.1.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "asynckit": "0.4.0", - "combined-stream": "1.0.5", - "mime-types": "2.1.15" - } - }, - "fs.realpath": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "fstream": { - "version": "1.0.11", - "bundled": true, - "dev": true, - "requires": { - "graceful-fs": "4.1.11", - "inherits": "2.0.3", - "mkdirp": "0.5.1", - "rimraf": "2.6.1" - } - }, - "fstream-ignore": { - "version": "1.0.5", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "fstream": "1.0.11", - "inherits": "2.0.3", - "minimatch": "3.0.4" - } - }, - "gauge": { - "version": "2.7.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "aproba": "1.1.1", - "console-control-strings": "1.1.0", - "has-unicode": "2.0.1", - "object-assign": "4.1.1", - "signal-exit": "3.0.2", - "string-width": "1.0.2", - "strip-ansi": "3.0.1", - "wide-align": "1.1.2" - } - }, - "getpass": { - "version": "0.1.7", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "assert-plus": "1.0.0" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - } - } - }, - "glob": { - "version": "7.1.2", - "bundled": true, - "dev": true, - "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" - } - }, - "graceful-fs": { - "version": "4.1.11", - "bundled": true, - "dev": true - }, - "har-schema": { - "version": "1.0.5", - "bundled": true, - "dev": true, - "optional": true - }, - "har-validator": { - "version": "4.2.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "ajv": "4.11.8", - "har-schema": "1.0.5" - } - }, - "has-unicode": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "hawk": { - "version": "3.1.3", - "bundled": true, - "dev": true, - "requires": { - "boom": "2.10.1", - "cryptiles": "2.0.5", - "hoek": "2.16.3", - "sntp": "1.0.9" - } - }, - "hoek": { - "version": "2.16.3", - "bundled": true, - "dev": true - }, - "http-signature": { - "version": "1.1.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "assert-plus": "0.2.0", - "jsprim": "1.4.0", - "sshpk": "1.13.0" - } - }, - "inflight": { - "version": "1.0.6", - "bundled": true, - "dev": true, - "requires": { - "once": "1.4.0", - "wrappy": "1.0.2" - } - }, - "inherits": { - "version": "2.0.3", - "bundled": true, - "dev": true - }, - "ini": { - "version": "1.3.4", - "bundled": true, - "dev": true, - "optional": true - }, - "is-fullwidth-code-point": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "requires": { - "number-is-nan": "1.0.1" - } - }, - "is-typedarray": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "isarray": { - "version": "1.0.0", - "bundled": true, - "dev": true - }, - "isstream": { - "version": "0.1.2", - "bundled": true, - "dev": true, - "optional": true - }, - "jodid25519": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "jsbn": "0.1.1" - } - }, - "jsbn": { - "version": "0.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "json-schema": { - "version": "0.2.3", - "bundled": true, - "dev": true, - "optional": true - }, - "json-stable-stringify": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "jsonify": "0.0.0" - } - }, - "json-stringify-safe": { - "version": "5.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "jsonify": { - "version": "0.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "jsprim": { - "version": "1.4.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "assert-plus": "1.0.0", - "extsprintf": "1.0.2", - "json-schema": "0.2.3", - "verror": "1.3.6" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - } - } - }, - "mime-db": { - "version": "1.27.0", - "bundled": true, - "dev": true - }, - "mime-types": { - "version": "2.1.15", - "bundled": true, - "dev": true, - "requires": { - "mime-db": "1.27.0" - } - }, - "minimatch": { - "version": "3.0.4", - "bundled": true, - "dev": true, - "requires": { - "brace-expansion": "1.1.7" - } - }, - "minimist": { - "version": "0.0.8", - "bundled": true, - "dev": true - }, - "mkdirp": { - "version": "0.5.1", - "bundled": true, - "dev": true, - "requires": { - "minimist": "0.0.8" - } - }, - "ms": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "node-pre-gyp": { - "version": "0.6.39", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "detect-libc": "1.0.2", - "hawk": "3.1.3", - "mkdirp": "0.5.1", - "nopt": "4.0.1", - "npmlog": "4.1.0", - "rc": "1.2.1", - "request": "2.81.0", - "rimraf": "2.6.1", - "semver": "5.3.0", - "tar": "2.2.1", - "tar-pack": "3.4.0" - } - }, - "nopt": { - "version": "4.0.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "abbrev": "1.1.0", - "osenv": "0.1.4" - } - }, - "npmlog": { - "version": "4.1.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "are-we-there-yet": "1.1.4", - "console-control-strings": "1.1.0", - "gauge": "2.7.4", - "set-blocking": "2.0.0" - } - }, - "number-is-nan": { - "version": "1.0.1", - "bundled": true, - "dev": true - }, - "oauth-sign": { - "version": "0.8.2", - "bundled": true, - "dev": true, - "optional": true - }, - "object-assign": { - "version": "4.1.1", - "bundled": true, - "dev": true, - "optional": true - }, - "once": { - "version": "1.4.0", - "bundled": true, - "dev": true, - "requires": { - "wrappy": "1.0.2" - } - }, - "os-homedir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "os-tmpdir": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "osenv": { - "version": "0.1.4", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "os-homedir": "1.0.2", - "os-tmpdir": "1.0.2" - } - }, - "path-is-absolute": { - "version": "1.0.1", - "bundled": true, - "dev": true - }, - "performance-now": { - "version": "0.2.0", - "bundled": true, - "dev": true, - "optional": true - }, - "process-nextick-args": { - "version": "1.0.7", - "bundled": true, - "dev": true - }, - "punycode": { - "version": "1.4.1", - "bundled": true, - "dev": true, - "optional": true - }, - "qs": { - "version": "6.4.0", - "bundled": true, - "dev": true, - "optional": true - }, - "rc": { - "version": "1.2.1", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "deep-extend": "0.4.2", - "ini": "1.3.4", - "minimist": "1.2.0", - "strip-json-comments": "2.0.1" - }, - "dependencies": { - "minimist": { - "version": "1.2.0", - "bundled": true, - "dev": true, - "optional": true - } - } - }, - "readable-stream": { - "version": "2.2.9", - "bundled": true, - "dev": true, - "requires": { - "buffer-shims": "1.0.0", - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "1.0.7", - "string_decoder": "1.0.1", - "util-deprecate": "1.0.2" - } - }, - "request": { - "version": "2.81.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "aws-sign2": "0.6.0", - "aws4": "1.6.0", - "caseless": "0.12.0", - "combined-stream": "1.0.5", - "extend": "3.0.1", - "forever-agent": "0.6.1", - "form-data": "2.1.4", - "har-validator": "4.2.1", - "hawk": "3.1.3", - "http-signature": "1.1.1", - "is-typedarray": "1.0.0", - "isstream": "0.1.2", - "json-stringify-safe": "5.0.1", - "mime-types": "2.1.15", - "oauth-sign": "0.8.2", - "performance-now": "0.2.0", - "qs": "6.4.0", - "safe-buffer": "5.0.1", - "stringstream": "0.0.5", - "tough-cookie": "2.3.2", - "tunnel-agent": "0.6.0", - "uuid": "3.0.1" - } - }, - "rimraf": { - "version": "2.6.1", - "bundled": true, - "dev": true, - "requires": { - "glob": "7.1.2" - } - }, - "safe-buffer": { - "version": "5.0.1", - "bundled": true, - "dev": true - }, - "semver": { - "version": "5.3.0", - "bundled": true, - "dev": true, - "optional": true - }, - "set-blocking": { - "version": "2.0.0", - "bundled": true, - "dev": true, - "optional": true - }, - "signal-exit": { - "version": "3.0.2", - "bundled": true, - "dev": true, - "optional": true - }, - "sntp": { - "version": "1.0.9", - "bundled": true, - "dev": true, - "requires": { - "hoek": "2.16.3" - } - }, - "sshpk": { - "version": "1.13.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "asn1": "0.2.3", - "assert-plus": "1.0.0", - "bcrypt-pbkdf": "1.0.1", - "dashdash": "1.14.1", - "ecc-jsbn": "0.1.1", - "getpass": "0.1.7", - "jodid25519": "1.0.2", - "jsbn": "0.1.1", - "tweetnacl": "0.14.5" - }, - "dependencies": { - "assert-plus": { - "version": "1.0.0", - "bundled": true, - "dev": true, - "optional": true - } - } - }, - "string-width": { - "version": "1.0.2", - "bundled": true, - "dev": true, - "requires": { - "code-point-at": "1.1.0", - "is-fullwidth-code-point": "1.0.0", - "strip-ansi": "3.0.1" - } - }, - "string_decoder": { - "version": "1.0.1", - "bundled": true, - "dev": true, - "requires": { - "safe-buffer": "5.0.1" - } - }, - "stringstream": { - "version": "0.0.5", - "bundled": true, - "dev": true, - "optional": true - }, - "strip-ansi": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "requires": { - "ansi-regex": "2.1.1" - } - }, - "strip-json-comments": { - "version": "2.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "tar": { - "version": "2.2.1", - "bundled": true, - "dev": true, - "requires": { - "block-stream": "0.0.9", - "fstream": "1.0.11", - "inherits": "2.0.3" - } - }, - "tar-pack": { - "version": "3.4.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "debug": "2.6.8", - "fstream": "1.0.11", - "fstream-ignore": "1.0.5", - "once": "1.4.0", - "readable-stream": "2.2.9", - "rimraf": "2.6.1", - "tar": "2.2.1", - "uid-number": "0.0.6" - } - }, - "tough-cookie": { - "version": "2.3.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "punycode": "1.4.1" - } - }, - "tunnel-agent": { - "version": "0.6.0", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "safe-buffer": "5.0.1" - } - }, - "tweetnacl": { - "version": "0.14.5", - "bundled": true, - "dev": true, - "optional": true - }, - "uid-number": { - "version": "0.0.6", - "bundled": true, - "dev": true, - "optional": true - }, - "util-deprecate": { - "version": "1.0.2", - "bundled": true, - "dev": true - }, - "uuid": { - "version": "3.0.1", - "bundled": true, - "dev": true, - "optional": true - }, - "verror": { - "version": "1.3.6", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "extsprintf": "1.0.2" - } - }, - "wide-align": { - "version": "1.1.2", - "bundled": true, - "dev": true, - "optional": true, - "requires": { - "string-width": "1.0.2" - } - }, - "wrappy": { - "version": "1.0.2", - "bundled": true, - "dev": true - } - } - }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", @@ -3458,7 +2553,7 @@ "integrity": "sha1-QLcJU30k0dRXZ9takIaJ3+aaxE8=", "dev": true, "requires": { - "globule": "~0.1.0" + "globule": "0.1.0" } }, "get-stdin": { @@ -3479,7 +2574,7 @@ "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", "dev": true, "requires": { - "assert-plus": "^1.0.0" + "assert-plus": "1.0.0" }, "dependencies": { "assert-plus": { @@ -3496,12 +2591,12 @@ "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", "dev": true, "requires": { - "fs.realpath": "^1.0.0", - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^3.0.4", - "once": "^1.3.0", - "path-is-absolute": "^1.0.0" + "fs.realpath": "1.0.0", + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "3.0.4", + "once": "1.4.0", + "path-is-absolute": "1.0.1" } }, "glob-base": { @@ -3510,8 +2605,8 @@ "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", "dev": true, "requires": { - "glob-parent": "^2.0.0", - "is-glob": "^2.0.0" + "glob-parent": "2.0.0", + "is-glob": "2.0.1" }, "dependencies": { "glob-parent": { @@ -3520,7 +2615,7 @@ "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", "dev": true, "requires": { - "is-glob": "^2.0.0" + "is-glob": "2.0.1" } }, "is-extglob": { @@ -3535,7 +2630,7 @@ "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", "dev": true, "requires": { - "is-extglob": "^1.0.0" + "is-extglob": "1.0.0" } } } @@ -3546,8 +2641,8 @@ "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", "dev": true, "requires": { - "is-glob": "^3.1.0", - "path-dirname": "^1.0.0" + "is-glob": "3.1.0", + "path-dirname": "1.0.2" } }, "glob-stream": { @@ -3556,12 +2651,12 @@ "integrity": "sha1-kXCl8St5Awb9/lmPMT+PeVT9FDs=", "dev": true, "requires": { - "glob": "^4.3.1", - "glob2base": "^0.0.12", - "minimatch": "^2.0.1", - "ordered-read-streams": "^0.1.0", - "through2": "^0.6.1", - "unique-stream": "^1.0.0" + "glob": "4.5.3", + "glob2base": "0.0.12", + "minimatch": "2.0.10", + "ordered-read-streams": "0.1.0", + "through2": "0.6.5", + "unique-stream": "1.0.0" }, "dependencies": { "glob": { @@ -3570,10 +2665,10 @@ "integrity": "sha1-xstz0yJsHv7wTePFbQEvAzd+4V8=", "dev": true, "requires": { - "inflight": "^1.0.4", - "inherits": "2", - "minimatch": "^2.0.1", - "once": "^1.3.0" + "inflight": "1.0.6", + "inherits": "2.0.3", + "minimatch": "2.0.10", + "once": "1.4.0" } }, "minimatch": { @@ -3582,7 +2677,7 @@ "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", "dev": true, "requires": { - "brace-expansion": "^1.0.0" + "brace-expansion": "1.1.11" } }, "readable-stream": { @@ -3591,10 +2686,10 @@ "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", + "core-util-is": "1.0.2", + "inherits": "2.0.3", "isarray": "0.0.1", - "string_decoder": "~0.10.x" + "string_decoder": "0.10.31" } }, "through2": { @@ -3603,8 +2698,8 @@ "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", "dev": true, "requires": { - "readable-stream": ">=1.0.33-1 <1.1.0-0", - "xtend": ">=4.0.0 <4.1.0-0" + "readable-stream": "1.0.34", + "xtend": "4.0.1" } } } @@ -3615,7 +2710,7 @@ "integrity": "sha1-uVtKjfdLOcgymLDAXJeLTZo7cQs=", "dev": true, "requires": { - "gaze": "^0.5.1" + "gaze": "0.5.2" } }, "glob2base": { @@ -3624,7 +2719,7 @@ "integrity": "sha1-nUGbPijxLoOjYhZKJ3BVkiycDVY=", "dev": true, "requires": { - "find-index": "^0.1.1" + "find-index": "0.1.1" } }, "global-modules": { @@ -3633,9 +2728,9 @@ "integrity": "sha1-bXcPDrUjrHgWTXK15xqIdyZcw+o=", "dev": true, "requires": { - "global-prefix": "^1.0.1", - "is-windows": "^1.0.1", - "resolve-dir": "^1.0.0" + "global-prefix": "1.0.2", + "is-windows": "1.0.2", + "resolve-dir": "1.0.1" } }, "global-prefix": { @@ -3644,11 +2739,11 @@ "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", "dev": true, "requires": { - "expand-tilde": "^2.0.2", - "homedir-polyfill": "^1.0.1", - "ini": "^1.3.4", - "is-windows": "^1.0.1", - "which": "^1.2.14" + "expand-tilde": "2.0.2", + "homedir-polyfill": "1.0.1", + "ini": "1.3.5", + "is-windows": "1.0.2", + "which": "1.3.0" } }, "globule": { @@ -3657,9 +2752,9 @@ "integrity": "sha1-2cjt3h2nnRJaFRt5UzuXhnY0auU=", "dev": true, "requires": { - "glob": "~3.1.21", - "lodash": "~1.0.1", - "minimatch": "~0.2.11" + "glob": "3.1.21", + "lodash": "1.0.2", + "minimatch": "0.2.14" }, "dependencies": { "glob": { @@ -3668,9 +2763,9 @@ "integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=", "dev": true, "requires": { - "graceful-fs": "~1.2.0", - "inherits": "1", - "minimatch": "~0.2.11" + "graceful-fs": "1.2.3", + "inherits": "1.0.2", + "minimatch": "0.2.14" } }, "graceful-fs": { @@ -3697,8 +2792,8 @@ "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", "dev": true, "requires": { - "lru-cache": "2", - "sigmund": "~1.0.0" + "lru-cache": "2.7.3", + "sigmund": "1.0.1" } } } @@ -3709,7 +2804,7 @@ "integrity": "sha1-3PdY5EeJzD89MsHzVio2duajSBA=", "dev": true, "requires": { - "sparkles": "^1.0.0" + "sparkles": "1.0.0" } }, "graceful-fs": { @@ -3718,7 +2813,7 @@ "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", "dev": true, "requires": { - "natives": "^1.1.0" + "natives": "1.1.2" } }, "gulp": { @@ -3727,19 +2822,19 @@ "integrity": "sha1-VxzkWSjdQK9lFPxAEYZgFsE4RbQ=", "dev": true, "requires": { - "archy": "^1.0.0", - "chalk": "^1.0.0", - "deprecated": "^0.0.1", - "gulp-util": "^3.0.0", - "interpret": "^1.0.0", - "liftoff": "^2.1.0", - "minimist": "^1.1.0", - "orchestrator": "^0.3.0", - "pretty-hrtime": "^1.0.0", - "semver": "^4.1.0", - "tildify": "^1.0.0", - "v8flags": "^2.0.2", - "vinyl-fs": "^0.3.0" + "archy": "1.0.0", + "chalk": "1.1.3", + "deprecated": "0.0.1", + "gulp-util": "3.0.8", + "interpret": "1.1.0", + "liftoff": "2.5.0", + "minimist": "1.2.0", + "orchestrator": "0.3.8", + "pretty-hrtime": "1.0.3", + "semver": "4.3.6", + "tildify": "1.2.0", + "v8flags": "2.1.1", + "vinyl-fs": "0.3.14" }, "dependencies": { "minimist": { @@ -3756,9 +2851,9 @@ "integrity": "sha1-Yz0WyV2IUEYorQJmVmPO5aR5M1M=", "dev": true, "requires": { - "concat-with-sourcemaps": "^1.0.0", - "through2": "^2.0.0", - "vinyl": "^2.0.0" + "concat-with-sourcemaps": "1.0.5", + "through2": "2.0.3", + "vinyl": "2.1.0" }, "dependencies": { "clone": { @@ -3785,12 +2880,12 @@ "integrity": "sha1-Ah+cLPlR1rk5lDyJ617lrdT9kkw=", "dev": true, "requires": { - "clone": "^2.1.1", - "clone-buffer": "^1.0.0", - "clone-stats": "^1.0.0", - "cloneable-readable": "^1.0.0", - "remove-trailing-separator": "^1.0.1", - "replace-ext": "^1.0.0" + "clone": "2.1.2", + "clone-buffer": "1.0.0", + "clone-stats": "1.0.0", + "cloneable-readable": "1.1.2", + "remove-trailing-separator": "1.1.0", + "replace-ext": "1.0.0" } } } @@ -3801,11 +2896,11 @@ "integrity": "sha1-8v3zBq6RFGg2jCKF8teC8T7dr04=", "dev": true, "requires": { - "connect": "^2.30.0", - "connect-livereload": "^0.5.4", - "event-stream": "^3.3.2", - "gulp-util": "^3.0.6", - "tiny-lr": "^0.2.1" + "connect": "2.30.2", + "connect-livereload": "0.5.4", + "event-stream": "3.3.4", + "gulp-util": "3.0.8", + "tiny-lr": "0.2.1" } }, "gulp-less": { @@ -3814,13 +2909,13 @@ "integrity": "sha1-gBT0ad38ZUTX3aUAmN7wNxu7T3g=", "dev": true, "requires": { - "accord": "^0.28.0", - "less": "2.6.x || ^2.7.1", - "object-assign": "^4.0.1", - "plugin-error": "^0.1.2", - "replace-ext": "^1.0.0", - "through2": "^2.0.0", - "vinyl-sourcemaps-apply": "^0.2.0" + "accord": "0.28.0", + "less": "2.7.3", + "object-assign": "4.1.1", + "plugin-error": "0.1.2", + "replace-ext": "1.0.0", + "through2": "2.0.3", + "vinyl-sourcemaps-apply": "0.2.1" }, "dependencies": { "replace-ext": { @@ -3837,8 +2932,8 @@ "integrity": "sha1-J7Z6Ql6zh1ImNFq4lgTXN/Y1fCE=", "dev": true, "requires": { - "angular": "~1.3.1", - "angular-animate": "~1.3.1", + "angular": "1.3.20", + "angular-animate": "1.3.20", "canonical-path": "0.0.2", "extend": "1.3.0", "gulp-util": "3.0.0", @@ -3869,11 +2964,11 @@ "integrity": "sha1-Zjs6ZItotV0EaQ1JFnqoN4WPIXQ=", "dev": true, "requires": { - "ansi-styles": "^1.1.0", - "escape-string-regexp": "^1.0.0", - "has-ansi": "^0.1.0", - "strip-ansi": "^0.3.0", - "supports-color": "^0.2.0" + "ansi-styles": "1.1.0", + "escape-string-regexp": "1.0.5", + "has-ansi": "0.1.0", + "strip-ansi": "0.3.0", + "supports-color": "0.2.0" } }, "clone": { @@ -3888,8 +2983,8 @@ "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=", "dev": true, "requires": { - "get-stdin": "^4.0.1", - "meow": "^3.3.0" + "get-stdin": "4.0.1", + "meow": "3.7.0" } }, "extend": { @@ -3904,15 +2999,15 @@ "integrity": "sha1-b+7cR9aXKCO6zplH/F9GvYo0Zuc=", "dev": true, "requires": { - "chalk": "^0.5.0", - "dateformat": "^1.0.7-1.2.3", - "lodash": "^2.4.1", - "lodash._reinterpolate": "^2.4.1", - "lodash.template": "^2.4.1", - "minimist": "^0.2.0", - "multipipe": "^0.1.0", - "through2": "^0.5.0", - "vinyl": "^0.2.1" + "chalk": "0.5.1", + "dateformat": "1.0.12", + "lodash": "2.4.1", + "lodash._reinterpolate": "2.4.1", + "lodash.template": "2.4.1", + "minimist": "0.2.0", + "multipipe": "0.1.2", + "through2": "0.5.1", + "vinyl": "0.2.3" }, "dependencies": { "through2": { @@ -3921,8 +3016,8 @@ "integrity": "sha1-390BLrnHAOIyP9M084rGIqs3Lac=", "dev": true, "requires": { - "readable-stream": "~1.0.17", - "xtend": "~3.0.0" + "readable-stream": "1.0.34", + "xtend": "3.0.0" } } } @@ -3933,7 +3028,7 @@ "integrity": "sha1-hPJlqujA5qiKEtcCKJS3VoiUxi4=", "dev": true, "requires": { - "ansi-regex": "^0.2.0" + "ansi-regex": "0.2.1" } }, "lodash": { @@ -3954,8 +3049,8 @@ "integrity": "sha1-p+iIXwXmiFEUS24SqPNngCa8TFQ=", "dev": true, "requires": { - "lodash._objecttypes": "~2.4.1", - "lodash.keys": "~2.4.1" + "lodash._objecttypes": "2.4.1", + "lodash.keys": "2.4.1" } }, "lodash.escape": { @@ -3964,9 +3059,9 @@ "integrity": "sha1-LOEsXghNsKV92l5dHu659dF1o7Q=", "dev": true, "requires": { - "lodash._escapehtmlchar": "~2.4.1", - "lodash._reunescapedhtml": "~2.4.1", - "lodash.keys": "~2.4.1" + "lodash._escapehtmlchar": "2.4.1", + "lodash._reunescapedhtml": "2.4.1", + "lodash.keys": "2.4.1" } }, "lodash.keys": { @@ -3975,9 +3070,9 @@ "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", "dev": true, "requires": { - "lodash._isnative": "~2.4.1", - "lodash._shimkeys": "~2.4.1", - "lodash.isobject": "~2.4.1" + "lodash._isnative": "2.4.1", + "lodash._shimkeys": "2.4.1", + "lodash.isobject": "2.4.1" } }, "lodash.template": { @@ -3986,13 +3081,13 @@ "integrity": "sha1-nmEQB+32KRKal0qzxIuBez4c8g0=", "dev": true, "requires": { - "lodash._escapestringchar": "~2.4.1", - "lodash._reinterpolate": "~2.4.1", - "lodash.defaults": "~2.4.1", - "lodash.escape": "~2.4.1", - "lodash.keys": "~2.4.1", - "lodash.templatesettings": "~2.4.1", - "lodash.values": "~2.4.1" + "lodash._escapestringchar": "2.4.1", + "lodash._reinterpolate": "2.4.1", + "lodash.defaults": "2.4.1", + "lodash.escape": "2.4.1", + "lodash.keys": "2.4.1", + "lodash.templatesettings": "2.4.1", + "lodash.values": "2.4.1" } }, "lodash.templatesettings": { @@ -4001,8 +3096,8 @@ "integrity": "sha1-6nbHXRHrhtTb6JqDiTu4YZKaxpk=", "dev": true, "requires": { - "lodash._reinterpolate": "~2.4.1", - "lodash.escape": "~2.4.1" + "lodash._reinterpolate": "2.4.1", + "lodash.escape": "2.4.1" } }, "merge-stream": { @@ -4011,7 +3106,7 @@ "integrity": "sha1-5oIPet267gA/SMpKWMfFolPV4Fw=", "dev": true, "requires": { - "through2": "^0.5.1" + "through2": "0.5.1" }, "dependencies": { "through2": { @@ -4020,8 +3115,8 @@ "integrity": "sha1-390BLrnHAOIyP9M084rGIqs3Lac=", "dev": true, "requires": { - "readable-stream": "~1.0.17", - "xtend": "~3.0.0" + "readable-stream": "1.0.34", + "xtend": "3.0.0" } } } @@ -4038,10 +3133,10 @@ "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", + "core-util-is": "1.0.2", + "inherits": "2.0.3", "isarray": "0.0.1", - "string_decoder": "~0.10.x" + "string_decoder": "0.10.31" } }, "strip-ansi": { @@ -4050,7 +3145,7 @@ "integrity": "sha1-JfSOoiynkYfzF0pNuHWTR7sSYiA=", "dev": true, "requires": { - "ansi-regex": "^0.2.1" + "ansi-regex": "0.2.1" } }, "supports-color": { @@ -4065,8 +3160,8 @@ "integrity": "sha1-90KzKJPovSYUbnieT9LMssB6cX4=", "dev": true, "requires": { - "readable-stream": ">=1.0.27-1 <1.1.0-0", - "xtend": ">=4.0.0 <4.1.0-0" + "readable-stream": "1.0.34", + "xtend": "4.0.1" }, "dependencies": { "xtend": { @@ -4083,7 +3178,7 @@ "integrity": "sha1-vKk4IJWC7FpJrVOKAPofEl5RMlI=", "dev": true, "requires": { - "clone-stats": "~0.0.1" + "clone-stats": "0.0.1" } }, "vinyl-fs": { @@ -4092,14 +3187,14 @@ "integrity": "sha1-LiXP5t9cgIGPl/9Be/XCGkHkpJs=", "dev": true, "requires": { - "glob-stream": "^3.1.5", - "glob-watcher": "^0.0.6", - "graceful-fs": "^3.0.0", - "lodash": "^2.4.1", - "mkdirp": "^0.5.0", - "strip-bom": "^1.0.0", - "through2": "^0.6.1", - "vinyl": "^0.4.0" + "glob-stream": "3.1.18", + "glob-watcher": "0.0.6", + "graceful-fs": "3.0.11", + "lodash": "2.4.1", + "mkdirp": "0.5.1", + "strip-bom": "1.0.0", + "through2": "0.6.1", + "vinyl": "0.4.6" }, "dependencies": { "vinyl": { @@ -4108,8 +3203,8 @@ "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", "dev": true, "requires": { - "clone": "^0.2.0", - "clone-stats": "^0.0.1" + "clone": "0.2.0", + "clone-stats": "0.0.1" } } } @@ -4128,10 +3223,10 @@ "integrity": "sha1-rAHu6JjXenrAgS+tTz1T0IaH1Bw=", "dev": true, "requires": { - "colors": "^1.1.2", + "colors": "1.2.1", "open": "0.0.5", - "plugin-log": "^0.1.0", - "through2": "^2.0.1" + "plugin-log": "0.1.0", + "through2": "2.0.3" } }, "gulp-postcss": { @@ -4140,10 +3235,10 @@ "integrity": "sha1-eKMuPIeqbNzsWuHJBeGW1HjoxdU=", "dev": true, "requires": { - "gulp-util": "^3.0.8", - "postcss": "^5.2.12", - "postcss-load-config": "^1.2.0", - "vinyl-sourcemaps-apply": "^0.2.1" + "gulp-util": "3.0.8", + "postcss": "5.2.18", + "postcss-load-config": "1.2.0", + "vinyl-sourcemaps-apply": "0.2.1" } }, "gulp-rename": { @@ -4158,7 +3253,7 @@ "integrity": "sha1-xnYqLx8N4KP8WVohWZ0/rI26Gso=", "dev": true, "requires": { - "through2": "^2.0.1" + "through2": "2.0.3" } }, "gulp-util": { @@ -4167,24 +3262,24 @@ "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", "dev": true, "requires": { - "array-differ": "^1.0.0", - "array-uniq": "^1.0.2", - "beeper": "^1.0.0", - "chalk": "^1.0.0", - "dateformat": "^2.0.0", - "fancy-log": "^1.1.0", - "gulplog": "^1.0.0", - "has-gulplog": "^0.1.0", - "lodash._reescape": "^3.0.0", - "lodash._reevaluate": "^3.0.0", - "lodash._reinterpolate": "^3.0.0", - "lodash.template": "^3.0.0", - "minimist": "^1.1.0", - "multipipe": "^0.1.2", - "object-assign": "^3.0.0", + "array-differ": "1.0.0", + "array-uniq": "1.0.3", + "beeper": "1.1.1", + "chalk": "1.1.3", + "dateformat": "2.2.0", + "fancy-log": "1.3.2", + "gulplog": "1.0.0", + "has-gulplog": "0.1.0", + "lodash._reescape": "3.0.0", + "lodash._reevaluate": "3.0.0", + "lodash._reinterpolate": "3.0.0", + "lodash.template": "3.6.2", + "minimist": "1.2.0", + "multipipe": "0.1.2", + "object-assign": "3.0.0", "replace-ext": "0.0.1", - "through2": "^2.0.0", - "vinyl": "^0.5.0" + "through2": "2.0.3", + "vinyl": "0.5.3" }, "dependencies": { "minimist": { @@ -4207,16 +3302,16 @@ "integrity": "sha1-Fi/FY96fx3DpH5p845VVE6mhGMA=", "dev": true, "requires": { - "anymatch": "^1.3.0", - "chokidar": "^1.6.1", - "glob-parent": "^3.0.1", - "gulp-util": "^3.0.7", - "object-assign": "^4.1.0", - "path-is-absolute": "^1.0.1", - "readable-stream": "^2.2.2", - "slash": "^1.0.0", - "vinyl": "^1.2.0", - "vinyl-file": "^2.0.0" + "anymatch": "1.3.2", + "chokidar": "1.7.0", + "glob-parent": "3.1.0", + "gulp-util": "3.0.8", + "object-assign": "4.1.1", + "path-is-absolute": "1.0.1", + "readable-stream": "2.3.5", + "slash": "1.0.0", + "vinyl": "1.2.0", + "vinyl-file": "2.0.0" }, "dependencies": { "isarray": { @@ -4231,13 +3326,13 @@ "integrity": "sha1-tPhQA6k4y7bsvOKhJPsQEr0ag40=", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.0.3", - "util-deprecate": "~1.0.1" + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" } }, "string_decoder": { @@ -4246,7 +3341,7 @@ "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", "dev": true, "requires": { - "safe-buffer": "~5.1.0" + "safe-buffer": "5.1.1" } }, "vinyl": { @@ -4255,8 +3350,8 @@ "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", "dev": true, "requires": { - "clone": "^1.0.0", - "clone-stats": "^0.0.1", + "clone": "1.0.4", + "clone-stats": "0.0.1", "replace-ext": "0.0.1" } } @@ -4268,16 +3363,16 @@ "integrity": "sha1-kPsLSieiZkM4Mv98YSLbXB7olMY=", "dev": true, "requires": { - "consolidate": "^0.14.1", - "es6-promise": "^3.1.2", - "fs-readfile-promise": "^2.0.1", - "gulp-util": "^3.0.3", - "js-yaml": "^3.2.6", - "lodash": "^4.11.1", - "node.extend": "^1.1.2", - "through2": "^2.0.1", - "tryit": "^1.0.1", - "vinyl-bufferstream": "^1.0.1" + "consolidate": "0.14.5", + "es6-promise": "3.3.1", + "fs-readfile-promise": "2.0.1", + "gulp-util": "3.0.8", + "js-yaml": "3.7.0", + "lodash": "4.17.5", + "node.extend": "1.1.6", + "through2": "2.0.3", + "tryit": "1.0.3", + "vinyl-bufferstream": "1.0.1" } }, "gulp-wrap-js": { @@ -4286,12 +3381,12 @@ "integrity": "sha1-3uYqpISqupVHqT0f9c0MPQvtwDE=", "dev": true, "requires": { - "escodegen": "^1.6.1", - "esprima": "^2.3.0", - "estemplate": "*", - "gulp-util": "~3.0.5", - "through2": "*", - "vinyl-sourcemaps-apply": "^0.1.4" + "escodegen": "1.9.1", + "esprima": "2.7.3", + "estemplate": "0.5.1", + "gulp-util": "3.0.8", + "through2": "2.0.3", + "vinyl-sourcemaps-apply": "0.1.4" }, "dependencies": { "source-map": { @@ -4300,7 +3395,7 @@ "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", "dev": true, "requires": { - "amdefine": ">=0.0.4" + "amdefine": "1.0.1" } }, "vinyl-sourcemaps-apply": { @@ -4309,7 +3404,7 @@ "integrity": "sha1-xfy9Q+LyOEI8LcmL3db3m3K8NFs=", "dev": true, "requires": { - "source-map": "^0.1.39" + "source-map": "0.1.43" } } } @@ -4320,7 +3415,7 @@ "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", "dev": true, "requires": { - "glogg": "^1.0.0" + "glogg": "1.0.1" } }, "har-schema": { @@ -4335,8 +3430,8 @@ "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=", "dev": true, "requires": { - "ajv": "^4.9.1", - "har-schema": "^1.0.5" + "ajv": "4.11.8", + "har-schema": "1.0.5" } }, "has": { @@ -4345,7 +3440,7 @@ "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=", "dev": true, "requires": { - "function-bind": "^1.0.2" + "function-bind": "1.1.1" } }, "has-ansi": { @@ -4354,7 +3449,7 @@ "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", "dev": true, "requires": { - "ansi-regex": "^2.0.0" + "ansi-regex": "2.1.1" } }, "has-binary": { @@ -4384,7 +3479,7 @@ "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", "dev": true, "requires": { - "sparkles": "^1.0.0" + "sparkles": "1.0.0" } }, "has-value": { @@ -4393,9 +3488,9 @@ "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", "dev": true, "requires": { - "get-value": "^2.0.6", - "has-values": "^1.0.0", - "isobject": "^3.0.0" + "get-value": "2.0.6", + "has-values": "1.0.0", + "isobject": "3.0.1" } }, "has-values": { @@ -4404,8 +3499,8 @@ "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", "dev": true, "requires": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" + "is-number": "3.0.0", + "kind-of": "4.0.0" }, "dependencies": { "kind-of": { @@ -4414,7 +3509,7 @@ "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.6" } } } @@ -4425,8 +3520,8 @@ "integrity": "sha1-eNfL/B5tZjA/55g3NlmEUXsvbuE=", "dev": true, "requires": { - "is-stream": "^1.0.1", - "pinkie-promise": "^2.0.0" + "is-stream": "1.1.0", + "pinkie-promise": "2.0.1" } }, "hawk": { @@ -4435,10 +3530,10 @@ "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", "dev": true, "requires": { - "boom": "2.x.x", - "cryptiles": "2.x.x", - "hoek": "2.x.x", - "sntp": "1.x.x" + "boom": "2.10.1", + "cryptiles": "2.0.5", + "hoek": "2.16.3", + "sntp": "1.0.9" } }, "hoek": { @@ -4453,7 +3548,7 @@ "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", "dev": true, "requires": { - "parse-passwd": "^1.0.0" + "parse-passwd": "1.0.0" } }, "hosted-git-info": { @@ -4474,8 +3569,8 @@ "integrity": "sha1-GX4izevUGYWF6GlO9nhhl7ke2UI=", "dev": true, "requires": { - "inherits": "~2.0.1", - "statuses": "1" + "inherits": "2.0.3", + "statuses": "1.5.0" } }, "http-parser-js": { @@ -4490,8 +3585,8 @@ "integrity": "sha1-Bt/ykpUr9k2+hHH6nfcwZtTzd0I=", "dev": true, "requires": { - "eventemitter3": "1.x.x", - "requires-port": "1.x.x" + "eventemitter3": "1.2.0", + "requires-port": "1.0.0" } }, "http-signature": { @@ -4500,9 +3595,9 @@ "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", "dev": true, "requires": { - "assert-plus": "^0.2.0", - "jsprim": "^1.2.2", - "sshpk": "^1.7.0" + "assert-plus": "0.2.0", + "jsprim": "1.4.1", + "sshpk": "1.14.1" } }, "iconv-lite": { @@ -4524,7 +3619,7 @@ "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", "dev": true, "requires": { - "repeating": "^2.0.0" + "repeating": "2.0.1" } }, "indexes-of": { @@ -4551,8 +3646,8 @@ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "dev": true, "requires": { - "once": "^1.3.0", - "wrappy": "1" + "once": "1.4.0", + "wrappy": "1.0.2" } }, "inherits": { @@ -4585,8 +3680,8 @@ "integrity": "sha1-OV4a6EsR8mrReV5zwXN45IowFXY=", "dev": true, "requires": { - "is-relative": "^1.0.0", - "is-windows": "^1.0.1" + "is-relative": "1.0.0", + "is-windows": "1.0.2" } }, "is-absolute-url": { @@ -4601,7 +3696,7 @@ "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", "dev": true, "requires": { - "kind-of": "^6.0.0" + "kind-of": "6.0.2" } }, "is-arrayish": { @@ -4616,7 +3711,7 @@ "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", "dev": true, "requires": { - "binary-extensions": "^1.0.0" + "binary-extensions": "1.11.0" } }, "is-buffer": { @@ -4631,7 +3726,7 @@ "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", "dev": true, "requires": { - "builtin-modules": "^1.0.0" + "builtin-modules": "1.1.1" } }, "is-data-descriptor": { @@ -4640,7 +3735,7 @@ "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", "dev": true, "requires": { - "kind-of": "^6.0.0" + "kind-of": "6.0.2" } }, "is-descriptor": { @@ -4649,9 +3744,9 @@ "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", "dev": true, "requires": { - "is-accessor-descriptor": "^1.0.0", - "is-data-descriptor": "^1.0.0", - "kind-of": "^6.0.2" + "is-accessor-descriptor": "1.0.0", + "is-data-descriptor": "1.0.0", + "kind-of": "6.0.2" } }, "is-directory": { @@ -4672,7 +3767,7 @@ "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", "dev": true, "requires": { - "is-primitive": "^2.0.0" + "is-primitive": "2.0.0" } }, "is-extendable": { @@ -4693,7 +3788,7 @@ "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", "dev": true, "requires": { - "number-is-nan": "^1.0.0" + "number-is-nan": "1.0.1" } }, "is-glob": { @@ -4702,7 +3797,7 @@ "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", "dev": true, "requires": { - "is-extglob": "^2.1.0" + "is-extglob": "2.1.1" } }, "is-number": { @@ -4711,7 +3806,7 @@ "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", "dev": true, "requires": { - "kind-of": "^3.0.2" + "kind-of": "3.2.2" }, "dependencies": { "kind-of": { @@ -4720,7 +3815,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.6" } } } @@ -4731,7 +3826,7 @@ "integrity": "sha1-dkZiRnH9fqVYzNmieVGC8pWPGyQ=", "dev": true, "requires": { - "is-number": "^4.0.0" + "is-number": "4.0.0" }, "dependencies": { "is-number": { @@ -4754,7 +3849,7 @@ "integrity": "sha1-LBY7P6+xtgbZ0Xko8FwqHDjgdnc=", "dev": true, "requires": { - "isobject": "^3.0.1" + "isobject": "3.0.1" } }, "is-posix-bracket": { @@ -4775,7 +3870,7 @@ "integrity": "sha1-obtpNc6MXboei5dUubLcwCDiJg0=", "dev": true, "requires": { - "is-unc-path": "^1.0.0" + "is-unc-path": "1.0.0" } }, "is-stream": { @@ -4790,7 +3885,7 @@ "integrity": "sha1-z2EJDaDZ77yrhyLeum8DIgjbsOk=", "dev": true, "requires": { - "html-comment-regex": "^1.1.0" + "html-comment-regex": "1.1.1" } }, "is-typedarray": { @@ -4805,7 +3900,7 @@ "integrity": "sha1-1zHoiY7QkKEsNSrS6u1Qla0yLJ0=", "dev": true, "requires": { - "unc-path-regex": "^0.1.2" + "unc-path-regex": "0.1.2" } }, "is-utf8": { @@ -4868,8 +3963,8 @@ "integrity": "sha1-XJZ93YN6m/3KXy3oQlOr6KHAO4A=", "dev": true, "requires": { - "argparse": "^1.0.7", - "esprima": "^2.6.0" + "argparse": "1.0.10", + "esprima": "2.7.3" } }, "jsbn": { @@ -4891,7 +3986,7 @@ "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", "dev": true, "requires": { - "jsonify": "~0.0.0" + "jsonify": "0.0.0" } }, "json-stringify-safe": { @@ -4912,7 +4007,7 @@ "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", "dev": true, "requires": { - "graceful-fs": "^4.1.6" + "graceful-fs": "4.1.11" }, "dependencies": { "graceful-fs": { @@ -4956,33 +4051,33 @@ "integrity": "sha1-hcwI6eCiLXzpzKN8ShvoJPaisa4=", "dev": true, "requires": { - "bluebird": "^3.3.0", - "body-parser": "^1.16.1", - "chokidar": "^1.4.1", - "colors": "^1.1.0", - "combine-lists": "^1.0.0", - "connect": "^3.6.0", - "core-js": "^2.2.0", - "di": "^0.0.1", - "dom-serialize": "^2.2.0", - "expand-braces": "^0.1.1", - "glob": "^7.1.1", - "graceful-fs": "^4.1.2", - "http-proxy": "^1.13.0", - "isbinaryfile": "^3.0.0", - "lodash": "^3.8.0", - "log4js": "^0.6.31", - "mime": "^1.3.4", - "minimatch": "^3.0.2", - "optimist": "^0.6.1", - "qjobs": "^1.1.4", - "range-parser": "^1.2.0", - "rimraf": "^2.6.0", - "safe-buffer": "^5.0.1", + "bluebird": "3.5.1", + "body-parser": "1.18.2", + "chokidar": "1.7.0", + "colors": "1.2.1", + "combine-lists": "1.0.1", + "connect": "3.6.6", + "core-js": "2.5.4", + "di": "0.0.1", + "dom-serialize": "2.2.1", + "expand-braces": "0.1.2", + "glob": "7.1.2", + "graceful-fs": "4.1.11", + "http-proxy": "1.16.2", + "isbinaryfile": "3.0.2", + "lodash": "3.10.1", + "log4js": "0.6.38", + "mime": "1.3.4", + "minimatch": "3.0.4", + "optimist": "0.6.1", + "qjobs": "1.2.0", + "range-parser": "1.2.0", + "rimraf": "2.6.2", + "safe-buffer": "5.1.1", "socket.io": "1.7.3", - "source-map": "^0.5.3", + "source-map": "0.5.7", "tmp": "0.0.31", - "useragent": "^2.1.12" + "useragent": "2.3.0" }, "dependencies": { "body-parser": { @@ -4992,15 +4087,15 @@ "dev": true, "requires": { "bytes": "3.0.0", - "content-type": "~1.0.4", + "content-type": "1.0.4", "debug": "2.6.9", - "depd": "~1.1.1", - "http-errors": "~1.6.2", + "depd": "1.1.2", + "http-errors": "1.6.2", "iconv-lite": "0.4.19", - "on-finished": "~2.3.0", + "on-finished": "2.3.0", "qs": "6.5.1", "raw-body": "2.3.2", - "type-is": "~1.6.15" + "type-is": "1.6.16" } }, "bytes": { @@ -5017,7 +4112,7 @@ "requires": { "debug": "2.6.9", "finalhandler": "1.1.0", - "parseurl": "~1.3.2", + "parseurl": "1.3.2", "utils-merge": "1.0.1" } }, @@ -5034,12 +4129,12 @@ "dev": true, "requires": { "debug": "2.6.9", - "encodeurl": "~1.0.1", - "escape-html": "~1.0.3", - "on-finished": "~2.3.0", - "parseurl": "~1.3.2", - "statuses": "~1.3.1", - "unpipe": "~1.0.0" + "encodeurl": "1.0.2", + "escape-html": "1.0.3", + "on-finished": "2.3.0", + "parseurl": "1.3.2", + "statuses": "1.3.1", + "unpipe": "1.0.0" }, "dependencies": { "statuses": { @@ -5065,7 +4160,7 @@ "depd": "1.1.1", "inherits": "2.0.3", "setprototypeof": "1.0.3", - "statuses": ">= 1.3.1 < 2" + "statuses": "1.5.0" }, "dependencies": { "depd": { @@ -5132,8 +4227,8 @@ "integrity": "sha1-0jyjSAG9qYY60xjju0vUBisTrNI=", "dev": true, "requires": { - "lodash": "^4.0.1", - "phantomjs-prebuilt": "^2.1.7" + "lodash": "4.17.5", + "phantomjs-prebuilt": "2.1.16" } }, "kew": { @@ -5154,7 +4249,7 @@ "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", "dev": true, "requires": { - "graceful-fs": "^4.1.9" + "graceful-fs": "4.1.11" }, "dependencies": { "graceful-fs": { @@ -5178,14 +4273,14 @@ "integrity": "sha1-zBJg9RyQCp7A2R+2mYE54CUHtjs=", "dev": true, "requires": { - "errno": "^0.1.1", - "graceful-fs": "^4.1.2", - "image-size": "~0.5.0", - "mime": "^1.2.11", - "mkdirp": "^0.5.0", - "promise": "^7.1.1", + "errno": "0.1.7", + "graceful-fs": "4.1.11", + "image-size": "0.5.5", + "mime": "1.3.4", + "mkdirp": "0.5.1", + "promise": "7.3.1", "request": "2.81.0", - "source-map": "^0.5.3" + "source-map": "0.5.7" }, "dependencies": { "graceful-fs": { @@ -5203,8 +4298,8 @@ "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", "dev": true, "requires": { - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2" + "prelude-ls": "1.1.2", + "type-check": "0.3.2" } }, "liftoff": { @@ -5213,14 +4308,14 @@ "integrity": "sha1-IAkpG7Mc6oYbvxCnwVooyvdcMew=", "dev": true, "requires": { - "extend": "^3.0.0", - "findup-sync": "^2.0.0", - "fined": "^1.0.1", - "flagged-respawn": "^1.0.0", - "is-plain-object": "^2.0.4", - "object.map": "^1.0.0", - "rechoir": "^0.6.2", - "resolve": "^1.1.7" + "extend": "3.0.1", + "findup-sync": "2.0.0", + "fined": "1.1.0", + "flagged-respawn": "1.0.0", + "is-plain-object": "2.0.4", + "object.map": "1.0.1", + "rechoir": "0.6.2", + "resolve": "1.6.0" } }, "livereload-js": { @@ -5235,11 +4330,11 @@ "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "parse-json": "^2.2.0", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0" + "graceful-fs": "4.1.11", + "parse-json": "2.2.0", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "strip-bom": "2.0.0" }, "dependencies": { "graceful-fs": { @@ -5254,7 +4349,7 @@ "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", "dev": true, "requires": { - "is-utf8": "^0.2.0" + "is-utf8": "0.2.1" } } } @@ -5289,7 +4384,7 @@ "integrity": "sha1-32fDu2t+jh6DGrSL+geVuSr+iZ0=", "dev": true, "requires": { - "lodash._htmlescapes": "~2.4.1" + "lodash._htmlescapes": "2.4.1" } }, "lodash._escapestringchar": { @@ -5352,8 +4447,8 @@ "integrity": "sha1-dHxPxAED6zu4oJduVx96JlnpO6c=", "dev": true, "requires": { - "lodash._htmlescapes": "~2.4.1", - "lodash.keys": "~2.4.1" + "lodash._htmlescapes": "2.4.1", + "lodash.keys": "2.4.1" }, "dependencies": { "lodash.keys": { @@ -5362,9 +4457,9 @@ "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", "dev": true, "requires": { - "lodash._isnative": "~2.4.1", - "lodash._shimkeys": "~2.4.1", - "lodash.isobject": "~2.4.1" + "lodash._isnative": "2.4.1", + "lodash._shimkeys": "2.4.1", + "lodash.isobject": "2.4.1" } } } @@ -5381,7 +4476,7 @@ "integrity": "sha1-bpzJZm/wgfC1psl4uD4kLmlJ0gM=", "dev": true, "requires": { - "lodash._objecttypes": "~2.4.1" + "lodash._objecttypes": "2.4.1" } }, "lodash.clone": { @@ -5402,7 +4497,7 @@ "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", "dev": true, "requires": { - "lodash._root": "^3.0.0" + "lodash._root": "3.0.1" } }, "lodash.flatten": { @@ -5429,7 +4524,7 @@ "integrity": "sha1-Wi5H/mmVPx7mMafrof5k0tBlWPU=", "dev": true, "requires": { - "lodash._objecttypes": "~2.4.1" + "lodash._objecttypes": "2.4.1" } }, "lodash.keys": { @@ -5438,9 +4533,9 @@ "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", "dev": true, "requires": { - "lodash._getnative": "^3.0.0", - "lodash.isarguments": "^3.0.0", - "lodash.isarray": "^3.0.0" + "lodash._getnative": "3.9.1", + "lodash.isarguments": "3.1.0", + "lodash.isarray": "3.0.4" } }, "lodash.memoize": { @@ -5479,15 +4574,15 @@ "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", "dev": true, "requires": { - "lodash._basecopy": "^3.0.0", - "lodash._basetostring": "^3.0.0", - "lodash._basevalues": "^3.0.0", - "lodash._isiterateecall": "^3.0.0", - "lodash._reinterpolate": "^3.0.0", - "lodash.escape": "^3.0.0", - "lodash.keys": "^3.0.0", - "lodash.restparam": "^3.0.0", - "lodash.templatesettings": "^3.0.0" + "lodash._basecopy": "3.0.1", + "lodash._basetostring": "3.0.1", + "lodash._basevalues": "3.0.0", + "lodash._isiterateecall": "3.0.9", + "lodash._reinterpolate": "3.0.0", + "lodash.escape": "3.2.0", + "lodash.keys": "3.1.2", + "lodash.restparam": "3.6.1", + "lodash.templatesettings": "3.1.1" } }, "lodash.templatesettings": { @@ -5496,8 +4591,8 @@ "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", "dev": true, "requires": { - "lodash._reinterpolate": "^3.0.0", - "lodash.escape": "^3.0.0" + "lodash._reinterpolate": "3.0.0", + "lodash.escape": "3.2.0" } }, "lodash.uniq": { @@ -5512,7 +4607,7 @@ "integrity": "sha1-q/UUQ2s8twUAFieXjLzzCxKA7qQ=", "dev": true, "requires": { - "lodash.keys": "~2.4.1" + "lodash.keys": "2.4.1" }, "dependencies": { "lodash.keys": { @@ -5521,9 +4616,9 @@ "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", "dev": true, "requires": { - "lodash._isnative": "~2.4.1", - "lodash._shimkeys": "~2.4.1", - "lodash.isobject": "~2.4.1" + "lodash._isnative": "2.4.1", + "lodash._shimkeys": "2.4.1", + "lodash.isobject": "2.4.1" } } } @@ -5534,8 +4629,8 @@ "integrity": "sha1-LElBFmldb7JUgJQ9P8hy5mKlIv0=", "dev": true, "requires": { - "readable-stream": "~1.0.2", - "semver": "~4.3.3" + "readable-stream": "1.0.34", + "semver": "4.3.6" }, "dependencies": { "readable-stream": { @@ -5544,10 +4639,10 @@ "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", + "core-util-is": "1.0.2", + "inherits": "2.0.3", "isarray": "0.0.1", - "string_decoder": "~0.10.x" + "string_decoder": "0.10.31" } } } @@ -5564,8 +4659,8 @@ "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", "dev": true, "requires": { - "currently-unhandled": "^0.4.1", - "signal-exit": "^3.0.0" + "currently-unhandled": "0.4.1", + "signal-exit": "3.0.2" } }, "lru-cache": { @@ -5586,7 +4681,7 @@ "integrity": "sha1-V7713IXSOSO6I3ZzJNjo+PPZaUs=", "dev": true, "requires": { - "kind-of": "^3.1.0" + "kind-of": "3.2.2" }, "dependencies": { "kind-of": { @@ -5595,7 +4690,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.6" } } } @@ -5624,7 +4719,7 @@ "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", "dev": true, "requires": { - "object-visit": "^1.0.0" + "object-visit": "1.0.1" } }, "marked": { @@ -5651,16 +4746,16 @@ "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", "dev": true, "requires": { - "camelcase-keys": "^2.0.0", - "decamelize": "^1.1.2", - "loud-rejection": "^1.0.0", - "map-obj": "^1.0.1", - "minimist": "^1.1.3", - "normalize-package-data": "^2.3.4", - "object-assign": "^4.0.1", - "read-pkg-up": "^1.0.1", - "redent": "^1.0.0", - "trim-newlines": "^1.0.0" + "camelcase-keys": "2.1.0", + "decamelize": "1.2.0", + "loud-rejection": "1.6.0", + "map-obj": "1.0.1", + "minimist": "1.2.0", + "normalize-package-data": "2.4.0", + "object-assign": "4.1.1", + "read-pkg-up": "1.0.1", + "redent": "1.0.0", + "trim-newlines": "1.0.0" }, "dependencies": { "minimist": { @@ -5677,7 +4772,7 @@ "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", "dev": true, "requires": { - "readable-stream": "^2.0.1" + "readable-stream": "2.3.5" }, "dependencies": { "isarray": { @@ -5692,13 +4787,13 @@ "integrity": "sha1-tPhQA6k4y7bsvOKhJPsQEr0ag40=", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.0.3", - "util-deprecate": "~1.0.1" + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" } }, "string_decoder": { @@ -5707,7 +4802,7 @@ "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", "dev": true, "requires": { - "safe-buffer": "~5.1.0" + "safe-buffer": "5.1.1" } } } @@ -5719,9 +4814,9 @@ "dev": true, "requires": { "debug": "2.6.9", - "methods": "~1.1.2", - "parseurl": "~1.3.2", - "vary": "~1.1.2" + "methods": "1.1.2", + "parseurl": "1.3.2", + "vary": "1.1.2" }, "dependencies": { "vary": { @@ -5744,19 +4839,19 @@ "integrity": "sha1-cIWbyVyYQJUvNZoGij/En57PrCM=", "dev": true, "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "braces": "^2.3.1", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "extglob": "^2.0.4", - "fragment-cache": "^0.2.1", - "kind-of": "^6.0.2", - "nanomatch": "^1.2.9", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.2" + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "braces": "2.3.1", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "extglob": "2.0.4", + "fragment-cache": "0.2.1", + "kind-of": "6.0.2", + "nanomatch": "1.2.9", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" } }, "mime": { @@ -5777,7 +4872,7 @@ "integrity": "sha1-bzI/YKg9ERRvgx/xH9ZuL+VQO7g=", "dev": true, "requires": { - "mime-db": "~1.33.0" + "mime-db": "1.33.0" } }, "minimatch": { @@ -5786,7 +4881,7 @@ "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", "dev": true, "requires": { - "brace-expansion": "^1.1.7" + "brace-expansion": "1.1.11" } }, "minimist": { @@ -5801,8 +4896,8 @@ "integrity": "sha1-pJ5yaNzhoNlpjkUybFYm3zVD0P4=", "dev": true, "requires": { - "for-in": "^1.0.2", - "is-extendable": "^1.0.1" + "for-in": "1.0.2", + "is-extendable": "1.0.1" }, "dependencies": { "is-extendable": { @@ -5811,7 +4906,7 @@ "integrity": "sha1-p0cPnkJnM9gb2B4RVSZOOjUHyrQ=", "dev": true, "requires": { - "is-plain-object": "^2.0.4" + "is-plain-object": "2.0.4" } } } @@ -5831,11 +4926,11 @@ "integrity": "sha1-X9gYOYxoGcuiinzWZk8pL+HAu/I=", "dev": true, "requires": { - "basic-auth": "~1.0.3", - "debug": "~2.2.0", - "depd": "~1.0.1", - "on-finished": "~2.3.0", - "on-headers": "~1.0.0" + "basic-auth": "1.0.4", + "debug": "2.2.0", + "depd": "1.0.1", + "on-finished": "2.3.0", + "on-headers": "1.0.1" }, "dependencies": { "debug": { @@ -5867,8 +4962,8 @@ "integrity": "sha1-Nd5oBNwZZD5SSfPT473GyM4wHT8=", "dev": true, "requires": { - "readable-stream": "~1.1.9", - "stream-counter": "~0.2.0" + "readable-stream": "1.1.14", + "stream-counter": "0.2.0" } }, "multipipe": { @@ -5880,31 +4975,24 @@ "duplexer2": "0.0.2" } }, - "nan": { - "version": "2.10.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz", - "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==", - "dev": true, - "optional": true - }, "nanomatch": { "version": "1.2.9", "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.9.tgz", "integrity": "sha1-h59xUMstq3pHElkGbBBO7m4Pp8I=", "dev": true, "requires": { - "arr-diff": "^4.0.0", - "array-unique": "^0.3.2", - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "fragment-cache": "^0.2.1", - "is-odd": "^2.0.0", - "is-windows": "^1.0.2", - "kind-of": "^6.0.2", - "object.pick": "^1.3.0", - "regex-not": "^1.0.0", - "snapdragon": "^0.8.1", - "to-regex": "^3.0.1" + "arr-diff": "4.0.0", + "array-unique": "0.3.2", + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "fragment-cache": "0.2.1", + "is-odd": "2.0.0", + "is-windows": "1.0.2", + "kind-of": "6.0.2", + "object.pick": "1.3.0", + "regex-not": "1.0.2", + "snapdragon": "0.8.2", + "to-regex": "3.0.2" } }, "natives": { @@ -5931,7 +5019,7 @@ "integrity": "sha1-p7iCyC1sk6SGOlUEvV3o7IYli5Y=", "dev": true, "requires": { - "is": "^3.1.0" + "is": "3.2.1" } }, "nopt": { @@ -5940,7 +5028,7 @@ "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", "dev": true, "requires": { - "abbrev": "1" + "abbrev": "1.1.1" } }, "normalize-package-data": { @@ -5949,10 +5037,10 @@ "integrity": "sha1-EvlaMH1YNSB1oEkHuErIvpisAS8=", "dev": true, "requires": { - "hosted-git-info": "^2.1.4", - "is-builtin-module": "^1.0.0", - "semver": "2 || 3 || 4 || 5", - "validate-npm-package-license": "^3.0.1" + "hosted-git-info": "2.6.0", + "is-builtin-module": "1.0.0", + "semver": "4.3.6", + "validate-npm-package-license": "3.0.3" } }, "normalize-path": { @@ -5961,7 +5049,7 @@ "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", "dev": true, "requires": { - "remove-trailing-separator": "^1.0.1" + "remove-trailing-separator": "1.1.0" } }, "normalize-range": { @@ -5976,10 +5064,10 @@ "integrity": "sha1-LMDWazHqIwNkWENuNiDYWVTGbDw=", "dev": true, "requires": { - "object-assign": "^4.0.1", - "prepend-http": "^1.0.0", - "query-string": "^4.1.0", - "sort-keys": "^1.0.0" + "object-assign": "4.1.1", + "prepend-http": "1.0.4", + "query-string": "4.3.4", + "sort-keys": "1.1.2" } }, "num2fraction": { @@ -6018,9 +5106,9 @@ "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", "dev": true, "requires": { - "copy-descriptor": "^0.1.0", - "define-property": "^0.2.5", - "kind-of": "^3.0.3" + "copy-descriptor": "0.1.1", + "define-property": "0.2.5", + "kind-of": "3.2.2" }, "dependencies": { "define-property": { @@ -6029,7 +5117,7 @@ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "^0.1.0" + "is-descriptor": "0.1.6" } }, "is-accessor-descriptor": { @@ -6038,7 +5126,7 @@ "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", "dev": true, "requires": { - "kind-of": "^3.0.2" + "kind-of": "3.2.2" } }, "is-data-descriptor": { @@ -6047,7 +5135,7 @@ "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", "dev": true, "requires": { - "kind-of": "^3.0.2" + "kind-of": "3.2.2" } }, "is-descriptor": { @@ -6056,9 +5144,9 @@ "integrity": "sha1-Nm2CQN3kh8pRgjsaufB6EKeCUco=", "dev": true, "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" }, "dependencies": { "kind-of": { @@ -6075,7 +5163,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.6" } } } @@ -6086,7 +5174,7 @@ "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", "dev": true, "requires": { - "isobject": "^3.0.0" + "isobject": "3.0.1" } }, "object.defaults": { @@ -6095,10 +5183,10 @@ "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", "dev": true, "requires": { - "array-each": "^1.0.1", - "array-slice": "^1.0.0", - "for-own": "^1.0.0", - "isobject": "^3.0.0" + "array-each": "1.0.1", + "array-slice": "1.1.0", + "for-own": "1.0.0", + "isobject": "3.0.1" } }, "object.map": { @@ -6107,8 +5195,8 @@ "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", "dev": true, "requires": { - "for-own": "^1.0.0", - "make-iterator": "^1.0.0" + "for-own": "1.0.0", + "make-iterator": "1.0.0" } }, "object.omit": { @@ -6117,8 +5205,8 @@ "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", "dev": true, "requires": { - "for-own": "^0.1.4", - "is-extendable": "^0.1.1" + "for-own": "0.1.5", + "is-extendable": "0.1.1" }, "dependencies": { "for-own": { @@ -6127,7 +5215,7 @@ "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", "dev": true, "requires": { - "for-in": "^1.0.1" + "for-in": "1.0.2" } } } @@ -6138,7 +5226,7 @@ "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", "dev": true, "requires": { - "isobject": "^3.0.1" + "isobject": "3.0.1" } }, "on-finished": { @@ -6162,7 +5250,7 @@ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, "requires": { - "wrappy": "1" + "wrappy": "1.0.2" } }, "open": { @@ -6177,8 +5265,8 @@ "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", "dev": true, "requires": { - "minimist": "~0.0.1", - "wordwrap": "~0.0.2" + "minimist": "0.0.8", + "wordwrap": "0.0.2" } }, "optionator": { @@ -6187,12 +5275,12 @@ "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", "dev": true, "requires": { - "deep-is": "~0.1.3", - "fast-levenshtein": "~2.0.4", - "levn": "~0.3.0", - "prelude-ls": "~1.1.2", - "type-check": "~0.3.2", - "wordwrap": "~1.0.0" + "deep-is": "0.1.3", + "fast-levenshtein": "2.0.6", + "levn": "0.3.0", + "prelude-ls": "1.1.2", + "type-check": "0.3.2", + "wordwrap": "1.0.0" }, "dependencies": { "wordwrap": { @@ -6215,9 +5303,9 @@ "integrity": "sha1-FOfp4nZPcxX7rBhOUGx6pt+UrX4=", "dev": true, "requires": { - "end-of-stream": "~0.1.5", - "sequencify": "~0.0.7", - "stream-consume": "~0.1.0" + "end-of-stream": "0.1.5", + "sequencify": "0.0.7", + "stream-consume": "0.1.1" } }, "ordered-read-streams": { @@ -6244,9 +5332,9 @@ "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", "dev": true, "requires": { - "is-absolute": "^1.0.0", - "map-cache": "^0.2.0", - "path-root": "^0.1.1" + "is-absolute": "1.0.0", + "map-cache": "0.2.2", + "path-root": "0.1.1" } }, "parse-glob": { @@ -6255,10 +5343,10 @@ "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", "dev": true, "requires": { - "glob-base": "^0.3.0", - "is-dotfile": "^1.0.0", - "is-extglob": "^1.0.0", - "is-glob": "^2.0.0" + "glob-base": "0.3.0", + "is-dotfile": "1.0.3", + "is-extglob": "1.0.0", + "is-glob": "2.0.1" }, "dependencies": { "is-extglob": { @@ -6273,7 +5361,7 @@ "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", "dev": true, "requires": { - "is-extglob": "^1.0.0" + "is-extglob": "1.0.0" } } } @@ -6284,7 +5372,7 @@ "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", "dev": true, "requires": { - "error-ex": "^1.2.0" + "error-ex": "1.3.1" } }, "parse-passwd": { @@ -6299,7 +5387,7 @@ "integrity": "sha1-q343WfIJ7OmUN5c/fQ8fZK4OZKs=", "dev": true, "requires": { - "better-assert": "~1.0.0" + "better-assert": "1.0.2" } }, "parseqs": { @@ -6308,7 +5396,7 @@ "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", "dev": true, "requires": { - "better-assert": "~1.0.0" + "better-assert": "1.0.2" } }, "parseuri": { @@ -6317,7 +5405,7 @@ "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", "dev": true, "requires": { - "better-assert": "~1.0.0" + "better-assert": "1.0.2" } }, "parseurl": { @@ -6350,7 +5438,7 @@ "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", "dev": true, "requires": { - "pinkie-promise": "^2.0.0" + "pinkie-promise": "2.0.1" } }, "path-is-absolute": { @@ -6371,7 +5459,7 @@ "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", "dev": true, "requires": { - "path-root-regex": "^0.1.0" + "path-root-regex": "0.1.2" } }, "path-root-regex": { @@ -6386,9 +5474,9 @@ "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.0.0", - "pinkie-promise": "^2.0.0" + "graceful-fs": "4.1.11", + "pify": "2.3.0", + "pinkie-promise": "2.0.1" }, "dependencies": { "graceful-fs": { @@ -6411,7 +5499,7 @@ "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", "dev": true, "requires": { - "through": "~2.3" + "through": "2.3.8" } }, "pend": { @@ -6432,15 +5520,15 @@ "integrity": "sha1-79ISpKOWbTZHaE6ouniFSb4q7+8=", "dev": true, "requires": { - "es6-promise": "^4.0.3", - "extract-zip": "^1.6.5", - "fs-extra": "^1.0.0", - "hasha": "^2.2.0", - "kew": "^0.7.0", - "progress": "^1.1.8", - "request": "^2.81.0", - "request-progress": "^2.0.1", - "which": "^1.2.10" + "es6-promise": "4.2.4", + "extract-zip": "1.6.6", + "fs-extra": "1.0.0", + "hasha": "2.2.0", + "kew": "0.7.0", + "progress": "1.1.8", + "request": "2.81.0", + "request-progress": "2.0.1", + "which": "1.3.0" }, "dependencies": { "es6-promise": { @@ -6469,7 +5557,7 @@ "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", "dev": true, "requires": { - "pinkie": "^2.0.0" + "pinkie": "2.0.4" } }, "plugin-error": { @@ -6478,11 +5566,11 @@ "integrity": "sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4=", "dev": true, "requires": { - "ansi-cyan": "^0.1.1", - "ansi-red": "^0.1.1", - "arr-diff": "^1.0.1", - "arr-union": "^2.0.1", - "extend-shallow": "^1.1.2" + "ansi-cyan": "0.1.1", + "ansi-red": "0.1.1", + "arr-diff": "1.1.0", + "arr-union": "2.1.0", + "extend-shallow": "1.1.4" }, "dependencies": { "arr-diff": { @@ -6491,8 +5579,8 @@ "integrity": "sha1-aHwydYFjWI/vfeezb6vklesaOZo=", "dev": true, "requires": { - "arr-flatten": "^1.0.1", - "array-slice": "^0.2.3" + "arr-flatten": "1.1.0", + "array-slice": "0.2.3" } }, "arr-union": { @@ -6513,7 +5601,7 @@ "integrity": "sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE=", "dev": true, "requires": { - "kind-of": "^1.1.0" + "kind-of": "1.1.0" } }, "kind-of": { @@ -6530,8 +5618,8 @@ "integrity": "sha1-hgSc9qsQgzOYqTHzaJy67nteEzM=", "dev": true, "requires": { - "chalk": "^1.1.1", - "dateformat": "^1.0.11" + "chalk": "1.1.3", + "dateformat": "1.0.12" }, "dependencies": { "dateformat": { @@ -6540,8 +5628,8 @@ "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=", "dev": true, "requires": { - "get-stdin": "^4.0.1", - "meow": "^3.3.0" + "get-stdin": "4.0.1", + "meow": "3.7.0" } } } @@ -6558,10 +5646,10 @@ "integrity": "sha1-ut+hSX1GJE9jkPWLMZgw2RB4U8U=", "dev": true, "requires": { - "chalk": "^1.1.3", - "js-base64": "^2.1.9", - "source-map": "^0.5.6", - "supports-color": "^3.2.3" + "chalk": "1.1.3", + "js-base64": "2.4.3", + "source-map": "0.5.7", + "supports-color": "3.2.3" } }, "postcss-calc": { @@ -6570,9 +5658,9 @@ "integrity": "sha1-d7rnypKK2FcW4v2kLyYb98HWW14=", "dev": true, "requires": { - "postcss": "^5.0.2", - "postcss-message-helpers": "^2.0.0", - "reduce-css-calc": "^1.2.6" + "postcss": "5.2.18", + "postcss-message-helpers": "2.0.0", + "reduce-css-calc": "1.3.0" } }, "postcss-colormin": { @@ -6581,9 +5669,9 @@ "integrity": "sha1-ZjFBfV8OkJo9fsJrJMio0eT5bks=", "dev": true, "requires": { - "colormin": "^1.0.5", - "postcss": "^5.0.13", - "postcss-value-parser": "^3.2.3" + "colormin": "1.1.2", + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" } }, "postcss-convert-values": { @@ -6592,8 +5680,8 @@ "integrity": "sha1-u9hZPFwf0uPRwyK7kl3K6Nrk1i0=", "dev": true, "requires": { - "postcss": "^5.0.11", - "postcss-value-parser": "^3.1.2" + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" } }, "postcss-discard-comments": { @@ -6602,7 +5690,7 @@ "integrity": "sha1-vv6J+v1bPazlzM5Rt2uBUUvgDj0=", "dev": true, "requires": { - "postcss": "^5.0.14" + "postcss": "5.2.18" } }, "postcss-discard-duplicates": { @@ -6611,7 +5699,7 @@ "integrity": "sha1-uavye4isGIFYpesSq8riAmO5GTI=", "dev": true, "requires": { - "postcss": "^5.0.4" + "postcss": "5.2.18" } }, "postcss-discard-empty": { @@ -6620,7 +5708,7 @@ "integrity": "sha1-0rS9nVztXr2Nyt52QMfXzX9PkrU=", "dev": true, "requires": { - "postcss": "^5.0.14" + "postcss": "5.2.18" } }, "postcss-discard-overridden": { @@ -6629,7 +5717,7 @@ "integrity": "sha1-ix6vVU9ob7KIzYdMVWZ7CqNmjVg=", "dev": true, "requires": { - "postcss": "^5.0.16" + "postcss": "5.2.18" } }, "postcss-discard-unused": { @@ -6638,8 +5726,8 @@ "integrity": "sha1-vOMLLMWR/8Y0Mitfs0ZLbZNPRDM=", "dev": true, "requires": { - "postcss": "^5.0.14", - "uniqs": "^2.0.0" + "postcss": "5.2.18", + "uniqs": "2.0.0" } }, "postcss-filter-plugins": { @@ -6648,8 +5736,8 @@ "integrity": "sha1-bYWGJTTXNaxCDkqFgG4fXUKG2Ew=", "dev": true, "requires": { - "postcss": "^5.0.4", - "uniqid": "^4.0.0" + "postcss": "5.2.18", + "uniqid": "4.1.1" } }, "postcss-load-config": { @@ -6658,10 +5746,10 @@ "integrity": "sha1-U56a/J3chiASHr+djDZz4M5Q0oo=", "dev": true, "requires": { - "cosmiconfig": "^2.1.0", - "object-assign": "^4.1.0", - "postcss-load-options": "^1.2.0", - "postcss-load-plugins": "^2.3.0" + "cosmiconfig": "2.2.2", + "object-assign": "4.1.1", + "postcss-load-options": "1.2.0", + "postcss-load-plugins": "2.3.0" } }, "postcss-load-options": { @@ -6670,8 +5758,8 @@ "integrity": "sha1-sJixVZ3awt8EvAuzdfmaXP4rbYw=", "dev": true, "requires": { - "cosmiconfig": "^2.1.0", - "object-assign": "^4.1.0" + "cosmiconfig": "2.2.2", + "object-assign": "4.1.1" } }, "postcss-load-plugins": { @@ -6680,8 +5768,8 @@ "integrity": "sha1-dFdoEWWZrKLwCfrUJrABdQSdjZI=", "dev": true, "requires": { - "cosmiconfig": "^2.1.1", - "object-assign": "^4.1.0" + "cosmiconfig": "2.2.2", + "object-assign": "4.1.1" } }, "postcss-merge-idents": { @@ -6690,9 +5778,9 @@ "integrity": "sha1-TFUwMTwI4dWzu/PSu8dH4njuonA=", "dev": true, "requires": { - "has": "^1.0.1", - "postcss": "^5.0.10", - "postcss-value-parser": "^3.1.1" + "has": "1.0.1", + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" } }, "postcss-merge-longhand": { @@ -6701,7 +5789,7 @@ "integrity": "sha1-I9kM0Sewp3mUkVMyc5A0oaTz1lg=", "dev": true, "requires": { - "postcss": "^5.0.4" + "postcss": "5.2.18" } }, "postcss-merge-rules": { @@ -6710,11 +5798,11 @@ "integrity": "sha1-0d9d+qexrMO+VT8OnhDofGG19yE=", "dev": true, "requires": { - "browserslist": "^1.5.2", - "caniuse-api": "^1.5.2", - "postcss": "^5.0.4", - "postcss-selector-parser": "^2.2.2", - "vendors": "^1.0.0" + "browserslist": "1.7.7", + "caniuse-api": "1.6.1", + "postcss": "5.2.18", + "postcss-selector-parser": "2.2.3", + "vendors": "1.0.1" } }, "postcss-message-helpers": { @@ -6729,9 +5817,9 @@ "integrity": "sha1-S1jttWZB66fIR0qzUmyv17vey2k=", "dev": true, "requires": { - "object-assign": "^4.0.1", - "postcss": "^5.0.4", - "postcss-value-parser": "^3.0.2" + "object-assign": "4.1.1", + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" } }, "postcss-minify-gradients": { @@ -6740,8 +5828,8 @@ "integrity": "sha1-Xb2hE3NwP4PPtKPqOIHY11/15uE=", "dev": true, "requires": { - "postcss": "^5.0.12", - "postcss-value-parser": "^3.3.0" + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" } }, "postcss-minify-params": { @@ -6750,10 +5838,10 @@ "integrity": "sha1-rSzgcTc7lDs9kwo/pZo1jCjW8fM=", "dev": true, "requires": { - "alphanum-sort": "^1.0.1", - "postcss": "^5.0.2", - "postcss-value-parser": "^3.0.2", - "uniqs": "^2.0.0" + "alphanum-sort": "1.0.2", + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0", + "uniqs": "2.0.0" } }, "postcss-minify-selectors": { @@ -6762,10 +5850,10 @@ "integrity": "sha1-ssapjAByz5G5MtGkllCBFDEXNb8=", "dev": true, "requires": { - "alphanum-sort": "^1.0.2", - "has": "^1.0.1", - "postcss": "^5.0.14", - "postcss-selector-parser": "^2.0.0" + "alphanum-sort": "1.0.2", + "has": "1.0.1", + "postcss": "5.2.18", + "postcss-selector-parser": "2.2.3" } }, "postcss-normalize-charset": { @@ -6774,7 +5862,7 @@ "integrity": "sha1-757nEhLX/nWceO0WL2HtYrXLk/E=", "dev": true, "requires": { - "postcss": "^5.0.5" + "postcss": "5.2.18" } }, "postcss-normalize-url": { @@ -6783,10 +5871,10 @@ "integrity": "sha1-EI90s/L82viRov+j6kWSJ5/HgiI=", "dev": true, "requires": { - "is-absolute-url": "^2.0.0", - "normalize-url": "^1.4.0", - "postcss": "^5.0.14", - "postcss-value-parser": "^3.2.3" + "is-absolute-url": "2.1.0", + "normalize-url": "1.9.1", + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" } }, "postcss-ordered-values": { @@ -6795,8 +5883,8 @@ "integrity": "sha1-7sbCpntsQSqNsgQud/6NpD+VwR0=", "dev": true, "requires": { - "postcss": "^5.0.4", - "postcss-value-parser": "^3.0.1" + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" } }, "postcss-reduce-idents": { @@ -6805,8 +5893,8 @@ "integrity": "sha1-wsbSDMlYKE9qv75j92Cb9AkFmtM=", "dev": true, "requires": { - "postcss": "^5.0.4", - "postcss-value-parser": "^3.0.2" + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" } }, "postcss-reduce-initial": { @@ -6815,7 +5903,7 @@ "integrity": "sha1-aPgGlfBF0IJjqHmtJA343WT2ROo=", "dev": true, "requires": { - "postcss": "^5.0.4" + "postcss": "5.2.18" } }, "postcss-reduce-transforms": { @@ -6824,9 +5912,9 @@ "integrity": "sha1-/3b02CEkN7McKYpC0uFEQCV3GuE=", "dev": true, "requires": { - "has": "^1.0.1", - "postcss": "^5.0.8", - "postcss-value-parser": "^3.0.1" + "has": "1.0.1", + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0" } }, "postcss-selector-parser": { @@ -6835,9 +5923,9 @@ "integrity": "sha1-+UN3iGBsPJrO4W/+jYsWKX8nu5A=", "dev": true, "requires": { - "flatten": "^1.0.2", - "indexes-of": "^1.0.1", - "uniq": "^1.0.1" + "flatten": "1.0.2", + "indexes-of": "1.0.1", + "uniq": "1.0.1" } }, "postcss-svgo": { @@ -6846,10 +5934,10 @@ "integrity": "sha1-tt8YqmE7Zm4TPwittSGcJoSsEI0=", "dev": true, "requires": { - "is-svg": "^2.0.0", - "postcss": "^5.0.14", - "postcss-value-parser": "^3.2.3", - "svgo": "^0.7.0" + "is-svg": "2.1.0", + "postcss": "5.2.18", + "postcss-value-parser": "3.3.0", + "svgo": "0.7.2" } }, "postcss-unique-selectors": { @@ -6858,9 +5946,9 @@ "integrity": "sha1-mB1X0p3csz57Hf4f1DuGSfkzyh0=", "dev": true, "requires": { - "alphanum-sort": "^1.0.1", - "postcss": "^5.0.4", - "uniqs": "^2.0.0" + "alphanum-sort": "1.0.2", + "postcss": "5.2.18", + "uniqs": "2.0.0" } }, "postcss-value-parser": { @@ -6875,9 +5963,9 @@ "integrity": "sha1-0hCd3AVbka9n/EyzsCWUZjnSryI=", "dev": true, "requires": { - "has": "^1.0.1", - "postcss": "^5.0.4", - "uniqs": "^2.0.0" + "has": "1.0.1", + "postcss": "5.2.18", + "uniqs": "2.0.0" } }, "prelude-ls": { @@ -6923,7 +6011,7 @@ "dev": true, "optional": true, "requires": { - "asap": "~2.0.3" + "asap": "2.0.6" } }, "prr": { @@ -6969,8 +6057,8 @@ "integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=", "dev": true, "requires": { - "object-assign": "^4.1.0", - "strict-uri-encode": "^1.0.0" + "object-assign": "4.1.1", + "strict-uri-encode": "1.1.0" } }, "random-bytes": { @@ -6985,8 +6073,8 @@ "integrity": "sha1-x6vpzIuHwLqodrGf3oP9RkeX44w=", "dev": true, "requires": { - "is-number": "^3.0.0", - "kind-of": "^4.0.0" + "is-number": "3.0.0", + "kind-of": "4.0.0" }, "dependencies": { "kind-of": { @@ -6995,7 +6083,7 @@ "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.6" } } } @@ -7037,9 +6125,9 @@ "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", "dev": true, "requires": { - "load-json-file": "^1.0.0", - "normalize-package-data": "^2.3.2", - "path-type": "^1.0.0" + "load-json-file": "1.1.0", + "normalize-package-data": "2.4.0", + "path-type": "1.1.0" } }, "read-pkg-up": { @@ -7048,8 +6136,8 @@ "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", "dev": true, "requires": { - "find-up": "^1.0.0", - "read-pkg": "^1.0.0" + "find-up": "1.1.2", + "read-pkg": "1.1.0" } }, "readable-stream": { @@ -7058,10 +6146,10 @@ "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", + "core-util-is": "1.0.2", + "inherits": "2.0.3", "isarray": "0.0.1", - "string_decoder": "~0.10.x" + "string_decoder": "0.10.31" } }, "readdirp": { @@ -7070,10 +6158,10 @@ "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=", "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "minimatch": "^3.0.2", - "readable-stream": "^2.0.2", - "set-immediate-shim": "^1.0.1" + "graceful-fs": "4.1.11", + "minimatch": "3.0.4", + "readable-stream": "2.3.5", + "set-immediate-shim": "1.0.1" }, "dependencies": { "graceful-fs": { @@ -7094,13 +6182,13 @@ "integrity": "sha1-tPhQA6k4y7bsvOKhJPsQEr0ag40=", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.0.3", - "util-deprecate": "~1.0.1" + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" } }, "string_decoder": { @@ -7109,7 +6197,7 @@ "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", "dev": true, "requires": { - "safe-buffer": "~5.1.0" + "safe-buffer": "5.1.1" } } } @@ -7120,7 +6208,7 @@ "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", "dev": true, "requires": { - "resolve": "^1.1.6" + "resolve": "1.6.0" } }, "redent": { @@ -7129,8 +6217,8 @@ "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", "dev": true, "requires": { - "indent-string": "^2.1.0", - "strip-indent": "^1.0.1" + "indent-string": "2.1.0", + "strip-indent": "1.0.1" } }, "reduce-css-calc": { @@ -7139,9 +6227,9 @@ "integrity": "sha1-dHyRTgSWFKTJz7umKYca0dKSdxY=", "dev": true, "requires": { - "balanced-match": "^0.4.2", - "math-expression-evaluator": "^1.2.14", - "reduce-function-call": "^1.0.1" + "balanced-match": "0.4.2", + "math-expression-evaluator": "1.2.17", + "reduce-function-call": "1.0.2" }, "dependencies": { "balanced-match": { @@ -7158,7 +6246,7 @@ "integrity": "sha1-WiAL+S4ON3UXUv5FsKszD9S2vpk=", "dev": true, "requires": { - "balanced-match": "^0.4.2" + "balanced-match": "0.4.2" }, "dependencies": { "balanced-match": { @@ -7175,7 +6263,7 @@ "integrity": "sha1-db3FiioUls7EihKDW8VMjVYjNt0=", "dev": true, "requires": { - "is-equal-shallow": "^0.1.3" + "is-equal-shallow": "0.1.3" } }, "regex-not": { @@ -7184,8 +6272,8 @@ "integrity": "sha1-H07OJ+ALC2XgJHpoEOaoXYOldSw=", "dev": true, "requires": { - "extend-shallow": "^3.0.2", - "safe-regex": "^1.1.0" + "extend-shallow": "3.0.2", + "safe-regex": "1.1.0" } }, "remove-trailing-separator": { @@ -7212,7 +6300,7 @@ "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", "dev": true, "requires": { - "is-finite": "^1.0.0" + "is-finite": "1.0.2" } }, "replace-ext": { @@ -7227,28 +6315,28 @@ "integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=", "dev": true, "requires": { - "aws-sign2": "~0.6.0", - "aws4": "^1.2.1", - "caseless": "~0.12.0", - "combined-stream": "~1.0.5", - "extend": "~3.0.0", - "forever-agent": "~0.6.1", - "form-data": "~2.1.1", - "har-validator": "~4.2.1", - "hawk": "~3.1.3", - "http-signature": "~1.1.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.7", - "oauth-sign": "~0.8.1", - "performance-now": "^0.2.0", - "qs": "~6.4.0", - "safe-buffer": "^5.0.1", - "stringstream": "~0.0.4", - "tough-cookie": "~2.3.0", - "tunnel-agent": "^0.6.0", - "uuid": "^3.0.0" + "aws-sign2": "0.6.0", + "aws4": "1.6.0", + "caseless": "0.12.0", + "combined-stream": "1.0.6", + "extend": "3.0.1", + "forever-agent": "0.6.1", + "form-data": "2.1.4", + "har-validator": "4.2.1", + "hawk": "3.1.3", + "http-signature": "1.1.1", + "is-typedarray": "1.0.0", + "isstream": "0.1.2", + "json-stringify-safe": "5.0.1", + "mime-types": "2.1.18", + "oauth-sign": "0.8.2", + "performance-now": "0.2.0", + "qs": "6.4.0", + "safe-buffer": "5.1.1", + "stringstream": "0.0.5", + "tough-cookie": "2.3.4", + "tunnel-agent": "0.6.0", + "uuid": "3.2.1" }, "dependencies": { "qs": { @@ -7265,7 +6353,7 @@ "integrity": "sha1-XTa7V5YcZzqlt4jbyBQf3yO0Tgg=", "dev": true, "requires": { - "throttleit": "^1.0.0" + "throttleit": "1.0.0" } }, "require-from-string": { @@ -7286,7 +6374,7 @@ "integrity": "sha1-D70hJ4sntABEgcOVNJ56umCp/1w=", "dev": true, "requires": { - "path-parse": "^1.0.5" + "path-parse": "1.0.5" } }, "resolve-dir": { @@ -7295,8 +6383,8 @@ "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", "dev": true, "requires": { - "expand-tilde": "^2.0.0", - "global-modules": "^1.0.0" + "expand-tilde": "2.0.2", + "global-modules": "1.0.0" } }, "resolve-url": { @@ -7311,8 +6399,8 @@ "integrity": "sha1-/6cbq5UtYvfB1Jt0NDVfvGjf/Fo=", "dev": true, "requires": { - "depd": "~1.1.0", - "on-headers": "~1.0.1" + "depd": "1.1.2", + "on-headers": "1.0.1" }, "dependencies": { "depd": { @@ -7335,7 +6423,7 @@ "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", "dev": true, "requires": { - "align-text": "^0.1.1" + "align-text": "0.1.4" } }, "rimraf": { @@ -7344,7 +6432,7 @@ "integrity": "sha1-LtgVDSShbqhlHm1u8PR8QVjOejY=", "dev": true, "requires": { - "glob": "^7.0.5" + "glob": "7.1.2" } }, "rndm": { @@ -7359,9 +6447,9 @@ "integrity": "sha1-HOZD2jb9jH6n4akynaM/wriJhJU=", "dev": true, "requires": { - "chalk": "^1.1.3", - "fancy-log": "^1.3.2", - "plugin-error": "^0.1.2" + "chalk": "1.1.3", + "fancy-log": "1.3.2", + "plugin-error": "0.1.2" } }, "safe-buffer": { @@ -7376,7 +6464,7 @@ "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", "dev": true, "requires": { - "ret": "~0.1.10" + "ret": "0.1.15" } }, "sax": { @@ -7397,18 +6485,18 @@ "integrity": "sha1-dl52B8gFVFK7pvCwUllTUJhgNt4=", "dev": true, "requires": { - "debug": "~2.2.0", - "depd": "~1.1.0", - "destroy": "~1.0.4", - "escape-html": "~1.0.3", - "etag": "~1.7.0", + "debug": "2.2.0", + "depd": "1.1.2", + "destroy": "1.0.4", + "escape-html": "1.0.3", + "etag": "1.7.0", "fresh": "0.3.0", - "http-errors": "~1.3.1", + "http-errors": "1.3.1", "mime": "1.3.4", "ms": "0.7.1", - "on-finished": "~2.3.0", - "range-parser": "~1.0.3", - "statuses": "~1.2.1" + "on-finished": "2.3.0", + "range-parser": "1.0.3", + "statuses": "1.2.1" }, "dependencies": { "debug": { @@ -7452,10 +6540,10 @@ "integrity": "sha1-3UGeJo3gEqtysxnTN/IQUBP5OB8=", "dev": true, "requires": { - "etag": "~1.7.0", + "etag": "1.7.0", "fresh": "0.3.0", "ms": "0.7.2", - "parseurl": "~1.3.1" + "parseurl": "1.3.2" }, "dependencies": { "ms": { @@ -7472,13 +6560,13 @@ "integrity": "sha1-egV/xu4o3GP2RWbl+lexEahq7NI=", "dev": true, "requires": { - "accepts": "~1.2.13", + "accepts": "1.2.13", "batch": "0.5.3", - "debug": "~2.2.0", - "escape-html": "~1.0.3", - "http-errors": "~1.3.1", - "mime-types": "~2.1.9", - "parseurl": "~1.3.1" + "debug": "2.2.0", + "escape-html": "1.0.3", + "http-errors": "1.3.1", + "mime-types": "2.1.18", + "parseurl": "1.3.2" }, "dependencies": { "debug": { @@ -7504,8 +6592,8 @@ "integrity": "sha1-zlpuzTEB/tXsCYJ9rCKpwpv7BTU=", "dev": true, "requires": { - "escape-html": "~1.0.3", - "parseurl": "~1.3.1", + "escape-html": "1.0.3", + "parseurl": "1.3.2", "send": "0.13.2" } }, @@ -7521,10 +6609,10 @@ "integrity": "sha1-ca5KiPD+77v1LR6mBPP7MV67YnQ=", "dev": true, "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.3", - "split-string": "^3.0.1" + "extend-shallow": "2.0.1", + "is-extendable": "0.1.1", + "is-plain-object": "2.0.4", + "split-string": "3.1.0" }, "dependencies": { "extend-shallow": { @@ -7533,7 +6621,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "^0.1.0" + "is-extendable": "0.1.1" } } } @@ -7568,14 +6656,14 @@ "integrity": "sha1-ZJIufFZbDhQgS6GqfWlkJ40lGC0=", "dev": true, "requires": { - "base": "^0.11.1", - "debug": "^2.2.0", - "define-property": "^0.2.5", - "extend-shallow": "^2.0.1", - "map-cache": "^0.2.2", - "source-map": "^0.5.6", - "source-map-resolve": "^0.5.0", - "use": "^3.1.0" + "base": "0.11.2", + "debug": "2.6.9", + "define-property": "0.2.5", + "extend-shallow": "2.0.1", + "map-cache": "0.2.2", + "source-map": "0.5.7", + "source-map-resolve": "0.5.1", + "use": "3.1.0" }, "dependencies": { "define-property": { @@ -7584,7 +6672,7 @@ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "^0.1.0" + "is-descriptor": "0.1.6" } }, "extend-shallow": { @@ -7593,7 +6681,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "^0.1.0" + "is-extendable": "0.1.1" } }, "is-accessor-descriptor": { @@ -7602,7 +6690,7 @@ "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", "dev": true, "requires": { - "kind-of": "^3.0.2" + "kind-of": "3.2.2" }, "dependencies": { "kind-of": { @@ -7611,7 +6699,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.6" } } } @@ -7622,7 +6710,7 @@ "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", "dev": true, "requires": { - "kind-of": "^3.0.2" + "kind-of": "3.2.2" }, "dependencies": { "kind-of": { @@ -7631,7 +6719,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.6" } } } @@ -7642,9 +6730,9 @@ "integrity": "sha1-Nm2CQN3kh8pRgjsaufB6EKeCUco=", "dev": true, "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" } }, "kind-of": { @@ -7661,9 +6749,9 @@ "integrity": "sha1-bBdfhv8UvbByRWPo88GwIaKGhTs=", "dev": true, "requires": { - "define-property": "^1.0.0", - "isobject": "^3.0.0", - "snapdragon-util": "^3.0.1" + "define-property": "1.0.0", + "isobject": "3.0.1", + "snapdragon-util": "3.0.1" }, "dependencies": { "define-property": { @@ -7672,7 +6760,7 @@ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", "dev": true, "requires": { - "is-descriptor": "^1.0.0" + "is-descriptor": "1.0.2" } } } @@ -7683,7 +6771,7 @@ "integrity": "sha1-+VZHlIbyrNeXAGk/b3uAXkWrVuI=", "dev": true, "requires": { - "kind-of": "^3.2.0" + "kind-of": "3.2.2" }, "dependencies": { "kind-of": { @@ -7692,7 +6780,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.6" } } } @@ -7703,7 +6791,7 @@ "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", "dev": true, "requires": { - "hoek": "2.x.x" + "hoek": "2.16.3" } }, "socket.io": { @@ -7848,7 +6936,7 @@ "integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=", "dev": true, "requires": { - "is-plain-obj": "^1.0.0" + "is-plain-obj": "1.1.0" } }, "source-map": { @@ -7863,11 +6951,11 @@ "integrity": "sha1-etD1k/IoFZjoVN+A8ZquS5LXoRo=", "dev": true, "requires": { - "atob": "^2.0.0", - "decode-uri-component": "^0.2.0", - "resolve-url": "^0.2.1", - "source-map-url": "^0.4.0", - "urix": "^0.1.0" + "atob": "2.1.0", + "decode-uri-component": "0.2.0", + "resolve-url": "0.2.1", + "source-map-url": "0.4.0", + "urix": "0.1.0" } }, "source-map-url": { @@ -7888,8 +6976,8 @@ "integrity": "sha1-BaW01xU6GVvJLDxCW2nzsqlSTII=", "dev": true, "requires": { - "spdx-expression-parse": "^3.0.0", - "spdx-license-ids": "^3.0.0" + "spdx-expression-parse": "3.0.0", + "spdx-license-ids": "3.0.0" } }, "spdx-exceptions": { @@ -7904,8 +6992,8 @@ "integrity": "sha1-meEZt6XaAOBUkcn6M4t5BII7QdA=", "dev": true, "requires": { - "spdx-exceptions": "^2.1.0", - "spdx-license-ids": "^3.0.0" + "spdx-exceptions": "2.1.0", + "spdx-license-ids": "3.0.0" } }, "spdx-license-ids": { @@ -7920,7 +7008,7 @@ "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", "dev": true, "requires": { - "through": "2" + "through": "2.3.8" } }, "split-string": { @@ -7929,7 +7017,7 @@ "integrity": "sha1-fLCd2jqGWFcFxks5pkZgOGguj+I=", "dev": true, "requires": { - "extend-shallow": "^3.0.0" + "extend-shallow": "3.0.2" } }, "sprintf-js": { @@ -7944,14 +7032,14 @@ "integrity": "sha1-Ew9Zde3a2WPx1W+SuaxsUfqfg+s=", "dev": true, "requires": { - "asn1": "~0.2.3", - "assert-plus": "^1.0.0", - "bcrypt-pbkdf": "^1.0.0", - "dashdash": "^1.12.0", - "ecc-jsbn": "~0.1.1", - "getpass": "^0.1.1", - "jsbn": "~0.1.0", - "tweetnacl": "~0.14.0" + "asn1": "0.2.3", + "assert-plus": "1.0.0", + "bcrypt-pbkdf": "1.0.1", + "dashdash": "1.14.1", + "ecc-jsbn": "0.1.1", + "getpass": "0.1.7", + "jsbn": "0.1.1", + "tweetnacl": "0.14.5" }, "dependencies": { "assert-plus": { @@ -7968,8 +7056,8 @@ "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", "dev": true, "requires": { - "define-property": "^0.2.5", - "object-copy": "^0.1.0" + "define-property": "0.2.5", + "object-copy": "0.1.0" }, "dependencies": { "define-property": { @@ -7978,7 +7066,7 @@ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "^0.1.0" + "is-descriptor": "0.1.6" } }, "is-accessor-descriptor": { @@ -7987,7 +7075,7 @@ "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", "dev": true, "requires": { - "kind-of": "^3.0.2" + "kind-of": "3.2.2" }, "dependencies": { "kind-of": { @@ -7996,7 +7084,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.6" } } } @@ -8007,7 +7095,7 @@ "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", "dev": true, "requires": { - "kind-of": "^3.0.2" + "kind-of": "3.2.2" }, "dependencies": { "kind-of": { @@ -8016,7 +7104,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.6" } } } @@ -8027,9 +7115,9 @@ "integrity": "sha1-Nm2CQN3kh8pRgjsaufB6EKeCUco=", "dev": true, "requires": { - "is-accessor-descriptor": "^0.1.6", - "is-data-descriptor": "^0.1.4", - "kind-of": "^5.0.0" + "is-accessor-descriptor": "0.1.6", + "is-data-descriptor": "0.1.4", + "kind-of": "5.1.0" } }, "kind-of": { @@ -8052,7 +7140,7 @@ "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", "dev": true, "requires": { - "duplexer": "~0.1.1" + "duplexer": "0.1.1" } }, "stream-consume": { @@ -8067,7 +7155,7 @@ "integrity": "sha1-3tJmVWMZyLDiIoErnPOyb6fZR94=", "dev": true, "requires": { - "readable-stream": "~1.1.8" + "readable-stream": "1.1.14" } }, "strict-uri-encode": { @@ -8094,7 +7182,7 @@ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "requires": { - "ansi-regex": "^2.0.0" + "ansi-regex": "2.1.1" } }, "strip-bom": { @@ -8103,8 +7191,8 @@ "integrity": "sha1-hbiGLzhEtabV7IRnqTWYFzo295Q=", "dev": true, "requires": { - "first-chunk-stream": "^1.0.0", - "is-utf8": "^0.2.0" + "first-chunk-stream": "1.0.0", + "is-utf8": "0.2.1" } }, "strip-bom-stream": { @@ -8113,8 +7201,8 @@ "integrity": "sha1-+H217yYT9paKpUWr/h7HKLaoKco=", "dev": true, "requires": { - "first-chunk-stream": "^2.0.0", - "strip-bom": "^2.0.0" + "first-chunk-stream": "2.0.0", + "strip-bom": "2.0.0" }, "dependencies": { "first-chunk-stream": { @@ -8123,7 +7211,7 @@ "integrity": "sha1-G97NuOCDwGZLkZRVgVd6Q6nzHXA=", "dev": true, "requires": { - "readable-stream": "^2.0.2" + "readable-stream": "2.3.5" } }, "isarray": { @@ -8138,13 +7226,13 @@ "integrity": "sha1-tPhQA6k4y7bsvOKhJPsQEr0ag40=", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.0.3", - "util-deprecate": "~1.0.1" + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" } }, "string_decoder": { @@ -8153,7 +7241,7 @@ "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", "dev": true, "requires": { - "safe-buffer": "~5.1.0" + "safe-buffer": "5.1.1" } }, "strip-bom": { @@ -8162,7 +7250,7 @@ "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", "dev": true, "requires": { - "is-utf8": "^0.2.0" + "is-utf8": "0.2.1" } } } @@ -8173,7 +7261,7 @@ "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", "dev": true, "requires": { - "get-stdin": "^4.0.1" + "get-stdin": "4.0.1" } }, "supports-color": { @@ -8182,7 +7270,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "^1.0.0" + "has-flag": "1.0.0" } }, "svgo": { @@ -8191,13 +7279,13 @@ "integrity": "sha1-n1dyQTlSE1xv779Ar+ak+qiLS7U=", "dev": true, "requires": { - "coa": "~1.0.1", - "colors": "~1.1.2", - "csso": "~2.3.1", - "js-yaml": "~3.7.0", - "mkdirp": "~0.5.1", - "sax": "~1.2.1", - "whet.extend": "~0.9.9" + "coa": "1.0.4", + "colors": "1.1.2", + "csso": "2.3.2", + "js-yaml": "3.7.0", + "mkdirp": "0.5.1", + "sax": "1.2.4", + "whet.extend": "0.9.9" }, "dependencies": { "colors": { @@ -8226,8 +7314,8 @@ "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", "dev": true, "requires": { - "readable-stream": "^2.1.5", - "xtend": "~4.0.1" + "readable-stream": "2.3.5", + "xtend": "4.0.1" }, "dependencies": { "isarray": { @@ -8242,13 +7330,13 @@ "integrity": "sha1-tPhQA6k4y7bsvOKhJPsQEr0ag40=", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.0.3", - "util-deprecate": "~1.0.1" + "core-util-is": "1.0.2", + "inherits": "2.0.3", + "isarray": "1.0.0", + "process-nextick-args": "2.0.0", + "safe-buffer": "5.1.1", + "string_decoder": "1.0.3", + "util-deprecate": "1.0.2" } }, "string_decoder": { @@ -8257,7 +7345,7 @@ "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", "dev": true, "requires": { - "safe-buffer": "~5.1.0" + "safe-buffer": "5.1.1" } } } @@ -8268,7 +7356,7 @@ "integrity": "sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo=", "dev": true, "requires": { - "os-homedir": "^1.0.0" + "os-homedir": "1.0.2" } }, "time-stamp": { @@ -8283,12 +7371,12 @@ "integrity": "sha1-s/26gC5dVqM8L28QeUsy5Hescp0=", "dev": true, "requires": { - "body-parser": "~1.14.0", - "debug": "~2.2.0", - "faye-websocket": "~0.10.0", - "livereload-js": "^2.2.0", - "parseurl": "~1.3.0", - "qs": "~5.1.0" + "body-parser": "1.14.2", + "debug": "2.2.0", + "faye-websocket": "0.10.0", + "livereload-js": "2.3.0", + "parseurl": "1.3.2", + "qs": "5.1.0" }, "dependencies": { "body-parser": { @@ -8298,15 +7386,15 @@ "dev": true, "requires": { "bytes": "2.2.0", - "content-type": "~1.0.1", - "debug": "~2.2.0", - "depd": "~1.1.0", - "http-errors": "~1.3.1", + "content-type": "1.0.4", + "debug": "2.2.0", + "depd": "1.1.2", + "http-errors": "1.3.1", "iconv-lite": "0.4.13", - "on-finished": "~2.3.0", + "on-finished": "2.3.0", "qs": "5.2.0", - "raw-body": "~2.1.5", - "type-is": "~1.6.10" + "raw-body": "2.1.7", + "type-is": "1.6.16" }, "dependencies": { "qs": { @@ -8364,7 +7452,7 @@ "integrity": "sha1-jzirlDjhcxXl29izZX6L+yd65Kc=", "dev": true, "requires": { - "os-tmpdir": "~1.0.1" + "os-tmpdir": "1.0.2" } }, "to-array": { @@ -8379,7 +7467,7 @@ "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", "dev": true, "requires": { - "kind-of": "^3.0.2" + "kind-of": "3.2.2" }, "dependencies": { "kind-of": { @@ -8388,7 +7476,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "^1.1.5" + "is-buffer": "1.1.6" } } } @@ -8399,10 +7487,10 @@ "integrity": "sha1-E8/dmzNlUvMLUfM6iuG0Knp1mc4=", "dev": true, "requires": { - "define-property": "^2.0.2", - "extend-shallow": "^3.0.2", - "regex-not": "^1.0.2", - "safe-regex": "^1.1.0" + "define-property": "2.0.2", + "extend-shallow": "3.0.2", + "regex-not": "1.0.2", + "safe-regex": "1.1.0" } }, "to-regex-range": { @@ -8411,8 +7499,8 @@ "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", "dev": true, "requires": { - "is-number": "^3.0.0", - "repeat-string": "^1.6.1" + "is-number": "3.0.0", + "repeat-string": "1.6.1" } }, "tough-cookie": { @@ -8421,7 +7509,7 @@ "integrity": "sha1-7GDO44rGdQY//JelwYlwV47oNlU=", "dev": true, "requires": { - "punycode": "^1.4.1" + "punycode": "1.4.1" } }, "trim-newlines": { @@ -8448,7 +7536,7 @@ "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", "dev": true, "requires": { - "safe-buffer": "^5.0.1" + "safe-buffer": "5.1.1" } }, "tweetnacl": { @@ -8464,7 +7552,7 @@ "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", "dev": true, "requires": { - "prelude-ls": "~1.1.2" + "prelude-ls": "1.1.2" } }, "type-is": { @@ -8474,7 +7562,7 @@ "dev": true, "requires": { "media-typer": "0.3.0", - "mime-types": "~2.1.18" + "mime-types": "2.1.18" } }, "typedarray": { @@ -8489,9 +7577,9 @@ "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", "dev": true, "requires": { - "source-map": "~0.5.1", - "uglify-to-browserify": "~1.0.0", - "yargs": "~3.10.0" + "source-map": "0.5.7", + "uglify-to-browserify": "1.0.2", + "yargs": "3.10.0" } }, "uglify-to-browserify": { @@ -8507,7 +7595,7 @@ "integrity": "sha1-Otbzg2jG1MjHXsF2I/t5qh0HHYE=", "dev": true, "requires": { - "random-bytes": "~1.0.0" + "random-bytes": "1.0.0" } }, "ultron": { @@ -8528,10 +7616,10 @@ "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", "dev": true, "requires": { - "arr-union": "^3.1.0", - "get-value": "^2.0.6", - "is-extendable": "^0.1.1", - "set-value": "^0.4.3" + "arr-union": "3.1.0", + "get-value": "2.0.6", + "is-extendable": "0.1.1", + "set-value": "0.4.3" }, "dependencies": { "extend-shallow": { @@ -8540,7 +7628,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "^0.1.0" + "is-extendable": "0.1.1" } }, "set-value": { @@ -8549,10 +7637,10 @@ "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", "dev": true, "requires": { - "extend-shallow": "^2.0.1", - "is-extendable": "^0.1.1", - "is-plain-object": "^2.0.1", - "to-object-path": "^0.3.0" + "extend-shallow": "2.0.1", + "is-extendable": "0.1.1", + "is-plain-object": "2.0.4", + "to-object-path": "0.3.0" } } } @@ -8569,7 +7657,7 @@ "integrity": "sha1-iSIN32t1GuUrX3JISGNShZa7hME=", "dev": true, "requires": { - "macaddress": "^0.2.8" + "macaddress": "0.2.8" } }, "uniqs": { @@ -8596,8 +7684,8 @@ "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", "dev": true, "requires": { - "has-value": "^0.3.1", - "isobject": "^3.0.0" + "has-value": "0.3.1", + "isobject": "3.0.1" }, "dependencies": { "has-value": { @@ -8606,9 +7694,9 @@ "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", "dev": true, "requires": { - "get-value": "^2.0.3", - "has-values": "^0.1.4", - "isobject": "^2.0.0" + "get-value": "2.0.6", + "has-values": "0.1.4", + "isobject": "2.1.0" }, "dependencies": { "isobject": { @@ -8648,7 +7736,7 @@ "integrity": "sha1-FHFr8D/f79AwQK71jYtLhfOnxUQ=", "dev": true, "requires": { - "kind-of": "^6.0.2" + "kind-of": "6.0.2" } }, "user-home": { @@ -8663,8 +7751,8 @@ "integrity": "sha1-IX+UOtVAyyEoZYqyP8lg9qiMmXI=", "dev": true, "requires": { - "lru-cache": "4.1.x", - "tmp": "0.0.x" + "lru-cache": "4.1.2", + "tmp": "0.0.31" }, "dependencies": { "lru-cache": { @@ -8673,8 +7761,8 @@ "integrity": "sha1-RSNLLm4vKzPaElYkxGZJKaAiTD8=", "dev": true, "requires": { - "pseudomap": "^1.0.2", - "yallist": "^2.1.2" + "pseudomap": "1.0.2", + "yallist": "2.1.2" } } } @@ -8703,7 +7791,7 @@ "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", "dev": true, "requires": { - "user-home": "^1.1.1" + "user-home": "1.1.1" } }, "validate-npm-package-license": { @@ -8712,8 +7800,8 @@ "integrity": "sha1-gWQ7y+8b3+zUYjeT3EZIlIupgzg=", "dev": true, "requires": { - "spdx-correct": "^3.0.0", - "spdx-expression-parse": "^3.0.0" + "spdx-correct": "3.0.0", + "spdx-expression-parse": "3.0.0" } }, "vary": { @@ -8734,9 +7822,9 @@ "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", "dev": true, "requires": { - "assert-plus": "^1.0.0", + "assert-plus": "1.0.0", "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" + "extsprintf": "1.3.0" }, "dependencies": { "assert-plus": { @@ -8759,8 +7847,8 @@ "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", "dev": true, "requires": { - "clone": "^1.0.0", - "clone-stats": "^0.0.1", + "clone": "1.0.4", + "clone-stats": "0.0.1", "replace-ext": "0.0.1" } }, @@ -8779,12 +7867,12 @@ "integrity": "sha1-p+v1/779obfRjRQPyweyI++2dRo=", "dev": true, "requires": { - "graceful-fs": "^4.1.2", - "pify": "^2.3.0", - "pinkie-promise": "^2.0.0", - "strip-bom": "^2.0.0", - "strip-bom-stream": "^2.0.0", - "vinyl": "^1.1.0" + "graceful-fs": "4.1.11", + "pify": "2.3.0", + "pinkie-promise": "2.0.1", + "strip-bom": "2.0.0", + "strip-bom-stream": "2.0.0", + "vinyl": "1.2.0" }, "dependencies": { "graceful-fs": { @@ -8799,7 +7887,7 @@ "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", "dev": true, "requires": { - "is-utf8": "^0.2.0" + "is-utf8": "0.2.1" } }, "vinyl": { @@ -8808,8 +7896,8 @@ "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", "dev": true, "requires": { - "clone": "^1.0.0", - "clone-stats": "^0.0.1", + "clone": "1.0.4", + "clone-stats": "0.0.1", "replace-ext": "0.0.1" } } @@ -8821,14 +7909,14 @@ "integrity": "sha1-mmhRzhysHBzqX+hsCTHWIMLPqeY=", "dev": true, "requires": { - "defaults": "^1.0.0", - "glob-stream": "^3.1.5", - "glob-watcher": "^0.0.6", - "graceful-fs": "^3.0.0", - "mkdirp": "^0.5.0", - "strip-bom": "^1.0.0", - "through2": "^0.6.1", - "vinyl": "^0.4.0" + "defaults": "1.0.3", + "glob-stream": "3.1.18", + "glob-watcher": "0.0.6", + "graceful-fs": "3.0.11", + "mkdirp": "0.5.1", + "strip-bom": "1.0.0", + "through2": "0.6.5", + "vinyl": "0.4.6" }, "dependencies": { "clone": { @@ -8843,10 +7931,10 @@ "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", "dev": true, "requires": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", + "core-util-is": "1.0.2", + "inherits": "2.0.3", "isarray": "0.0.1", - "string_decoder": "~0.10.x" + "string_decoder": "0.10.31" } }, "through2": { @@ -8855,8 +7943,8 @@ "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", "dev": true, "requires": { - "readable-stream": ">=1.0.33-1 <1.1.0-0", - "xtend": ">=4.0.0 <4.1.0-0" + "readable-stream": "1.0.34", + "xtend": "4.0.1" } }, "vinyl": { @@ -8865,8 +7953,8 @@ "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", "dev": true, "requires": { - "clone": "^0.2.0", - "clone-stats": "^0.0.1" + "clone": "0.2.0", + "clone-stats": "0.0.1" } } } @@ -8877,7 +7965,7 @@ "integrity": "sha1-q2VJ1h0XLCsbh75cUI0jnI74dwU=", "dev": true, "requires": { - "source-map": "^0.5.1" + "source-map": "0.5.7" } }, "void-elements": { @@ -8892,8 +7980,8 @@ "integrity": "sha1-DK+dLXVdk67gSdS90NP+LMoqJOs=", "dev": true, "requires": { - "http-parser-js": ">=0.4.0", - "websocket-extensions": ">=0.1.1" + "http-parser-js": "0.4.11", + "websocket-extensions": "0.1.3" } }, "websocket-extensions": { @@ -8920,7 +8008,7 @@ "integrity": "sha1-/wS9/AEO5UfXgL7DjhrBwnd9JTo=", "dev": true, "requires": { - "isexe": "^2.0.0" + "isexe": "2.0.0" } }, "window-size": { @@ -8947,8 +8035,8 @@ "integrity": "sha1-iiRPoFJAHgjJiGz0SoUYnh/UBn8=", "dev": true, "requires": { - "options": ">=0.0.5", - "ultron": "1.0.x" + "options": "0.0.6", + "ultron": "1.0.2" } }, "wtf-8": { @@ -8981,9 +8069,9 @@ "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", "dev": true, "requires": { - "camelcase": "^1.0.2", - "cliui": "^2.1.0", - "decamelize": "^1.0.0", + "camelcase": "1.2.1", + "cliui": "2.1.0", + "decamelize": "1.2.0", "window-size": "0.1.0" } }, @@ -8993,7 +8081,7 @@ "integrity": "sha1-lSj0QtqxsihOWLQ3m7GU4i4MQAU=", "dev": true, "requires": { - "fd-slicer": "~1.0.1" + "fd-slicer": "1.0.1" } }, "yeast": { diff --git a/src/Umbraco.Web.UI.Client/src/app.js b/src/Umbraco.Web.UI.Client/src/app.js index 4a44959b15..97096c9733 100644 --- a/src/Umbraco.Web.UI.Client/src/app.js +++ b/src/Umbraco.Web.UI.Client/src/app.js @@ -6,9 +6,11 @@ var app = angular.module('umbraco', [ 'umbraco.packages', 'umbraco.views', + 'ngRoute', + 'ngAnimate', 'ngCookies', 'ngSanitize', - 'ngMobile', + 'ngTouch', 'tmh.dynamicLocale', 'ngFileUpload', 'LocalStorageModule' diff --git a/src/Umbraco.Web/UI/JavaScript/JsInitialize.js b/src/Umbraco.Web/UI/JavaScript/JsInitialize.js index 877bba06f4..d03f825dc5 100644 --- a/src/Umbraco.Web/UI/JavaScript/JsInitialize.js +++ b/src/Umbraco.Web/UI/JavaScript/JsInitialize.js @@ -1,6 +1,6 @@ [ 'lib/jquery/jquery.min.js', - 'lib/angular/1.1.5/angular.min.js', + 'lib/angular/angular.js', 'lib/underscore/underscore-min.js', 'lib/moment/moment.min.js', @@ -10,9 +10,11 @@ 'lib/jquery-ui/jquery-ui.min.js', 'lib/jquery-ui-touch-punch/jquery.ui.touch-punch.js', - 'lib/angular/1.1.5/angular-cookies.min.js', - 'lib/angular/1.1.5/angular-mobile.js', - 'lib/angular/1.1.5/angular-sanitize.min.js', + 'lib/angular-route/angular-route.js', + 'lib/angular-cookies/angular-cookies.js', + 'lib/angular-touch/angular-touch.js', + 'lib/angular-sanitize/angular-sanitize.js', + 'lib/angular-animate/angular-animate.js', 'lib/angular/angular-ui-sortable.js', From fa0b3049ee4f09524eb9bebfb3c9dc74abbb4b1a Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 28 May 2018 20:48:52 +0200 Subject: [PATCH 002/115] update requestHelper to handle new promises --- .../src/common/services/umbrequesthelper.service.js | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js index d950d39619..4edcfdbed0 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js @@ -121,6 +121,7 @@ function umbRequestHelper($http, $q, umbDataFormatter, angularHelper, dialogServ /** The default success callback used if one is not supplied in the opts */ function defaultSuccess(data, status, headers, config) { //when it's successful, just return the data + console.log("succes promise", data); return data; } @@ -140,28 +141,28 @@ function umbRequestHelper($http, $q, umbDataFormatter, angularHelper, dialogServ error: ((!opts || !opts.error) ? defaultError : opts.error) }; - httpPromise.success(function (data, status, headers, config) { + httpPromise.then(function (response) { //invoke the callback - var result = callbacks.success.apply(this, [data, status, headers, config]); + var result = callbacks.success.apply(this, [response.data, response.status, response.headers, response.config]); //when it's successful, just return the data deferred.resolve(result); - }).error(function (data, status, headers, config) { + }).catch(function (response) { //invoke the callback - var result = callbacks.error.apply(this, [data, status, headers, config]); + var result = callbacks.error.apply(this, [response.data, response.status, response.headers, response.config]); //when there's a 500 (unhandled) error show a YSOD overlay if debugging is enabled. - if (status >= 500 && status < 600) { + if (response.status >= 500 && response.status < 600) { //show a ysod dialog if (Umbraco.Sys.ServerVariables["isDebuggingEnabled"] === true) { eventsService.emit('app.ysod', { errorMsg: 'An error occured', - data: data + data: response.data }); } else { From 66894e81e144f2903dba6278cbc5fa6182a4a254 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 28 May 2018 20:52:35 +0200 Subject: [PATCH 003/115] temp comment out securityInterceptor --- .../src/common/security/securityinterceptor.js | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/security/securityinterceptor.js b/src/Umbraco.Web.UI.Client/src/common/security/securityinterceptor.js index 550c227613..80dbe37e2c 100644 --- a/src/Umbraco.Web.UI.Client/src/common/security/securityinterceptor.js +++ b/src/Umbraco.Web.UI.Client/src/common/security/securityinterceptor.js @@ -123,6 +123,7 @@ angular.module('umbraco.security.interceptor') .config(['$httpProvider', function ($httpProvider) { $httpProvider.defaults.xsrfHeaderName = 'X-UMB-XSRF-TOKEN'; $httpProvider.defaults.xsrfCookieName = 'UMB-XSRF-TOKEN'; - $httpProvider.responseInterceptors.push('securityInterceptor'); + // Fixme: https://stackoverflow.com/questions/23804981/alternative-of-httpprovider-responseinterceptors + // $httpProvider.interceptors.push('securityInterceptor'); $httpProvider.interceptors.push('umbracoRequestInterceptor'); }]); From 8b96efc02e89b520004b39f66d3942dd613b4c94 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 28 May 2018 20:55:56 +0200 Subject: [PATCH 004/115] move umbTree markup to template --- .../components/tree/umbtree.directive.js | 255 ++++++++---------- .../src/views/components/tree/umb-tree.html | 14 + 2 files changed, 130 insertions(+), 139 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/views/components/tree/umb-tree.html diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/tree/umbtree.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/tree/umbtree.directive.js index be743ea21c..c4ee4bacca 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/tree/umbtree.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/tree/umbtree.directive.js @@ -9,7 +9,7 @@ function umbTreeDirective($compile, $log, $q, $rootScope, treeService, notificat restrict: 'E', replace: true, terminal: false, - + templateUrl: 'views/components/tree/umb-tree.html', scope: { section: '@', treealias: '@', @@ -22,82 +22,59 @@ function umbTreeDirective($compile, $log, $q, $rootScope, treeService, notificat customtreeparams: '@', enablecheckboxes: '@', enablelistviewsearch: '@', - enablelistviewexpand: '@', - - api: '=?', + enablelistviewexpand: '@', + api: '=?', onInit: '&?' }, + controller: function ($scope, $element) { - compile: function (element, attrs) { - //config - //var showheader = (attrs.showheader !== 'false'); - var hideoptions = (attrs.hideoptions === 'true') ? "hide-options" : ""; - var template = '
  • '; - template += '
    ' + - '
    ' + - ' {{tree.name}}
    ' + - '' + - '
    '; - template += '
      ' + - '' + - '
    ' + - '
  • ' + - '
'; + $scope.hideoptions = ($scope.hideoptions === 'true') ? "hide-options" : ""; - element.replaceWith(template); - - return function (scope, elem, attr, controller) { - - }; - }, - - controller: function ($scope, $element) { - var vm = this; - - var registeredCallbacks = { - treeNodeExpanded: [], - treeNodeSelect: [], - treeLoaded: [], - treeSynced: [], - treeOptionsClick: [], + + var registeredCallbacks = { + treeNodeExpanded: [], + treeNodeSelect: [], + treeLoaded: [], + treeSynced: [], + treeOptionsClick: [], treeNodeAltSelect: [] - }; - - //this is the API exposed by this directive, for either hosting controllers or for other directives - vm.callbacks = { - treeNodeExpanded: function (f) { + }; + + //this is the API exposed by this directive, for either hosting controllers or for other directives + vm.callbacks = { + treeNodeExpanded: function (f) { registeredCallbacks.treeNodeExpanded.push(f); - }, - treeNodeSelect: function (f) { + }, + treeNodeSelect: function (f) { registeredCallbacks.treeNodeSelect.push(f); - }, - treeLoaded: function (f) { + }, + treeLoaded: function (f) { registeredCallbacks.treeLoaded.push(f); - }, - treeSynced: function (f) { + }, + treeSynced: function (f) { registeredCallbacks.treeSynced.push(f); - }, - treeOptionsClick: function (f) { + }, + treeOptionsClick: function (f) { registeredCallbacks.treeOptionsClick.push(f); - }, - treeNodeAltSelect: function (f) { + }, + treeNodeAltSelect: function (f) { registeredCallbacks.treeNodeAltSelect.push(f); } - }; - vm.emitEvent = emitEvent; - vm.load = load; - vm.reloadNode = reloadNode; - vm.syncTree = syncTree; - + }; + vm.emitEvent = emitEvent; + vm.load = load; + vm.reloadNode = reloadNode; + vm.syncTree = syncTree; + //wire up the exposed api object for hosting controllers - if ($scope.api) { - $scope.api.callbacks = vm.callbacks; - $scope.api.load = vm.load; - $scope.api.reloadNode = vm.reloadNode; + if ($scope.api) { + $scope.api.callbacks = vm.callbacks; + $scope.api.load = vm.load; + $scope.api.reloadNode = vm.reloadNode; $scope.api.syncTree = vm.syncTree; - } - + } + //flag to track the last loaded section when the tree 'un-loads'. We use this to determine if we should // re-load the tree again. For example, if we hover over 'content' the content tree is shown. Then we hover // outside of the tree and the tree 'un-loads'. When we re-hover over 'content', we don't want to re-load the @@ -110,9 +87,9 @@ function umbTreeDirective($compile, $log, $q, $rootScope, treeService, notificat var deleteAnimations = false; /** Helper function to emit tree events */ - function emitEvent(eventName, args) { - if (registeredCallbacks[eventName] && angular.isArray(registeredCallbacks[eventName])) { - _.each(registeredCallbacks[eventName], function (c) { + function emitEvent(eventName, args) { + if (registeredCallbacks[eventName] && angular.isArray(registeredCallbacks[eventName])) { + _.each(registeredCallbacks[eventName], function (c) { c(args);//call it }); } @@ -126,37 +103,37 @@ function umbTreeDirective($compile, $log, $q, $rootScope, treeService, notificat deleteAnimations = true; }, 0, false); } - - function clearCache(section) { + + function clearCache(section) { treeService.clearCache({ section: section }); } - + /** * Re-loads the tree with the updated parameters * @param {any} args either a string representing the 'section' or an object containing: 'section', 'treeAlias', 'customTreeParams', 'cacheKey' - */ - function load(args) { - if (angular.isString(args)) { + */ + function load(args) { + if (angular.isString(args)) { $scope.section = args; - } - else if (args) { - if (args.section) { + } + else if (args) { + if (args.section) { $scope.section = args.section; - } - if (args.customTreeParams) { - $scope.customtreeparams = args.customTreeParams; - } - if (args.treeAlias) { - $scope.treealias = args.treeAlias; - } - if (args.cacheKey) { - $scope.cachekey = args.cacheKey; } - } + if (args.customTreeParams) { + $scope.customtreeparams = args.customTreeParams; + } + if (args.treeAlias) { + $scope.treealias = args.treeAlias; + } + if (args.cacheKey) { + $scope.cachekey = args.cacheKey; + } + } return loadTree(); - } - + } + function reloadNode(node) { if (!node) { @@ -165,24 +142,24 @@ function umbTreeDirective($compile, $log, $q, $rootScope, treeService, notificat if (node) { return $scope.loadChildren(node, true); - } - + } + return $q.reject(); - } - + } + /** * Used to do the tree syncing - * @param {any} args + * @param {any} args * @returns a promise with an object containing 'node' and 'activate' - */ - function syncTree(args) { + */ + function syncTree(args) { if (!args) { throw "args cannot be null"; } if (!args.path) { throw "args.path cannot be null"; } - + if (angular.isString(args.path)) { args.path = args.path.replace('"', '').split(','); } @@ -214,7 +191,7 @@ function umbTreeDirective($compile, $log, $q, $rootScope, treeService, notificat args.path = args.path.splice(_.indexOf(args.path, found)); } }); - + deleteAnimations = false; var treeNode = loadActiveTree(args.tree); @@ -231,8 +208,8 @@ function umbTreeDirective($compile, $log, $q, $rootScope, treeService, notificat emitEvent("treeSynced", { node: data, activate: args.activate }); - enableDeleteAnimations(); - + enableDeleteAnimations(); + return $q.when({ node: data, activate: args.activate }); }); }); @@ -242,17 +219,17 @@ function umbTreeDirective($compile, $log, $q, $rootScope, treeService, notificat //given a tree alias, this will search the current section tree for the specified tree alias and set the current active tree to it's root node function loadActiveTree(treeAlias) { - if (!$scope.tree) { - throw "Err in umbtree.directive.loadActiveTree, $scope.tree is null"; - } - - //if its not specified, it should have been specified before - if (!treeAlias) { - if (!$scope.activeTree) { + if (!$scope.tree) { + throw "Err in umbtree.directive.loadActiveTree, $scope.tree is null"; + } + + //if its not specified, it should have been specified before + if (!treeAlias) { + if (!$scope.activeTree) { throw "Err in umbtree.directive.loadActiveTree, $scope.activeTree is null"; } return $scope.activeTree; - } + } var childrenAndSelf = [$scope.tree.root].concat($scope.tree.root.children); $scope.activeTree = _.find(childrenAndSelf, function (node) { @@ -266,8 +243,8 @@ function umbTreeDirective($compile, $log, $q, $rootScope, treeService, notificat throw "Could not find the tree " + treeAlias; } - emitEvent("activeTreeLoaded", { tree: $scope.activeTree }); - + emitEvent("activeTreeLoaded", { tree: $scope.activeTree }); + return $scope.activeTree; } @@ -297,21 +274,21 @@ function umbTreeDirective($compile, $log, $q, $rootScope, treeService, notificat enableDeleteAnimations(); $scope.loading = false; - + //set the root as the current active tree - $scope.activeTree = $scope.tree.root; + $scope.activeTree = $scope.tree.root; emitEvent("treeLoaded", { tree: $scope.tree }); emitEvent("treeNodeExpanded", { tree: $scope.tree, node: $scope.tree.root, children: $scope.tree.root.children }); return $q.when(data); }, function (reason) { $scope.loading = false; - notificationsService.error("Tree Error", reason); + notificationsService.error("Tree Error", reason); return $q.reject(reason); }); - } - else { - return $q.reject(); + } + else { + return $q.reject(); } } @@ -374,7 +351,7 @@ function umbTreeDirective($compile, $log, $q, $rootScope, treeService, notificat emitEvent("treeNodeExpanded", { tree: $scope.tree, node: node, children: data }); enableDeleteAnimations(); - + return $q.when(data); }); } @@ -420,36 +397,36 @@ function umbTreeDirective($compile, $log, $q, $rootScope, treeService, notificat $scope.altSelect = function (n, ev) { emitEvent("treeNodeAltSelect", { element: $element, tree: $scope.tree, node: n, event: ev }); - }; + }; - //call the onInit method, if the result is a promise then load the tree after that resolves (if it's not a promise this will just resolve automatically). + //call the onInit method, if the result is a promise then load the tree after that resolves (if it's not a promise this will just resolve automatically). //NOTE: The promise cannot be rejected, else the tree won't be loaded and we'll get exceptions if some API calls syncTree or similar. - $q.when($scope.onInit(), function (args) { - - //the promise resolution can pass in parameters - if (args) { - if (args.section) { + $q.when($scope.onInit(), function (args) { + + //the promise resolution can pass in parameters + if (args) { + if (args.section) { $scope.section = args.section; - } - if (args.customTreeParams) { - $scope.customtreeparams = args.customTreeParams; - } - if (args.treealias) { - $scope.treealias = args.treealias; - } - if (args.cacheKey) { - $scope.cachekey = args.cacheKey; } - } - - //load the tree - loadTree().then(function () { - //because angular doesn't return a promise for the resolve method, we need to resort to some hackery, else - //like normal JS promises we could do resolve(...).then() - if (args.onLoaded && angular.isFunction(args.onLoaded)) { + if (args.customTreeParams) { + $scope.customtreeparams = args.customTreeParams; + } + if (args.treealias) { + $scope.treealias = args.treealias; + } + if (args.cacheKey) { + $scope.cachekey = args.cacheKey; + } + } + + //load the tree + loadTree().then(function () { + //because angular doesn't return a promise for the resolve method, we need to resort to some hackery, else + //like normal JS promises we could do resolve(...).then() + if (args.onLoaded && angular.isFunction(args.onLoaded)) { args.onLoaded(); - } - }); + } + }); }); } }; diff --git a/src/Umbraco.Web.UI.Client/src/views/components/tree/umb-tree.html b/src/Umbraco.Web.UI.Client/src/views/components/tree/umb-tree.html new file mode 100644 index 0000000000..1b45668ed5 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/views/components/tree/umb-tree.html @@ -0,0 +1,14 @@ + \ No newline at end of file From 5670fc14e0b09e56868282f683965afe697b0738 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 28 May 2018 21:16:57 +0200 Subject: [PATCH 005/115] add optional marker to routes --- src/Umbraco.Web.UI.Client/src/routes.js | 374 ++++++++++++------------ 1 file changed, 187 insertions(+), 187 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/routes.js b/src/Umbraco.Web.UI.Client/src/routes.js index 94521eaa0e..cf6af40d4b 100644 --- a/src/Umbraco.Web.UI.Client/src/routes.js +++ b/src/Umbraco.Web.UI.Client/src/routes.js @@ -1,195 +1,195 @@ -app.config(function ($routeProvider) { - - /** - * This determines if the route can continue depending on authentication and initialization requirements - * @param {boolean} authRequired If true, it checks if the user is authenticated and will resolve successfully - otherwise the route will fail and the $routeChangeError event will execute, in that handler we will redirect to the rejected - path that is resolved from this method and prevent default (prevent the route from executing) - * @returns {promise} - */ - var canRoute = function(authRequired) { - - return { - /** Checks that the user is authenticated, then ensures that are requires assets are loaded */ - isAuthenticatedAndReady: function ($q, userService, $route, assetsService, appState) { - - //don't need to check if we've redirected to login and we've already checked auth - if (!$route.current.params.section - && ($route.current.params.check === false || $route.current.params.check === "false")) { - return $q.when(true); - } - - return userService.isAuthenticated() - .then(function () { +app.config(function ($routeProvider) { + + /** + * This determines if the route can continue depending on authentication and initialization requirements + * @param {boolean} authRequired If true, it checks if the user is authenticated and will resolve successfully + otherwise the route will fail and the $routeChangeError event will execute, in that handler we will redirect to the rejected + path that is resolved from this method and prevent default (prevent the route from executing) + * @returns {promise} + */ + var canRoute = function(authRequired) { - //before proceeding all initial assets must be loaded - return assetsService._loadInitAssets().then(function () { - - //This could be the first time has loaded after the user has logged in, in this case - // we need to broadcast the authenticated event - this will be handled by the startup (init) - // handler to set/broadcast the ready state - var broadcast = appState.getGlobalState("isReady") !== true; - - return userService.getCurrentUser({ broadcastEvent: broadcast }).then(function (user) { - //is auth, check if we allow or reject - if (authRequired) { - - //This checks the current section and will force a redirect to 'content' as the default - if ($route.current.params.section.toLowerCase() === "default" || $route.current.params.section.toLowerCase() === "umbraco" || $route.current.params.section === "") { - $route.current.params.section = "content"; - } - - // U4-5430, Benjamin Howarth - // We need to change the current route params if the user only has access to a single section - // To do this we need to grab the current user's allowed sections, then reject the promise with the correct path. + return { + /** Checks that the user is authenticated, then ensures that are requires assets are loaded */ + isAuthenticatedAndReady: function ($q, userService, $route, assetsService, appState) { + + //don't need to check if we've redirected to login and we've already checked auth + if (!$route.current.params.section + && ($route.current.params.check === false || $route.current.params.check === "false")) { + return $q.when(true); + } + + return userService.isAuthenticated() + .then(function () { + + //before proceeding all initial assets must be loaded + return assetsService._loadInitAssets().then(function () { + + //This could be the first time has loaded after the user has logged in, in this case + // we need to broadcast the authenticated event - this will be handled by the startup (init) + // handler to set/broadcast the ready state + var broadcast = appState.getGlobalState("isReady") !== true; + + return userService.getCurrentUser({ broadcastEvent: broadcast }).then(function (user) { + //is auth, check if we allow or reject + if (authRequired) { + + //This checks the current section and will force a redirect to 'content' as the default + if ($route.current.params.section.toLowerCase() === "default" || $route.current.params.section.toLowerCase() === "umbraco" || $route.current.params.section === "") { + $route.current.params.section = "content"; + } + + // U4-5430, Benjamin Howarth + // We need to change the current route params if the user only has access to a single section + // To do this we need to grab the current user's allowed sections, then reject the promise with the correct path. if (user.allowedSections.indexOf($route.current.params.section) > -1) { - //this will resolve successfully so the route will continue - return $q.when(true); - } else { - return $q.reject({ path: "/" + user.allowedSections[0] }); - } - } - else { - return $q.reject({ path: "/" }); - } - }); - - }); - - }, function () { - //not auth, check if we allow or reject - if (authRequired) { - //the check=false is checked above so that we don't have to make another http call to check - //if they are logged in since we already know they are not. - return $q.reject({ path: "/login/false" }); - } - else { - //this will resolve successfully so the route will continue - return $q.when(true); - } - }); - - } - }; - }; - - /** When this is used to resolve it will attempt to log the current user out */ - var doLogout = function() { - return { - isLoggedOut: function ($q, userService) { - return userService.logout().then(function () { - //success so continue - return $q.when(true); - }, function() { - //logout failed somehow ? we'll reject with the login page i suppose - return $q.reject({ path: "/login/false" }); - }); - } - } - } - - $routeProvider - .when('/login', { - templateUrl: 'views/common/login.html', - //ensure auth is *not* required so it will redirect to / - resolve: canRoute(false) - }) - .when('/login/:check', { - templateUrl: 'views/common/login.html', - //ensure auth is *not* required so it will redirect to / - resolve: canRoute(false) - }) - .when('/logout', { - redirectTo: '/login/false', - resolve: doLogout() - }) - .when('/:section', { - //This allows us to dynamically change the template for this route since you cannot inject services into the templateUrl method. - template: "
", - //This controller will execute for this route, then we can execute some code in order to set the template Url - controller: function ($scope, $route, $routeParams, $location, sectionService) { - - //We are going to check the currently loaded sections for the user and if the section we are navigating - //to has a custom route path we'll use that - sectionService.getSectionsForUser().then(function(sections) { - //find the one we're requesting - var found = _.find(sections, function(s) { - return s.alias === $routeParams.section; - }) - if (found && found.routePath) { - //there's a custom route path so redirect - $location.path(found.routePath); - } - else { - //there's no custom route path so continue as normal - $routeParams.url = "dashboard.aspx?app=" + $routeParams.section; - $scope.templateUrl = 'views/common/dashboard.html'; - } - }); + //this will resolve successfully so the route will continue + return $q.when(true); + } else { + return $q.reject({ path: "/" + user.allowedSections[0] }); + } + } + else { + return $q.when(true); + } + }); + + }); + + }, function () { + //not auth, check if we allow or reject + if (authRequired) { + //the check=false is checked above so that we don't have to make another http call to check + //if they are logged in since we already know they are not. + return $q.reject({ path: "/login/false" }); + } + else { + //this will resolve successfully so the route will continue + return $q.when(true); + } + }); + + } + }; + }; + + /** When this is used to resolve it will attempt to log the current user out */ + var doLogout = function() { + return { + isLoggedOut: function ($q, userService) { + return userService.logout().then(function () { + //success so continue + return $q.when(true); + }, function() { + //logout failed somehow ? we'll reject with the login page i suppose + return $q.reject({ path: "/login/false" }); + }); + } + } + } + + $routeProvider + .when('/login', { + templateUrl: 'views/common/login.html', + //ensure auth is *not* required so it will redirect to / + resolve: canRoute(false) + }) + .when('/login/:check', { + templateUrl: 'views/common/login.html', + //ensure auth is *not* required so it will redirect to / + resolve: canRoute(false) + }) + .when('/logout', { + redirectTo: '/login/false', + resolve: doLogout() + }) + .when('/:section?', { + //This allows us to dynamically change the template for this route since you cannot inject services into the templateUrl method. + template: "
", + //This controller will execute for this route, then we can execute some code in order to set the template Url + controller: function ($scope, $route, $routeParams, $location, sectionService) { + + //We are going to check the currently loaded sections for the user and if the section we are navigating + //to has a custom route path we'll use that + sectionService.getSectionsForUser().then(function(sections) { + //find the one we're requesting + var found = _.find(sections, function(s) { + return s.alias === $routeParams.section; + }) + if (found && found.routePath) { + //there's a custom route path so redirect + $location.path(found.routePath); + } + else { + //there's no custom route path so continue as normal + $routeParams.url = "dashboard.aspx?app=" + $routeParams.section; + $scope.templateUrl = 'views/common/dashboard.html'; + } + }); }, - reloadOnSearch: false, - resolve: canRoute(true) - }) - .when('/:section/framed/:url', { - //This occurs when we need to launch some content in an iframe - templateUrl: function (rp) { - if (!rp.url) - throw "A framed resource must have a url route parameter"; - - return 'views/common/legacy.html'; + reloadOnSearch: false, + resolve: canRoute(true) + }) + .when('/:section/framed/:url', { + //This occurs when we need to launch some content in an iframe + templateUrl: function (rp) { + if (!rp.url) + throw "A framed resource must have a url route parameter"; + + return 'views/common/legacy.html'; }, - reloadOnSearch: false, - resolve: canRoute(true) - }) - .when('/:section/:tree/:method', { - templateUrl: function (rp) { - - //if there is no method registered for this then show the dashboard - if (!rp.method) - return "views/common/dashboard.html"; - - return ('views/' + rp.tree + '/' + rp.method + '.html'); + reloadOnSearch: false, + resolve: canRoute(true) + }) + .when('/:section/:tree/:method?', { + templateUrl: function (rp) { + + //if there is no method registered for this then show the dashboard + if (!rp.method) + return "views/common/dashboard.html"; + + return ('views/' + rp.tree + '/' + rp.method + '.html'); }, - reloadOnSearch: false, - resolve: canRoute(true) - }) - .when('/:section/:tree/:method/:id', { - //This allows us to dynamically change the template for this route since you cannot inject services into the templateUrl method. - template: "
", - //This controller will execute for this route, then we replace the template dynamnically based on the current tree. - controller: function ($scope, $route, $routeParams, treeService) { - - if (!$routeParams.tree || !$routeParams.method) { - $scope.templateUrl = "views/common/dashboard.html"; - } - - // Here we need to figure out if this route is for a package tree and if so then we need - // to change it's convention view path to: - // /App_Plugins/{mypackage}/backoffice/{treetype}/{method}.html - - // otherwise if it is a core tree we use the core paths: - // views/{treetype}/{method}.html - - var packageTreeFolder = treeService.getTreePackageFolder($routeParams.tree); - - if (packageTreeFolder) { - $scope.templateUrl = (Umbraco.Sys.ServerVariables.umbracoSettings.appPluginsPath + - "/" + packageTreeFolder + - "/backoffice/" + $routeParams.tree + "/" + $routeParams.method + ".html"); - } - else { - $scope.templateUrl = ('views/' + $routeParams.tree + '/' + $routeParams.method + '.html'); - } - + reloadOnSearch: false, + resolve: canRoute(true) + }) + .when('/:section/:tree/:method?/:id', { + //This allows us to dynamically change the template for this route since you cannot inject services into the templateUrl method. + template: "
", + //This controller will execute for this route, then we replace the template dynamnically based on the current tree. + controller: function ($scope, $route, $routeParams, treeService) { + + if (!$routeParams.tree || !$routeParams.method) { + $scope.templateUrl = "views/common/dashboard.html"; + } + + // Here we need to figure out if this route is for a package tree and if so then we need + // to change it's convention view path to: + // /App_Plugins/{mypackage}/backoffice/{treetype}/{method}.html + + // otherwise if it is a core tree we use the core paths: + // views/{treetype}/{method}.html + + var packageTreeFolder = treeService.getTreePackageFolder($routeParams.tree); + + if (packageTreeFolder) { + $scope.templateUrl = (Umbraco.Sys.ServerVariables.umbracoSettings.appPluginsPath + + "/" + packageTreeFolder + + "/backoffice/" + $routeParams.tree + "/" + $routeParams.method + ".html"); + } + else { + $scope.templateUrl = ('views/' + $routeParams.tree + '/' + $routeParams.method + '.html'); + } + }, - reloadOnSearch: false, - resolve: canRoute(true) - }) - .otherwise({ redirectTo: '/login' }); - }).config(function ($locationProvider) { - - //$locationProvider.html5Mode(false).hashPrefix('!'); //turn html5 mode off + reloadOnSearch: false, + resolve: canRoute(true) + }) + .otherwise({ redirectTo: '/login' }); + }).config(function ($locationProvider) { + + //$locationProvider.html5Mode(false).hashPrefix('!'); //turn html5 mode off // $locationProvider.html5Mode(true); //turn html5 mode on - - }); + + }); From 6510dce9d49b7a8fe7a7f7546d792b67e02dbc28 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 28 May 2018 21:17:50 +0200 Subject: [PATCH 006/115] fix link for header avatar --- .../src/views/components/application/umb-app-header.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/components/application/umb-app-header.html b/src/Umbraco.Web.UI.Client/src/views/components/application/umb-app-header.html index f69a01b27a..618bff5565 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/application/umb-app-header.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/application/umb-app-header.html @@ -20,7 +20,7 @@ - + Date: Mon, 28 May 2018 21:18:08 +0200 Subject: [PATCH 007/115] fix transclude for overlays --- .../src/views/components/overlays/umb-overlay.html | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/components/overlays/umb-overlay.html b/src/Umbraco.Web.UI.Client/src/views/components/overlays/umb-overlay.html index 14a7ebf006..5aab9c6335 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/overlays/umb-overlay.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/overlays/umb-overlay.html @@ -6,7 +6,8 @@

{{model.subtitle}}

-
+
+
From 4c50ab6042aaf14eaa986c6eee8eb405e421b24d Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 28 May 2018 21:18:39 +0200 Subject: [PATCH 008/115] fix button translations in overlay --- .../overlays/umboverlay.directive.js | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/overlays/umboverlay.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/overlays/umboverlay.directive.js index 64d5afdd27..56a68f9596 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/overlays/umboverlay.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/overlays/umboverlay.directive.js @@ -464,12 +464,20 @@ Opens an overlay to show a custom YSOD.
} function setButtonText() { - if (!scope.model.closeButtonLabelKey && !scope.model.closeButtonLabel) { - scope.model.closeButtonLabel = localizationService.localize("general_close"); - } - if (!scope.model.submitButtonLabelKey && !scope.model.submitButtonLabel) { - scope.model.submitButtonLabel = localizationService.localize("general_submit"); - } + + var labelKeys = [ + "general_close", + "general_submit" + ]; + + localizationService.localizeMany(labelKeys).then(function (values) { + if (!scope.model.closeButtonLabelKey && !scope.model.closeButtonLabel) { + scope.model.closeButtonLabel = values[0]; + } + if (!scope.model.submitButtonLabelKey && !scope.model.submitButtonLabel) { + scope.model.submitButtonLabel = values[1]; + } + }); } function registerOverlay() { From d7a8d433de6e15d81a17cae89089901802a61414 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 28 May 2018 21:19:23 +0200 Subject: [PATCH 009/115] add null check + remove weird ngShow support --- .../overlays/umboverlay.directive.js | 28 +++++-------------- 1 file changed, 7 insertions(+), 21 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/overlays/umboverlay.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/overlays/umboverlay.directive.js index 56a68f9596..d339b4c0f3 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/overlays/umboverlay.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/overlays/umboverlay.directive.js @@ -674,35 +674,21 @@ Opens an overlay to show a custom YSOD.
unregisterOverlay(); - if (scope.model.close) { - scope.model = modelCopy; + if (scope.model && scope.model.close) { + scope.model = modelCopy; scope.model.close(scope.model); } else { scope.model.show = false; - scope.model = null; + scope.model = null; } }; - // angular does not support ng-show on custom directives - // width isolated scopes. So we have to make our own. - if (attr.hasOwnProperty("ngShow")) { - scope.$watch("ngShow", function(value) { - if (value) { - el.show(); - activate(); - } else { - unregisterOverlay(); - el.hide(); - } - }); - } else { - activate(); - } - - scope.$on('$destroy', function(){ + scope.$on('$destroy', function(){ unregisterOverlay(); - }); + }); + + activate(); } From a293ff0200cb78b828ea8eebcbdf2d6414cbbdeb Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 29 May 2018 11:05:19 +0200 Subject: [PATCH 010/115] fix localisation of doc type subviews --- .../views/documenttypes/edit.controller.js | 76 +++++++++++-------- 1 file changed, 46 insertions(+), 30 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/documenttypes/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/documenttypes/edit.controller.js index 022196328e..1451a3d0c4 100644 --- a/src/Umbraco.Web.UI.Client/src/views/documenttypes/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/documenttypes/edit.controller.js @@ -15,34 +15,7 @@ var evts = []; var disableTemplates = Umbraco.Sys.ServerVariables.features.disabledFeatures.disableTemplates; - - var buttons = [ - { - "name": localizationService.localize("general_design"), - "alias": "design", - "icon": "icon-document-dashed-line", - "view": "views/documenttypes/views/design/design.html", - "active": true - }, - { - "name": localizationService.localize("general_listView"), - "alias": "listView", - "icon": "icon-list", - "view": "views/documenttypes/views/listview/listview.html" - }, - { - "name": localizationService.localize("general_rights"), - "alias": "permissions", - "icon": "icon-keychain", - "view": "views/documenttypes/views/permissions/permissions.html" - }, - { - "name": localizationService.localize("treeHeaders_templates"), - "alias": "templates", - "icon": "icon-layout", - "view": "views/documenttypes/views/templates/templates.html" - } - ]; + vm.labels = {}; vm.save = save; @@ -54,7 +27,50 @@ vm.page.saveButtonState = "init"; vm.page.navigation = []; - loadButtons(); + var labelKeys = [ + "general_design", + "general_listView", + "general_rights", + "treeHeaders_templates" + ]; + + localizationService.localizeMany(labelKeys).then(function (values) { + vm.labels.design = values[0]; + vm.labels.listview = values[1]; + vm.labels.permissions = values[2]; + vm.labels.templates = values[3]; + + var buttons = [ + { + "name": vm.labels.design, + "alias": "design", + "icon": "icon-document-dashed-line", + "view": "views/documenttypes/views/design/design.html", + "active": true + }, + { + "name": vm.labels.listview, + "alias": "listView", + "icon": "icon-list", + "view": "views/documenttypes/views/listview/listview.html" + }, + { + "name": vm.labels.permissions, + "alias": "permissions", + "icon": "icon-keychain", + "view": "views/documenttypes/views/permissions/permissions.html" + }, + { + "name": vm.labels.templates, + "alias": "templates", + "icon": "icon-layout", + "view": "views/documenttypes/views/templates/templates.html" + } + ]; + + loadButtons(buttons); + + }); vm.page.keyboardShortcutsOverview = [ { @@ -212,7 +228,7 @@ }); } - function loadButtons() { + function loadButtons(buttons) { angular.forEach(buttons, function (val, index) { From c86e2b30319b8b958ee9cba3539288af0ca59a54 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 29 May 2018 11:05:53 +0200 Subject: [PATCH 011/115] Make subviews clickable again --- .../src/views/components/editor/umb-editor-navigation.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-navigation.html b/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-navigation.html index 26cc7c794d..df64055d1e 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-navigation.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-navigation.html @@ -1,4 +1,4 @@ -
    +
    • Date: Tue, 29 May 2018 13:33:26 +0200 Subject: [PATCH 012/115] changed ng-bind-html-unsafe to ng-bind-html --- .../src/views/common/overlays/embed/embed.html | 2 +- .../src/views/dashboard/default/StartupDashboardIntro.html | 2 +- .../src/views/packages/views/install-local.html | 2 +- src/Umbraco.Web.UI.Client/src/views/packages/views/repo.html | 4 ++-- .../src/views/propertyeditors/grid/editors/embed.html | 2 +- .../src/views/propertyeditors/grid/editors/macro.html | 2 +- 6 files changed, 7 insertions(+), 7 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/common/overlays/embed/embed.html b/src/Umbraco.Web.UI.Client/src/views/common/overlays/embed/embed.html index 0421e31df5..a1f6ff8ffe 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/overlays/embed/embed.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/overlays/embed/embed.html @@ -7,7 +7,7 @@

      -
      +
      diff --git a/src/Umbraco.Web.UI.Client/src/views/dashboard/default/StartupDashboardIntro.html b/src/Umbraco.Web.UI.Client/src/views/dashboard/default/StartupDashboardIntro.html index b2222d07c4..b48812c347 100644 --- a/src/Umbraco.Web.UI.Client/src/views/dashboard/default/StartupDashboardIntro.html +++ b/src/Umbraco.Web.UI.Client/src/views/dashboard/default/StartupDashboardIntro.html @@ -19,7 +19,7 @@
      -
      +
      diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/views/install-local.html b/src/Umbraco.Web.UI.Client/src/views/packages/views/install-local.html index 993b85954d..f7843fb0fc 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/views/install-local.html +++ b/src/Umbraco.Web.UI.Client/src/views/packages/views/install-local.html @@ -128,7 +128,7 @@
      Read me
      - +
      diff --git a/src/Umbraco.Web.UI.Client/src/views/packages/views/repo.html b/src/Umbraco.Web.UI.Client/src/views/packages/views/repo.html index 00634c7922..7b4b960c2c 100644 --- a/src/Umbraco.Web.UI.Client/src/views/packages/views/repo.html +++ b/src/Umbraco.Web.UI.Client/src/views/packages/views/repo.html @@ -131,7 +131,7 @@
      {{ vm.package.name }}
      -
      +
      From 04c4a8cd34296caab9466f7b7a02c74d64250b9b Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 29 May 2018 14:13:38 +0200 Subject: [PATCH 013/115] fix lexer error in tree --- .../src/views/components/tree/umb-tree.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/components/tree/umb-tree.html b/src/Umbraco.Web.UI.Client/src/views/components/tree/umb-tree.html index 1b45668ed5..f26c2c1352 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/tree/umb-tree.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/tree/umb-tree.html @@ -3,7 +3,7 @@
      - + {{tree.name}}
      From 3d5d2648ff4b7f2efc23d011c6329ceae38b4db9 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 29 May 2018 14:39:17 +0200 Subject: [PATCH 014/115] upgrade angular-local-storage --- src/Umbraco.Web.UI.Client/bower.json | 2 +- .../src/views/propertyeditors/listview/listview.controller.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/bower.json b/src/Umbraco.Web.UI.Client/bower.json index e8fb7d78fa..1ede0c4784 100644 --- a/src/Umbraco.Web.UI.Client/bower.json +++ b/src/Umbraco.Web.UI.Client/bower.json @@ -34,7 +34,7 @@ "ng-file-upload": "~7.3.8", "tinymce": "~4.7.1", "codemirror": "~5.3.0", - "angular-local-storage": "~0.2.3", + "angular-local-storage": "~0.7.1", "moment": "~2.10.3", "ace-builds": "^1.2.3", "clipboard": "1.7.1", diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.controller.js index 8f9279fb02..e736c12f1c 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.controller.js @@ -1,4 +1,4 @@ -function listViewController($rootScope, $scope, $routeParams, $injector, $cookieStore, notificationsService, iconHelper, dialogService, editorState, localizationService, $location, appState, $timeout, $q, mediaResource, listViewHelper, userService, navigationService, treeService) { +function listViewController($rootScope, $scope, $routeParams, $injector, notificationsService, iconHelper, dialogService, editorState, localizationService, $location, appState, $timeout, $q, mediaResource, listViewHelper, userService, navigationService, treeService) { //this is a quick check to see if we're in create mode, if so just exit - we cannot show children for content // that isn't created yet, if we continue this will use the parent id in the route params which isn't what From 6de4d85783c06e791413d1317c8a7f3888e19cde Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 30 May 2018 11:41:20 +0200 Subject: [PATCH 015/115] upgrade ng-file-upload --- src/Umbraco.Web.UI.Client/bower.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/bower.json b/src/Umbraco.Web.UI.Client/bower.json index 1ede0c4784..97a21bc5d3 100644 --- a/src/Umbraco.Web.UI.Client/bower.json +++ b/src/Umbraco.Web.UI.Client/bower.json @@ -31,7 +31,7 @@ "jquery-ui": "1.11.4", "jquery-migrate": "1.4.0", "angular-dynamic-locale": "0.1.28", - "ng-file-upload": "~7.3.8", + "ng-file-upload": "~12.2.13", "tinymce": "~4.7.1", "codemirror": "~5.3.0", "angular-local-storage": "~0.7.1", From 264d545325902474135f994dc44cc29d5efb42e5 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 30 May 2018 11:42:33 +0200 Subject: [PATCH 016/115] update required formProps to recognize a form --- .../src/common/services/angularhelper.service.js | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/services/angularhelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/angularhelper.service.js index 24db2e5989..6e704b7c78 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/angularhelper.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/angularhelper.service.js @@ -90,8 +90,7 @@ function angularHelper($log, $q) { // is to inject the $element object and use: $element.inheritedData('$formController'); var form = null; - //var requiredFormProps = ["$error", "$name", "$dirty", "$pristine", "$valid", "$invalid", "$addControl", "$removeControl", "$setValidity", "$setDirty"]; - var requiredFormProps = ["$addControl", "$removeControl", "$setValidity", "$setDirty", "$setPristine"]; + var requiredFormProps = ["$error", "$name", "$dirty", "$pristine", "$valid", "$submitted", "$pending"]; // a method to check that the collection of object prop names contains the property name expected function propertyExists(objectPropNames) { @@ -169,4 +168,4 @@ function angularHelper($log, $q) { } }; } -angular.module('umbraco.services').factory('angularHelper', angularHelper); +angular.module('umbraco.services').factory('angularHelper', angularHelper); From 82f70ac453f97cdee03d01b1759dc8243f2e9ad7 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 30 May 2018 11:43:09 +0200 Subject: [PATCH 017/115] update $http request --- .../src/common/services/umbrequesthelper.service.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js index 4edcfdbed0..7a2e91fdde 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js @@ -324,14 +324,14 @@ function umbRequestHelper($http, $q, umbDataFormatter, angularHelper, dialogServ }, data: jsonData }). - success(function (data, status, headers, config) { + then(function (response) { if (successCallback) { - successCallback.apply(this, [data, status, headers, config]); + successCallback.apply(this, [response.data, response.status, response.headers, response.config]); } }). - error(function (data, status, headers, config) { + catch(function (response) { if (failureCallback) { - failureCallback.apply(this, [data, status, headers, config]); + failureCallback.apply(this, [response.data, response.status, response.headers, response.config]); } }); }, From b73769d4c7610f1efbf8cdedc15a6f051e3441a1 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 30 May 2018 17:08:27 +0200 Subject: [PATCH 018/115] temp comment out val-form-manager --- .../directives/validation/valformmanager.directive.js | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valformmanager.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valformmanager.directive.js index 9a00d5718c..9d01b41190 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valformmanager.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valformmanager.directive.js @@ -39,6 +39,12 @@ function valFormManager(serverValidationManager, $rootScope, $log, $timeout, not }, link: function (scope, element, attr, formCtrl) { + + /* + FIXME: This is commented out because it caused this error + http://uixdk.com/angular/docs/error/ng/cpws + resulting in an endless digest loop for all editors + scope.$watch(function () { return formCtrl.$error; }, function (e) { @@ -127,6 +133,7 @@ function valFormManager(serverValidationManager, $rootScope, $log, $timeout, not $timeout(function(){ formCtrl.$setPristine(); }, 1000); + */ } }; } From 07349bcd71c1a09ed338d4fc03e8f42f481a6aa2 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 30 May 2018 17:17:49 +0200 Subject: [PATCH 019/115] fix orderBy error in content create dialog --- src/Umbraco.Web.UI.Client/src/views/content/create.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/content/create.html b/src/Umbraco.Web.UI.Client/src/views/content/create.html index 5bad56988d..c624023145 100644 --- a/src/Umbraco.Web.UI.Client/src/views/content/create.html +++ b/src/Umbraco.Web.UI.Client/src/views/content/create.html @@ -8,7 +8,7 @@

      -
        + -
          +
          • From f5499b1755be57e428fd71fa4e4a1f5457e98b8f Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 31 May 2018 10:42:09 +0200 Subject: [PATCH 020/115] fix help drawer --- .../common/drawers/help/help.controller.js | 7 +- .../src/views/common/drawers/help/help.html | 207 +++++++++--------- 2 files changed, 111 insertions(+), 103 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/common/drawers/help/help.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/drawers/help/help.controller.js index 4d2b43c078..df40539aac 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/drawers/help/help.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/drawers/help/help.controller.js @@ -6,7 +6,7 @@ var vm = this; var evts = []; - vm.title = localizationService.localize("general_help"); + vm.title = ""; vm.subtitle = "Umbraco version" + " " + Umbraco.Sys.ServerVariables.application.version; vm.section = $routeParams.section; vm.tree = $routeParams.tree; @@ -26,6 +26,11 @@ function oninit() { + // set title + localizationService.localize("general_help").then(function(data){ + vm.title = data; + }); + tourService.getGroupedTours().then(function(groupedTours) { vm.tours = groupedTours; getTourGroupCompletedPercentage(); diff --git a/src/Umbraco.Web.UI.Client/src/views/common/drawers/help/help.html b/src/Umbraco.Web.UI.Client/src/views/common/drawers/help/help.html index 4829c8964a..79c2118aca 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/drawers/help/help.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/drawers/help/help.html @@ -1,130 +1,133 @@ - +
            + - - + + - + - -
            + +
            -
            Tours
            - -
            +
            Tours
            + +
            -
            +
            - -
            - {{tourGroup.group}} - Other -
            - - -
            + +
            + {{tourGroup.group}} + Other +
            + + +
            -
            -
            -
            -
            -
            {{ $index + 1 }}
            - - {{ tour.name }} -
            -
            - - +
            +
            +
            +
            +
            {{ $index + 1 }}
            + + {{ tour.name }} +
            +
            + + +
            +
            -
            - - -
            -
            - \ No newline at end of file From f473ff879583aa1caa9eaf1ad2e19c54a36b3b23 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 31 May 2018 11:23:29 +0200 Subject: [PATCH 021/115] fix translations for users overview --- .../src/views/users/overview.controller.js | 69 ++++++++++++------- 1 file changed, 46 insertions(+), 23 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/users/overview.controller.js b/src/Umbraco.Web.UI.Client/src/views/users/overview.controller.js index 4eb3402baa..abe287ed88 100644 --- a/src/Umbraco.Web.UI.Client/src/views/users/overview.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/users/overview.controller.js @@ -15,37 +15,60 @@ //note on the below, we dont assign a view unless it's the right route since if we did that it will load in that controller //for the view which is unecessary and will cause extra overhead/requests to occur vm.page = {}; - vm.page.name = localizationService.localize("user_userManagement"); - vm.page.navigation = [ - { - "name": localizationService.localize("sections_users"), - "icon": "icon-user", - "action": function() { - $location.search("subview", "users") - }, - "view": !usersUri || usersUri === "users" ? "views/users/views/users/users.html" : null, - "active": !usersUri || usersUri === "users" - }, - { - "name": localizationService.localize("general_groups"), - "icon": "icon-users", - "action": function () { - $location.search("subview", "groups") - }, - "view": usersUri === "groups" ? "views/users/views/groups/groups.html" : null, - "active": usersUri === "groups" - } - ]; + vm.page.labels = {}; + vm.page.name = ""; + vm.page.navigation = []; - function init() { + function onInit() { + + loadNavigation(); + + setPageName(); $timeout(function () { navigationService.syncTree({ tree: "users", path: "-1" }); }); } + + function loadNavigation() { + + var labels = ["sections_users", "general_groups"]; + + localizationService.localizeMany(labels).then(function(data){ + vm.page.labels.users = data[0]; + vm.page.labels.groups = data[1]; + + vm.page.navigation = [ + { + "name": vm.page.labels.users, + "icon": "icon-user", + "action": function() { + $location.search("subview", "users") + }, + "view": !usersUri || usersUri === "users" ? "views/users/views/users/users.html" : null, + "active": !usersUri || usersUri === "users" + }, + { + "name": vm.page.labels.groups, + "icon": "icon-users", + "action": function () { + $location.search("subview", "groups") + }, + "view": usersUri === "groups" ? "views/users/views/groups/groups.html" : null, + "active": usersUri === "groups" + } + ]; + }); + } + + function setPageName() { + localizationService.localize("user_userManagement").then(function(data){ + vm.page.name = data; + }) + } - init(); + onInit(); } From 3a9b2069af07a29c9349c73e6ea9e456fe138456 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 31 May 2018 11:30:15 +0200 Subject: [PATCH 022/115] fix localisation in umbControlGroup --- .../components/html/umbcontrolgroup.directive.js | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/html/umbcontrolgroup.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/html/umbcontrolgroup.directive.js index c4382240c0..bd2f0ca0b3 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/html/umbcontrolgroup.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/html/umbcontrolgroup.directive.js @@ -31,14 +31,20 @@ angular.module("umbraco.directives.html") }; if (scope.label && scope.label[0] === "@") { - scope.labelstring = localizationService.localize(scope.label.substring(1)); + localizationService.localize(scope.label.substring(1)) + .then(function(data){ + scope.labelstring = data; + }); } else { scope.labelstring = scope.label; } if (scope.description && scope.description[0] === "@") { - scope.descriptionstring = localizationService.localize(scope.description.substring(1)); + localizationService.localize(scope.description.substring(1)) + .then(function(data){ + scope.descriptionstring = data; + }); } else { scope.descriptionstring = scope.description; From 07b0faadd9b210a17127d35acf37610eeef7ab40 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 31 May 2018 12:43:56 +0200 Subject: [PATCH 023/115] move ng-controller to its own element --- .../datatypepicker/datatypepicker.html | 251 +++++++++--------- 1 file changed, 127 insertions(+), 124 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/datatypepicker/datatypepicker.html b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/datatypepicker/datatypepicker.html index 2c8cd91af4..fabc03f5df 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/datatypepicker/datatypepicker.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/datatypepicker/datatypepicker.html @@ -1,136 +1,139 @@ - +
            + -
            + - - + + - - - + + + - -
            - - - -
            - - - -
            -
            -
            {{key}}
            - -
            -
            -
            -
            -
            {{key}}
            - -
            -
            -
            -
            -
            - -
            -
            -
            -
            -
            {{key}}
            - +
            +
            +
            +
            {{key}}
            + +
            +
            + + +
            + +
            +
            +
            +
            +
            {{key}}
            + +
            +
            +
            +
            +
            +
            {{key}}
            + +
            -
            -
            -
            -
            {{key}}
            - -
            -
            -
            - - - + + + - - - - - - + + + + + + - + - \ No newline at end of file + + +
            \ No newline at end of file From a07c43a7901cabd2fac75c59bf67890b4f964d70 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 31 May 2018 12:44:23 +0200 Subject: [PATCH 024/115] fix localisation in data type picker --- .../datatypepicker.controller.js | 57 +++++++++++++------ 1 file changed, 39 insertions(+), 18 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/datatypepicker/datatypepicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/datatypepicker/datatypepicker.controller.js index ae4eeaa02f..bd2a60f50e 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/datatypepicker/datatypepicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/datatypepicker/datatypepicker.controller.js @@ -14,29 +14,14 @@ var vm = this; - if (!$scope.model.title) { - $scope.model.title = localizationService.localize("defaultdialogs_selectEditor"); - } - vm.searchTerm = ""; vm.showTabs = false; vm.tabsLoaded = 0; vm.typesAndEditors = []; vm.userConfigured = []; vm.loading = false; - vm.tabs = [{ - active: true, - id: 1, - label: localizationService.localize("contentTypeEditor_availableEditors"), - alias: "Default", - typesAndEditors: [] - }, { - active: false, - id: 2, - label: localizationService.localize("contentTypeEditor_reuse"), - alias: "Reuse", - userConfigured: [] - }]; + vm.tabs = []; + vm.labels = {}; vm.filterItems = filterItems; vm.showDetailsOverlay = showDetailsOverlay; @@ -46,12 +31,48 @@ vm.close = close; function activate() { - + setTitle(); + loadTabs(); getGroupedDataTypes(); getGroupedPropertyEditors(); } + function setTitle() { + if (!$scope.model.title) { + localizationService.localize("defaultdialogs_selectEditor") + .then(function(data){ + $scope.model.title = data; + }); + } + } + + function loadTabs() { + + var labels = ["contentTypeEditor_availableEditors", "contentTypeEditor_reuse"]; + + localizationService.localizeMany(labels) + .then(function(data){ + vm.labels.availableDataTypes = data[0]; + vm.labels.reuse = data[1]; + + vm.tabs = [{ + active: true, + id: 1, + label: vm.labels.availableDataTypes, + alias: "Default", + typesAndEditors: [] + }, { + active: false, + id: 2, + label: vm.labels.reuse, + alias: "Reuse", + userConfigured: [] + }]; + + }); + } + function getGroupedPropertyEditors() { vm.loading = true; From 3829936d06137f7918e303c272a019c2786fab11 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 31 May 2018 12:56:36 +0200 Subject: [PATCH 025/115] move ng-controller --- .../common/infiniteeditors/iconpicker/iconpicker.html | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/iconpicker/iconpicker.html b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/iconpicker/iconpicker.html index b39d3e956d..320e0cee8a 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/iconpicker/iconpicker.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/iconpicker/iconpicker.html @@ -1,6 +1,9 @@ -
            + - + Date: Thu, 31 May 2018 12:57:08 +0200 Subject: [PATCH 026/115] Fix title localisation --- .../iconpicker/iconpicker.controller.js | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/iconpicker/iconpicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/iconpicker/iconpicker.controller.js index 175bab3dee..f428e64e3e 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/iconpicker/iconpicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/iconpicker/iconpicker.controller.js @@ -17,9 +17,7 @@ function IconPickerController($scope, iconHelper, localizationService) { vm.loading = true; - if (!$scope.model.title) { - $scope.model.title = localizationService.localize("defaultdialogs_selectIcon"); - } + setTitle(); iconHelper.getIcons().then(function (icons) { vm.icons = icons; @@ -28,6 +26,15 @@ function IconPickerController($scope, iconHelper, localizationService) { } + function setTitle() { + if (!$scope.model.title) { + localizationService.localize("defaultdialogs_selectIcon") + .then(function(data){ + $scope.model.title = data; + }); + } + } + function selectIcon(icon, color) { $scope.model.icon = icon; $scope.model.color = color; From 078e45b7ea8860eba6d41fce721b0105be389927 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 1 Jun 2018 09:40:41 +0200 Subject: [PATCH 027/115] move ng-controller in media picker to its own element --- .../common/infiniteeditors/mediapicker/mediapicker.html | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/mediapicker.html b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/mediapicker.html index b87451cce1..f17a08dd47 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/mediapicker.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/mediapicker.html @@ -1,4 +1,5 @@ - +
            + - \ No newline at end of file + + +
            \ No newline at end of file From 0aec09a258e67f10f71ca6987e53fbc795f07911 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 1 Jun 2018 10:05:45 +0200 Subject: [PATCH 028/115] temp fix to bring infinite editors back to life --- .../views/components/editor/umb-editors.html | 24 +++++++++++++++---- 1 file changed, 20 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editors.html b/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editors.html index 6211889d4d..6f04b702b2 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editors.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editors.html @@ -1,6 +1,22 @@
            - - + + + + + +
            +
            +
            +
            +
            +
            From 6d84e1bb40295935b306cbbf9dde95ccad20e950 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 1 Jun 2018 10:09:19 +0200 Subject: [PATCH 029/115] move ng-controller to its own element --- .../infiniteeditors/datatypesettings/datatypesettings.html | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/datatypesettings/datatypesettings.html b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/datatypesettings/datatypesettings.html index 63ac035441..edba569dd2 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/datatypesettings/datatypesettings.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/datatypesettings/datatypesettings.html @@ -1,4 +1,5 @@ - +
            + @@ -65,4 +66,5 @@ - \ No newline at end of file + +
            \ No newline at end of file From b8a77b866157d0c121d532731e44d860cdc02bc3 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 1 Jun 2018 12:19:22 +0200 Subject: [PATCH 030/115] fix localisation in property settings editor --- .../propertysettings.controller.js | 92 ++++++++++++------- 1 file changed, 60 insertions(+), 32 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/propertysettings/propertysettings.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/propertysettings/propertysettings.controller.js index d6afa3f395..f5dcc55b9f 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/propertysettings/propertysettings.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/propertysettings/propertysettings.controller.js @@ -18,32 +18,8 @@ vm.focusOnPatternField = false; vm.focusOnMandatoryField = false; vm.selectedValidationType = {}; - vm.validationTypes = [ - { - "name": localizationService.localize("validation_validateAsEmail"), - "key": "email", - "pattern": "[a-zA-Z0-9_\.\+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-\.]+", - "enableEditing": true - }, - { - "name": localizationService.localize("validation_validateAsNumber"), - "key": "number", - "pattern": "^[0-9]*$", - "enableEditing": true - }, - { - "name": localizationService.localize("validation_validateAsUrl"), - "key": "url", - "pattern": "https?\:\/\/[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,}", - "enableEditing": true - }, - { - "name": localizationService.localize("validation_enterCustomValidation"), - "key": "custom", - "pattern": "", - "enableEditing": true - } - ]; + vm.validationTypes = []; + vm.labels = {}; vm.changeValidationType = changeValidationType; vm.changeValidationPattern = changeValidationPattern; @@ -53,17 +29,69 @@ vm.submit = submit; vm.close = close; - userService.getCurrentUser().then(function(user) { - vm.showSensitiveData = user.userGroups.indexOf("sensitiveData") != -1; - }); + function onInit() { + + userService.getCurrentUser().then(function(user) { + vm.showSensitiveData = user.userGroups.indexOf("sensitiveData") != -1; + }); - function activate() { //make the default the same as the content type if (!$scope.model.property.id) { $scope.model.property.allowCultureVariant = $scope.model.contentTypeAllowCultureVariant; } - matchValidationType(); + loadValidationTypes(); + + } + + function loadValidationTypes() { + + var labels = [ + "validation_validateAsEmail", + "validation_validateAsNumber", + "validation_validateAsUrl", + "validation_enterCustomValidation" + ]; + + localizationService.localizeMany(labels) + .then(function(data){ + + vm.labels.validateAsEmail = data[0]; + vm.labels.validateAsNumber = data[1]; + vm.labels.validateAsUrl = data[2]; + vm.labels.customValidation = data[3]; + + vm.validationTypes = [ + { + "name": vm.labels.validateAsEmail, + "key": "email", + "pattern": "[a-zA-Z0-9_\.\+-]+@[a-zA-Z0-9-]+\.[a-zA-Z0-9-\.]+", + "enableEditing": true + }, + { + "name": vm.labels.validateAsNumber, + "key": "number", + "pattern": "^[0-9]*$", + "enableEditing": true + }, + { + "name": vm.labels.validateAsUrl, + "key": "url", + "pattern": "https?\:\/\/[a-zA-Z0-9\-\.]+\.[a-zA-Z]{2,}", + "enableEditing": true + }, + { + "name": vm.labels.customValidation, + "key": "custom", + "pattern": "", + "enableEditing": true + } + ]; + + matchValidationType(); + + }); + } function changeValidationPattern() { @@ -205,7 +233,7 @@ } - activate(); + onInit(); } From 328f83c0c7458b41d3f5987c6914f86767bd2f1c Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 1 Jun 2018 12:39:07 +0200 Subject: [PATCH 031/115] fix title on media picker --- .../infiniteeditors/mediapicker/mediapicker.controller.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/mediapicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/mediapicker.controller.js index 6bbd5984ee..1d34482358 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/mediapicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/mediapicker/mediapicker.controller.js @@ -4,7 +4,10 @@ angular.module("umbraco") function($scope, mediaResource, umbRequestHelper, entityResource, $log, mediaHelper, mediaTypeHelper, eventsService, treeService, $element, $timeout, $cookies, localStorageService, localizationService, editorService) { if (!$scope.model.title) { - $scope.model.title = localizationService.localize("defaultdialogs_selectMedia"); + localizationService.localize("defaultdialogs_selectMedia") + .then(function(data){ + $scope.model.title = data; + }); } var dialogOptions = $scope.model; From 0216bea233dd5d820bb9dd99b7db15ed969309a1 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Fri, 1 Jun 2018 14:59:45 +0200 Subject: [PATCH 032/115] dropzone can now upload files again --- .../src/views/components/upload/umb-file-dropzone.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/components/upload/umb-file-dropzone.html b/src/Umbraco.Web.UI.Client/src/views/components/upload/umb-file-dropzone.html index 211060c03f..03d1a84908 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/upload/umb-file-dropzone.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/upload/umb-file-dropzone.html @@ -4,7 +4,7 @@
            From fefb6e4454605878e0cd610c17f1b88f5c00ccb8 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 4 Jun 2018 12:08:19 +0200 Subject: [PATCH 033/115] fix more localisation issues --- .../datatypepicker.controller.js | 1 - .../datatypesettings.controller.js | 14 +++++- .../propertysettings.controller.js | 1 - .../src/views/mediatypes/edit.controller.js | 50 ++++++++++++------- .../src/views/membertypes/edit.controller.js | 21 +++++--- 5 files changed, 59 insertions(+), 28 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/datatypepicker/datatypepicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/datatypepicker/datatypepicker.controller.js index bd2a60f50e..4f706f23e8 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/datatypepicker/datatypepicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/datatypepicker/datatypepicker.controller.js @@ -137,7 +137,6 @@ function pickEditor(propertyEditor) { var dataTypeSettings = { - title: localizationService.localize("contentTypeEditor_editorSettings"), propertyEditor: propertyEditor, property: $scope.model.property, contentTypeName: $scope.model.contentTypeName, diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/datatypesettings/datatypesettings.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/datatypesettings/datatypesettings.controller.js index f20c8c5d6f..9fbbad8f09 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/datatypesettings/datatypesettings.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/datatypesettings/datatypesettings.controller.js @@ -10,7 +10,7 @@ (function () { "use strict"; - function DataTypeSettingsController($scope, dataTypeResource, dataTypeHelper) { + function DataTypeSettingsController($scope, dataTypeResource, dataTypeHelper, localizationService) { var vm = this; @@ -22,6 +22,9 @@ vm.submit = submit; function onInit() { + + setTitle(); + if($scope.model.create) { createNewDataType(); } else { @@ -29,6 +32,15 @@ } } + function setTitle() { + if(!$scope.model.title) { + localizationService.localize("contentTypeEditor_editorSettings") + .then(function(data){ + $scope.model.title = data; + }); + } + } + function createNewDataType() { vm.loadingDataType = true; diff --git a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/propertysettings/propertysettings.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/propertysettings/propertysettings.controller.js index f5dcc55b9f..1366eb10e4 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/propertysettings/propertysettings.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/infiniteeditors/propertysettings/propertysettings.controller.js @@ -137,7 +137,6 @@ vm.focusOnMandatoryField = false; var dataTypeSettings = { - title: "Data type settings", view: "views/common/infiniteeditors/datatypesettings/datatypesettings.html", id: property.dataTypeId, submit: function(model) { diff --git a/src/Umbraco.Web.UI.Client/src/views/mediatypes/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/mediatypes/edit.controller.js index f4898ce653..5e7e93fcd9 100644 --- a/src/Umbraco.Web.UI.Client/src/views/mediatypes/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/mediatypes/edit.controller.js @@ -21,25 +21,41 @@ vm.page = {}; vm.page.loading = false; vm.page.saveButtonState = "init"; - vm.page.navigation = [ - { - "name": localizationService.localize("general_design"), - "icon": "icon-document-dashed-line", - "view": "views/mediatypes/views/design/design.html", - "active": true - }, - { - "name": localizationService.localize("general_listView"), - "icon": "icon-list", - "view": "views/mediatypes/views/listview/listview.html" - }, - { - "name": localizationService.localize("general_rights"), - "icon": "icon-keychain", - "view": "views/mediatypes/views/permissions/permissions.html" - } + vm.labels = {}; + + var labelKeys = [ + "general_design", + "general_listView", + "general_rights" ]; + localizationService.localizeMany(labelKeys).then(function (values) { + + vm.labels.design = values[0]; + vm.labels.listview = values[1]; + vm.labels.permissions = values[2]; + + vm.page.navigation = [ + { + "name": vm.labels.design, + "icon": "icon-document-dashed-line", + "view": "views/mediatypes/views/design/design.html", + "active": true + }, + { + "name": vm.labels.listview, + "icon": "icon-list", + "view": "views/mediatypes/views/listview/listview.html" + }, + { + "name": vm.labels.permissions, + "icon": "icon-keychain", + "view": "views/mediatypes/views/permissions/permissions.html" + } + ]; + + }); + vm.page.keyboardShortcutsOverview = [ { "name": localizationService.localize("main_sections"), diff --git a/src/Umbraco.Web.UI.Client/src/views/membertypes/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/membertypes/edit.controller.js index b94ce9f032..64d560d9ec 100644 --- a/src/Umbraco.Web.UI.Client/src/views/membertypes/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/membertypes/edit.controller.js @@ -20,14 +20,19 @@ vm.page = {}; vm.page.loading = false; vm.page.saveButtonState = "init"; - vm.page.navigation = [ - { - "name": localizationService.localize("general_design"), - "icon": "icon-document-dashed-line", - "view": "views/membertypes/views/design/design.html", - "active": true - } - ]; + vm.labels = {}; + + localizationService.localize("general_design").then(function(data){ + vm.labels.design = data; + vm.page.navigation = [ + { + "name": vm.labels.design, + "icon": "icon-document-dashed-line", + "view": "views/membertypes/views/design/design.html", + "active": true + } + ]; + }); vm.page.keyboardShortcutsOverview = [ { From 2b5ef7b45c12febc10790106142b6500a5080dce Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 4 Jun 2018 13:48:36 +0200 Subject: [PATCH 034/115] change angular.lowercase() to .toLowerCase() --- .../boolean/boolean.controller.js | 2 +- .../colorpicker/colorpicker.controller.js | 36 +++++++++---------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/boolean/boolean.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/boolean/boolean.controller.js index 422f761851..123af3fc72 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/boolean/boolean.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/boolean/boolean.controller.js @@ -9,7 +9,7 @@ function booleanEditorController($scope, $rootScope, assetsService) { $scope.renderModel.value = true; } - if ($scope.model && $scope.model.value && ($scope.model.value.toString() === "1" || angular.lowercase($scope.model.value) === "true")) { + if ($scope.model && $scope.model.value && ($scope.model.value.toString() === "1" || $scope.model.value.toString().toLowerCase() === "true")) { $scope.renderModel.value = true; } } diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/colorpicker/colorpicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/colorpicker/colorpicker.controller.js index 5230f9ef2c..56ef917510 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/colorpicker/colorpicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/colorpicker/colorpicker.controller.js @@ -12,42 +12,42 @@ function ColorPickerController($scope) { $scope.model.useLabel = isTrue($scope.model.config.useLabel); initActiveColor(); } - + $scope.toggleItem = function (color) { var currentColor = ($scope.model.value && $scope.model.value.hasOwnProperty("value")) ? $scope.model.value.value : $scope.model.value; - var newColor; + var newColor; if (currentColor === color.value) { // deselect $scope.model.value = $scope.model.useLabel ? { value: "", label: "" } : ""; newColor = ""; } else { - // select + // select $scope.model.value = $scope.model.useLabel ? { value: color.value, label: color.label } : color.value; - newColor = color.value; + newColor = color.value; } // this is required to re-validate $scope.propertyForm.modelValue.$setViewValue(newColor); }; - - // Method required by the valPropertyValidator directive (returns true if the property editor has at least one color selected) + + // Method required by the valPropertyValidator directive (returns true if the property editor has at least one color selected) $scope.validateMandatory = function () { var isValid = !$scope.model.validation.mandatory || ( $scope.model.value != null && $scope.model.value != "" && (!$scope.model.value.hasOwnProperty("value") || $scope.model.value.value !== "") - ); - return { - isValid: isValid, - errorMsg: "Value cannot be empty", - errorKey: "required" - }; - } + ); + return { + isValid: isValid, + errorMsg: "Value cannot be empty", + errorKey: "required" + }; + } $scope.isConfigured = $scope.model.config && $scope.model.config.items && _.keys($scope.model.config.items).length > 0; // A color is active if it matches the value and label of the model. @@ -124,8 +124,8 @@ function ColorPickerController($scope) { // figures out if a value is trueish enough function isTrue(bool) { - return !!bool && bool !== "0" && angular.lowercase(bool) !== "false"; - } -} - -angular.module("umbraco").controller("Umbraco.PropertyEditors.ColorPickerController", ColorPickerController); + return !!bool && bool !== "0" && bool.toString().toLowerCase() !== "false"; + } +} + +angular.module("umbraco").controller("Umbraco.PropertyEditors.ColorPickerController", ColorPickerController); From 4dbec70f000163172e2aa7c363682faa8eca4da4 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 4 Jun 2018 21:26:34 +0200 Subject: [PATCH 035/115] fix localisation for node publish state --- .../content/umbcontentnodeinfo.directive.js | 29 +++++++++++++++---- 1 file changed, 23 insertions(+), 6 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbcontentnodeinfo.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbcontentnodeinfo.directive.js index 703d1b8717..d93df1cdd5 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbcontentnodeinfo.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/umbcontentnodeinfo.directive.js @@ -7,12 +7,31 @@ var evts = []; var isInfoTab = false; + var labels = {}; scope.publishStatus = {}; scope.disableTemplates = Umbraco.Sys.ServerVariables.features.disabledFeatures.disableTemplates; function onInit() { + var keys = [ + "general_deleted", + "content_unpublished", + "content_published", + "content_publishedPendingChanges" + ]; + + localizationService.localizeMany(keys) + .then(function(data){ + labels.deleted = data[0]; + labels.unpublished = data[1]; + labels.published = data[2]; + labels.publishedPendingChanges = data[3]; + + setNodePublishStatus(scope.node); + + }); + scope.allowOpen = true; scope.datePickerConfig = { @@ -40,8 +59,6 @@ // make sure dates are formatted to the user's locale formatDatesToLocal(); - - setNodePublishStatus(scope.node); } @@ -125,25 +142,25 @@ // deleted node if(node.trashed === true) { - scope.publishStatus.label = localizationService.localize("general_deleted"); + scope.publishStatus.label = labels.deleted; scope.publishStatus.color = "danger"; } // unpublished node if(node.published === false && node.trashed === false) { - scope.publishStatus.label = localizationService.localize("content_unpublished"); + scope.publishStatus.label = labels.unpublished; scope.publishStatus.color = "gray"; } // published node if(node.publishDate && node.published === true) { - scope.publishStatus.label = localizationService.localize("content_published"); + scope.publishStatus.label = labels.published; scope.publishStatus.color = "success"; } // published node with pending changes if (node.edited === true && node.publishDate) { - scope.publishStatus.label = localizationService.localize("content_publishedPendingChanges"); + scope.publishStatus.label = labels.publishedPendingChanges; scope.publishStatus.color = "success" } From 6697c67f38d9e8a9c6468022e2064ea5567521a8 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 4 Jun 2018 22:44:12 +0200 Subject: [PATCH 036/115] fix keys for keyboard shortcuts in content type editors --- .../views/documenttypes/edit.controller.js | 154 ++++++++++-------- .../src/views/mediatypes/edit.controller.js | 135 ++++++++------- .../src/views/membertypes/edit.controller.js | 69 +++++--- 3 files changed, 208 insertions(+), 150 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/documenttypes/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/documenttypes/edit.controller.js index 1451a3d0c4..69d12fcb73 100644 --- a/src/Umbraco.Web.UI.Client/src/views/documenttypes/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/documenttypes/edit.controller.js @@ -31,14 +31,36 @@ "general_design", "general_listView", "general_rights", - "treeHeaders_templates" + "treeHeaders_templates", + "main_sections", + "shortcuts_navigateSections", + "shortcuts_addTab", + "shortcuts_addProperty", + "shortcuts_addEditor", + "shortcuts_editDataType", + "shortcuts_toggleListView", + "shortcuts_toggleAllowAsRoot", + "shortcuts_addChildNode", + "shortcuts_addTemplate" ]; localizationService.localizeMany(labelKeys).then(function (values) { + // navigation vm.labels.design = values[0]; vm.labels.listview = values[1]; vm.labels.permissions = values[2]; vm.labels.templates = values[3]; + // keyboard shortcuts + vm.labels.sections = values[4]; + vm.labels.navigateSections = values[5]; + vm.labels.addTab = values[6]; + vm.labels.addProperty = values[7]; + vm.labels.addEditor = values[8]; + vm.labels.editDataType = values[9]; + vm.labels.toggleListView = values[10]; + vm.labels.allowAsRoot = values[11]; + vm.labels.addChildNode = values[12]; + vm.labels.addTemplate = values[13]; var buttons = [ { @@ -68,75 +90,75 @@ } ]; + vm.page.keyboardShortcutsOverview = [ + { + "name": vm.labels.sections, + "shortcuts": [ + { + "description": vm.labels.navigateSections, + "keys": [{ "key": "1" }, { "key": "4" }], + "keyRange": true + } + ] + }, + { + "name": vm.labels.design, + "shortcuts": [ + { + "description": vm.labels.addTab, + "keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "t" }] + }, + { + "description": vm.labels.addProperty, + "keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "p" }] + }, + { + "description": vm.labels.addEditor, + "keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "e" }] + }, + { + "description": vm.labels.editDataType, + "keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "d" }] + } + ] + }, + { + "name": vm.labels.listview, + "shortcuts": [ + { + "description": vm.labels.toggleListView, + "keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "l" }] + } + ] + }, + { + "name": vm.labels.permissions, + "shortcuts": [ + { + "description": vm.labels.allowAsRoot, + "keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "r" }] + }, + { + "description": vm.labels.addChildNode, + "keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "c" }] + } + ] + }, + { + "name": vm.labels.templates, + "shortcuts": [ + { + "description": vm.labels.addTemplate, + "keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "t" }] + } + ] + } + ]; + loadButtons(buttons); }); - vm.page.keyboardShortcutsOverview = [ - { - "name": localizationService.localize("main_sections"), - "shortcuts": [ - { - "description": localizationService.localize("shortcuts_navigateSections"), - "keys": [{ "key": "1" }, { "key": "4" }], - "keyRange": true - } - ] - }, - { - "name": localizationService.localize("general_design"), - "shortcuts": [ - { - "description": localizationService.localize("shortcuts_addTab"), - "keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "t" }] - }, - { - "description": localizationService.localize("shortcuts_addProperty"), - "keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "p" }] - }, - { - "description": localizationService.localize("shortcuts_addEditor"), - "keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "e" }] - }, - { - "description": localizationService.localize("shortcuts_editDataType"), - "keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "d" }] - } - ] - }, - { - "name": localizationService.localize("general_listView"), - "shortcuts": [ - { - "description": localizationService.localize("shortcuts_toggleListView"), - "keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "l" }] - } - ] - }, - { - "name": localizationService.localize("general_rights"), - "shortcuts": [ - { - "description": localizationService.localize("shortcuts_toggleAllowAsRoot"), - "keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "r" }] - }, - { - "description": localizationService.localize("shortcuts_addChildNode"), - "keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "c" }] - } - ] - }, - { - "name": localizationService.localize("treeHeaders_templates"), - "shortcuts": [ - { - "description": localizationService.localize("shortcuts_addTemplate"), - "keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "t" }] - } - ] - } - ]; - contentTypeHelper.checkModelsBuilderStatus().then(function (result) { vm.page.modelsBuilder = result; if (result) { diff --git a/src/Umbraco.Web.UI.Client/src/views/mediatypes/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/mediatypes/edit.controller.js index 5e7e93fcd9..47377ae01b 100644 --- a/src/Umbraco.Web.UI.Client/src/views/mediatypes/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/mediatypes/edit.controller.js @@ -26,14 +26,34 @@ var labelKeys = [ "general_design", "general_listView", - "general_rights" + "general_rights", + + "main_sections", + "shortcuts_navigateSections", + "shortcuts_addTab", + "shortcuts_addProperty", + "shortcuts_addEditor", + "shortcuts_editDataType", + "shortcuts_toggleListView", + "shortcuts_toggleAllowAsRoot", + "shortcuts_addChildNode" ]; localizationService.localizeMany(labelKeys).then(function (values) { - + // navigation vm.labels.design = values[0]; vm.labels.listview = values[1]; vm.labels.permissions = values[2]; + // keyboard shortcuts + vm.labels.sections = values[3]; + vm.labels.navigateSections = values[4]; + vm.labels.addTab = values[5]; + vm.labels.addProperty = values[6]; + vm.labels.addEditor = values[7]; + vm.labels.editDataType = values[8]; + vm.labels.toggleListView = values[9]; + vm.labels.allowAsRoot = values[10]; + vm.labels.addChildNode = values[11]; vm.page.navigation = [ { @@ -54,64 +74,63 @@ } ]; + vm.page.keyboardShortcutsOverview = [ + { + "name": vm.labels.sections, + "shortcuts": [ + { + "description": vm.labels.navigateSections, + "keys": [{ "key": "1" }, { "key": "3" }], + "keyRange": true + } + ] + }, + { + "name": vm.labels.design, + "shortcuts": [ + { + "description": vm.labels.addTab, + "keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "t" }] + }, + { + "description": vm.labels.addProperty, + "keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "p" }] + }, + { + "description": vm.labels.addEditor, + "keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "e" }] + }, + { + "description": vm.labels.editDataType, + "keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "d" }] + } + ] + }, + { + "name": vm.labels.listview, + "shortcuts": [ + { + "description": vm.labels.toggleListView, + "keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "l" }] + } + ] + }, + { + "name": vm.labels.permissions, + "shortcuts": [ + { + "description": vm.labels.allowAsRoot, + "keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "r" }] + }, + { + "description": vm.labels.addChildNode, + "keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "c" }] + } + ] + } + ]; }); - vm.page.keyboardShortcutsOverview = [ - { - "name": localizationService.localize("main_sections"), - "shortcuts": [ - { - "description": localizationService.localize("shortcuts_navigateSections"), - "keys": [{ "key": "1" }, { "key": "3" }], - "keyRange": true - } - ] - }, - { - "name": localizationService.localize("general_design"), - "shortcuts": [ - { - "description": localizationService.localize("shortcuts_addTab"), - "keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "t" }] - }, - { - "description": localizationService.localize("shortcuts_addProperty"), - "keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "p" }] - }, - { - "description": localizationService.localize("shortcuts_addEditor"), - "keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "e" }] - }, - { - "description": localizationService.localize("shortcuts_editDataType"), - "keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "d" }] - } - ] - }, - { - "name": localizationService.localize("general_listView"), - "shortcuts": [ - { - "description": localizationService.localize("shortcuts_toggleListView"), - "keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "l" }] - } - ] - }, - { - "name": localizationService.localize("general_rights"), - "shortcuts": [ - { - "description": localizationService.localize("shortcuts_toggleAllowAsRoot"), - "keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "r" }] - }, - { - "description": localizationService.localize("shortcuts_addChildNode"), - "keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "c" }] - } - ] - } - ]; - contentTypeHelper.checkModelsBuilderStatus().then(function (result) { vm.page.modelsBuilder = result; if (result) { diff --git a/src/Umbraco.Web.UI.Client/src/views/membertypes/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/membertypes/edit.controller.js index 64d560d9ec..27fc36bc0c 100644 --- a/src/Umbraco.Web.UI.Client/src/views/membertypes/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/membertypes/edit.controller.js @@ -22,8 +22,24 @@ vm.page.saveButtonState = "init"; vm.labels = {}; - localizationService.localize("general_design").then(function(data){ - vm.labels.design = data; + var labelKeys = [ + "general_design", + "shortcuts_shortcut", + "shortcuts_addTab", + "shortcuts_addProperty", + "shortcuts_addEditor", + "shortcuts_editDataType" + ]; + + localizationService.localizeMany(labelKeys).then(function(values){ + + vm.labels.design = values[0]; + vm.labels.shortcut = values[1]; + vm.labels.addTab = values[2]; + vm.labels.addProperty = values[3]; + vm.labels.addEditor = values[4]; + vm.labels.editDataType = values[5]; + vm.page.navigation = [ { "name": vm.labels.design, @@ -32,31 +48,32 @@ "active": true } ]; - }); - vm.page.keyboardShortcutsOverview = [ - { - "name": localizationService.localize("shortcuts_shortcut"), - "shortcuts": [ - { - "description": localizationService.localize("shortcuts_addTab"), - "keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "t" }] - }, - { - "description": localizationService.localize("shortcuts_addProperty"), - "keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "p" }] - }, - { - "description": localizationService.localize("shortcuts_addEditor"), - "keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "e" }] - }, - { - "description": localizationService.localize("shortcuts_editDataType"), - "keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "d" }] - } - ] - } - ]; + vm.page.keyboardShortcutsOverview = [ + { + "name": vm.labels.shortcut, + "shortcuts": [ + { + "description": vm.labels.addTab, + "keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "t" }] + }, + { + "description": vm.labels.addProperty, + "keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "p" }] + }, + { + "description": vm.labels.addEditor, + "keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "e" }] + }, + { + "description": vm.labels.editDataType, + "keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "d" }] + } + ] + } + ]; + + }); contentTypeHelper.checkModelsBuilderStatus().then(function (result) { vm.page.modelsBuilder = result; From 2330ff334b6f2f5792ee14ad54a8fa0a2319a116 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 5 Jun 2018 11:24:16 +0200 Subject: [PATCH 037/115] fix content-type in request header when saving content --- .../src/common/services/umbrequesthelper.service.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js index 7a2e91fdde..5d561585fd 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js @@ -300,9 +300,9 @@ function umbRequestHelper($http, $q, umbDataFormatter, angularHelper, dialogServ url: url, //IMPORTANT!!! You might think this should be set to 'multipart/form-data' but this is not true because when we are sending up files // the request needs to include a 'boundary' parameter which identifies the boundary name between parts in this multi-part request - // and setting the Content-type manually will not set this boundary parameter. For whatever reason, setting the Content-type to 'false' + // and setting the Content-type manually will not set this boundary parameter. For whatever reason, setting the Content-type to 'undefined' // will force the request to automatically populate the headers properly including the boundary parameter. - headers: { 'Content-Type': false }, + headers: { 'Content-Type': undefined }, transformRequest: function (data) { var formData = new FormData(); //add the json data From 99589789dd92f748992424baac4e06bbe67a1614 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 5 Jun 2018 15:20:35 +0200 Subject: [PATCH 038/115] renames onlyinitialized because angular thinks its an onclick --- .../common/directives/components/tree/umbtree.directive.js | 4 ++-- .../src/views/common/overlays/treepicker/treepicker.html | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/tree/umbtree.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/tree/umbtree.directive.js index d7743d4bac..8e38420886 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/tree/umbtree.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/tree/umbtree.directive.js @@ -17,7 +17,7 @@ function umbTreeDirective($compile, $log, $q, $rootScope, treeService, notificat hideheader: '@', cachekey: '@', isdialog: '@', - onlyinitialized: '@', + onlyInitialized: '@', //Custom query string arguments to pass in to the tree as a string, example: "startnodeid=123&something=value" customtreeparams: '@', enablecheckboxes: '@', @@ -258,7 +258,7 @@ function umbTreeDirective($compile, $log, $q, $rootScope, treeService, notificat deleteAnimations = false; //default args - var args = { section: $scope.section, tree: $scope.treealias, cacheKey: $scope.cachekey, isDialog: $scope.isdialog ? $scope.isdialog : false, onlyinitialized: $scope.onlyinitialized }; + var args = { section: $scope.section, tree: $scope.treealias, cacheKey: $scope.cachekey, isDialog: $scope.isdialog ? $scope.isdialog : false, onlyinitialized: $scope.onlyInitialized }; //add the extra query string params if specified if ($scope.customtreeparams) { diff --git a/src/Umbraco.Web.UI.Client/src/views/common/overlays/treepicker/treepicker.html b/src/Umbraco.Web.UI.Client/src/views/common/overlays/treepicker/treepicker.html index 1beffb585e..80b930bf6a 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/overlays/treepicker/treepicker.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/overlays/treepicker/treepicker.html @@ -37,12 +37,12 @@ hideheader="{{vm.hideHeader}}" hideoptions="true" isdialog="true" - onlyinitialized="{{vm.onlyInitialized}}" + only-initialized="{{vm.onlyInitialized}}" customtreeparams="{{vm.customTreeParams}}" enablelistviewsearch="true" enablelistviewexpand="true" - enablecheckboxes="{{vm.multiPicker}}" - on-init="vm.initDialogTree()" + enablecheckboxes="{{vm.multiPicker}}" + on-init="vm.initDialogTree()" api="vm.dialogTreeApi">
            From 7287d8c565fd3c99dc828a37069618a34488be4a Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 5 Jun 2018 15:21:18 +0200 Subject: [PATCH 039/115] move hideoptions to ng-class --- .../src/common/directives/components/tree/umbtree.directive.js | 2 -- .../src/views/components/tree/umb-tree.html | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/tree/umbtree.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/tree/umbtree.directive.js index 8e38420886..07b3158a2a 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/tree/umbtree.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/tree/umbtree.directive.js @@ -28,8 +28,6 @@ function umbTreeDirective($compile, $log, $q, $rootScope, treeService, notificat }, controller: function ($scope, $element) { - $scope.hideoptions = ($scope.hideoptions === 'true') ? "hide-options" : ""; - var vm = this; var registeredCallbacks = { diff --git a/src/Umbraco.Web.UI.Client/src/views/components/tree/umb-tree.html b/src/Umbraco.Web.UI.Client/src/views/components/tree/umb-tree.html index f26c2c1352..d30d9fb83a 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/tree/umb-tree.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/tree/umb-tree.html @@ -1,4 +1,4 @@ -
              +
              • From 394fa9215a2f57c4cc26455bddb4c004562be205 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 5 Jun 2018 19:58:58 +0200 Subject: [PATCH 040/115] fix title in insert overlay --- .../overlays/insert/insert.controller.js | 26 +++++++++++++------ 1 file changed, 18 insertions(+), 8 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/common/overlays/insert/insert.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/overlays/insert/insert.controller.js index ed82ff0d76..a46dd14781 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/overlays/insert/insert.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/overlays/insert/insert.controller.js @@ -5,19 +5,27 @@ var vm = this; - if(!$scope.model.title) { - $scope.model.title = localizationService.localize("template_insert"); - } - - if(!$scope.model.subtitle) { - $scope.model.subtitle = localizationService.localize("template_insertDesc"); - } - vm.openMacroPicker = openMacroPicker; vm.openPageFieldOverlay = openPageFieldOverlay; vm.openDictionaryItemOverlay = openDictionaryItemOverlay; vm.openPartialOverlay = openPartialOverlay; + function onInit() { + + if(!$scope.model.title) { + localizationService.localize("template_insert").then(function(value){ + $scope.model.title = value; + }); + } + + if(!$scope.model.subtitle) { + localizationService.localize("template_insertDesc").then(function(value){ + $scope.model.subtitle = value; + }); + } + + } + function openMacroPicker() { vm.macroPickerOverlay = { @@ -137,6 +145,8 @@ }; } + onInit(); + } angular.module("umbraco").controller("Umbraco.Overlays.InsertOverlay", InsertOverlayController); From ccd8ecd05529f30a1d12d716b23459d1d0e9b8c5 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 5 Jun 2018 20:22:56 +0200 Subject: [PATCH 041/115] add title to query builder --- .../common/overlays/querybuilder/querybuilder.controller.js | 6 ++++++ .../src/views/templates/edit.controller.js | 1 - 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/common/overlays/querybuilder/querybuilder.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/overlays/querybuilder/querybuilder.controller.js index 176f23f687..7c1c6c78f3 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/overlays/querybuilder/querybuilder.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/overlays/querybuilder/querybuilder.controller.js @@ -34,6 +34,12 @@ function onInit() { + if(!$scope.model.title) { + localizationService.localize("template_queryBuilder").then(function(value){ + $scope.model.title = value; + }); + } + vm.query = { contentType: { name: everything diff --git a/src/Umbraco.Web.UI.Client/src/views/templates/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/templates/edit.controller.js index 92076ff605..6e5d10db83 100644 --- a/src/Umbraco.Web.UI.Client/src/views/templates/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/templates/edit.controller.js @@ -483,7 +483,6 @@ vm.queryBuilderOverlay = { view: "querybuilder", show: true, - title: localizationService.localize("template_queryBuilder"), submit: function (model) { var code = templateHelper.getQuerySnippet(model.result.queryExpression); From a9a274dea5ca6adde3115475d230bbe56d1d989d Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 5 Jun 2018 21:03:43 +0200 Subject: [PATCH 042/115] Added an empty "/" route to default to "content" --- src/Umbraco.Web.UI.Client/src/routes.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/routes.js b/src/Umbraco.Web.UI.Client/src/routes.js index cf6af40d4b..e4b7466155 100644 --- a/src/Umbraco.Web.UI.Client/src/routes.js +++ b/src/Umbraco.Web.UI.Client/src/routes.js @@ -89,6 +89,9 @@ app.config(function ($routeProvider) { } $routeProvider + .when("/", { + redirectTo: '/content' + }) .when('/login', { templateUrl: 'views/common/login.html', //ensure auth is *not* required so it will redirect to / From 764a706143aab9241f44ec830c8da933ecdefb11 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 6 Jun 2018 09:09:05 +0200 Subject: [PATCH 043/115] fix copy-dialog title --- .../common/overlays/copy/copy.controller.js | 24 ++++++++++++------- .../listview/listview.controller.js | 1 - 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/common/overlays/copy/copy.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/overlays/copy/copy.controller.js index 47e078d33c..5de36dfd44 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/overlays/copy/copy.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/overlays/copy/copy.controller.js @@ -5,10 +5,6 @@ var vm = this; - if(!$scope.model.title) { - $scope.model.title = localizationService.localize("general_copy"); - } - vm.hideSearch = hideSearch; vm.selectResult = selectResult; vm.onSearchResults = onSearchResults; @@ -17,10 +13,6 @@ var searchText = "Search..."; var node = dialogOptions.currentNode; - localizationService.localize("general_search").then(function (value) { - searchText = value + "..."; - }); - $scope.model.relateToOriginal = true; $scope.dialogTreeApi = {}; @@ -35,6 +27,21 @@ // get entity type based on the section $scope.entityType = entityHelper.getEntityTypeFromSection(dialogOptions.section); + function onInit() { + + if(!$scope.model.title) { + localizationService.localize("general_copy").then(function (value) { + $scope.model.title = value; + }); + } + + localizationService.localize("general_search").then(function (value) { + searchText = value + "..."; + }); + + } + + function nodeSelectHandler(args) { if(args && args.event) { args.event.preventDefault(); @@ -98,6 +105,7 @@ $scope.miniListView = node; } + onInit(); } diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.controller.js index e736c12f1c..c53415cf7a 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.controller.js @@ -503,7 +503,6 @@ function listViewController($rootScope, $scope, $routeParams, $injector, notific $scope.copy = function () { $scope.copyDialog = {}; - $scope.copyDialog.title = localizationService.localize("general_copy"); $scope.copyDialog.section = $scope.entityType; $scope.copyDialog.currentNode = $scope.contentId; $scope.copyDialog.view = "copy"; From 11a0b36ff090e172c2c094532bd447f95544cd86 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 6 Jun 2018 09:12:57 +0200 Subject: [PATCH 044/115] fix move-dialog title --- .../common/overlays/move/move.controller.js | 24 ++++++++++++------- .../listview/listview.controller.js | 1 - 2 files changed, 16 insertions(+), 9 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/common/overlays/move/move.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/overlays/move/move.controller.js index adf616a603..bccf7487bb 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/overlays/move/move.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/overlays/move/move.controller.js @@ -13,14 +13,6 @@ var searchText = "Search..."; var node = dialogOptions.currentNode; - localizationService.localize("general_search").then(function (value) { - searchText = value + "..."; - }); - - if(!$scope.model.title) { - $scope.model.title = localizationService.localize("actions_move"); - } - $scope.model.relateToOriginal = true; $scope.dialogTreeApi = {}; @@ -35,6 +27,20 @@ // get entity type based on the section $scope.entityType = entityHelper.getEntityTypeFromSection(dialogOptions.section); + function onInit() { + + if (!$scope.model.title) { + localizationService.localize("actions_move").then(function (value) { + $scope.model.title = value; + }); + } + + localizationService.localize("general_search").then(function (value) { + searchText = value + "..."; + }); + + } + function nodeSelectHandler(args) { if(args && args.event) { @@ -99,6 +105,8 @@ $scope.miniListView = node; } + onInit(); + } angular.module("umbraco").controller("Umbraco.Overlays.MoveOverlay", MoveOverlay); diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.controller.js index c53415cf7a..4b88223bbf 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.controller.js @@ -432,7 +432,6 @@ function listViewController($rootScope, $scope, $routeParams, $injector, notific $scope.move = function() { $scope.moveDialog = {}; - $scope.moveDialog.title = localizationService.localize("general_move"); $scope.moveDialog.section = $scope.entityType; $scope.moveDialog.currentNode = $scope.contentId; $scope.moveDialog.view = "move"; From c2aa3e9d0645cd08476c27315d0225af77abad0b Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 6 Jun 2018 09:58:49 +0200 Subject: [PATCH 045/115] fix title in macro dialog --- .../overlays/macropicker/macropicker.controller.js | 14 +++++++++----- .../src/views/templates/edit.controller.js | 1 - 2 files changed, 9 insertions(+), 6 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/common/overlays/macropicker/macropicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/overlays/macropicker/macropicker.controller.js index 69f9851926..c858ca03b9 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/overlays/macropicker/macropicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/overlays/macropicker/macropicker.controller.js @@ -1,10 +1,5 @@ function MacroPickerController($scope, entityResource, macroResource, umbPropEditorHelper, macroService, formHelper, localizationService) { - - if(!$scope.model.title) { - $scope.model.title = localizationService.localize("defaultdialogs_selectMacro"); - } - $scope.macros = []; $scope.model.selectedMacro = null; $scope.model.macroParams = []; @@ -12,6 +7,14 @@ function MacroPickerController($scope, entityResource, macroResource, umbPropEdi $scope.wizardStep = "macroSelect"; $scope.noMacroParams = false; + function onInit() { + if(!$scope.model.title) { + localizationService.localize("defaultdialogs_selectMacro").then(function(value){ + $scope.model.title = value; + }); + } + } + $scope.selectMacro = function (macro) { $scope.model.selectedMacro = macro; @@ -121,6 +124,7 @@ function MacroPickerController($scope, entityResource, macroResource, umbPropEdi $scope.wizardStep = "macroSelect"; }); + onInit(); } diff --git a/src/Umbraco.Web.UI.Client/src/views/templates/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/templates/edit.controller.js index 6e5d10db83..6632d4140f 100644 --- a/src/Umbraco.Web.UI.Client/src/views/templates/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/templates/edit.controller.js @@ -375,7 +375,6 @@ view: "macropicker", dialogData: {}, show: true, - title: localizationService.localize("template_insertMacro"), submit: function (model) { var macroObject = macroService.collectValueData(model.selectedMacro, model.macroParams, "Mvc"); From ed1d7fb2c5c6402a50fb4d29b91cda105e672d06 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 6 Jun 2018 09:59:21 +0200 Subject: [PATCH 046/115] fix title in embed dialog --- .../common/overlays/embed/embed.controller.js | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/common/overlays/embed/embed.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/overlays/embed/embed.controller.js index 0ae93baf27..c64430d9fe 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/overlays/embed/embed.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/overlays/embed/embed.controller.js @@ -7,10 +7,6 @@ var origWidth = 500; var origHeight = 300; - if(!$scope.model.title) { - $scope.model.title = localizationService.localize("general_embed"); - } - $scope.model.embed = { url: "", width: 360, @@ -25,6 +21,14 @@ vm.showPreview = showPreview; vm.changeSize = changeSize; + function onInit() { + if(!$scope.model.title) { + localizationService.localize("general_embed").then(function(value){ + $scope.model.title = value; + }); + } + } + function showPreview() { if ($scope.model.embed.url) { @@ -95,6 +99,8 @@ } + onInit(); + } angular.module("umbraco").controller("Umbraco.Overlays.EmbedOverlay", EmbedOverlay); From b98aa215c3ec9b2ed59c7c0c03ab63cb75ec33d6 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 6 Jun 2018 10:15:50 +0200 Subject: [PATCH 047/115] fix title in insert field dialog --- .../common/overlays/insertfield/insertfield.controller.js | 6 ++++-- .../src/views/templates/edit.controller.js | 1 - 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/common/overlays/insertfield/insertfield.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/overlays/insertfield/insertfield.controller.js index 7cdd25285a..ebe2feabb9 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/overlays/insertfield/insertfield.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/overlays/insertfield/insertfield.controller.js @@ -1,7 +1,7 @@ (function () { "use strict"; - function InsertFieldController($scope, $http, contentTypeResource) { + function InsertFieldController($scope, $http, contentTypeResource, localizationService) { var vm = this; @@ -34,7 +34,9 @@ // set default title if(!$scope.model.title) { - $scope.model.title = "Insert value"; + localizationService.localize("template_insertPageField").then(function(value){ + $scope.model.title = value; + }); } // Load all fields diff --git a/src/Umbraco.Web.UI.Client/src/views/templates/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/templates/edit.controller.js index 6632d4140f..2335105d3a 100644 --- a/src/Umbraco.Web.UI.Client/src/views/templates/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/templates/edit.controller.js @@ -401,7 +401,6 @@ closeButtonlabel: "Cancel", view: "insertfield", show: true, - title: localizationService.localize("template_insertPageField"), submit: function (model) { insert(model.umbracoField); vm.pageFieldOverlay.show = false; From 3f6ac3fcd6114bef3f79a14ba8cbda081077caba Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 6 Jun 2018 10:36:16 +0200 Subject: [PATCH 048/115] fix titles for dictionary items and partial views dialog --- .../src/views/templates/edit.controller.js | 122 ++++++++++-------- 1 file changed, 70 insertions(+), 52 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/templates/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/templates/edit.controller.js index 2335105d3a..72e39c3b48 100644 --- a/src/Umbraco.Web.UI.Client/src/views/templates/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/templates/edit.controller.js @@ -418,63 +418,81 @@ function openDictionaryItemOverlay() { - vm.dictionaryItemOverlay = { - view: "treepicker", - section: "settings", - treeAlias: "dictionary", - entityType: "dictionary", - multiPicker: false, - show: true, - title: localizationService.localize("template_insertDictionaryItem"), - emptyStateMessage: localizationService.localize("emptyStates_emptyDictionaryTree"), - select: function(node){ - var code = templateHelper.getInsertDictionarySnippet(node.name); - insert(code); - vm.dictionaryItemOverlay.show = false; - vm.dictionaryItemOverlay = null; - }, - close: function (model) { - // close dialog - vm.dictionaryItemOverlay.show = false; - vm.dictionaryItemOverlay = null; - // focus editor - vm.editor.focus(); - } - }; + var labelKeys = [ + "template_insertDictionaryItem", + "emptyStates_emptyDictionaryTree" + ]; + + localizationService.localizeMany(labelKeys).then(function(values){ + var title = values[0]; + var emptyStateMessage = values[1]; + + vm.dictionaryItemOverlay = { + view: "treepicker", + section: "settings", + treeAlias: "dictionary", + entityType: "dictionary", + multiPicker: false, + show: true, + title: title, + emptyStateMessage: emptyStateMessage, + select: function(node){ + var code = templateHelper.getInsertDictionarySnippet(node.name); + insert(code); + + vm.dictionaryItemOverlay.show = false; + vm.dictionaryItemOverlay = null; + }, + close: function (model) { + // close dialog + vm.dictionaryItemOverlay.show = false; + vm.dictionaryItemOverlay = null; + // focus editor + vm.editor.focus(); + } + }; + + }); + } function openPartialOverlay() { - vm.partialItemOverlay = { - view: "treepicker", - section: "settings", - treeAlias: "partialViews", - entityType: "partialView", - multiPicker: false, - show: true, - title: localizationService.localize("template_insertPartialView"), - filter: function(i) { - if(i.name.indexOf(".cshtml") === -1 && i.name.indexOf(".vbhtml") === -1) { - return true; - } - }, - filterCssClass: "not-allowed", - select: function(node){ - - var code = templateHelper.getInsertPartialSnippet(node.parentId, node.name); - insert(code); - vm.partialItemOverlay.show = false; - vm.partialItemOverlay = null; - }, - close: function (model) { - // close dialog - vm.partialItemOverlay.show = false; - vm.partialItemOverlay = null; - // focus editor - vm.editor.focus(); - } - }; + localizationService.localize("template_insertPartialView").then(function(value){ + var title = value; + + vm.partialItemOverlay = { + view: "treepicker", + section: "settings", + treeAlias: "partialViews", + entityType: "partialView", + multiPicker: false, + show: true, + title: title, + filter: function(i) { + if(i.name.indexOf(".cshtml") === -1 && i.name.indexOf(".vbhtml") === -1) { + return true; + } + }, + filterCssClass: "not-allowed", + select: function(node){ + + var code = templateHelper.getInsertPartialSnippet(node.parentId, node.name); + insert(code); + + vm.partialItemOverlay.show = false; + vm.partialItemOverlay = null; + }, + close: function (model) { + // close dialog + vm.partialItemOverlay.show = false; + vm.partialItemOverlay = null; + // focus editor + vm.editor.focus(); + } + }; + }); } function openQueryBuilderOverlay() { From 33be5a496090576fc1f69f6427ed80994a006ef5 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 6 Jun 2018 10:59:35 +0200 Subject: [PATCH 049/115] fixing titles in the insert dialog --- .../overlays/insert/insert.controller.js | 132 ++++++++++-------- 1 file changed, 73 insertions(+), 59 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/common/overlays/insert/insert.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/overlays/insert/insert.controller.js index a46dd14781..e4c27fa63b 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/overlays/insert/insert.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/overlays/insert/insert.controller.js @@ -30,7 +30,6 @@ vm.macroPickerOverlay = { view: "macropicker", - title: localizationService.localize("template_insertMacro"), dialogData: {}, show: true, submit: function(model) { @@ -53,8 +52,6 @@ function openPageFieldOverlay() { vm.pageFieldOverlay = { - title: localizationService.localize("template_insertPageField"), - description: localizationService.localize("template_insertPageFieldDesc"), submitButtonLabel: "Insert", closeButtonlabel: "Cancel", view: "insertfield", @@ -80,69 +77,86 @@ function openDictionaryItemOverlay() { - vm.dictionaryItemOverlay = { - view: "treepicker", - section: "settings", - treeAlias: "dictionary", - entityType: "dictionary", - multiPicker: false, - title: localizationService.localize("template_insertDictionaryItem"), - description: localizationService.localize("template_insertDictionaryItemDesc"), - emptyStateMessage: localizationService.localize("emptyStates_emptyDictionaryTree"), - show: true, - select: function(node){ + var labelKeys = [ + "template_insertDictionaryItem", + "template_insertDictionaryItemDesc", + "emptyStates_emptyDictionaryTree" + ]; - $scope.model.insert = { - "type": "dictionary", - "node": node - }; + localizationService.localizeMany(labelKeys).then(function(values){ + var title = values[0]; + var subtitle = values[1]; + var emptyStateMessage = values[2]; - $scope.model.submit($scope.model); - - vm.dictionaryItemOverlay.show = false; - vm.dictionaryItemOverlay = null; - }, - - close: function(model) { - vm.dictionaryItemOverlay.show = false; - vm.dictionaryItemOverlay = null; - } - }; + vm.dictionaryItemOverlay = { + view: "treepicker", + section: "settings", + treeAlias: "dictionary", + entityType: "dictionary", + multiPicker: false, + title: title, + subtitle: subtitle, + emptyStateMessage: emptyStateMessage, + show: true, + select: function(node){ + + $scope.model.insert = { + "type": "dictionary", + "node": node + }; + + $scope.model.submit($scope.model); + + vm.dictionaryItemOverlay.show = false; + vm.dictionaryItemOverlay = null; + }, + + close: function(model) { + vm.dictionaryItemOverlay.show = false; + vm.dictionaryItemOverlay = null; + } + }; + }); } function openPartialOverlay() { - vm.partialItemOverlay = { - view: "treepicker", - section: "settings", - treeAlias: "partialViews", - entityType: "partialView", - multiPicker: false, - filter: function(i) { - if(i.name.indexOf(".cshtml") === -1 && i.name.indexOf(".vbhtml") === -1) { - return true; + localizationService.localize("template_insertPartialView").then(function(value){ + var title = value; + + vm.partialItemOverlay = { + view: "treepicker", + section: "settings", + treeAlias: "partialViews", + entityType: "partialView", + multiPicker: false, + title: title, + filter: function(i) { + if(i.name.indexOf(".cshtml") === -1 && i.name.indexOf(".vbhtml") === -1) { + return true; + } + }, + filterCssClass: "not-allowed", + show: true, + select: function(node){ + + $scope.model.insert = { + "type": "partial", + "node": node + }; + + $scope.model.submit($scope.model); + + vm.partialItemOverlay.show = false; + vm.partialItemOverlay = null; + }, + + close: function (model) { + vm.partialItemOverlay.show = false; + vm.partialItemOverlay = null; } - }, - filterCssClass: "not-allowed", - title: localizationService.localize("template_insertPartialView"), - show: true, - select: function(node){ - - $scope.model.insert = { - "type": "partial", - "node": node - }; + }; - $scope.model.submit($scope.model); - - vm.partialItemOverlay.show = false; - vm.partialItemOverlay = null; - }, - - close: function (model) { - vm.partialItemOverlay.show = false; - vm.partialItemOverlay = null; - } - }; + }); } onInit(); From eb6da7a41aef390c2c9312d37e85294784a7895e Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 6 Jun 2018 11:26:34 +0200 Subject: [PATCH 050/115] fixing item picker title and master template title --- .../itempicker/itempicker.controller.js | 14 +++-- .../src/views/templates/edit.controller.js | 56 ++++++++++--------- 2 files changed, 40 insertions(+), 30 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/common/overlays/itempicker/itempicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/overlays/itempicker/itempicker.controller.js index a848c0ae90..9e758a5b21 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/overlays/itempicker/itempicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/overlays/itempicker/itempicker.controller.js @@ -1,16 +1,22 @@ function ItemPickerOverlay($scope, localizationService) { - if (!$scope.model.title) { - $scope.model.title = localizationService.localize("defaultdialogs_selectItem"); - } + function onInit() { + $scope.model.hideSubmitButton = true; - $scope.model.hideSubmitButton = true; + if (!$scope.model.title) { + localizationService.localize("defaultdialogs_selectItem").then(function(value){ + $scope.model.title = value; + }); + } + } $scope.selectItem = function(item) { $scope.model.selectedItem = item; $scope.submitForm($scope.model); }; + onInit(); + } angular.module("umbraco").controller("Umbraco.Overlays.ItemPickerOverlay", ItemPickerOverlay); diff --git a/src/Umbraco.Web.UI.Client/src/views/templates/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/templates/edit.controller.js index 72e39c3b48..571dc05286 100644 --- a/src/Umbraco.Web.UI.Client/src/views/templates/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/templates/edit.controller.js @@ -569,34 +569,38 @@ } }); - vm.masterTemplateOverlay = { - view: "itempicker", - title: localizationService.localize("template_mastertemplate"), - availableItems: availableMasterTemplates, - show: true, - submit: function(model) { + localizationService.localize("template_mastertemplate").then(function(value){ + var title = value; - var template = model.selectedItem; - - if (template && template.alias) { - vm.template.masterTemplateAlias = template.alias; - setLayout(template.alias + ".cshtml"); - } else { - vm.template.masterTemplateAlias = null; - setLayout(null); + vm.masterTemplateOverlay = { + view: "itempicker", + title: title, + availableItems: availableMasterTemplates, + show: true, + submit: function(model) { + + var template = model.selectedItem; + + if (template && template.alias) { + vm.template.masterTemplateAlias = template.alias; + setLayout(template.alias + ".cshtml"); + } else { + vm.template.masterTemplateAlias = null; + setLayout(null); + } + + vm.masterTemplateOverlay.show = false; + vm.masterTemplateOverlay = null; + }, + close: function(oldModel) { + // close dialog + vm.masterTemplateOverlay.show = false; + vm.masterTemplateOverlay = null; + // focus editor + vm.editor.focus(); } - - vm.masterTemplateOverlay.show = false; - vm.masterTemplateOverlay = null; - }, - close: function(oldModel) { - // close dialog - vm.masterTemplateOverlay.show = false; - vm.masterTemplateOverlay = null; - // focus editor - vm.editor.focus(); - } - }; + }; + }); } From d9df6e12be582b812ab4ec069ea9ef752f0ac5a8 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 6 Jun 2018 13:18:46 +0200 Subject: [PATCH 051/115] fix loading of recycle bin controller --- .../src/views/content/recyclebin.html | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/content/recyclebin.html b/src/Umbraco.Web.UI.Client/src/views/content/recyclebin.html index 7e45549ea7..3e2c032df7 100644 --- a/src/Umbraco.Web.UI.Client/src/views/content/recyclebin.html +++ b/src/Umbraco.Web.UI.Client/src/views/content/recyclebin.html @@ -1,16 +1,19 @@ - -
                - + + + + - -
                - + +
                +
                \ No newline at end of file From b5333fe2d6de08591484f5cc52b2fb536a140820 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 6 Jun 2018 13:19:34 +0200 Subject: [PATCH 052/115] make sure the placeholder template name and alias is updated correcly so you can create doc types --- .../views/templates/templates.controller.js | 9 +++++++-- .../views/documenttypes/views/templates/templates.html | 2 +- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/documenttypes/views/templates/templates.controller.js b/src/Umbraco.Web.UI.Client/src/views/documenttypes/views/templates/templates.controller.js index fe1b0f0e7e..2aa856ba66 100644 --- a/src/Umbraco.Web.UI.Client/src/views/documenttypes/views/templates/templates.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/documenttypes/views/templates/templates.controller.js @@ -17,13 +17,14 @@ vm.availableTemplates = []; vm.updateTemplatePlaceholder = false; + vm.loadingTemplates = false; /* ---------- INIT ---------- */ - init(); + function onInit() { - function init() { + vm.loadingTemplates = true; entityResource.getAll("Template").then(function(templates){ @@ -35,10 +36,14 @@ vm.availableTemplates = contentTypeHelper.insertTemplatePlaceholder(vm.availableTemplates); } + vm.loadingTemplates = false; + }); } + onInit(); + } angular.module("umbraco").controller("Umbraco.Editors.DocumentType.TemplatesController", TemplatesController); diff --git a/src/Umbraco.Web.UI.Client/src/views/documenttypes/views/templates/templates.html b/src/Umbraco.Web.UI.Client/src/views/documenttypes/views/templates/templates.html index c3bc28a145..0be23bd934 100644 --- a/src/Umbraco.Web.UI.Client/src/views/documenttypes/views/templates/templates.html +++ b/src/Umbraco.Web.UI.Client/src/views/documenttypes/views/templates/templates.html @@ -10,7 +10,7 @@
                Date: Wed, 6 Jun 2018 20:38:21 +0200 Subject: [PATCH 053/115] fix more localize problems --- .../overlays/usergrouppicker/usergrouppicker.controller.js | 4 +++- .../views/common/overlays/userpicker/userpicker.controller.js | 4 +++- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/common/overlays/usergrouppicker/usergrouppicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/overlays/usergrouppicker/usergrouppicker.controller.js index 81d5d27de7..b86c7286f7 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/overlays/usergrouppicker/usergrouppicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/overlays/usergrouppicker/usergrouppicker.controller.js @@ -18,7 +18,9 @@ // set default title if(!$scope.model.title) { - $scope.model.title = localizationService.localize("defaultdialogs_selectUsers"); + localizationService.localize("defaultdialogs_selectUsers").then(function(value){ + $scope.model.title = value; + }); } // make sure we can push to something diff --git a/src/Umbraco.Web.UI.Client/src/views/common/overlays/userpicker/userpicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/overlays/userpicker/userpicker.controller.js index 2d55f9d431..2ccd17934b 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/overlays/userpicker/userpicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/overlays/userpicker/userpicker.controller.js @@ -21,7 +21,9 @@ // set default title if(!$scope.model.title) { - $scope.model.title = localizationService.localize("defaultdialogs_selectUsers"); + localizationService.localize("defaultdialogs_selectUsers").then(function(value){ + $scope.model.title = value; + }); } // make sure we can push to something From 297c4a8e7383de6ec6ead03d8a1dc69d71294dce Mon Sep 17 00:00:00 2001 From: Stephan Date: Mon, 11 Jun 2018 12:31:33 +0200 Subject: [PATCH 054/115] Fix new media not showing in published cache --- .../PublishedCache/NuCache/DataSource/DatabaseDataSource.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web/PublishedCache/NuCache/DataSource/DatabaseDataSource.cs b/src/Umbraco.Web/PublishedCache/NuCache/DataSource/DatabaseDataSource.cs index 3c241d1c15..fdc18b43aa 100644 --- a/src/Umbraco.Web/PublishedCache/NuCache/DataSource/DatabaseDataSource.cs +++ b/src/Umbraco.Web/PublishedCache/NuCache/DataSource/DatabaseDataSource.cs @@ -141,7 +141,7 @@ namespace Umbraco.Web.PublishedCache.NuCache.DataSource .OrderBy(x => x.Level, x => x.SortOrder); var dto = scope.Database.Fetch(sql).FirstOrDefault(); - return dto == null ? new ContentNodeKit() : CreateContentNodeKit(dto); + return dto == null ? new ContentNodeKit() : CreateMediaNodeKit(dto); } public IEnumerable GetAllMediaSources(IScope scope) From c89423946a601196d6c9425d0ba61bfe584cb22a Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 11 Jun 2018 13:16:29 +0200 Subject: [PATCH 055/115] fix more localisation labels --- .../components/content/edit.controller.js | 1 - .../linkpicker/linkpicker.controller.js | 4 +- .../mediaPicker/mediapicker.controller.js | 4 +- .../membergrouppicker.controller.js | 24 ++- .../overlays/publish/publish.controller.js | 7 + .../sectionpicker/sectionpicker.controller.js | 4 +- .../treepicker/treepicker.controller.js | 198 +++++++++--------- .../common/overlays/user/user.controller.js | 4 +- .../common/overlays/ysod/ysod.controller.js | 42 ++-- .../dashboard/dashboard.tabs.controller.js | 28 ++- .../developer/redirecturls.controller.js | 25 ++- .../permissions/permissions.controller.js | 4 +- .../src/views/languages/edit.controller.js | 4 +- 13 files changed, 207 insertions(+), 142 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js index 17bbc95bf1..a4fa759aa6 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js @@ -320,7 +320,6 @@ if (formHelper.submitForm({ scope: $scope, action: "publish"})) { var dialog = { - title: localizationService.localize("content_readyToPublish"), view: "publish", variants: $scope.content.variants, //set a model property for the dialog skipFormValidation: true, //when submitting the overlay form, skip any client side validation diff --git a/src/Umbraco.Web.UI.Client/src/views/common/overlays/linkpicker/linkpicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/overlays/linkpicker/linkpicker.controller.js index 653403a0f5..9bbf38568f 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/overlays/linkpicker/linkpicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/overlays/linkpicker/linkpicker.controller.js @@ -9,7 +9,9 @@ angular.module("umbraco").controller("Umbraco.Overlays.LinkPickerController", }); if(!$scope.model.title) { - $scope.model.title = localizationService.localize("defaultdialogs_selectLink"); + localizationService.localize("defaultdialogs_selectLink").then(function(value){ + $scope.model.title = value; + }); } $scope.dialogTreeApi = {}; diff --git a/src/Umbraco.Web.UI.Client/src/views/common/overlays/mediaPicker/mediapicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/overlays/mediaPicker/mediapicker.controller.js index ccb033a57c..c3f95dd026 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/overlays/mediaPicker/mediapicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/overlays/mediaPicker/mediapicker.controller.js @@ -4,7 +4,9 @@ angular.module("umbraco") function($scope, mediaResource, umbRequestHelper, entityResource, $log, mediaHelper, mediaTypeHelper, eventsService, treeService, $element, $timeout, $cookies, localStorageService, localizationService) { if (!$scope.model.title) { - $scope.model.title = localizationService.localize("defaultdialogs_selectMedia"); + localizationService.localize("defaultdialogs_selectMedia").then(function(value){ + $scope.model.title = value; + }); } var dialogOptions = $scope.model; diff --git a/src/Umbraco.Web.UI.Client/src/views/common/overlays/membergrouppicker/membergrouppicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/overlays/membergrouppicker/membergrouppicker.controller.js index d60f3c32f5..482732e3a3 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/overlays/membergrouppicker/membergrouppicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/overlays/membergrouppicker/membergrouppicker.controller.js @@ -2,20 +2,22 @@ angular.module("umbraco").controller("Umbraco.Overlays.MemberGroupPickerController", function($scope, eventsService, entityResource, searchService, $log, localizationService) { - if(!$scope.model.title) { - $scope.model.title = localizationService.localize("defaultdialogs_selectMemberGroup"); - } - $scope.dialogTreeApi = {}; $scope.multiPicker = $scope.model.multiPicker; function activate() { - if($scope.multiPicker) { - $scope.model.selectedMemberGroups = []; - } else { - $scope.model.selectedMemberGroup = ""; - } + if(!$scope.model.title) { + localizationService.localize("defaultdialogs_selectMemberGroup").then(function(value){ + $scope.model.title = value; + }); + } + + if ($scope.multiPicker) { + $scope.model.selectedMemberGroups = []; + } else { + $scope.model.selectedMemberGroup = ""; + } } @@ -52,8 +54,8 @@ angular.module("umbraco").controller("Umbraco.Overlays.MemberGroupPickerControll //toggle checked state args.node.selected = args.node.selected === true ? false : true; } - - $scope.onTreeInit = function () { + + $scope.onTreeInit = function () { $scope.dialogTreeApi.callbacks.treeNodeSelect(nodeSelectHandler); }; diff --git a/src/Umbraco.Web.UI.Client/src/views/common/overlays/publish/publish.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/overlays/publish/publish.controller.js index cebbdea7fd..c18bb0b888 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/overlays/publish/publish.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/overlays/publish/publish.controller.js @@ -47,6 +47,13 @@ } function onInit() { + + if(!$scope.model.title) { + localizationService.localize("content_readyToPublish").then(function(value){ + $scope.model.title = value; + }); + } + vm.hasPristineVariants = false; _.each(vm.variants, diff --git a/src/Umbraco.Web.UI.Client/src/views/common/overlays/sectionpicker/sectionpicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/overlays/sectionpicker/sectionpicker.controller.js index e13f4e6dcd..f39da7074d 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/overlays/sectionpicker/sectionpicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/overlays/sectionpicker/sectionpicker.controller.js @@ -18,7 +18,9 @@ // set default title if(!$scope.model.title) { - $scope.model.title = localizationService.localize("defaultdialogs_selectSections"); + localizationService.localize("defaultdialogs_selectSections").then(function(value){ + $scope.model.title = value; + }); } // make sure we can push to something diff --git a/src/Umbraco.Web.UI.Client/src/views/common/overlays/treepicker/treepicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/overlays/treepicker/treepicker.controller.js index aea4e6051d..ecf1bfe548 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/overlays/treepicker/treepicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/overlays/treepicker/treepicker.controller.js @@ -14,21 +14,21 @@ angular.module("umbraco").controller("Umbraco.Overlays.TreePickerController", mediaResource, memberResource, languageResource) { - - //used as the result selection - $scope.model.selection = []; - - //the tree object when it loads - var tree = null; - + + //used as the result selection + $scope.model.selection = []; + + //the tree object when it loads + var tree = null; + // Search and listviews is only working for content, media and member section - var searchableSections = ["content", "media", "member"]; - // tracks all expanded paths so when the language is switched we can resync it with the already loaded paths - var expandedPaths = []; - - var vm = this; - vm.treeReady = false; - vm.dialogTreeApi = {}; + var searchableSections = ["content", "media", "member"]; + // tracks all expanded paths so when the language is switched we can resync it with the already loaded paths + var expandedPaths = []; + + var vm = this; + vm.treeReady = false; + vm.dialogTreeApi = {}; vm.initDialogTree = initDialogTree; vm.section = $scope.model.section; vm.treeAlias = $scope.model.treeAlias; @@ -42,7 +42,7 @@ angular.module("umbraco").controller("Umbraco.Overlays.TreePickerController", showSearch: false, results: [], selectedSearchResults: [] - } + } vm.startNodeId = $scope.model.startNodeId; //Used for toggling an empty-state message //Some trees can have no items (dictionary & forms email templates) @@ -50,32 +50,32 @@ angular.module("umbraco").controller("Umbraco.Overlays.TreePickerController", vm.emptyStateMessage = $scope.model.emptyStateMessage; vm.languages = []; vm.selectedLanguage = {}; - vm.languageSelectorIsOpen = false; - vm.showLanguageSelector = $scope.model.showLanguageSelector; + vm.languageSelectorIsOpen = false; + vm.showLanguageSelector = $scope.model.showLanguageSelector; // Allow the entity type to be passed in but defaults to Document for backwards compatibility. - vm.entityType = $scope.model.entityType ? $scope.model.entityType : "Document"; - vm.enableSearh = searchableSections.indexOf(vm.section) !== -1; - - - vm.toggleLanguageSelector = toggleLanguageSelector; - vm.selectLanguage = selectLanguage; - vm.onSearchResults = onSearchResults; - vm.hideSearch = hideSearch; - vm.closeMiniListView = closeMiniListView; - vm.selectListViewNode = selectListViewNode; - - function initDialogTree() { - vm.dialogTreeApi.callbacks.treeLoaded(treeLoadedHandler); + vm.entityType = $scope.model.entityType ? $scope.model.entityType : "Document"; + vm.enableSearh = searchableSections.indexOf(vm.section) !== -1; + + + vm.toggleLanguageSelector = toggleLanguageSelector; + vm.selectLanguage = selectLanguage; + vm.onSearchResults = onSearchResults; + vm.hideSearch = hideSearch; + vm.closeMiniListView = closeMiniListView; + vm.selectListViewNode = selectListViewNode; + + function initDialogTree() { + vm.dialogTreeApi.callbacks.treeLoaded(treeLoadedHandler); //TODO: Also deal with unexpanding!! vm.dialogTreeApi.callbacks.treeNodeExpanded(nodeExpandedHandler); vm.dialogTreeApi.callbacks.treeNodeSelect(nodeSelectHandler); - } - + } + /** * Performs the initialization of this component */ - function onInit () { - + function onInit () { + // load languages languageResource.getAll().then(function (languages) { vm.languages = languages; @@ -87,26 +87,32 @@ angular.module("umbraco").controller("Umbraco.Overlays.TreePickerController", vm.languageSelectorIsOpen = false; } }); - }); + }); if (vm.treeAlias === "content") { vm.entityType = "Document"; if (!$scope.model.title) { - $scope.model.title = localizationService.localize("defaultdialogs_selectContent"); + localizationService.localize("defaultdialogs_selectContent").then(function(value){ + $scope.model.title = value; + }); } - } + } else if (vm.treeAlias === "member" || vm.section) { vm.entityType = "Member"; if (!$scope.model.title) { - $scope.model.title = localizationService.localize("defaultdialogs_selectMember"); + localizationService.localize("defaultdialogs_selectMember").then(function(value){ + $scope.model.title = value; + }) } - } + } else if (vm.treeAlias === "media" || vm.section === "media") { vm.entityType = "Media"; if (!$scope.model.title) { - $scope.model.title = localizationService.localize("defaultdialogs_selectMedia"); + localizationService.localize("defaultdialogs_selectMedia").then(function(value){ + $scope.model.title = value; + }); } - } + } //TODO: Seems odd this logic is here, i don't think it needs to be and should just exist on the property editor using this if ($scope.model.minNumber) { @@ -127,7 +133,7 @@ angular.module("umbraco").controller("Umbraco.Overlays.TreePickerController", } initTree(); }); - } + } else { initTree(); } @@ -141,10 +147,10 @@ angular.module("umbraco").controller("Umbraco.Overlays.TreePickerController", //used advanced filtering if (angular.isFunction($scope.model.filter)) { $scope.model.filterAdvanced = true; - } + } else if (angular.isObject($scope.model.filter)) { $scope.model.filterAdvanced = true; - } + } else { if ($scope.model.filter.startsWith("!")) { $scope.model.filterExclude = true; @@ -160,50 +166,50 @@ angular.module("umbraco").controller("Umbraco.Overlays.TreePickerController", } } } - + /** * Updates the tree's query parameters */ function initTree() { - //create the custom query string param for this tree - var queryParams = {}; - if (vm.startNodeId) { + //create the custom query string param for this tree + var queryParams = {}; + if (vm.startNodeId) { queryParams["startNodeId"] = $scope.model.startNodeId; - } - if (vm.selectedLanguage && vm.selectedLanguage.id) { + } + if (vm.selectedLanguage && vm.selectedLanguage.id) { queryParams["culture"] = vm.selectedLanguage.culture; - } - var queryString = $.param(queryParams); //create the query string from the params object - - if (!queryString) { + } + var queryString = $.param(queryParams); //create the query string from the params object + + if (!queryString) { vm.customTreeParams = $scope.model.customTreeParams; - } - else { - vm.customTreeParams = queryString; - if ($scope.model.customTreeParams) { + } + else { + vm.customTreeParams = queryString; + if ($scope.model.customTreeParams) { vm.customTreeParams += "&" + $scope.model.customTreeParams; } - } + } vm.treeReady = true; } - + function selectLanguage(language) { vm.selectedLanguage = language; // close the language selector - vm.languageSelectorIsOpen = false; - - initTree(); //this will reset the tree params and the tree directive will pick up the changes in a $watch - - //execute after next digest because the internal watch on the customtreeparams needs to be bound now that we've changed it - $timeout(function () { - //reload the tree with it's updated querystring args - vm.dialogTreeApi.load(vm.section).then(function () { - - //create the list of promises - var promises = []; - for (var i = 0; i < expandedPaths.length; i++) { - promises.push(vm.dialogTreeApi.syncTree({ path: expandedPaths[i], activate: false })); + vm.languageSelectorIsOpen = false; + + initTree(); //this will reset the tree params and the tree directive will pick up the changes in a $watch + + //execute after next digest because the internal watch on the customtreeparams needs to be bound now that we've changed it + $timeout(function () { + //reload the tree with it's updated querystring args + vm.dialogTreeApi.load(vm.section).then(function () { + + //create the list of promises + var promises = []; + for (var i = 0; i < expandedPaths.length; i++) { + promises.push(vm.dialogTreeApi.syncTree({ path: expandedPaths[i], activate: false })); } //execute them sequentially angularHelper.executeSequentialPromises(promises); @@ -213,14 +219,14 @@ angular.module("umbraco").controller("Umbraco.Overlays.TreePickerController", function toggleLanguageSelector() { vm.languageSelectorIsOpen = !vm.languageSelectorIsOpen; - }; + }; function nodeExpandedHandler(args) { - - //store the reference to the expanded node path - if (args.node) { + + //store the reference to the expanded node path + if (args.node) { treeService._trackExpandedPaths(args.node, expandedPaths); - } + } // open mini list view for list views if (args.node.metaData.isContainer) { @@ -280,7 +286,7 @@ angular.module("umbraco").controller("Umbraco.Overlays.TreePickerController", function (i) { return i.id == args.node.id; }); - } + } else { eventsService.emit("dialogs.treePickerController.select", args); @@ -292,7 +298,7 @@ angular.module("umbraco").controller("Umbraco.Overlays.TreePickerController", //from the server in this method. if ($scope.model.select) { $scope.model.select(args.node); - } + } else { select(args.node.name, args.node.id); //toggle checked state @@ -317,23 +323,23 @@ angular.module("umbraco").controller("Umbraco.Overlays.TreePickerController", if (vm.multiPicker) { if (entity) { multiSelectItem(entity); - } + } else { multiSelectItem(rootNode); } - } + } else { $scope.model.selection.push(rootNode); $scope.model.submit($scope.model); } - } + } else { if (vm.multiPicker) { if (entity) { multiSelectItem(entity); - } + } else { //otherwise we have to get it from the server entityResource.getById(id, vm.entityType).then(function (ent) { @@ -341,7 +347,7 @@ angular.module("umbraco").controller("Umbraco.Overlays.TreePickerController", }); } - } + } else { hideSearch(); @@ -350,7 +356,7 @@ angular.module("umbraco").controller("Umbraco.Overlays.TreePickerController", if (entity) { $scope.model.selection.push(entity); $scope.model.submit($scope.model); - } + } else { //otherwise we have to get it from the server entityResource.getById(id, vm.entityType).then(function (ent) { @@ -379,7 +385,7 @@ angular.module("umbraco").controller("Umbraco.Overlays.TreePickerController", if (found) { $scope.model.selection.splice(foundIndex, 1); - } + } else { $scope.model.selection.push(item); } @@ -416,7 +422,7 @@ angular.module("umbraco").controller("Umbraco.Overlays.TreePickerController", value.cssClasses.push($scope.model.filterCssClass); } }); - } + } else { var a = $scope.model.filter.toLowerCase().replace(/\s/g, '').split(','); angular.forEach(nodes, @@ -437,10 +443,10 @@ angular.module("umbraco").controller("Umbraco.Overlays.TreePickerController", }); } } - + function openMiniListView(node) { vm.miniListView = node; - } + } function multiSubmit(result) { entityResource.getByIds(result, vm.entityType).then(function (ents) { @@ -463,7 +469,7 @@ angular.module("umbraco").controller("Umbraco.Overlays.TreePickerController", //add/remove to our custom tracked list of selected search results if (result.selected) { vm.searchInfo.selectedSearchResults.push(result); - } + } else { vm.searchInfo.selectedSearchResults = _.reject(vm.searchInfo.selectedSearchResults, function (i) { @@ -592,8 +598,8 @@ angular.module("umbraco").controller("Umbraco.Overlays.TreePickerController", }); vm.searchInfo.showSearch = true; - } - + } + function selectListViewNode(node) { select(node.name, node.id); //toggle checked state @@ -603,8 +609,8 @@ angular.module("umbraco").controller("Umbraco.Overlays.TreePickerController", function closeMiniListView() { vm.miniListView = undefined; } - - //initialize - onInit(); + + //initialize + onInit(); }); diff --git a/src/Umbraco.Web.UI.Client/src/views/common/overlays/user/user.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/overlays/user/user.controller.js index e8b1bb0f68..108a7589f6 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/overlays/user/user.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/overlays/user/user.controller.js @@ -8,7 +8,9 @@ angular.module("umbraco") $scope.model.subtitle = "Umbraco version" + " " + $scope.version; if(!$scope.model.title) { - $scope.model.title = localizationService.localize("general_user"); + localizationService.localize("general_user").then(function(value){ + $scope.model.title = value; + }); } $scope.externalLoginProviders = externalLoginInfo.providers; diff --git a/src/Umbraco.Web.UI.Client/src/views/common/overlays/ysod/ysod.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/overlays/ysod/ysod.controller.js index 5d42edd3a5..0499059aca 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/overlays/ysod/ysod.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/overlays/ysod/ysod.controller.js @@ -1,25 +1,33 @@ angular.module("umbraco") .controller("Umbraco.Overlays.YsodController", function ($scope, legacyResource, treeService, navigationService, localizationService) { - if(!$scope.model.title) { - $scope.model.title = localizationService.localize("errors_receivedErrorFromServer"); - } + function onInit() { - if ($scope.model.error && $scope.model.error.data && $scope.model.error.data.StackTrace) { - //trim whitespace - $scope.model.error.data.StackTrace = $scope.model.error.data.StackTrace.trim(); - } - - if ($scope.model.error && $scope.model.error.data) { - $scope.model.error.data.InnerExceptions = []; - var ex = $scope.model.error.data.InnerException; - while (ex) { - if (ex.StackTrace) { - ex.StackTrace = ex.StackTrace.trim(); - } - $scope.model.error.data.InnerExceptions.push(ex); - ex = ex.InnerException; + if(!$scope.model.title) { + localizationService.localize("errors_receivedErrorFromServer").then(function(value){ + $scope.model.title = value; + }); } + + if ($scope.model.error && $scope.model.error.data && $scope.model.error.data.StackTrace) { + //trim whitespace + $scope.model.error.data.StackTrace = $scope.model.error.data.StackTrace.trim(); + } + + if ($scope.model.error && $scope.model.error.data) { + $scope.model.error.data.InnerExceptions = []; + var ex = $scope.model.error.data.InnerException; + while (ex) { + if (ex.StackTrace) { + ex.StackTrace = ex.StackTrace.trim(); + } + $scope.model.error.data.InnerExceptions.push(ex); + ex = ex.InnerException; + } + } + } + onInit(); + }); diff --git a/src/Umbraco.Web.UI.Client/src/views/dashboard/dashboard.tabs.controller.js b/src/Umbraco.Web.UI.Client/src/views/dashboard/dashboard.tabs.controller.js index 0dfdfbc3fe..a23f8b09c5 100644 --- a/src/Umbraco.Web.UI.Client/src/views/dashboard/dashboard.tabs.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/dashboard/dashboard.tabs.controller.js @@ -126,27 +126,45 @@ angular.module("umbraco").controller("Umbraco.Dashboard.StartUpDynamicContentCon function FormsController($scope, $route, $cookieStore, packageResource, localizationService) { + + var labels = {}; + var labelKeys = [ + "packager_installStateDownloading", + "packager_installStateImporting", + "packager_installStateInstalling", + "packager_installStateRestarting", + "packager_installStateComplete" + ]; + + localizationService.localizeMany(labelKeys).then(function(values){ + labels.installStateDownloading = values[0]; + labels.installStateImporting = values[1]; + labels.installStateInstalling = values[2]; + labels.installStateRestarting = values[3]; + labels.installStateComplete = values[4]; + }); + $scope.installForms = function(){ - $scope.state = localizationService.localize("packager_installStateDownloading"); + $scope.state = labels.installStateDownloading; packageResource .fetch("CD44CF39-3D71-4C19-B6EE-948E1FAF0525") .then(function(pack) { - $scope.state = localizationService.localize("packager_installStateImporting"); + $scope.state = labels.installStateImporting; return packageResource.import(pack); }, $scope.error) .then(function(pack) { - $scope.state = localizationService.localize("packager_installStateInstalling"); + $scope.state = labels.installStateInstalling; return packageResource.installFiles(pack); }, $scope.error) .then(function(pack) { - $scope.state = localizationService.localize("packager_installStateRestarting"); + $scope.state = labels.installStateRestarting; return packageResource.installData(pack); }, $scope.error) .then(function(pack) { - $scope.state = localizationService.localize("packager_installStateComplete"); + $scope.state = installStateComplete; return packageResource.cleanUp(pack); }, $scope.error) diff --git a/src/Umbraco.Web.UI.Client/src/views/dashboard/developer/redirecturls.controller.js b/src/Umbraco.Web.UI.Client/src/views/dashboard/developer/redirecturls.controller.js index 7acab72455..9cef913e79 100644 --- a/src/Umbraco.Web.UI.Client/src/views/dashboard/developer/redirecturls.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/dashboard/developer/redirecturls.controller.js @@ -86,7 +86,10 @@ var index = vm.redirectUrls.indexOf(redirectToDelete); vm.redirectUrls.splice(index, 1); - notificationsService.success(localizationService.localize("redirectUrls_redirectRemoved")); + + localizationService.localize("redirectUrls_redirectRemoved").then(function(value){ + notificationsService.success(value); + }); // check if new redirects needs to be loaded if (vm.redirectUrls.length === 0 && vm.pagination.totalPages > 1) { @@ -100,7 +103,9 @@ search(); } }, function (error) { - notificationsService.error(localizationService.localize("redirectUrls_redirectRemoveError")); + localizationService.localize("redirectUrls_redirectRemoveError").then(function(value){ + notificationsService.error(value); + }); }); } }); @@ -113,9 +118,13 @@ redirectUrlsResource.toggleUrlTracker(true).then(function () { activate(); - notificationsService.success(localizationService.localize("redirectUrls_disabledConfirm")); + localizationService.localize("redirectUrls_disabledConfirm").then(function(value){ + notificationsService.success(value); + }); }, function (error) { - notificationsService.warning(localizationService.localize("redirectUrls_disableError")); + localizationService.localize("redirectUrls_disableError").then(function(value){ + notificationsService.warning(value); + }); }); } @@ -125,9 +134,13 @@ function enableUrlTracker() { redirectUrlsResource.toggleUrlTracker(false).then(function() { activate(); - notificationsService.success(localizationService.localize("redirectUrls_enabledConfirm")); + localizationService.localize("redirectUrls_enabledConfirm").then(function(value){ + notificationsService.success(value); + }); }, function(error) { - notificationsService.warning(localizationService.localize("redirectUrls_enableError")); + localizationService.localize("redirectUrls_enableError").then(function(value){ + notificationsService.warning(value); + }); }); } diff --git a/src/Umbraco.Web.UI.Client/src/views/documenttypes/views/permissions/permissions.controller.js b/src/Umbraco.Web.UI.Client/src/views/documenttypes/views/permissions/permissions.controller.js index 071f4c6480..954dab0077 100644 --- a/src/Umbraco.Web.UI.Client/src/views/documenttypes/views/permissions/permissions.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/documenttypes/views/permissions/permissions.controller.js @@ -30,7 +30,9 @@ function init() { - childNodeSelectorOverlayTitle = localizationService.localize("contentTypeEditor_chooseChildNode"); + localizationService.localize("contentTypeEditor_chooseChildNode").then(function(value){ + childNodeSelectorOverlayTitle = value; + }); contentTypeResource.getAll().then(function(contentTypes){ diff --git a/src/Umbraco.Web.UI.Client/src/views/languages/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/languages/edit.controller.js index 6ee5a5bd7a..1bbbfd0ab4 100644 --- a/src/Umbraco.Web.UI.Client/src/views/languages/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/languages/edit.controller.js @@ -91,7 +91,9 @@ vm.language = lang; vm.page.saveButtonState = "success"; - notificationsService.success(localizationService.localize("speechBubbles_languageSaved")); + localizationService.localize("speechBubbles_languageSaved").then(function(value){ + notificationsService.success(value); + }); // emit event when language is created if($routeParams.create) { From 4670ba9fe004c45c83bf6d25e47f113e09e1ce8a Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 11 Jun 2018 13:32:13 +0200 Subject: [PATCH 056/115] inject localizationService into the publish dialog --- .../src/views/common/overlays/publish/publish.controller.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/common/overlays/publish/publish.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/overlays/publish/publish.controller.js index c18bb0b888..ba8d4f1712 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/overlays/publish/publish.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/overlays/publish/publish.controller.js @@ -1,7 +1,7 @@ (function () { "use strict"; - function PublishController($scope) { + function PublishController($scope, localizationService) { var vm = this; vm.variants = $scope.model.variants; From 9388089b9e3d3cb1fe50975e3ec85ce243980b1b Mon Sep 17 00:00:00 2001 From: Warren Date: Mon, 11 Jun 2018 14:13:16 +0100 Subject: [PATCH 057/115] Fix #55 - Search icon outside input field on list views for Angular 1.7 upgrade --- .../src/views/propertyeditors/listview/listview.html | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.html index 21667a89b2..453d274ed6 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.html @@ -5,7 +5,7 @@
                - + @@ -69,7 +69,7 @@ - From 6dae1924972dcbb03d2faf21da9618eacb7456af Mon Sep 17 00:00:00 2001 From: Warren Date: Mon, 11 Jun 2018 15:01:31 +0100 Subject: [PATCH 058/115] Fixes up missing listview create button - due to the HTTP promise being directly assigned to the Angular property on the model as opposed to the items/result of the promise --- .../views/propertyeditors/listview/listview.controller.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.controller.js index 4b88223bbf..41c8216a77 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.controller.js @@ -36,7 +36,7 @@ function listViewController($rootScope, $scope, $routeParams, $injector, notific else { $scope.entityType = "content"; contentResource = $injector.get('contentResource'); - getContentTypesCallback = $injector.get('contentTypeResource').getAllowedTypes; + getContentTypesCallback = $injector.get('contentTypeResource').getAllowedTypes; } getListResultsCallback = contentResource.getChildren; deleteItemCallback = contentResource.deleteById; @@ -604,8 +604,10 @@ function listViewController($rootScope, $scope, $routeParams, $injector, notific id = -1; } - $scope.listViewAllowedTypes = getContentTypesCallback(id); - + getContentTypesCallback(id).then(function (items) { + $scope.listViewAllowedTypes = items; + }); + $scope.contentId = id; $scope.isTrashed = id === "-20" || id === "-21"; From 94a65fa62859e6ca078fb7288f8b5eadb3c97c08 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 11 Jun 2018 20:46:43 +0200 Subject: [PATCH 059/115] fixing more localisation issues --- .../components/umbpagination.directive.js | 10 ++- .../common/overlays/help/help.controller.js | 4 +- .../permissions/permissions.controller.js | 4 +- .../partialviewmacros/edit.controller.js | 61 +++++++++++-------- .../src/views/partialviews/edit.controller.js | 58 ++++++++++-------- .../propertyeditors/grid/grid.controller.js | 34 ++++++----- 6 files changed, 103 insertions(+), 68 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbpagination.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbpagination.directive.js index 84b3adb471..e82e81140f 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/umbpagination.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/umbpagination.directive.js @@ -123,12 +123,18 @@ Use this directive to generate a pagination. //now, if the start is greater than 0 then '1' will not be displayed, so do the elipses thing if (start > 0) { - scope.pagination.unshift({ name: localizationService.localize("general_first"), val: 1, isActive: false }, {val: "...",isActive: false}); + localizationService.localize("general_first").then(function(value){ + var firstLabel = value; + scope.pagination.unshift({ name: firstLabel, val: 1, isActive: false }, {val: "...",isActive: false}); + }); } //same for the end if (start < maxIndex) { - scope.pagination.push({ val: "...", isActive: false }, { name: localizationService.localize("general_last"), val: scope.totalPages, isActive: false }); + localizationService.localize("general_last").then(function(value){ + var lastLabel = value; + scope.pagination.push({ val: "...", isActive: false }, { name: lastLabel, val: scope.totalPages, isActive: false }); + }); } } diff --git a/src/Umbraco.Web.UI.Client/src/views/common/overlays/help/help.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/overlays/help/help.controller.js index 81190b6efb..29f4be0261 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/overlays/help/help.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/overlays/help/help.controller.js @@ -5,7 +5,9 @@ angular.module("umbraco") $scope.model.subtitle = "Umbraco version" + " " + $scope.version; if(!$scope.model.title) { - $scope.model.title = localizationService.localize("general_help"); + localizationService.localize("general_help").then(function(value) { + $scope.model.title = value; + }); } if(!$scope.section){ diff --git a/src/Umbraco.Web.UI.Client/src/views/mediatypes/views/permissions/permissions.controller.js b/src/Umbraco.Web.UI.Client/src/views/mediatypes/views/permissions/permissions.controller.js index 9d7cb8a1da..758bc8cc1c 100644 --- a/src/Umbraco.Web.UI.Client/src/views/mediatypes/views/permissions/permissions.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/mediatypes/views/permissions/permissions.controller.js @@ -20,7 +20,9 @@ function init() { - childNodeSelectorOverlayTitle = localizationService.localize("contentTypeEditor_chooseChildNode"); + localizationService.localize("contentTypeEditor_chooseChildNode").then(function(value){ + childNodeSelectorOverlayTitle = value; + }); mediaTypeResource.getAll().then(function(mediaTypes){ diff --git a/src/Umbraco.Web.UI.Client/src/views/partialviewmacros/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/partialviewmacros/edit.controller.js index 35da2e8ea4..9176adf66a 100644 --- a/src/Umbraco.Web.UI.Client/src/views/partialviewmacros/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/partialviewmacros/edit.controller.js @@ -175,7 +175,6 @@ view: "macropicker", dialogData: {}, show: true, - title: "Insert macro", submit: function (model) { var macroObject = macroService.collectValueData(model.selectedMacro, model.macroParams, "Mvc"); @@ -219,39 +218,49 @@ function openDictionaryItemOverlay() { - vm.dictionaryItemOverlay = { - view: "treepicker", - section: "settings", - treeAlias: "dictionary", - entityType: "dictionary", - multiPicker: false, - show: true, - title: "Insert dictionary item", - emptyStateMessage: localizationService.localize("emptyStates_emptyDictionaryTree"), - select: function(node){ - var code = templateHelper.getInsertDictionarySnippet(node.name); - insert(code); + var labelKeys = [ + "template_insertDictionaryItem", + "emptyStates_emptyDictionaryTree" + ]; - vm.dictionaryItemOverlay.show = false; - vm.dictionaryItemOverlay = null; - }, - close: function (model) { - // close dialog - vm.dictionaryItemOverlay.show = false; - vm.dictionaryItemOverlay = null; - // focus editor - vm.editor.focus(); - } - }; + localizationService.localizeMany(labelKeys).then(function(values){ + var title = values[0]; + var emptyStateMessage = values[1]; + + vm.dictionaryItemOverlay = { + view: "treepicker", + section: "settings", + treeAlias: "dictionary", + entityType: "dictionary", + multiPicker: false, + show: true, + title: title, + emptyStateMessage: emptyStateMessage, + select: function(node){ + + var code = templateHelper.getInsertDictionarySnippet(node.name); + insert(code); + + vm.dictionaryItemOverlay.show = false; + vm.dictionaryItemOverlay = null; + }, + close: function (model) { + // close dialog + vm.dictionaryItemOverlay.show = false; + vm.dictionaryItemOverlay = null; + // focus editor + vm.editor.focus(); + } + }; + + }); } function openQueryBuilderOverlay() { vm.queryBuilderOverlay = { view: "querybuilder", show: true, - title: "Query for content", - submit: function (model) { var code = templateHelper.getQuerySnippet(model.result.queryExpression); diff --git a/src/Umbraco.Web.UI.Client/src/views/partialviews/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/partialviews/edit.controller.js index cb56fecbad..c3f06b09d9 100644 --- a/src/Umbraco.Web.UI.Client/src/views/partialviews/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/partialviews/edit.controller.js @@ -168,7 +168,6 @@ view: "macropicker", dialogData: {}, show: true, - title: "Insert macro", submit: function (model) { var macroObject = macroService.collectValueData(model.selectedMacro, model.macroParams, "Mvc"); @@ -212,31 +211,42 @@ function openDictionaryItemOverlay() { - vm.dictionaryItemOverlay = { - view: "treepicker", - section: "settings", - treeAlias: "dictionary", - entityType: "dictionary", - multiPicker: false, - show: true, - title: "Insert dictionary item", - emptyStateMessage: localizationService.localize("emptyStates_emptyDictionaryTree"), - select: function(node){ - var code = templateHelper.getInsertDictionarySnippet(node.name); - insert(code); + var labelKeys = [ + "template_insertDictionaryItem", + "emptyStates_emptyDictionaryTree" + ]; - vm.dictionaryItemOverlay.show = false; - vm.dictionaryItemOverlay = null; - }, - close: function (model) { - // close dialog - vm.dictionaryItemOverlay.show = false; - vm.dictionaryItemOverlay = null; - // focus editor - vm.editor.focus(); - } - }; + localizationService.localizeMany(labelKeys).then(function(values){ + var title = values[0]; + var emptyStateMessage = values[1]; + + vm.dictionaryItemOverlay = { + view: "treepicker", + section: "settings", + treeAlias: "dictionary", + entityType: "dictionary", + multiPicker: false, + show: true, + title: title, + emptyStateMessage: emptyStateMessage, + select: function(node){ + + var code = templateHelper.getInsertDictionarySnippet(node.name); + insert(code); + + vm.dictionaryItemOverlay.show = false; + vm.dictionaryItemOverlay = null; + }, + close: function (model) { + // close dialog + vm.dictionaryItemOverlay.show = false; + vm.dictionaryItemOverlay = null; + // focus editor + vm.editor.focus(); + } + }; + }); } function openQueryBuilderOverlay() { diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/grid.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/grid.controller.js index b59fc6ecad..8bdcfdc351 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/grid.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/grid/grid.controller.js @@ -274,19 +274,23 @@ angular.module("umbraco") // Add items overlay menu // ********************************************* $scope.openEditorOverlay = function(event, area, index, key) { - $scope.editorOverlay = { - view: "itempicker", - filter: area.$allowedEditors.length > 15, - title: localizationService.localize("grid_insertControl"), - availableItems: area.$allowedEditors, - event: event, - show: true, - submit: function(model) { - $scope.addControl(model.selectedItem, area, index); - $scope.editorOverlay.show = false; - $scope.editorOverlay = null; - } - }; + var title = ""; + localizationService.localize("grid_insertControl").then(function(value){ + title = value; + $scope.editorOverlay = { + view: "itempicker", + filter: area.$allowedEditors.length > 15, + title: title, + availableItems: area.$allowedEditors, + event: event, + show: true, + submit: function(model) { + $scope.addControl(model.selectedItem, area, index); + $scope.editorOverlay.show = false; + $scope.editorOverlay = null; + } + }; + }); }; // ********************************************* @@ -883,7 +887,9 @@ angular.module("umbraco") angular.forEach($scope.availableEditors, function (value, key) { //If no translation is provided, keep using the editor name from the manifest if (localizationService.dictionary.hasOwnProperty("grid_" + value.alias)) { - value.name = localizationService.localize("grid_" + value.alias); + localizationService.localize("grid_" + value.alias).then(function(value){ + value.name = value; + }); } }); From 945271cb67517b3071a42bcc205e83716e93470a Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Mon, 11 Jun 2018 22:12:40 +0200 Subject: [PATCH 060/115] correct error handling of http requests --- .../src/common/services/umbrequesthelper.service.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js index 5d561585fd..c98ce34c76 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js @@ -149,7 +149,7 @@ function umbRequestHelper($http, $q, umbDataFormatter, angularHelper, dialogServ //when it's successful, just return the data deferred.resolve(result); - }).catch(function (response) { + }, function (response) { //invoke the callback var result = callbacks.error.apply(this, [response.data, response.status, response.headers, response.config]); From 9b0bf28d15ab10686710fff062000d7627fd6ec7 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 12 Jun 2018 11:26:08 +0200 Subject: [PATCH 061/115] fixing unit tests --- .../common/services/angularhelper.service.js | 8 +++++- .../contentpicker/contentpicker.controller.js | 2 ++ .../template-editor-controller.spec.js | 28 +++++++++++-------- 3 files changed, 25 insertions(+), 13 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/services/angularhelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/angularhelper.service.js index 6e704b7c78..6a1b4916b7 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/angularhelper.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/angularhelper.service.js @@ -152,18 +152,24 @@ function angularHelper($log, $q) { * Returns a null angular FormController, mostly for use in unit tests * NOTE: This is actually the same construct as angular uses internally for creating a null form but they don't expose * any of this publicly to us, so we need to create our own. + * NOTE: The properties has been added to the null form because we use them to get a form on a scope. * * @param {string} formName The form name to assign */ getNullForm: function (formName) { return { + $error: {}, + $dirty: false, + $pristine: true, + $valid: true, + $submitted: false, + $pending: undefined, $addControl: angular.noop, $removeControl: angular.noop, $setValidity: angular.noop, $setDirty: angular.noop, $setPristine: angular.noop, $name: formName - //NOTE: we don't include the 'properties', just the methods. }; } }; diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js index 13c31ea1ad..bbbea7e0a2 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/contentpicker/contentpicker.controller.js @@ -197,6 +197,8 @@ function contentPickerController($scope, entityResource, editorState, iconHelper }); } + angularHelper.getCurrentForm($scope).$setDirty(); + $scope.contentPickerOverlay.show = false; $scope.contentPickerOverlay = null; } diff --git a/src/Umbraco.Web.UI.Client/test/unit/app/templates/template-editor-controller.spec.js b/src/Umbraco.Web.UI.Client/test/unit/app/templates/template-editor-controller.spec.js index 642dc5ab20..fe82048c5f 100644 --- a/src/Umbraco.Web.UI.Client/test/unit/app/templates/template-editor-controller.spec.js +++ b/src/Umbraco.Web.UI.Client/test/unit/app/templates/template-editor-controller.spec.js @@ -127,12 +127,14 @@ controller.setLayout = function() {}; controller.openMasterTemplateOverlay(); - controller.masterTemplateOverlay.submit({ - selectedItem: { - alias: "NewMasterPage" - } - }); - expect(controller.template.masterTemplateAlias).toBe("NewMasterPage"); + setTimeout(function(){ + controller.masterTemplateOverlay.submit({ + selectedItem: { + alias: "NewMasterPage" + } + }); + expect(controller.template.masterTemplateAlias).toBe("NewMasterPage"); + }, 1000); }); it("changes layout value when masterpage is selected", function() { @@ -147,12 +149,14 @@ } controller.openMasterTemplateOverlay(); - controller.masterTemplateOverlay.submit({ - selectedItem: { - alias: "NewMasterPage" - } - }); - expect(newTemplate).toBe("@{ Layout = \"NewMasterPage.cshtml\"; }"); + setTimeout(function(){ + controller.masterTemplateOverlay.submit({ + selectedItem: { + alias: "NewMasterPage" + } + }); + expect(newTemplate).toBe("@{ Layout = \"NewMasterPage.cshtml\"; }"); + }, 1000); }); }); From 083fbbf3c639161c3dd2e3f2a16252aa507a835e Mon Sep 17 00:00:00 2001 From: Warren Date: Tue, 12 Jun 2018 10:54:49 +0100 Subject: [PATCH 062/115] WIP - refactor of interceptor to new format - having issues getting the x-umb-user-seconds --- .../common/security/securityinterceptor.js | 213 ++++++++++-------- 1 file changed, 119 insertions(+), 94 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/security/securityinterceptor.js b/src/Umbraco.Web.UI.Client/src/common/security/securityinterceptor.js index 80dbe37e2c..c36ae48a8d 100644 --- a/src/Umbraco.Web.UI.Client/src/common/security/securityinterceptor.js +++ b/src/Umbraco.Web.UI.Client/src/common/security/securityinterceptor.js @@ -1,105 +1,130 @@ angular.module('umbraco.security.interceptor') // This http interceptor listens for authentication successes and failures .factory('securityInterceptor', ['$injector', 'securityRetryQueue', 'notificationsService', 'eventsService', 'requestInterceptorFilter', function ($injector, queue, notifications, eventsService, requestInterceptorFilter) { - return function (promise) { + return { - return promise.then( - function (originalResponse) { - // Intercept successful requests + 'request': function(config) { + // do something on success + // request for data - if we want to modify headers or url etc + console.log('request config', config); + return config; + }, - //Here we'll check if our custom header is in the response which indicates how many seconds the user's session has before it - //expires. Then we'll update the user in the user service accordingly. - var headers = originalResponse.headers(); - if (headers["x-umb-user-seconds"]) { - // We must use $injector to get the $http service to prevent circular dependency - var userService = $injector.get('userService'); - userService.setUserTimeout(headers["x-umb-user-seconds"]); - } + 'requestError': function(rejection) { + // do something on error + + console.log('request error rejection', rejection); + return $q.reject(rejection); + }, - //this checks if the user's values have changed, in which case we need to update the user details throughout - //the back office similar to how we do when a user logs in - if (headers["x-umb-user-modified"]) { - eventsService.emit("app.userRefresh"); - } - - return promise; - }, function (originalResponse) { - // Intercept failed requests - - // Make sure we have the configuration of the request (don't we always?) - var config = originalResponse.config ? originalResponse.config : {}; - - // Make sure we have an object for the headers of the request - var headers = config.headers ? config.headers : {}; - - //Here we'll check if we should ignore the error (either based on the original header set or the request configuration) - if (headers["x-umb-ignore-error"] === "ignore" || config.umbIgnoreErrors === true || (angular.isArray(config.umbIgnoreStatus) && config.umbIgnoreStatus.indexOf(originalResponse.status) !== -1)) { - //exit/ignore - return promise; - } - var filtered = _.find(requestInterceptorFilter(), function (val) { - return config.url.indexOf(val) > 0; - }); - if (filtered) { - return promise; - } - - //A 401 means that the user is not logged in - if (originalResponse.status === 401 && !originalResponse.config.url.endsWith("umbraco/backoffice/UmbracoApi/Authentication/GetCurrentUser")) { - - var userService = $injector.get('userService'); // see above - - //Associate the user name with the retry to ensure we retry for the right user - promise = userService.getCurrentUser() - .then(function (user) { - var userName = user ? user.name : null; - //The request bounced because it was not authorized - add a new request to the retry queue - return queue.pushRetryFn('unauthorized-server', userName, function retryRequest() { - // We must use $injector to get the $http service to prevent circular dependency - return $injector.get('$http')(originalResponse.config); - }); - }); - } - else if (originalResponse.status === 404) { - - //a 404 indicates that the request was not found - this could be due to a non existing url, or it could - //be due to accessing a url with a parameter that doesn't exist, either way we should notifiy the user about it - - var errMsg = "The URL returned a 404 (not found):
                " + originalResponse.config.url.split('?')[0] + ""; - if (originalResponse.data && originalResponse.data.ExceptionMessage) { - errMsg += "
                with error:
                " + originalResponse.data.ExceptionMessage + ""; - } - if (originalResponse.config.data) { - errMsg += "
                with data:
                " + angular.toJson(originalResponse.config.data) + "
                Contact your administrator for information."; - } - - notifications.error( - "Request error", - errMsg); - - } - else if (originalResponse.status === 403) { - //if the status was a 403 it means the user didn't have permission to do what the request was trying to do. - //How do we deal with this now, need to tell the user somehow that they don't have permission to do the thing that was - //requested. We can either deal with this globally here, or we can deal with it globally for individual requests on the umbRequestHelper, - // or completely custom for services calling resources. - - //http://issues.umbraco.org/issue/U4-2749 - - //It was decided to just put these messages into the normal status messages. - - var msg = "Unauthorized access to URL:
                " + originalResponse.config.url.split('?')[0] + ""; - if (originalResponse.config.data) { - msg += "
                with data:
                " + angular.toJson(originalResponse.config.data) + "
                Contact your administrator for information."; - } - - notifications.error( - "Authorization error", - msg); - } + 'response': function(response) { + // do something on success + console.log('response success', response); + var headers = response.headers(); + console.log('response success headers', headers); + /* + // Intercept successful requests + //Here we'll check if our custom header is in the response which indicates how many seconds the user's session has before it + //expires. Then we'll update the user in the user service accordingly. + var headers = originalResponse.headers(); + if (headers["x-umb-user-seconds"]) { + // We must use $injector to get the $http service to prevent circular dependency + var userService = $injector.get('userService'); + userService.setUserTimeout(headers["x-umb-user-seconds"]); + } + + //this checks if the user's values have changed, in which case we need to update the user details throughout + //the back office similar to how we do when a user logs in + if (headers["x-umb-user-modified"]) { + eventsService.emit("app.userRefresh"); + } + */ + + return response; + }, + + 'responseError': function(rejection) { + + console.log('response error rejection', rejection); + + /* + // Intercept failed requests + // Make sure we have the configuration of the request (don't we always?) + var config = originalResponse.config ? originalResponse.config : {}; + + // Make sure we have an object for the headers of the request + var headers = config.headers ? config.headers : {}; + + //Here we'll check if we should ignore the error (either based on the original header set or the request configuration) + if (headers["x-umb-ignore-error"] === "ignore" || config.umbIgnoreErrors === true || (angular.isArray(config.umbIgnoreStatus) && config.umbIgnoreStatus.indexOf(originalResponse.status) !== -1)) { + //exit/ignore return promise; + } + var filtered = _.find(requestInterceptorFilter(), function (val) { + return config.url.indexOf(val) > 0; }); + if (filtered) { + return promise; + } + + //A 401 means that the user is not logged in + if (originalResponse.status === 401 && !originalResponse.config.url.endsWith("umbraco/backoffice/UmbracoApi/Authentication/GetCurrentUser")) { + + var userService = $injector.get('userService'); // see above + + //Associate the user name with the retry to ensure we retry for the right user + promise = userService.getCurrentUser() + .then(function (user) { + var userName = user ? user.name : null; + //The request bounced because it was not authorized - add a new request to the retry queue + return queue.pushRetryFn('unauthorized-server', userName, function retryRequest() { + // We must use $injector to get the $http service to prevent circular dependency + return $injector.get('$http')(originalResponse.config); + }); + }); + } + else if (originalResponse.status === 404) { + + //a 404 indicates that the request was not found - this could be due to a non existing url, or it could + //be due to accessing a url with a parameter that doesn't exist, either way we should notifiy the user about it + + var errMsg = "The URL returned a 404 (not found):
                " + originalResponse.config.url.split('?')[0] + ""; + if (originalResponse.data && originalResponse.data.ExceptionMessage) { + errMsg += "
                with error:
                " + originalResponse.data.ExceptionMessage + ""; + } + if (originalResponse.config.data) { + errMsg += "
                with data:
                " + angular.toJson(originalResponse.config.data) + "
                Contact your administrator for information."; + } + + notifications.error( + "Request error", + errMsg); + + } + else if (originalResponse.status === 403) { + //if the status was a 403 it means the user didn't have permission to do what the request was trying to do. + //How do we deal with this now, need to tell the user somehow that they don't have permission to do the thing that was + //requested. We can either deal with this globally here, or we can deal with it globally for individual requests on the umbRequestHelper, + // or completely custom for services calling resources. + + //http://issues.umbraco.org/issue/U4-2749 + + //It was decided to just put these messages into the normal status messages. + + var msg = "Unauthorized access to URL:
                " + originalResponse.config.url.split('?')[0] + ""; + if (originalResponse.config.data) { + msg += "
                with data:
                " + angular.toJson(originalResponse.config.data) + "
                Contact your administrator for information."; + } + + notifications.error( + "Authorization error", + msg); + } + */ + + return $q.reject(rejection); + } }; }]) //used to set headers on all requests where necessary @@ -124,6 +149,6 @@ angular.module('umbraco.security.interceptor') $httpProvider.defaults.xsrfHeaderName = 'X-UMB-XSRF-TOKEN'; $httpProvider.defaults.xsrfCookieName = 'UMB-XSRF-TOKEN'; // Fixme: https://stackoverflow.com/questions/23804981/alternative-of-httpprovider-responseinterceptors - // $httpProvider.interceptors.push('securityInterceptor'); + $httpProvider.interceptors.push('securityInterceptor'); $httpProvider.interceptors.push('umbracoRequestInterceptor'); }]); From 939cac264adda2447c3a747c9d4474554ff2f7bd Mon Sep 17 00:00:00 2001 From: Warren Date: Tue, 12 Jun 2018 12:38:32 +0100 Subject: [PATCH 063/115] Get the x-umb-user-modified header to work - set a new profile photo or remove it and ensure header is sent down & the event is emitted to update the avatar --- .../src/common/security/securityinterceptor.js | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/security/securityinterceptor.js b/src/Umbraco.Web.UI.Client/src/common/security/securityinterceptor.js index c36ae48a8d..68e19d221c 100644 --- a/src/Umbraco.Web.UI.Client/src/common/security/securityinterceptor.js +++ b/src/Umbraco.Web.UI.Client/src/common/security/securityinterceptor.js @@ -18,28 +18,27 @@ angular.module('umbraco.security.interceptor') }, 'response': function(response) { - // do something on success - console.log('response success', response); - var headers = response.headers(); - console.log('response success headers', headers); - - /* // Intercept successful requests //Here we'll check if our custom header is in the response which indicates how many seconds the user's session has before it //expires. Then we'll update the user in the user service accordingly. - var headers = originalResponse.headers(); + var headers = response.headers(); + + //WB: Logging to help temp-debugging + console.log('response success', response); + console.log('response success headers', headers); + + if (headers["x-umb-user-seconds"]) { // We must use $injector to get the $http service to prevent circular dependency var userService = $injector.get('userService'); userService.setUserTimeout(headers["x-umb-user-seconds"]); } - + //this checks if the user's values have changed, in which case we need to update the user details throughout //the back office similar to how we do when a user logs in if (headers["x-umb-user-modified"]) { eventsService.emit("app.userRefresh"); } - */ return response; }, From 02c02a3abee406302dd841e36b91d881c5e7574c Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 12 Jun 2018 14:17:03 +0200 Subject: [PATCH 064/115] update responseError in security interceptor --- .../common/security/securityinterceptor.js | 36 ++++++++----------- 1 file changed, 15 insertions(+), 21 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/security/securityinterceptor.js b/src/Umbraco.Web.UI.Client/src/common/security/securityinterceptor.js index c36ae48a8d..93adf88d4a 100644 --- a/src/Umbraco.Web.UI.Client/src/common/security/securityinterceptor.js +++ b/src/Umbraco.Web.UI.Client/src/common/security/securityinterceptor.js @@ -45,19 +45,16 @@ angular.module('umbraco.security.interceptor') }, 'responseError': function(rejection) { - - console.log('response error rejection', rejection); - /* // Intercept failed requests // Make sure we have the configuration of the request (don't we always?) - var config = originalResponse.config ? originalResponse.config : {}; + var config = rejection.config ? rejection.config : {}; // Make sure we have an object for the headers of the request var headers = config.headers ? config.headers : {}; //Here we'll check if we should ignore the error (either based on the original header set or the request configuration) - if (headers["x-umb-ignore-error"] === "ignore" || config.umbIgnoreErrors === true || (angular.isArray(config.umbIgnoreStatus) && config.umbIgnoreStatus.indexOf(originalResponse.status) !== -1)) { + if (headers["x-umb-ignore-error"] === "ignore" || config.umbIgnoreErrors === true || (angular.isArray(config.umbIgnoreStatus) && config.umbIgnoreStatus.indexOf(rejection.status) !== -1)) { //exit/ignore return promise; } @@ -69,7 +66,7 @@ angular.module('umbraco.security.interceptor') } //A 401 means that the user is not logged in - if (originalResponse.status === 401 && !originalResponse.config.url.endsWith("umbraco/backoffice/UmbracoApi/Authentication/GetCurrentUser")) { + if (rejection.status === 401 && !rejection.config.url.endsWith("umbraco/backoffice/UmbracoApi/Authentication/GetCurrentUser")) { var userService = $injector.get('userService'); // see above @@ -80,21 +77,21 @@ angular.module('umbraco.security.interceptor') //The request bounced because it was not authorized - add a new request to the retry queue return queue.pushRetryFn('unauthorized-server', userName, function retryRequest() { // We must use $injector to get the $http service to prevent circular dependency - return $injector.get('$http')(originalResponse.config); + return $injector.get('$http')(rejection.config); }); }); } - else if (originalResponse.status === 404) { + else if (rejection.status === 404) { //a 404 indicates that the request was not found - this could be due to a non existing url, or it could //be due to accessing a url with a parameter that doesn't exist, either way we should notifiy the user about it - var errMsg = "The URL returned a 404 (not found):
                " + originalResponse.config.url.split('?')[0] + ""; - if (originalResponse.data && originalResponse.data.ExceptionMessage) { - errMsg += "
                with error:
                " + originalResponse.data.ExceptionMessage + ""; + var errMsg = "The URL returned a 404 (not found):
                " + rejection.config.url.split('?')[0] + ""; + if (rejection.data && rejection.data.ExceptionMessage) { + errMsg += "
                with error:
                " + rejection.data.ExceptionMessage + ""; } - if (originalResponse.config.data) { - errMsg += "
                with data:
                " + angular.toJson(originalResponse.config.data) + "
                Contact your administrator for information."; + if (rejection.config.data) { + errMsg += "
                with data:
                " + angular.toJson(rejection.config.data) + "
                Contact your administrator for information."; } notifications.error( @@ -102,7 +99,7 @@ angular.module('umbraco.security.interceptor') errMsg); } - else if (originalResponse.status === 403) { + else if (rejection.status === 403) { //if the status was a 403 it means the user didn't have permission to do what the request was trying to do. //How do we deal with this now, need to tell the user somehow that they don't have permission to do the thing that was //requested. We can either deal with this globally here, or we can deal with it globally for individual requests on the umbRequestHelper, @@ -112,16 +109,13 @@ angular.module('umbraco.security.interceptor') //It was decided to just put these messages into the normal status messages. - var msg = "Unauthorized access to URL:
                " + originalResponse.config.url.split('?')[0] + ""; - if (originalResponse.config.data) { - msg += "
                with data:
                " + angular.toJson(originalResponse.config.data) + "
                Contact your administrator for information."; + var msg = "Unauthorized access to URL:
                " + rejection.config.url.split('?')[0] + ""; + if (rejection.config.data) { + msg += "
                with data:
                " + angular.toJson(rejection.config.data) + "
                Contact your administrator for information."; } - notifications.error( - "Authorization error", - msg); + notifications.error("Authorization error", msg); } - */ return $q.reject(rejection); } From 4577ec1016fcefd23406007e15f05a32b44a4ef3 Mon Sep 17 00:00:00 2001 From: Warren Date: Tue, 12 Jun 2018 13:51:06 +0100 Subject: [PATCH 065/115] Remove the console.log debug from the interceptor for now - we may need to revisit this --- .../src/common/security/securityinterceptor.js | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/security/securityinterceptor.js b/src/Umbraco.Web.UI.Client/src/common/security/securityinterceptor.js index abdcf47612..834aa83e54 100644 --- a/src/Umbraco.Web.UI.Client/src/common/security/securityinterceptor.js +++ b/src/Umbraco.Web.UI.Client/src/common/security/securityinterceptor.js @@ -22,11 +22,6 @@ angular.module('umbraco.security.interceptor') //Here we'll check if our custom header is in the response which indicates how many seconds the user's session has before it //expires. Then we'll update the user in the user service accordingly. var headers = response.headers(); - - //WB: Logging to help temp-debugging - console.log('response success', response); - console.log('response success headers', headers); - if (headers["x-umb-user-seconds"]) { // We must use $injector to get the $http service to prevent circular dependency @@ -95,7 +90,7 @@ angular.module('umbraco.security.interceptor') notifications.error( "Request error", - errMsg); + errMsg); } else if (rejection.status === 403) { @@ -141,7 +136,7 @@ angular.module('umbraco.security.interceptor') .config(['$httpProvider', function ($httpProvider) { $httpProvider.defaults.xsrfHeaderName = 'X-UMB-XSRF-TOKEN'; $httpProvider.defaults.xsrfCookieName = 'UMB-XSRF-TOKEN'; - // Fixme: https://stackoverflow.com/questions/23804981/alternative-of-httpprovider-responseinterceptors + $httpProvider.interceptors.push('securityInterceptor'); $httpProvider.interceptors.push('umbracoRequestInterceptor'); }]); From 8337500356c9c7ce02d129e4efdb4b40d82281a3 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 12 Jun 2018 15:17:43 +0200 Subject: [PATCH 066/115] turn html5 mode on --- src/Umbraco.Web.UI.Client/src/routes.js | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/routes.js b/src/Umbraco.Web.UI.Client/src/routes.js index e4b7466155..4ff41dcd03 100644 --- a/src/Umbraco.Web.UI.Client/src/routes.js +++ b/src/Umbraco.Web.UI.Client/src/routes.js @@ -190,9 +190,5 @@ app.config(function ($routeProvider) { }) .otherwise({ redirectTo: '/login' }); }).config(function ($locationProvider) { - - //$locationProvider.html5Mode(false).hashPrefix('!'); //turn html5 mode off - // $locationProvider.html5Mode(true); //turn html5 mode on - - + $locationProvider.html5Mode(true); //turn html5 mode on }); From fde1d6f6fba4d2cd5dd0f88cd6be6eccc87992f7 Mon Sep 17 00:00:00 2001 From: Warren Date: Tue, 12 Jun 2018 14:34:45 +0100 Subject: [PATCH 067/115] Update the angular routing to be # as opposed to hash bang #! --- src/Umbraco.Web.UI.Client/src/routes.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/routes.js b/src/Umbraco.Web.UI.Client/src/routes.js index e4b7466155..5143d3edfe 100644 --- a/src/Umbraco.Web.UI.Client/src/routes.js +++ b/src/Umbraco.Web.UI.Client/src/routes.js @@ -191,8 +191,6 @@ app.config(function ($routeProvider) { .otherwise({ redirectTo: '/login' }); }).config(function ($locationProvider) { - //$locationProvider.html5Mode(false).hashPrefix('!'); //turn html5 mode off - // $locationProvider.html5Mode(true); //turn html5 mode on - + $locationProvider.html5Mode(false).hashPrefix(''); //turn html5 mode off }); From acab866b29ea6d01ca8522c37461b1f58933d636 Mon Sep 17 00:00:00 2001 From: Warren Date: Tue, 12 Jun 2018 14:40:44 +0100 Subject: [PATCH 068/115] Update list view create button to use ng-href now the hashbang is now just hash :) --- .../src/views/propertyeditors/listview/listview.html | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.html b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.html index 453d274ed6..2828f047d5 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.html +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.html @@ -18,7 +18,7 @@
                - + Create {{ listViewAllowedTypes[0].name }} From 90a53ddcc73526b9cda531a6fe2cd0e4b55e0617 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 12 Jun 2018 16:03:17 +0200 Subject: [PATCH 069/115] fix localisation for user groups picker --- .../overlays/usergrouppicker/usergrouppicker.controller.js | 2 +- .../src/views/users/views/users/users.controller.js | 6 ++---- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/common/overlays/usergrouppicker/usergrouppicker.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/overlays/usergrouppicker/usergrouppicker.controller.js index b86c7286f7..72d56f7884 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/overlays/usergrouppicker/usergrouppicker.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/overlays/usergrouppicker/usergrouppicker.controller.js @@ -18,7 +18,7 @@ // set default title if(!$scope.model.title) { - localizationService.localize("defaultdialogs_selectUsers").then(function(value){ + localizationService.localize("user_selectUserGroups").then(function(value){ $scope.model.title = value; }); } diff --git a/src/Umbraco.Web.UI.Client/src/views/users/views/users/users.controller.js b/src/Umbraco.Web.UI.Client/src/views/users/views/users/users.controller.js index cc6c01ad50..2235f333c8 100644 --- a/src/Umbraco.Web.UI.Client/src/views/users/views/users/users.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/users/views/users/users.controller.js @@ -315,10 +315,9 @@ vm.selectedBulkUserGroups = _.clone(firstSelectedUser.userGroups); vm.userGroupPicker = { - title: localizationService.localize("user_selectUserGroups"), view: "usergrouppicker", selection: vm.selectedBulkUserGroups, - closeButtonLabel: localizationService.localize("general_cancel"), + closeButtonLabelKey: "general_cancel", show: true, submit: function (model) { usersResource.setUserGroupsOnUsers(model.selection, vm.selection).then(function (data) { @@ -351,10 +350,9 @@ function openUserGroupPicker(event) { vm.userGroupPicker = { - title: localizationService.localize("user_selectUserGroups"), view: "usergrouppicker", selection: vm.newUser.userGroups, - closeButtonLabel: localizationService.localize("general_cancel"), + closeButtonLabelKey: "general_cancel", show: true, submit: function (model) { // apply changes From 09006352f705ea155de7fd77d2c11a9cffacc7b2 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 12 Jun 2018 20:51:22 +0200 Subject: [PATCH 070/115] fix logout --- src/Umbraco.Web.UI.Client/src/routes.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/routes.js b/src/Umbraco.Web.UI.Client/src/routes.js index 8efc5c885a..cbd99fb902 100644 --- a/src/Umbraco.Web.UI.Client/src/routes.js +++ b/src/Umbraco.Web.UI.Client/src/routes.js @@ -76,8 +76,11 @@ app.config(function ($routeProvider) { /** When this is used to resolve it will attempt to log the current user out */ var doLogout = function() { return { - isLoggedOut: function ($q, userService) { + isLoggedOut: function ($q, $location, userService) { return userService.logout().then(function () { + // we have to redirect here instead of the routes redirectTo + // https://github.com/angular/angular.js/commit/7f4b356c2bebb87f0c26b57a20415b004b20bcd1 + $location.path("/login/false"); //success so continue return $q.when(true); }, function() { @@ -103,7 +106,6 @@ app.config(function ($routeProvider) { resolve: canRoute(false) }) .when('/logout', { - redirectTo: '/login/false', resolve: doLogout() }) .when('/:section?', { From 3b4e1ea3d6f8e1a6c42177f69b48e11ccf4710c5 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Tue, 12 Jun 2018 20:57:08 +0200 Subject: [PATCH 071/115] fix media recycle bin --- .../src/views/media/recyclebin.html | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/media/recyclebin.html b/src/Umbraco.Web.UI.Client/src/views/media/recyclebin.html index 4a74e4affe..16649f214a 100644 --- a/src/Umbraco.Web.UI.Client/src/views/media/recyclebin.html +++ b/src/Umbraco.Web.UI.Client/src/views/media/recyclebin.html @@ -1,16 +1,17 @@ - -
                - + + + + -
                -
                +
                From f848746f332666551f15a58938efffcd7bb4c3fc Mon Sep 17 00:00:00 2001 From: Warren Date: Wed, 13 Jun 2018 08:31:28 +0100 Subject: [PATCH 072/115] Remove the unused functions in the security interceptor re-write --- .../src/common/security/securityinterceptor.js | 16 +--------------- 1 file changed, 1 insertion(+), 15 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/security/securityinterceptor.js b/src/Umbraco.Web.UI.Client/src/common/security/securityinterceptor.js index 834aa83e54..9976502b88 100644 --- a/src/Umbraco.Web.UI.Client/src/common/security/securityinterceptor.js +++ b/src/Umbraco.Web.UI.Client/src/common/security/securityinterceptor.js @@ -1,21 +1,7 @@ angular.module('umbraco.security.interceptor') // This http interceptor listens for authentication successes and failures .factory('securityInterceptor', ['$injector', 'securityRetryQueue', 'notificationsService', 'eventsService', 'requestInterceptorFilter', function ($injector, queue, notifications, eventsService, requestInterceptorFilter) { - return { - - 'request': function(config) { - // do something on success - // request for data - if we want to modify headers or url etc - console.log('request config', config); - return config; - }, - - 'requestError': function(rejection) { - // do something on error - - console.log('request error rejection', rejection); - return $q.reject(rejection); - }, + return { 'response': function(response) { // Intercept successful requests From 27891e304d07b3e0f97ac93fd3503e618a9b4a73 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 13 Jun 2018 10:16:25 +0200 Subject: [PATCH 073/115] fix icon contet flashes + update to new component syntax --- .../components/buttons/umbbutton.directive.js | 134 +++++++++--------- .../views/components/buttons/umb-button.html | 57 ++++---- 2 files changed, 97 insertions(+), 94 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/buttons/umbbutton.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/buttons/umbbutton.directive.js index 642ba3b529..047d67ffef 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/buttons/umbbutton.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/buttons/umbbutton.directive.js @@ -67,103 +67,107 @@ Use this directive to render an umbraco button. The directive can be used to gen @param {boolean=} disabled Set to true to disable the button. **/ -(function() { - 'use strict'; +(function () { + 'use strict'; - function ButtonDirective($timeout) { + angular + .module('umbraco.directives') + .component('umbButton', { + transclude: true, + templateUrl: 'views/components/buttons/umb-button.html', + controller: UmbButtonController, + controllerAs: 'vm', + bindings: { + action: "&?", + href: "@?", + type: "@", + buttonStyle: "@?", + state: " +
                -
                +
                +
                +
                +
                +
                +
                -
                + + + + {{vm.label}} + {{vm.label}} + + -
                + -
                - - - - - {{label}} - {{label}} - - - - - - +
                From 20cd36026ef739256700e7e5ee4f7b25c26ade4c Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 13 Jun 2018 11:51:44 +0200 Subject: [PATCH 074/115] fix overlay conent flash --- .../components/overlays/umb-overlay-backdrop.less | 11 +++++++++-- .../components/overlays/umb-overlay-backdrop.html | 2 +- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/less/components/overlays/umb-overlay-backdrop.less b/src/Umbraco.Web.UI.Client/src/less/components/overlays/umb-overlay-backdrop.less index 129ae9e757..5907c5bfab 100644 --- a/src/Umbraco.Web.UI.Client/src/less/components/overlays/umb-overlay-backdrop.less +++ b/src/Umbraco.Web.UI.Client/src/less/components/overlays/umb-overlay-backdrop.less @@ -2,11 +2,18 @@ position: fixed; width: 100%; height: 100%; - background-color: rgba(255, 255, 255, 0.50); + background-color: rgba(255, 255, 255, 0.5); z-index: @zindexOverlayBackdrop; top: @appHeaderHeight; left: 0; - animation: fadeIn 0.2s; +} + +.umb-overlay-backdrop.ng-enter { + animation: fadeIn 0.3s; +} + +.umb-overlay-backdrop.ng-leave { + animation: fadeOut 0.3s; } .umb-drawer-is-visible .umb-overlay-backdrop { diff --git a/src/Umbraco.Web.UI.Client/src/views/components/overlays/umb-overlay-backdrop.html b/src/Umbraco.Web.UI.Client/src/views/components/overlays/umb-overlay-backdrop.html index e73a43849f..dd94f8627c 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/overlays/umb-overlay-backdrop.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/overlays/umb-overlay-backdrop.html @@ -1 +1 @@ -
                +
                From f29167eb59d56d7c6d9169bd6a58a7cc5fed1275 Mon Sep 17 00:00:00 2001 From: Warren Date: Wed, 13 Jun 2018 12:04:05 +0100 Subject: [PATCH 075/115] Fix up nucache/published status dashboard - the responses back from the API calls are not JSON but a simple string and thus we did not need angular.fromJson() --- .../src/views/dashboard/developer/nucache.controller.js | 6 +++--- .../views/dashboard/developer/publishedstatus.controller.js | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/dashboard/developer/nucache.controller.js b/src/Umbraco.Web.UI.Client/src/views/dashboard/developer/nucache.controller.js index 8a6d3d5db3..aab133d786 100644 --- a/src/Umbraco.Web.UI.Client/src/views/dashboard/developer/nucache.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/dashboard/developer/nucache.controller.js @@ -21,7 +21,7 @@ 'Failed to verify the cache.') .then(function (result) { $scope.working = false; - $scope.status = angular.fromJson(result); + $scope.status = result; }); }; @@ -33,7 +33,7 @@ 'Failed to verify the cache.') .then(function (result) { $scope.working = false; - $scope.status = angular.fromJson(result); + $scope.status = result; }); }; @@ -46,7 +46,7 @@ 'Failed to rebuild the cache.') .then(function (result) { $scope.working = false; - $scope.status = angular.fromJson(result); + $scope.status = result; }); } }; diff --git a/src/Umbraco.Web.UI.Client/src/views/dashboard/developer/publishedstatus.controller.js b/src/Umbraco.Web.UI.Client/src/views/dashboard/developer/publishedstatus.controller.js index 2997369f29..507ed9c240 100644 --- a/src/Umbraco.Web.UI.Client/src/views/dashboard/developer/publishedstatus.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/dashboard/developer/publishedstatus.controller.js @@ -6,10 +6,10 @@ $http.get(umbRequestHelper.getApiUrl('publishedStatusBaseUrl', 'GetPublishedStatusUrl')), 'Failed to get published status url') .then(function (result) { - $scope.includeUrl = angular.fromJson(result); - }); - //$scope.includeUrl = 'views/dashboard/developer/xmldataintegrityreport.html'; + //result = 'views/dashboard/developer/nucache.html' + $scope.includeUrl = result; + }); } angular.module("umbraco").controller("Umbraco.Dashboard.PublishedStatusController", publishedStatusController); \ No newline at end of file From 3be22bd6a75545600b81cd80e3fdcf0a5ee46a48 Mon Sep 17 00:00:00 2001 From: Warren Date: Wed, 13 Jun 2018 12:27:22 +0100 Subject: [PATCH 076/115] Fix up modelsbuilder dashboard - we now use ng-bind-html directive as opposed to ng-bind-html-unsafe --- src/Umbraco.Web.UI/App_Plugins/ModelsBuilder/modelsbuilder.htm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI/App_Plugins/ModelsBuilder/modelsbuilder.htm b/src/Umbraco.Web.UI/App_Plugins/ModelsBuilder/modelsbuilder.htm index 5049e5f157..eeca93bf3a 100644 --- a/src/Umbraco.Web.UI/App_Plugins/ModelsBuilder/modelsbuilder.htm +++ b/src/Umbraco.Web.UI/App_Plugins/ModelsBuilder/modelsbuilder.htm @@ -11,7 +11,7 @@
                -
                +

                Models are out-of-date. From faad17a92ec297c95dc1e77b8398d7870c81480b Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 13 Jun 2018 14:10:17 +0200 Subject: [PATCH 077/115] fixes: #48 Subviews show a quick content flash of all views before they hide --- .../editor/umb-editor-sub-views.html | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-sub-views.html b/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-sub-views.html index 6327e9f310..76d3104924 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-sub-views.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-sub-views.html @@ -1,10 +1,17 @@

                -
                + +
                + +
                +
                +
                +
                From 44529f266ecca77237775cb93b3e34c3ce4ec0ee Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Wed, 13 Jun 2018 15:31:05 +0200 Subject: [PATCH 078/115] =?UTF-8?q?fixes:=20When=20opening=20the=20doctype?= =?UTF-8?q?,=20media=20type,=20member=20type=20editor=20the=20name=20field?= =?UTF-8?q?=20makes=20a=20small=20=E2=80=9Cjump=E2=80=9D.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/views/components/editor/umb-editor-header.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-header.html b/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-header.html index 8964aa1b97..f88b28f32f 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-header.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/editor/umb-editor-header.html @@ -83,7 +83,7 @@ ng-if="!hideDescription && !descriptionLocked" ng-model="$parent.description" /> -
                {{ description }}
                +
                {{ description }}
                From e630faa185f23d95868d478594030bdf7c52f5a4 Mon Sep 17 00:00:00 2001 From: Warren Date: Wed, 13 Jun 2018 15:46:20 +0100 Subject: [PATCH 079/115] Fixes translation items for the keyboard shortcuts in template editor & partial view editor * Angular does not auto expand promises when we assign to properties on scope & now we return a promise with the object data with the values translated from the localization service --- .../common/services/templatehelper.service.js | 135 ++++++++++++++---- .../src/views/partialviews/edit.controller.js | 14 +- .../src/views/templates/edit.controller.js | 13 +- 3 files changed, 130 insertions(+), 32 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/common/services/templatehelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/templatehelper.service.js index 5643ea8e48..6fc20524e9 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/templatehelper.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/templatehelper.service.js @@ -44,121 +44,204 @@ } function getGeneralShortcuts(){ - return { - "name": localizationService.localize("shortcuts_generalHeader"), + var keys = [ + "shortcuts_generalHeader", + "buttons_undo", + "buttons_redo", + "buttons_save" + ]; + + return localizationService.localizeMany(keys).then(function(data){ + + var labels = {}; + labels.header = data[0]; + labels.undo = data[1]; + labels.redo = data[2]; + labels.save = data[3]; + + return { + "name": labels.header, "shortcuts": [ { - "description": localizationService.localize("buttons_undo"), + "description": labels.undo, "keys": [{ "key": "ctrl" }, { "key": "z" }] }, { - "description": localizationService.localize("buttons_redo"), + "description": labels.redo, "keys": [{ "key": "ctrl" }, { "key": "y" }] }, { - "description": localizationService.localize("buttons_save"), + "description": labels.save, "keys": [{ "key": "ctrl" }, { "key": "s" }] } ] }; + }); } function getEditorShortcuts(){ - return { - "name": localizationService.localize("shortcuts_editorHeader"), + + var keys = [ + "shortcuts_editorHeader", + "shortcuts_commentLine", + "shortcuts_removeLine", + "shortcuts_copyLineUp", + "shortcuts_copyLineDown", + "shortcuts_moveLineUp", + "shortcuts_moveLineDown" + ]; + + return localizationService.localizeMany(keys).then(function(data){ + + var labels = {}; + labels.header = data[0]; + labels.commentline = data[1]; + labels.removeline = data[2]; + labels.copylineup = data[3]; + labels.copylinedown = data[4]; + labels.movelineup = data[5]; + labels.movelinedown = data[6]; + + return { + "name": labels.header, "shortcuts": [ { - "description": localizationService.localize("shortcuts_commentLine"), + "description":labels.commentline, "keys": [{ "key": "ctrl" }, { "key": "/" }] }, { - "description": localizationService.localize("shortcuts_removeLine"), + "description": labels.removeline, "keys": [{ "key": "ctrl" }, { "key": "d" }] }, { - "description": localizationService.localize("shortcuts_copyLineUp"), + "description": labels.copylineup, "keys": { "win": [{ "key": "alt" }, { "key": "shift" }, { "key": "up" }], "mac": [{ "key": "cmd" }, { "key": "alt" }, { "key": "up" }] } }, { - "description": localizationService.localize("shortcuts_copyLineDown"), + "description": labels.copylinedown, "keys": { "win": [{ "key": "alt" }, { "key": "shift" }, { "key": "down" }], "mac": [{ "key": "cmd" }, { "key": "alt" }, { "key": "down" }] } }, { - "description": localizationService.localize("shortcuts_moveLineUp"), + "description": labels.movelineup, "keys": [{ "key": "alt" }, { "key": "up" }] }, { - "description": localizationService.localize("shortcuts_moveLineDown"), + "description": labels.movelinedown, "keys": [{ "key": "alt" }, { "key": "down" }] } ] }; + }); } function getTemplateEditorShortcuts(){ - return { + var keys = [ + "template_insert", + "template_insertPageField", + "template_insertPartialView", + "template_insertDictionaryItem", + "template_insertMacro", + "template_queryBuilder", + "template_insertSections", + "template_mastertemplate" + ]; + + return localizationService.localizeMany(keys).then(function(data){ + + var labels = {}; + labels.insert = data[0]; + labels.pagefield = data[1]; + labels.partialview = data[2]; + labels.dictionary = data[3]; + labels.macro = data[4]; + labels.querybuilder = data[5]; + labels.sections = data[6]; + labels.mastertemplate = data[7]; + + return { "name": "Umbraco", //No need to localise Umbraco is the same in all languages :) "shortcuts": [ { - "description": localizationService.format(["template_insert", "template_insertPageField"], "%0% %1%"), + "description": labels.insert.concat(' ', labels.pagefield), "keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "v" }] }, { - "description": localizationService.format(["template_insert", "template_insertPartialView"], "%0% %1%"), + "description": labels.insert.concat(' ', labels.partialview), "keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "p" }] }, { - "description": localizationService.format(["template_insert", "template_insertDictionaryItem"], "%0% %1%"), + "description": labels.insert.concat(' ', labels.dictionary), "keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "d" }] }, { - "description": localizationService.format(["template_insert", "template_insertMacro"], "%0% %1%"), + "description": labels.insert.concat(' ', labels.macro), "keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "m" }] }, { - "description": localizationService.localize("template_queryBuilder"), + "description": labels.querybuilder, "keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "q" }] }, { - "description": localizationService.format(["template_insert", "template_insertSections"], "%0% %1%"), + "description": labels.insert.concat(' ', labels.sections), "keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "s" }] }, { - "description": localizationService.localize("template_mastertemplate"), + "description": labels.mastertemplate, "keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "t" }] } ] }; + }); } function getPartialViewEditorShortcuts(){ - return { + var keys = [ + "template_insert", + "template_insertPageField", + "template_insertDictionaryItem", + "template_insertMacro", + "template_queryBuilder" + ]; + + return localizationService.localizeMany(keys).then(function(data){ + + var labels = {}; + labels.insert = data[0]; + labels.pagefield = data[1]; + labels.dictionary = data[2]; + labels.macro = data[3]; + labels.querybuilder = data[4]; + + return { "name": "Umbraco", //No need to localise Umbraco is the same in all languages :) "shortcuts": [ { - "description": localizationService.format(["template_insert", "template_insertPageField"], "%0% %1%"), + "description": labels.insert.concat(' ', labels.pagefield), "keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "v" }] }, { - "description": localizationService.format(["template_insert", "template_insertDictionaryItem"], "%0% %1%"), + "description": labels.insert.concat(' ', labels.dictionary), "keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "d" }] }, { - "description": localizationService.format(["template_insert", "template_insertMacro"], "%0% %1%"), + "description": labels.insert.concat(' ', labels.macro), "keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "m" }] }, { - "description": localizationService.localize("template_queryBuilder"), + "description": labels.querybuilder, "keys": [{ "key": "alt" }, { "key": "shift" }, { "key": "q" }] } ] }; + }); + + } //////////// diff --git a/src/Umbraco.Web.UI.Client/src/views/partialviews/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/partialviews/edit.controller.js index c3f06b09d9..f6e017a8e9 100644 --- a/src/Umbraco.Web.UI.Client/src/views/partialviews/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/partialviews/edit.controller.js @@ -48,9 +48,17 @@ //Keyboard shortcuts for help dialog vm.page.keyboardShortcutsOverview = []; - vm.page.keyboardShortcutsOverview.push(templateHelper.getGeneralShortcuts()); - vm.page.keyboardShortcutsOverview.push(templateHelper.getEditorShortcuts()); - vm.page.keyboardShortcutsOverview.push(templateHelper.getPartialViewEditorShortcuts()); + + templateHelper.getGeneralShortcuts().then(function(data){ + vm.page.keyboardShortcutsOverview.push(data); + }); + templateHelper.getEditorShortcuts().then(function(data){ + vm.page.keyboardShortcutsOverview.push(data); + }); + templateHelper.getPartialViewEditorShortcuts().then(function(data){ + vm.page.keyboardShortcutsOverview.push(data); + }); + // bind functions to view model vm.save = save; diff --git a/src/Umbraco.Web.UI.Client/src/views/templates/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/templates/edit.controller.js index 571dc05286..5d75774ffb 100644 --- a/src/Umbraco.Web.UI.Client/src/views/templates/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/templates/edit.controller.js @@ -55,9 +55,16 @@ //Keyboard shortcuts for help dialog vm.page.keyboardShortcutsOverview = []; - vm.page.keyboardShortcutsOverview.push(templateHelper.getGeneralShortcuts()); - vm.page.keyboardShortcutsOverview.push(templateHelper.getEditorShortcuts()); - vm.page.keyboardShortcutsOverview.push(templateHelper.getTemplateEditorShortcuts()); + + templateHelper.getGeneralShortcuts().then(function(data){ + vm.page.keyboardShortcutsOverview.push(data); + }); + templateHelper.getEditorShortcuts().then(function(data){ + vm.page.keyboardShortcutsOverview.push(data); + }); + templateHelper.getTemplateEditorShortcuts().then(function(data){ + vm.page.keyboardShortcutsOverview.push(data); + }); vm.save = function () { From 500cd9da19d09f61c8c7ba995740bbd9dd950815 Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 14 Jun 2018 09:41:04 +0200 Subject: [PATCH 080/115] fix shortcuts for scripts editor --- .../src/views/scripts/edit.controller.js | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/scripts/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/scripts/edit.controller.js index 130be54e68..5c1a24611f 100644 --- a/src/Umbraco.Web.UI.Client/src/views/scripts/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/scripts/edit.controller.js @@ -19,9 +19,14 @@ //Keyboard shortcuts for help dialog vm.page.keyboardShortcutsOverview = []; - vm.page.keyboardShortcutsOverview.push(templateHelper.getGeneralShortcuts()); - vm.page.keyboardShortcutsOverview.push(templateHelper.getEditorShortcuts()); - + + templateHelper.getGeneralShortcuts().then(function(shortcuts){ + vm.page.keyboardShortcutsOverview.push(shortcuts); + }); + + templateHelper.getEditorShortcuts().then(function(shortcuts){ + vm.page.keyboardShortcutsOverview.push(shortcuts); + }); vm.script = {}; From 913364b2c7058901d7272120ad90411f5cb1cd24 Mon Sep 17 00:00:00 2001 From: Warren Date: Thu, 14 Jun 2018 09:31:19 +0100 Subject: [PATCH 081/115] Fixes test with the changes to the template editor shortcuts as they now return a promise --- .../unit/app/templates/template-editor-controller.spec.js | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/test/unit/app/templates/template-editor-controller.spec.js b/src/Umbraco.Web.UI.Client/test/unit/app/templates/template-editor-controller.spec.js index fe82048c5f..19f51d5bf6 100644 --- a/src/Umbraco.Web.UI.Client/test/unit/app/templates/template-editor-controller.spec.js +++ b/src/Umbraco.Web.UI.Client/test/unit/app/templates/template-editor-controller.spec.js @@ -112,9 +112,10 @@ getQuerySnippet: function() { return ""; }, getRenderBodySnippet: function() { return ""; }, getRenderSectionSnippet: function() { return ""; }, - getGeneralShortcuts: function() { return ""; }, - getEditorShortcuts: function() { return ""; }, - getTemplateEditorShortcuts: function() { return ""; } + + getGeneralShortcuts: resolvedPromise({}), + getEditorShortcuts: resolvedPromise({}), + getTemplateEditorShortcuts: resolvedPromise({}) } }); } @@ -137,6 +138,7 @@ }, 1000); }); + //TODO: THIS FAILED it("changes layout value when masterpage is selected", function() { var newTemplate; ace.clearSelection = nada; From 4171fc7bfa81d176fe8833438de370d58463dab6 Mon Sep 17 00:00:00 2001 From: Warren Date: Thu, 14 Jun 2018 10:26:32 +0100 Subject: [PATCH 082/115] Fixes Forms Dashboard Error - $cookieStore is no more & is now just $cookies in Angular --- .../src/views/dashboard/dashboard.tabs.controller.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/Umbraco.Web.UI.Client/src/views/dashboard/dashboard.tabs.controller.js b/src/Umbraco.Web.UI.Client/src/views/dashboard/dashboard.tabs.controller.js index a23f8b09c5..97acbf360f 100644 --- a/src/Umbraco.Web.UI.Client/src/views/dashboard/dashboard.tabs.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/dashboard/dashboard.tabs.controller.js @@ -125,7 +125,7 @@ function startUpDynamicContentController($timeout, $scope, dashboardResource, as angular.module("umbraco").controller("Umbraco.Dashboard.StartUpDynamicContentController", startUpDynamicContentController); -function FormsController($scope, $route, $cookieStore, packageResource, localizationService) { +function FormsController($scope, $route, $cookies, packageResource, localizationService) { var labels = {}; var labelKeys = [ @@ -173,7 +173,7 @@ function FormsController($scope, $route, $cookieStore, packageResource, localiza $scope.complete = function(result){ var url = window.location.href + "?init=true"; - $cookieStore.put("umbPackageInstallId", result.packageGuid); + $cookies.putObject("umbPackageInstallId", result.packageGuid); window.location.reload(true); }; From a380683833afda3e2fdd063321acc5c1a375e32d Mon Sep 17 00:00:00 2001 From: Stephan Date: Thu, 14 Jun 2018 11:43:36 +0200 Subject: [PATCH 083/115] New mediapath scheme becomes default --- .../UmbracoSettings/ContentElement.cs | 5 ++++ .../UmbracoSettings/IContentSection.cs | 4 +++- src/Umbraco.Core/IO/MediaFileSystem.cs | 24 +++++++++---------- 3 files changed, 19 insertions(+), 14 deletions(-) diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/ContentElement.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/ContentElement.cs index 4a00aeb3ee..612437a688 100644 --- a/src/Umbraco.Core/Configuration/UmbracoSettings/ContentElement.cs +++ b/src/Umbraco.Core/Configuration/UmbracoSettings/ContentElement.cs @@ -20,6 +20,9 @@ namespace Umbraco.Core.Configuration.UmbracoSettings [ConfigurationProperty("UploadAllowDirectories")] internal InnerTextConfigurationElement UploadAllowDirectories => GetOptionalTextElement("UploadAllowDirectories", true); + [ConfigurationProperty("UseTheNewMediaPathScheme")] + internal InnerTextConfigurationElement UseTheNewMediaPathScheme => GetOptionalTextElement("UseTheNewMediaPathScheme", true); + public IEnumerable Error404Collection => Errors.Error404Collection; [ConfigurationProperty("errors", IsRequired = true)] @@ -105,6 +108,8 @@ namespace Umbraco.Core.Configuration.UmbracoSettings bool IContentSection.UploadAllowDirectories => UploadAllowDirectories; + bool IContentSection.UseTheNewMediaPathScheme => UseTheNewMediaPathScheme; + bool IContentSection.EnsureUniqueNaming => EnsureUniqueNaming; bool IContentSection.XmlCacheEnabled => XmlCacheEnabled; diff --git a/src/Umbraco.Core/Configuration/UmbracoSettings/IContentSection.cs b/src/Umbraco.Core/Configuration/UmbracoSettings/IContentSection.cs index 879afd65bf..df0a39ad39 100644 --- a/src/Umbraco.Core/Configuration/UmbracoSettings/IContentSection.cs +++ b/src/Umbraco.Core/Configuration/UmbracoSettings/IContentSection.cs @@ -23,7 +23,9 @@ namespace Umbraco.Core.Configuration.UmbracoSettings bool ResolveUrlsFromTextString { get; } - bool UploadAllowDirectories { get; } + bool UploadAllowDirectories { get; } + + bool UseTheNewMediaPathScheme { get; } IEnumerable Error404Collection { get; } diff --git a/src/Umbraco.Core/IO/MediaFileSystem.cs b/src/Umbraco.Core/IO/MediaFileSystem.cs index 2c9773a9cb..b1404121e5 100644 --- a/src/Umbraco.Core/IO/MediaFileSystem.cs +++ b/src/Umbraco.Core/IO/MediaFileSystem.cs @@ -28,13 +28,6 @@ namespace Umbraco.Core.IO private long _folderCounter; private bool _folderCounterInitialized; - // fixme - remove - //private static readonly Dictionary DefaultSizes = new Dictionary - //{ - // { 100, "thumb" }, - // { 500, "big-thumb" } - //}; - public MediaFileSystem(IFileSystem wrapped) : base(wrapped) { @@ -52,10 +45,14 @@ namespace Umbraco.Core.IO internal ILogger Logger { get; set; } internal UploadAutoFillProperties UploadAutoFillProperties { get; } - - // note - this is currently experimental / being developed - //public static bool UseTheNewMediaPathScheme { get; set; } - public const bool UseTheNewMediaPathScheme = false; + + // fixme - work-in-progress + // the new scheme is now the default scheme - media items with old paths will still + // work, but whenever a file is uploaded, the new scheme is used. we have a temp. + // option to let people opt-out of the new scheme. eventually, the media filesystem + // will only support the new scheme - but it should be an interface, and it should + // be possible to switch its implementation to whatever people want to use + public bool UseTheNewMediaPathScheme => ContentConfig.UseTheNewMediaPathScheme; /// /// Deletes all files passed in. @@ -116,7 +113,6 @@ namespace Umbraco.Core.IO DeleteFile(file); #pragma warning disable 162 // unreachable code - // Not implemented yet, so need to disable warnings // ReSharper disable once ConditionIsAlwaysTrueOrFalse if (UseTheNewMediaPathScheme == false) { @@ -160,7 +156,6 @@ namespace Umbraco.Core.IO string folder; #pragma warning disable 162 // unreachable code - // Not implemented yet, so need to disable warnings // ReSharper disable once ConditionIsAlwaysTrueOrFalse if (UseTheNewMediaPathScheme == false) { @@ -207,6 +202,8 @@ namespace Umbraco.Core.IO /// specified by . Else, we CREATE a new one. Each time we are invoked. public string GetMediaPath(string filename, string prevpath, Guid cuid, Guid puid) { +#pragma warning disable 162 // unreachable code + // ReSharper disable once ConditionIsAlwaysTrueOrFalse if (UseTheNewMediaPathScheme || string.IsNullOrWhiteSpace(prevpath)) return GetMediaPath(filename, cuid, puid); @@ -230,6 +227,7 @@ namespace Umbraco.Core.IO : folder + "-" + filename; return filepath; +#pragma warning restore 162 // unreachable code } /// From 383d5527bb4559e52a7de7756829d8f2483ecdcb Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 14 Jun 2018 13:48:51 +0200 Subject: [PATCH 084/115] fixes slow UI by restricting angular animations to only work on elements with the umb-animated css class --- src/Umbraco.Web.UI.Client/src/app.js | 12 ++++++++++++ .../components/overlays/umb-overlay-backdrop.html | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/Umbraco.Web.UI.Client/src/app.js b/src/Umbraco.Web.UI.Client/src/app.js index 97096c9733..6a6555198a 100644 --- a/src/Umbraco.Web.UI.Client/src/app.js +++ b/src/Umbraco.Web.UI.Client/src/app.js @@ -16,6 +16,18 @@ var app = angular.module('umbraco', [ 'LocalStorageModule' ]); +// I configure the $animate service during bootstrap. +angular.module("umbraco").config( + function configureAnimate( $animateProvider ) { + // By default, the $animate service will check for animation styling + // on every structural change. This requires a lot of animateFrame-based + // DOM-inspection. However, we can tell $animate to only check for + // animations on elements that have a specific class name RegExp pattern + // present. In this case, we are requiring the "umb-animated" class. + $animateProvider.classNameFilter( /\bumb-animated\b/ ); + } +); + var packages = angular.module("umbraco.packages", []); //this ensures we can inject our own views into templateCache and clear diff --git a/src/Umbraco.Web.UI.Client/src/views/components/overlays/umb-overlay-backdrop.html b/src/Umbraco.Web.UI.Client/src/views/components/overlays/umb-overlay-backdrop.html index dd94f8627c..170ae605f4 100644 --- a/src/Umbraco.Web.UI.Client/src/views/components/overlays/umb-overlay-backdrop.html +++ b/src/Umbraco.Web.UI.Client/src/views/components/overlays/umb-overlay-backdrop.html @@ -1 +1 @@ -
                +
                From 4708293b186971375167ab29e12ab61e924196da Mon Sep 17 00:00:00 2001 From: Mads Rasmussen Date: Thu, 14 Jun 2018 19:37:49 +0200 Subject: [PATCH 085/115] remove debug info in production, disables execution of css and comment directives --- src/Umbraco.Web.UI.Client/src/app.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/Umbraco.Web.UI.Client/src/app.js b/src/Umbraco.Web.UI.Client/src/app.js index 6a6555198a..81230c73f3 100644 --- a/src/Umbraco.Web.UI.Client/src/app.js +++ b/src/Umbraco.Web.UI.Client/src/app.js @@ -16,6 +16,15 @@ var app = angular.module('umbraco', [ 'LocalStorageModule' ]); +app.config(['$compileProvider', function ($compileProvider) { + // when not in debug mode remove all angularjs debug css classes and HTML comments from the dom + $compileProvider.debugInfoEnabled(Umbraco.Sys.ServerVariables.isDebuggingEnabled); + // don't execute directives inside comments + $compileProvider.commentDirectivesEnabled(false); + // don't execute directives inside css classes + $compileProvider.cssClassDirectivesEnabled(false); +}]); + // I configure the $animate service during bootstrap. angular.module("umbraco").config( function configureAnimate( $animateProvider ) { From 80c585c21ed5b9798850168ab8b936b7e32e3379 Mon Sep 17 00:00:00 2001 From: Shannon Deminick Date: Fri, 15 Jun 2018 10:33:16 +1000 Subject: [PATCH 086/115] Temp8 validation fixing (#2699) * Showing notifications if any for any response with status 400 >= x < 500. * fixes valFormManager * Updates logic for the valpropertymsg.directive to simplify it and so that it doesn't need to query the DOM which was causing issues with timing. * commits package-lock * fixes some issues with the securityinterceptor, properly nests promises in contentEditingHelper, fixes errors occuring when not handling promise rejections due to validation problems, * another unhandled potential validation problem * Merge branch 'temp-U4-7757' of https://github.com/lars-erik/Umbraco-CMS into lars-erik-temp-U4-7757 # Conflicts: # src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js * cleans up the interceptor objects and puts them in appropriate modules and files, centralizes the logic to show notifications so that only happens in one place. * Fixes more places where notifications were manually shown. * Fixes validation with the variant publishing overlay and html descrepencies --- src/Umbraco.Web.UI.Client/gulpfile.js | 4 +- src/Umbraco.Web.UI.Client/package-lock.json | 5699 +++++++++++++---- .../src/canvasdesigner.loader.js | 2 +- .../components/content/edit.controller.js | 9 +- .../html/umbcontrolgroup.directive.js | 2 +- .../property/umbpropertyeditor.directive.js | 4 +- .../umbsetdirtyonchange.directive.js | 2 +- .../validation/valcompare.directive.js | 4 +- .../validation/valformmanager.directive.js | 47 +- .../validation/valpropertymsg.directive.js | 39 +- .../validation/valserverfield.directive.js | 3 +- .../validation/valsubview.directive.js | 2 +- .../directives/validation/valtab.directive.js | 4 +- .../validation/valtogglemsg.directive.js | 4 +- .../src/common/interceptors/_module.js | 9 + .../interceptors/debugrequest.interceptor.js | 25 + .../requestinterceptorfilter.value.js | 11 + .../security.interceptor.js} | 68 +- .../src/common/security/_module.js | 4 - .../src/common/security/retryqueue.js | 90 - .../src/common/services/_module.js | 2 +- .../common/services/angularhelper.service.js | 2 +- .../services/contenteditinghelper.service.js | 14 +- .../src/common/services/formhelper.service.js | 7 +- .../src/common/services/retryqueue.service.js | 97 + .../services/umbrequesthelper.service.js | 148 +- .../src/common/services/user.service.js | 14 +- src/Umbraco.Web.UI.Client/src/loader.dev.js | 4 +- .../views/common/dialogs/login.controller.js | 2 +- .../common/overlays/publish/publish.html | 18 +- .../common/overlays/user/user.controller.js | 2 +- .../views/content/content.copy.controller.js | 8 +- .../content.createblueprint.controller.js | 2 +- .../content/content.delete.controller.js | 6 - .../content.emptyrecyclebin.controller.js | 9 +- .../views/content/content.move.controller.js | 7 +- .../datatypes/datatype.edit.controller.js | 2 +- .../src/views/datatypes/move.controller.js | 7 +- .../views/documenttypes/copy.controller.js | 7 +- .../views/documenttypes/create.controller.js | 10 +- .../views/documenttypes/move.controller.js | 7 +- .../views/documenttypes/rename.controller.js | 26 +- .../src/views/languages/edit.controller.js | 10 +- .../views/languages/overview.controller.js | 6 - .../views/media/media.delete.controller.js | 5 - .../src/views/media/media.edit.controller.js | 9 +- .../media/media.emptyrecyclebin.controller.js | 7 - .../src/views/mediatypes/copy.controller.js | 7 +- .../src/views/mediatypes/move.controller.js | 7 +- .../views/member/member.edit.controller.js | 2 +- .../src/views/membergroups/edit.controller.js | 2 +- .../partialviewmacros/create.controller.js | 8 +- .../partialviewmacros/edit.controller.js | 6 +- .../views/partialviews/create.controller.js | 6 +- .../listview/listview.controller.js | 8 +- .../src/views/scripts/create.controller.js | 5 +- .../src/views/users/user.controller.js | 20 +- .../users/views/groups/groups.controller.js | 5 +- .../users/views/users/users.controller.js | 14 +- .../test/config/app.unit.js | 4 +- src/Umbraco.Web/UI/JavaScript/JsInitialize.js | 2 +- 61 files changed, 4852 insertions(+), 1714 deletions(-) create mode 100644 src/Umbraco.Web.UI.Client/src/common/interceptors/_module.js create mode 100644 src/Umbraco.Web.UI.Client/src/common/interceptors/debugrequest.interceptor.js create mode 100644 src/Umbraco.Web.UI.Client/src/common/interceptors/requestinterceptorfilter.value.js rename src/Umbraco.Web.UI.Client/src/common/{security/securityinterceptor.js => interceptors/security.interceptor.js} (71%) delete mode 100644 src/Umbraco.Web.UI.Client/src/common/security/_module.js delete mode 100644 src/Umbraco.Web.UI.Client/src/common/security/retryqueue.js create mode 100644 src/Umbraco.Web.UI.Client/src/common/services/retryqueue.service.js diff --git a/src/Umbraco.Web.UI.Client/gulpfile.js b/src/Umbraco.Web.UI.Client/gulpfile.js index afaaadf050..15f908a9e8 100644 --- a/src/Umbraco.Web.UI.Client/gulpfile.js +++ b/src/Umbraco.Web.UI.Client/gulpfile.js @@ -79,7 +79,7 @@ var sources = { filters: { files: ["src/common/filters/**/*.js"], out: "umbraco.filters.js" }, resources: { files: ["src/common/resources/**/*.js"], out: "umbraco.resources.js" }, services: { files: ["src/common/services/**/*.js"], out: "umbraco.services.js" }, - security: { files: ["src/common/security/**/*.js"], out: "umbraco.security.js" } + security: { files: ["src/common/interceptors/**/*.js"], out: "umbraco.interceptors.js" } }, //selectors for copying all views into the build @@ -406,4 +406,4 @@ gulp.task('test:e2e', function() { keepalive: true }) .start(); -}); \ No newline at end of file +}); diff --git a/src/Umbraco.Web.UI.Client/package-lock.json b/src/Umbraco.Web.UI.Client/package-lock.json index 79aab79300..2173d49119 100644 --- a/src/Umbraco.Web.UI.Client/package-lock.json +++ b/src/Umbraco.Web.UI.Client/package-lock.json @@ -16,7 +16,7 @@ "integrity": "sha1-5fHzkoxtlf2WVYw27D2dDeSm7Oo=", "dev": true, "requires": { - "mime-types": "2.1.18", + "mime-types": "~2.1.6", "negotiator": "0.5.3" } }, @@ -26,20 +26,20 @@ "integrity": "sha1-vsUWovci59UPX59C+Bt387lUSLo=", "dev": true, "requires": { - "convert-source-map": "1.5.1", - "glob": "7.1.2", - "indx": "0.2.3", - "lodash.clone": "4.5.0", - "lodash.defaults": "4.2.0", - "lodash.flatten": "4.4.0", - "lodash.merge": "4.6.1", - "lodash.partialright": "4.2.1", - "lodash.pick": "4.4.0", - "lodash.uniq": "4.5.0", - "resolve": "1.6.0", - "semver": "5.5.0", - "uglify-js": "2.8.29", - "when": "3.7.8" + "convert-source-map": "^1.5.0", + "glob": "^7.0.5", + "indx": "^0.2.3", + "lodash.clone": "^4.3.2", + "lodash.defaults": "^4.0.1", + "lodash.flatten": "^4.2.0", + "lodash.merge": "^4.4.0", + "lodash.partialright": "^4.1.4", + "lodash.pick": "^4.2.1", + "lodash.uniq": "^4.3.0", + "resolve": "^1.5.0", + "semver": "^5.3.0", + "uglify-js": "^2.8.22", + "when": "^3.7.8" }, "dependencies": { "semver": { @@ -62,8 +62,8 @@ "integrity": "sha1-gv+wKynmYq5TvcIK8VlHcGc5xTY=", "dev": true, "requires": { - "co": "4.6.0", - "json-stable-stringify": "1.0.1" + "co": "^4.6.0", + "json-stable-stringify": "^1.0.1" } }, "align-text": { @@ -72,9 +72,9 @@ "integrity": "sha1-DNkKVhCT810KmSVsIrcGlDP60Rc=", "dev": true, "requires": { - "kind-of": "3.2.2", - "longest": "1.0.1", - "repeat-string": "1.6.1" + "kind-of": "^3.0.2", + "longest": "^1.0.1", + "repeat-string": "^1.5.2" }, "dependencies": { "kind-of": { @@ -83,7 +83,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "^1.1.5" } } } @@ -163,8 +163,8 @@ "integrity": "sha1-VT3Lj5HjyImEXf26NMd3IbkLnXo=", "dev": true, "requires": { - "micromatch": "2.3.11", - "normalize-path": "2.1.1" + "micromatch": "^2.1.5", + "normalize-path": "^2.0.0" }, "dependencies": { "arr-diff": { @@ -173,7 +173,7 @@ "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", "dev": true, "requires": { - "arr-flatten": "1.1.0" + "arr-flatten": "^1.0.1" } }, "array-unique": { @@ -188,9 +188,9 @@ "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", "dev": true, "requires": { - "expand-range": "1.8.2", - "preserve": "0.2.0", - "repeat-element": "1.1.2" + "expand-range": "^1.8.1", + "preserve": "^0.2.0", + "repeat-element": "^1.1.2" } }, "expand-brackets": { @@ -199,7 +199,7 @@ "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", "dev": true, "requires": { - "is-posix-bracket": "0.1.1" + "is-posix-bracket": "^0.1.0" } }, "extglob": { @@ -208,7 +208,7 @@ "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", "dev": true, "requires": { - "is-extglob": "1.0.0" + "is-extglob": "^1.0.0" } }, "is-extglob": { @@ -223,7 +223,7 @@ "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", "dev": true, "requires": { - "is-extglob": "1.0.0" + "is-extglob": "^1.0.0" } }, "kind-of": { @@ -232,7 +232,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "^1.1.5" } }, "micromatch": { @@ -241,23 +241,40 @@ "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", "dev": true, "requires": { - "arr-diff": "2.0.0", - "array-unique": "0.2.1", - "braces": "1.8.5", - "expand-brackets": "0.1.5", - "extglob": "0.3.2", - "filename-regex": "2.0.1", - "is-extglob": "1.0.0", - "is-glob": "2.0.1", - "kind-of": "3.2.2", - "normalize-path": "2.1.1", - "object.omit": "2.0.1", - "parse-glob": "3.0.4", - "regex-cache": "0.4.4" + "arr-diff": "^2.0.0", + "array-unique": "^0.2.1", + "braces": "^1.8.2", + "expand-brackets": "^0.1.4", + "extglob": "^0.3.1", + "filename-regex": "^2.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.1", + "kind-of": "^3.0.2", + "normalize-path": "^2.0.1", + "object.omit": "^2.0.0", + "parse-glob": "^3.0.4", + "regex-cache": "^0.4.2" } } } }, + "archive-type": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/archive-type/-/archive-type-3.2.0.tgz", + "integrity": "sha1-nNnABpV+vpX62tW9YJiUKoE3N/Y=", + "dev": true, + "requires": { + "file-type": "^3.1.0" + }, + "dependencies": { + "file-type": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", + "integrity": "sha1-JXoHg4TR24CHvESdEH1SpSZyuek=", + "dev": true + } + } + }, "archy": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/archy/-/archy-1.0.0.tgz", @@ -270,7 +287,7 @@ "integrity": "sha1-vNZ5HqWuCXJeF+WtmIE0zUCz2RE=", "dev": true, "requires": { - "sprintf-js": "1.0.3" + "sprintf-js": "~1.0.2" } }, "arr-diff": { @@ -315,6 +332,15 @@ "integrity": "sha1-42jqFfibxwaff/uJrsOmx9SsItQ=", "dev": true }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, + "requires": { + "array-uniq": "^1.0.1" + } + }, "array-uniq": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", @@ -364,7 +390,7 @@ "integrity": "sha1-YaKau2/MAm/qd+VtHG7FOnlZUfQ=", "dev": true, "requires": { - "lodash": "4.17.5" + "lodash": "^4.14.0" } }, "async-each": { @@ -373,6 +399,13 @@ "integrity": "sha1-GdOGodntxufByF04iu28xW0zYC0=", "dev": true }, + "async-each-series": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/async-each-series/-/async-each-series-1.1.0.tgz", + "integrity": "sha1-9C/YFV048hpbjqB8KOBj7RcAsTg=", + "dev": true, + "optional": true + }, "asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -391,12 +424,12 @@ "integrity": "sha1-Hb0cg1ZY41zj+ZhAmdsAWFx4IBQ=", "dev": true, "requires": { - "browserslist": "1.7.7", - "caniuse-db": "1.0.30000821", - "normalize-range": "0.1.2", - "num2fraction": "1.2.2", - "postcss": "5.2.18", - "postcss-value-parser": "3.3.0" + "browserslist": "^1.7.6", + "caniuse-db": "^1.0.30000634", + "normalize-range": "^0.1.2", + "num2fraction": "^1.2.2", + "postcss": "^5.2.16", + "postcss-value-parser": "^3.2.3" } }, "aws-sign2": { @@ -429,13 +462,13 @@ "integrity": "sha1-e95c7RRbbVUakNuH+DxVi060io8=", "dev": true, "requires": { - "cache-base": "1.0.1", - "class-utils": "0.3.6", - "component-emitter": "1.2.1", - "define-property": "1.0.0", - "isobject": "3.0.1", - "mixin-deep": "1.3.1", - "pascalcase": "0.1.1" + "cache-base": "^1.0.1", + "class-utils": "^0.3.5", + "component-emitter": "^1.2.1", + "define-property": "^1.0.0", + "isobject": "^3.0.1", + "mixin-deep": "^1.2.0", + "pascalcase": "^0.1.1" }, "dependencies": { "define-property": { @@ -444,7 +477,7 @@ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", "dev": true, "requires": { - "is-descriptor": "1.0.2" + "is-descriptor": "^1.0.0" } } } @@ -492,7 +525,7 @@ "dev": true, "optional": true, "requires": { - "tweetnacl": "0.14.5" + "tweetnacl": "^0.14.3" } }, "beeper": { @@ -510,12 +543,147 @@ "callsite": "1.0.0" } }, + "bin-build": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/bin-build/-/bin-build-2.2.0.tgz", + "integrity": "sha1-EfjdYfcP/Por3KpbRvXo/t1CIcw=", + "dev": true, + "optional": true, + "requires": { + "archive-type": "^3.0.1", + "decompress": "^3.0.0", + "download": "^4.1.2", + "exec-series": "^1.0.0", + "rimraf": "^2.2.6", + "tempfile": "^1.0.0", + "url-regex": "^3.0.0" + }, + "dependencies": { + "tempfile": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/tempfile/-/tempfile-1.1.1.tgz", + "integrity": "sha1-W8xOrsxKsscH2LwR2ZzMmiyyh/I=", + "dev": true, + "optional": true, + "requires": { + "os-tmpdir": "^1.0.0", + "uuid": "^2.0.1" + } + }, + "uuid": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.3.tgz", + "integrity": "sha1-Z+LoY3lyFVMN/zGOW/nc6/1Hsho=", + "dev": true, + "optional": true + } + } + }, + "bin-check": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/bin-check/-/bin-check-2.0.0.tgz", + "integrity": "sha1-hvjm9CU4k99g3DFpV/WvAqywWTA=", + "dev": true, + "optional": true, + "requires": { + "executable": "^1.0.0" + } + }, + "bin-version": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/bin-version/-/bin-version-1.0.4.tgz", + "integrity": "sha1-nrSY7m/Xb3q5p8FgQ2+JV5Q1144=", + "dev": true, + "optional": true, + "requires": { + "find-versions": "^1.0.0" + } + }, + "bin-version-check": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/bin-version-check/-/bin-version-check-2.1.0.tgz", + "integrity": "sha1-5OXfKQuQaffRETJAMe/BP90RpbA=", + "dev": true, + "optional": true, + "requires": { + "bin-version": "^1.0.0", + "minimist": "^1.1.0", + "semver": "^4.0.3", + "semver-truncate": "^1.0.0" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true, + "optional": true + } + } + }, + "bin-wrapper": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/bin-wrapper/-/bin-wrapper-3.0.2.tgz", + "integrity": "sha1-Z9MwYmLksaXy+I7iNGT2plVneus=", + "dev": true, + "optional": true, + "requires": { + "bin-check": "^2.0.0", + "bin-version-check": "^2.1.0", + "download": "^4.0.0", + "each-async": "^1.1.1", + "lazy-req": "^1.0.0", + "os-filter-obj": "^1.0.0" + } + }, "binary-extensions": { "version": "1.11.0", "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.11.0.tgz", "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=", "dev": true }, + "bl": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/bl/-/bl-1.2.2.tgz", + "integrity": "sha512-e8tQYnZodmebYDWGH7KMRvtzKXaJHx3BbilrgZCfvyLUYdKpK1t5PSPmpkny/SgiTSCnjfLW7v5rlONXVFkQEA==", + "dev": true, + "requires": { + "readable-stream": "^2.3.5", + "safe-buffer": "^5.1.1" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, "blob": { "version": "0.0.4", "resolved": "https://registry.npmjs.org/blob/-/blob-0.0.4.tgz", @@ -535,15 +703,15 @@ "dev": true, "requires": { "bytes": "2.1.0", - "content-type": "1.0.4", - "debug": "2.2.0", - "depd": "1.0.1", - "http-errors": "1.3.1", + "content-type": "~1.0.1", + "debug": "~2.2.0", + "depd": "~1.0.1", + "http-errors": "~1.3.1", "iconv-lite": "0.4.11", - "on-finished": "2.3.0", + "on-finished": "~2.3.0", "qs": "4.0.0", - "raw-body": "2.1.7", - "type-is": "1.6.16" + "raw-body": "~2.1.2", + "type-is": "~1.6.6" }, "dependencies": { "debug": { @@ -563,13 +731,19 @@ } } }, + "boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24=", + "dev": true + }, "boom": { "version": "2.10.1", "resolved": "https://registry.npmjs.org/boom/-/boom-2.10.1.tgz", "integrity": "sha1-OciRjO/1eZ+D+UkqhI9iWt0Mdm8=", "dev": true, "requires": { - "hoek": "2.16.3" + "hoek": "2.x.x" } }, "bower": { @@ -584,14 +758,14 @@ "integrity": "sha1-z3g5tlQh0rJwqyLHT8hYpV46E3A=", "dev": true, "requires": { - "async": "2.6.0", - "bower": "1.8.4", - "colors": "1.2.1", - "glob": "7.1.2", - "lodash": "4.17.5", - "mkdirp": "0.5.1", - "node-fs": "0.1.7", - "nopt": "3.0.6" + "async": "^2.1.4", + "bower": "^1.8.0", + "colors": "^1.1.2", + "glob": "^7.1.1", + "lodash": "^4.17.2", + "mkdirp": "^0.5.1", + "node-fs": "~0.1.7", + "nopt": "^3.0.6" } }, "brace-expansion": { @@ -600,7 +774,7 @@ "integrity": "sha1-PH/L9SnYcibz0vUrlm/1Jx60Qd0=", "dev": true, "requires": { - "balanced-match": "1.0.0", + "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, @@ -610,18 +784,18 @@ "integrity": "sha1-cIbJE7TloI2+N6wO5qJQDEumkbs=", "dev": true, "requires": { - "arr-flatten": "1.1.0", - "array-unique": "0.3.2", - "define-property": "1.0.0", - "extend-shallow": "2.0.1", - "fill-range": "4.0.0", - "isobject": "3.0.1", - "kind-of": "6.0.2", - "repeat-element": "1.1.2", - "snapdragon": "0.8.2", - "snapdragon-node": "2.1.1", - "split-string": "3.1.0", - "to-regex": "3.0.2" + "arr-flatten": "^1.1.0", + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "extend-shallow": "^2.0.1", + "fill-range": "^4.0.0", + "isobject": "^3.0.1", + "kind-of": "^6.0.2", + "repeat-element": "^1.1.2", + "snapdragon": "^0.8.1", + "snapdragon-node": "^2.0.1", + "split-string": "^3.0.2", + "to-regex": "^3.0.1" }, "dependencies": { "define-property": { @@ -630,7 +804,7 @@ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", "dev": true, "requires": { - "is-descriptor": "1.0.2" + "is-descriptor": "^1.0.0" } }, "extend-shallow": { @@ -639,7 +813,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "0.1.1" + "is-extendable": "^0.1.0" } } } @@ -650,8 +824,104 @@ "integrity": "sha1-C9dnBCWL6CmyOYu1Dkti0aFmsLk=", "dev": true, "requires": { - "caniuse-db": "1.0.30000821", - "electron-to-chromium": "1.3.41" + "caniuse-db": "^1.0.30000639", + "electron-to-chromium": "^1.2.7" + } + }, + "buffer-alloc": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/buffer-alloc/-/buffer-alloc-1.2.0.tgz", + "integrity": "sha512-CFsHQgjtW1UChdXgbyJGtnm+O/uLQeZdtbDo8mfUgYXCHSM1wgrVxXm6bSyrUuErEb+4sYVGCzASBRot7zyrow==", + "dev": true, + "requires": { + "buffer-alloc-unsafe": "^1.1.0", + "buffer-fill": "^1.0.0" + } + }, + "buffer-alloc-unsafe": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-alloc-unsafe/-/buffer-alloc-unsafe-1.1.0.tgz", + "integrity": "sha512-TEM2iMIEQdJ2yjPJoSIsldnleVaAk1oW3DBVUykyOLsEsFmEc9kn+SFFPz+gl54KQNxlDnAwCXosOS9Okx2xAg==", + "dev": true + }, + "buffer-fill": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-fill/-/buffer-fill-1.0.0.tgz", + "integrity": "sha1-+PeLdniYiO858gXNY39o5wISKyw=", + "dev": true + }, + "buffer-from": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-0.1.2.tgz", + "integrity": "sha512-RiWIenusJsmI2KcvqQABB83tLxCByE3upSP8QU3rJDMVFGPWLvPQJt/O1Su9moRWeH7d+Q2HYb68f6+v+tw2vg==", + "dev": true, + "optional": true + }, + "buffer-to-vinyl": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/buffer-to-vinyl/-/buffer-to-vinyl-1.1.0.tgz", + "integrity": "sha1-APFfruOreh3aLN5tkSG//dB7ImI=", + "dev": true, + "requires": { + "file-type": "^3.1.0", + "readable-stream": "^2.0.2", + "uuid": "^2.0.1", + "vinyl": "^1.0.0" + }, + "dependencies": { + "file-type": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-3.9.0.tgz", + "integrity": "sha1-JXoHg4TR24CHvESdEH1SpSZyuek=", + "dev": true + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "uuid": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-2.0.3.tgz", + "integrity": "sha1-Z+LoY3lyFVMN/zGOW/nc6/1Hsho=", + "dev": true + }, + "vinyl": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", + "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", + "dev": true, + "requires": { + "clone": "^1.0.0", + "clone-stats": "^0.0.1", + "replace-ext": "0.0.1" + } + } } }, "bufferstreams": { @@ -660,7 +930,7 @@ "integrity": "sha1-z7GtlWjTujz+k1upq92VLeiKqyo=", "dev": true, "requires": { - "readable-stream": "1.1.14" + "readable-stream": "^1.0.33" } }, "builtin-modules": { @@ -681,15 +951,15 @@ "integrity": "sha1-Cn9GQWgxyLZi7jb+TnxZ129marI=", "dev": true, "requires": { - "collection-visit": "1.0.0", - "component-emitter": "1.2.1", - "get-value": "2.0.6", - "has-value": "1.0.0", - "isobject": "3.0.1", - "set-value": "2.0.0", - "to-object-path": "0.3.0", - "union-value": "1.0.0", - "unset-value": "1.0.0" + "collection-visit": "^1.0.0", + "component-emitter": "^1.2.1", + "get-value": "^2.0.6", + "has-value": "^1.0.0", + "isobject": "^3.0.1", + "set-value": "^2.0.0", + "to-object-path": "^0.3.0", + "union-value": "^1.0.0", + "unset-value": "^1.0.0" } }, "callsite": { @@ -710,8 +980,8 @@ "integrity": "sha1-MIvur/3ygRkFHvodkyITyRuPkuc=", "dev": true, "requires": { - "camelcase": "2.1.1", - "map-obj": "1.0.1" + "camelcase": "^2.0.0", + "map-obj": "^1.0.0" }, "dependencies": { "camelcase": { @@ -728,10 +998,10 @@ "integrity": "sha1-tTTnxzTE+B7F++isoq0kNUuWLGw=", "dev": true, "requires": { - "browserslist": "1.7.7", - "caniuse-db": "1.0.30000821", - "lodash.memoize": "4.1.2", - "lodash.uniq": "4.5.0" + "browserslist": "^1.3.6", + "caniuse-db": "^1.0.30000529", + "lodash.memoize": "^4.1.2", + "lodash.uniq": "^4.5.0" } }, "caniuse-db": { @@ -746,20 +1016,52 @@ "integrity": "sha1-4x65N6jJPuKgHfGDl5RyGQKHRXQ=", "dev": true }, + "capture-stack-trace": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/capture-stack-trace/-/capture-stack-trace-1.0.0.tgz", + "integrity": "sha1-Sm+gc5nCa7pH8LJJa00PtAjFVQ0=", + "dev": true + }, "caseless": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=", "dev": true }, + "caw": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/caw/-/caw-1.2.0.tgz", + "integrity": "sha1-/7Im/n78VHKI3GLuPpcHPCEtEDQ=", + "dev": true, + "requires": { + "get-proxy": "^1.0.1", + "is-obj": "^1.0.0", + "object-assign": "^3.0.0", + "tunnel-agent": "^0.4.0" + }, + "dependencies": { + "object-assign": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-3.0.0.tgz", + "integrity": "sha1-m+3VygiXlJvKR+f/QIBi1Un1h/I=", + "dev": true + }, + "tunnel-agent": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.4.3.tgz", + "integrity": "sha1-Y3PbdpCf5XDgjXNYM2Xtgop07us=", + "dev": true + } + } + }, "center-align": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", "integrity": "sha1-qg0yYptu6XIgBBHL1EYckHvCt60=", "dev": true, "requires": { - "align-text": "0.1.4", - "lazy-cache": "1.0.4" + "align-text": "^0.1.3", + "lazy-cache": "^1.0.3" } }, "chalk": { @@ -768,11 +1070,11 @@ "integrity": "sha1-qBFcVeSnAv5NFQq9OHKCKn4J/Jg=", "dev": true, "requires": { - "ansi-styles": "2.2.1", - "escape-string-regexp": "1.0.5", - "has-ansi": "2.0.0", - "strip-ansi": "3.0.1", - "supports-color": "2.0.0" + "ansi-styles": "^2.2.1", + "escape-string-regexp": "^1.0.2", + "has-ansi": "^2.0.0", + "strip-ansi": "^3.0.0", + "supports-color": "^2.0.0" }, "dependencies": { "supports-color": { @@ -789,14 +1091,15 @@ "integrity": "sha1-eY5ol3gVHIB2tLNg5e3SjNortGg=", "dev": true, "requires": { - "anymatch": "1.3.2", - "async-each": "1.0.1", - "glob-parent": "2.0.0", - "inherits": "2.0.3", - "is-binary-path": "1.0.1", - "is-glob": "2.0.1", - "path-is-absolute": "1.0.1", - "readdirp": "2.1.0" + "anymatch": "^1.3.0", + "async-each": "^1.0.0", + "fsevents": "^1.0.0", + "glob-parent": "^2.0.0", + "inherits": "^2.0.1", + "is-binary-path": "^1.0.0", + "is-glob": "^2.0.0", + "path-is-absolute": "^1.0.0", + "readdirp": "^2.0.0" }, "dependencies": { "glob-parent": { @@ -805,7 +1108,7 @@ "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", "dev": true, "requires": { - "is-glob": "2.0.1" + "is-glob": "^2.0.0" } }, "is-extglob": { @@ -820,7 +1123,7 @@ "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", "dev": true, "requires": { - "is-extglob": "1.0.0" + "is-extglob": "^1.0.0" } } } @@ -831,7 +1134,7 @@ "integrity": "sha1-TzZ0WzIAhJJVf0ZBLWbVDLmbzlE=", "dev": true, "requires": { - "chalk": "1.1.3" + "chalk": "^1.1.3" } }, "class-utils": { @@ -840,10 +1143,10 @@ "integrity": "sha1-+TNprouafOAv1B+q0MqDAzGQxGM=", "dev": true, "requires": { - "arr-union": "3.1.0", - "define-property": "0.2.5", - "isobject": "3.0.1", - "static-extend": "0.1.2" + "arr-union": "^3.1.0", + "define-property": "^0.2.5", + "isobject": "^3.0.0", + "static-extend": "^0.1.1" }, "dependencies": { "define-property": { @@ -852,7 +1155,7 @@ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "0.1.6" + "is-descriptor": "^0.1.0" } }, "is-accessor-descriptor": { @@ -861,7 +1164,7 @@ "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", "dev": true, "requires": { - "kind-of": "3.2.2" + "kind-of": "^3.0.2" }, "dependencies": { "kind-of": { @@ -870,7 +1173,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "^1.1.5" } } } @@ -881,7 +1184,7 @@ "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", "dev": true, "requires": { - "kind-of": "3.2.2" + "kind-of": "^3.0.2" }, "dependencies": { "kind-of": { @@ -890,7 +1193,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "^1.1.5" } } } @@ -901,9 +1204,9 @@ "integrity": "sha1-Nm2CQN3kh8pRgjsaufB6EKeCUco=", "dev": true, "requires": { - "is-accessor-descriptor": "0.1.6", - "is-data-descriptor": "0.1.4", - "kind-of": "5.1.0" + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" } }, "kind-of": { @@ -920,8 +1223,8 @@ "integrity": "sha1-S0dXYP+AJkx2LDoXGQMukcf+oNE=", "dev": true, "requires": { - "center-align": "0.1.3", - "right-align": "0.1.3", + "center-align": "^0.1.1", + "right-align": "^0.1.1", "wordwrap": "0.0.2" } }, @@ -949,9 +1252,9 @@ "integrity": "sha1-1ZHe5Kj4vBXaQ86X3O66E9Q+KmU=", "dev": true, "requires": { - "inherits": "2.0.3", - "process-nextick-args": "2.0.0", - "readable-stream": "2.3.5" + "inherits": "^2.0.1", + "process-nextick-args": "^2.0.0", + "readable-stream": "^2.3.5" }, "dependencies": { "isarray": { @@ -966,13 +1269,13 @@ "integrity": "sha1-tPhQA6k4y7bsvOKhJPsQEr0ag40=", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "2.0.0", - "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.0.3", + "util-deprecate": "~1.0.1" } }, "string_decoder": { @@ -981,7 +1284,7 @@ "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", "dev": true, "requires": { - "safe-buffer": "5.1.1" + "safe-buffer": "~5.1.0" } } } @@ -998,7 +1301,7 @@ "integrity": "sha1-qe8VNmDWqGqL3sAomlxoTSF0Mv0=", "dev": true, "requires": { - "q": "1.5.1" + "q": "^1.1.2" } }, "collection-visit": { @@ -1007,8 +1310,8 @@ "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA=", "dev": true, "requires": { - "map-visit": "1.0.0", - "object-visit": "1.0.1" + "map-visit": "^1.0.0", + "object-visit": "^1.0.0" } }, "color": { @@ -1017,9 +1320,9 @@ "integrity": "sha1-bXtcdPtl6EHNSHkq0e1eB7kE12Q=", "dev": true, "requires": { - "clone": "1.0.4", - "color-convert": "1.9.1", - "color-string": "0.3.0" + "clone": "^1.0.2", + "color-convert": "^1.3.0", + "color-string": "^0.3.0" } }, "color-convert": { @@ -1028,7 +1331,7 @@ "integrity": "sha1-wSYRB66y8pTr/+ye2eytUppgl+0=", "dev": true, "requires": { - "color-name": "1.1.3" + "color-name": "^1.1.1" } }, "color-name": { @@ -1043,7 +1346,7 @@ "integrity": "sha1-J9RvtnAlxcL6JZk7+/V55HhBuZE=", "dev": true, "requires": { - "color-name": "1.1.3" + "color-name": "^1.0.0" } }, "color-support": { @@ -1058,9 +1361,9 @@ "integrity": "sha1-6i90IKcrlogaOKrlnsEkpvcpgTM=", "dev": true, "requires": { - "color": "0.11.4", + "color": "^0.11.0", "css-color-names": "0.0.4", - "has": "1.0.1" + "has": "^1.0.1" } }, "colors": { @@ -1075,7 +1378,7 @@ "integrity": "sha1-RYwH4J4NkA/Ci3Cj/sLazR0st/Y=", "dev": true, "requires": { - "lodash": "4.17.5" + "lodash": "^4.5.0" } }, "combined-stream": { @@ -1084,7 +1387,16 @@ "integrity": "sha1-cj599ugBrFYTETp+RFqbactjKBg=", "dev": true, "requires": { - "delayed-stream": "1.0.0" + "delayed-stream": "~1.0.0" + } + }, + "commander": { + "version": "2.8.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.8.1.tgz", + "integrity": "sha1-Br42f+v9oMMwqh4qBy09yXYkJdQ=", + "dev": true, + "requires": { + "graceful-readlink": ">= 1.0.0" } }, "component-bind": { @@ -1111,7 +1423,7 @@ "integrity": "sha1-DRAgq5JLL9tNYnmHXH1tq6a6p6k=", "dev": true, "requires": { - "mime-db": "1.33.0" + "mime-db": ">= 1.33.0 < 2" } }, "compression": { @@ -1120,12 +1432,12 @@ "integrity": "sha1-sDuNhub4rSloPLqN+R3cb/x3s5U=", "dev": true, "requires": { - "accepts": "1.2.13", + "accepts": "~1.2.12", "bytes": "2.1.0", - "compressible": "2.0.13", - "debug": "2.2.0", - "on-headers": "1.0.1", - "vary": "1.0.1" + "compressible": "~2.0.5", + "debug": "~2.2.0", + "on-headers": "~1.0.0", + "vary": "~1.0.1" }, "dependencies": { "debug": { @@ -1157,9 +1469,9 @@ "integrity": "sha1-CqxmL9Ur54lk1VMvaUeE5wEQrPc=", "dev": true, "requires": { - "inherits": "2.0.3", - "readable-stream": "2.3.5", - "typedarray": "0.0.6" + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" }, "dependencies": { "isarray": { @@ -1174,13 +1486,13 @@ "integrity": "sha1-tPhQA6k4y7bsvOKhJPsQEr0ag40=", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "2.0.0", - "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.0.3", + "util-deprecate": "~1.0.1" } }, "string_decoder": { @@ -1189,7 +1501,7 @@ "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", "dev": true, "requires": { - "safe-buffer": "5.1.1" + "safe-buffer": "~5.1.0" } } } @@ -1200,7 +1512,7 @@ "integrity": "sha1-iWS8I0fQWBm2N5gQTYfW4AG+2NA=", "dev": true, "requires": { - "source-map": "0.6.1" + "source-map": "^0.6.1" }, "dependencies": { "source-map": { @@ -1218,36 +1530,36 @@ "dev": true, "requires": { "basic-auth-connect": "1.0.0", - "body-parser": "1.13.3", + "body-parser": "~1.13.3", "bytes": "2.1.0", - "compression": "1.5.2", - "connect-timeout": "1.6.2", - "content-type": "1.0.4", + "compression": "~1.5.2", + "connect-timeout": "~1.6.2", + "content-type": "~1.0.1", "cookie": "0.1.3", - "cookie-parser": "1.3.5", + "cookie-parser": "~1.3.5", "cookie-signature": "1.0.6", - "csurf": "1.8.3", - "debug": "2.2.0", - "depd": "1.0.1", - "errorhandler": "1.4.3", - "express-session": "1.11.3", + "csurf": "~1.8.3", + "debug": "~2.2.0", + "depd": "~1.0.1", + "errorhandler": "~1.4.2", + "express-session": "~1.11.3", "finalhandler": "0.4.0", "fresh": "0.3.0", - "http-errors": "1.3.1", - "method-override": "2.3.10", - "morgan": "1.6.1", + "http-errors": "~1.3.1", + "method-override": "~2.3.5", + "morgan": "~1.6.1", "multiparty": "3.3.2", - "on-headers": "1.0.1", - "parseurl": "1.3.2", + "on-headers": "~1.0.0", + "parseurl": "~1.3.0", "pause": "0.1.0", "qs": "4.0.0", - "response-time": "2.3.2", - "serve-favicon": "2.3.2", - "serve-index": "1.7.3", - "serve-static": "1.10.3", - "type-is": "1.6.16", + "response-time": "~2.3.1", + "serve-favicon": "~2.3.0", + "serve-index": "~1.7.2", + "serve-static": "~1.10.0", + "type-is": "~1.6.6", "utils-merge": "1.0.0", - "vhost": "3.0.2" + "vhost": "~3.0.1" }, "dependencies": { "debug": { @@ -1279,10 +1591,10 @@ "integrity": "sha1-3ppexh4zoStu2qt7XwYumMWZuI4=", "dev": true, "requires": { - "debug": "2.2.0", - "http-errors": "1.3.1", + "debug": "~2.2.0", + "http-errors": "~1.3.1", "ms": "0.7.1", - "on-headers": "1.0.1" + "on-headers": "~1.0.0" }, "dependencies": { "debug": { @@ -1302,13 +1614,20 @@ } } }, + "console-stream": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/console-stream/-/console-stream-0.1.1.tgz", + "integrity": "sha1-oJX+B7IEZZVfL6/Si11yvM2UnUQ=", + "dev": true, + "optional": true + }, "consolidate": { "version": "0.14.5", "resolved": "https://registry.npmjs.org/consolidate/-/consolidate-0.14.5.tgz", "integrity": "sha1-WiUEe8dvcwcmZ8jLUsmJiI9JTGM=", "dev": true, "requires": { - "bluebird": "3.5.1" + "bluebird": "^3.1.1" } }, "content-type": { @@ -1369,13 +1688,13 @@ "integrity": "sha1-YXPOvVb6wELB9DkO33r2wHx8uJI=", "dev": true, "requires": { - "is-directory": "0.3.1", - "js-yaml": "3.7.0", - "minimist": "1.2.0", - "object-assign": "4.1.1", - "os-homedir": "1.0.2", - "parse-json": "2.2.0", - "require-from-string": "1.2.1" + "is-directory": "^0.3.1", + "js-yaml": "^3.4.3", + "minimist": "^1.2.0", + "object-assign": "^4.1.0", + "os-homedir": "^1.0.1", + "parse-json": "^2.2.0", + "require-from-string": "^1.1.0" }, "dependencies": { "minimist": { @@ -1392,13 +1711,47 @@ "integrity": "sha1-+mIuG8OIvyVzCQgta2UgDOZwkLo=", "dev": true }, + "create-error-class": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/create-error-class/-/create-error-class-3.0.2.tgz", + "integrity": "sha1-Br56vvlHo/FKMP1hBnHUAbyot7Y=", + "dev": true, + "requires": { + "capture-stack-trace": "^1.0.0" + } + }, + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "dev": true, + "optional": true, + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "dependencies": { + "lru-cache": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.3.tgz", + "integrity": "sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==", + "dev": true, + "optional": true, + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + } + } + }, "cryptiles": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/cryptiles/-/cryptiles-2.0.5.tgz", "integrity": "sha1-O9/s3GCBR8HGcgL6KR59ylnqo7g=", "dev": true, "requires": { - "boom": "2.10.1" + "boom": "2.x.x" } }, "csrf": { @@ -1418,44 +1771,89 @@ "integrity": "sha1-gIrcLnnPhHOAabZGyyDsJ762KeA=", "dev": true }, + "css-select": { + "version": "1.3.0-rc0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-1.3.0-rc0.tgz", + "integrity": "sha1-b5MZaqrnN2ZuoQNqjLFKj8t6kjE=", + "dev": true, + "optional": true, + "requires": { + "boolbase": "^1.0.0", + "css-what": "2.1", + "domutils": "1.5.1", + "nth-check": "^1.0.1" + } + }, + "css-select-base-adapter": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.0.tgz", + "integrity": "sha1-AQKz0UYw34bD65+p9UVicBBs+ZA=", + "dev": true, + "optional": true + }, + "css-tree": { + "version": "1.0.0-alpha25", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha25.tgz", + "integrity": "sha512-XC6xLW/JqIGirnZuUWHXCHRaAjje2b3OIB0Vj5RIJo6mIi/AdJo30quQl5LxUl0gkXDIrTrFGbMlcZjyFplz1A==", + "dev": true, + "optional": true, + "requires": { + "mdn-data": "^1.0.0", + "source-map": "^0.5.3" + } + }, + "css-url-regex": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/css-url-regex/-/css-url-regex-1.1.0.tgz", + "integrity": "sha1-g4NCMMyfdMRX3lnuvRVD/uuDt+w=", + "dev": true, + "optional": true + }, + "css-what": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-2.1.0.tgz", + "integrity": "sha1-lGfQMsOM+u+58teVASUwYvh/ob0=", + "dev": true, + "optional": true + }, "cssnano": { "version": "3.10.0", "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-3.10.0.tgz", "integrity": "sha1-Tzj2zqK5sX+gFJDyPx3GjqZcHDg=", "dev": true, "requires": { - "autoprefixer": "6.7.7", - "decamelize": "1.2.0", - "defined": "1.0.0", - "has": "1.0.1", - "object-assign": "4.1.1", - "postcss": "5.2.18", - "postcss-calc": "5.3.1", - "postcss-colormin": "2.2.2", - "postcss-convert-values": "2.6.1", - "postcss-discard-comments": "2.0.4", - "postcss-discard-duplicates": "2.1.0", - "postcss-discard-empty": "2.1.0", - "postcss-discard-overridden": "0.1.1", - "postcss-discard-unused": "2.2.3", - "postcss-filter-plugins": "2.0.2", - "postcss-merge-idents": "2.1.7", - "postcss-merge-longhand": "2.0.2", - "postcss-merge-rules": "2.1.2", - "postcss-minify-font-values": "1.0.5", - "postcss-minify-gradients": "1.0.5", - "postcss-minify-params": "1.2.2", - "postcss-minify-selectors": "2.1.1", - "postcss-normalize-charset": "1.1.1", - "postcss-normalize-url": "3.0.8", - "postcss-ordered-values": "2.2.3", - "postcss-reduce-idents": "2.4.0", - "postcss-reduce-initial": "1.0.1", - "postcss-reduce-transforms": "1.0.4", - "postcss-svgo": "2.1.6", - "postcss-unique-selectors": "2.0.2", - "postcss-value-parser": "3.3.0", - "postcss-zindex": "2.2.0" + "autoprefixer": "^6.3.1", + "decamelize": "^1.1.2", + "defined": "^1.0.0", + "has": "^1.0.1", + "object-assign": "^4.0.1", + "postcss": "^5.0.14", + "postcss-calc": "^5.2.0", + "postcss-colormin": "^2.1.8", + "postcss-convert-values": "^2.3.4", + "postcss-discard-comments": "^2.0.4", + "postcss-discard-duplicates": "^2.0.1", + "postcss-discard-empty": "^2.0.1", + "postcss-discard-overridden": "^0.1.1", + "postcss-discard-unused": "^2.2.1", + "postcss-filter-plugins": "^2.0.0", + "postcss-merge-idents": "^2.1.5", + "postcss-merge-longhand": "^2.0.1", + "postcss-merge-rules": "^2.0.3", + "postcss-minify-font-values": "^1.0.2", + "postcss-minify-gradients": "^1.0.1", + "postcss-minify-params": "^1.0.4", + "postcss-minify-selectors": "^2.0.4", + "postcss-normalize-charset": "^1.1.0", + "postcss-normalize-url": "^3.0.7", + "postcss-ordered-values": "^2.1.0", + "postcss-reduce-idents": "^2.2.2", + "postcss-reduce-initial": "^1.0.0", + "postcss-reduce-transforms": "^1.0.3", + "postcss-svgo": "^2.1.1", + "postcss-unique-selectors": "^2.0.2", + "postcss-value-parser": "^3.2.3", + "postcss-zindex": "^2.0.1" } }, "csso": { @@ -1464,8 +1862,8 @@ "integrity": "sha1-3dUsWHAz9J6Utx/FVWnyUuj/X4U=", "dev": true, "requires": { - "clap": "1.2.3", - "source-map": "0.5.7" + "clap": "^1.0.9", + "source-map": "^0.5.3" } }, "csurf": { @@ -1476,8 +1874,8 @@ "requires": { "cookie": "0.1.3", "cookie-signature": "1.0.6", - "csrf": "3.0.6", - "http-errors": "1.3.1" + "csrf": "~3.0.0", + "http-errors": "~1.3.1" } }, "currently-unhandled": { @@ -1486,7 +1884,7 @@ "integrity": "sha1-mI3zP+qxke95mmE2nddsF635V+o=", "dev": true, "requires": { - "array-find-index": "1.0.2" + "array-find-index": "^1.0.1" } }, "custom-event": { @@ -1501,7 +1899,7 @@ "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", "dev": true, "requires": { - "assert-plus": "1.0.0" + "assert-plus": "^1.0.0" }, "dependencies": { "assert-plus": { @@ -1539,6 +1937,505 @@ "integrity": "sha1-6zkTMzRYd1y4TNGh+uBiEGu4dUU=", "dev": true }, + "decompress": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/decompress/-/decompress-3.0.0.tgz", + "integrity": "sha1-rx3VDQbjv8QyRh033hGzjA2ZG+0=", + "dev": true, + "requires": { + "buffer-to-vinyl": "^1.0.0", + "concat-stream": "^1.4.6", + "decompress-tar": "^3.0.0", + "decompress-tarbz2": "^3.0.0", + "decompress-targz": "^3.0.0", + "decompress-unzip": "^3.0.0", + "stream-combiner2": "^1.1.1", + "vinyl-assign": "^1.0.1", + "vinyl-fs": "^2.2.0" + }, + "dependencies": { + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "dev": true, + "requires": { + "arr-flatten": "^1.0.1" + } + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "dev": true, + "requires": { + "expand-range": "^1.8.1", + "preserve": "^0.2.0", + "repeat-element": "^1.1.2" + } + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "dev": true, + "requires": { + "is-posix-bracket": "^0.1.0" + } + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } + }, + "glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true, + "requires": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-stream": { + "version": "5.3.5", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-5.3.5.tgz", + "integrity": "sha1-pVZlqajM3EGRWofHAeMtTgFvrSI=", + "dev": true, + "requires": { + "extend": "^3.0.0", + "glob": "^5.0.3", + "glob-parent": "^3.0.0", + "micromatch": "^2.3.7", + "ordered-read-streams": "^0.3.0", + "through2": "^0.6.0", + "to-absolute-glob": "^0.1.1", + "unique-stream": "^2.0.2" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": ">=1.0.33-1 <1.1.0-0", + "xtend": ">=4.0.0 <4.1.0-0" + } + } + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "dev": true, + "requires": { + "arr-diff": "^2.0.0", + "array-unique": "^0.2.1", + "braces": "^1.8.2", + "expand-brackets": "^0.1.4", + "extglob": "^0.3.1", + "filename-regex": "^2.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.1", + "kind-of": "^3.0.2", + "normalize-path": "^2.0.1", + "object.omit": "^2.0.0", + "parse-glob": "^3.0.4", + "regex-cache": "^0.4.2" + } + }, + "ordered-read-streams": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.3.0.tgz", + "integrity": "sha1-cTfmmzKYuzQiR6G77jiByA4v14s=", + "dev": true, + "requires": { + "is-stream": "^1.0.1", + "readable-stream": "^2.0.1" + } + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "^0.2.0" + } + }, + "strip-bom-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-stream/-/strip-bom-stream-1.0.0.tgz", + "integrity": "sha1-5xRDmFd9Uaa+0PoZlPoF9D/ZiO4=", + "dev": true, + "requires": { + "first-chunk-stream": "^1.0.0", + "strip-bom": "^2.0.0" + } + }, + "unique-stream": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.2.1.tgz", + "integrity": "sha1-WqADz76Uxf+GbE59ZouxxNuts2k=", + "dev": true, + "requires": { + "json-stable-stringify": "^1.0.0", + "through2-filter": "^2.0.0" + } + }, + "vinyl": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", + "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", + "dev": true, + "requires": { + "clone": "^1.0.0", + "clone-stats": "^0.0.1", + "replace-ext": "0.0.1" + } + }, + "vinyl-fs": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-2.4.4.tgz", + "integrity": "sha1-vm/zJwy1Xf19MGNkDegfJddTIjk=", + "dev": true, + "requires": { + "duplexify": "^3.2.0", + "glob-stream": "^5.3.2", + "graceful-fs": "^4.0.0", + "gulp-sourcemaps": "1.6.0", + "is-valid-glob": "^0.3.0", + "lazystream": "^1.0.0", + "lodash.isequal": "^4.0.0", + "merge-stream": "^1.0.0", + "mkdirp": "^0.5.0", + "object-assign": "^4.0.0", + "readable-stream": "^2.0.4", + "strip-bom": "^2.0.0", + "strip-bom-stream": "^1.0.0", + "through2": "^2.0.0", + "through2-filter": "^2.0.0", + "vali-date": "^1.0.0", + "vinyl": "^1.0.0" + } + } + } + }, + "decompress-tar": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/decompress-tar/-/decompress-tar-3.1.0.tgz", + "integrity": "sha1-IXx4n5uURQ76rcXF5TeXj8MzxGY=", + "dev": true, + "requires": { + "is-tar": "^1.0.0", + "object-assign": "^2.0.0", + "strip-dirs": "^1.0.0", + "tar-stream": "^1.1.1", + "through2": "^0.6.1", + "vinyl": "^0.4.3" + }, + "dependencies": { + "clone": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", + "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", + "dev": true + }, + "object-assign": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-2.1.1.tgz", + "integrity": "sha1-Q8NuXVaf+OSBbE76i+AtJpZ8GKo=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": ">=1.0.33-1 <1.1.0-0", + "xtend": ">=4.0.0 <4.1.0-0" + } + }, + "vinyl": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", + "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", + "dev": true, + "requires": { + "clone": "^0.2.0", + "clone-stats": "^0.0.1" + } + } + } + }, + "decompress-tarbz2": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/decompress-tarbz2/-/decompress-tarbz2-3.1.0.tgz", + "integrity": "sha1-iyOTVoE1X58YnYclag+L3ZbZZm0=", + "dev": true, + "requires": { + "is-bzip2": "^1.0.0", + "object-assign": "^2.0.0", + "seek-bzip": "^1.0.3", + "strip-dirs": "^1.0.0", + "tar-stream": "^1.1.1", + "through2": "^0.6.1", + "vinyl": "^0.4.3" + }, + "dependencies": { + "clone": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", + "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", + "dev": true + }, + "object-assign": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-2.1.1.tgz", + "integrity": "sha1-Q8NuXVaf+OSBbE76i+AtJpZ8GKo=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": ">=1.0.33-1 <1.1.0-0", + "xtend": ">=4.0.0 <4.1.0-0" + } + }, + "vinyl": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", + "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", + "dev": true, + "requires": { + "clone": "^0.2.0", + "clone-stats": "^0.0.1" + } + } + } + }, + "decompress-targz": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/decompress-targz/-/decompress-targz-3.1.0.tgz", + "integrity": "sha1-ssE9+YFmJomRtxXWRH9kLpaW9aA=", + "dev": true, + "requires": { + "is-gzip": "^1.0.0", + "object-assign": "^2.0.0", + "strip-dirs": "^1.0.0", + "tar-stream": "^1.1.1", + "through2": "^0.6.1", + "vinyl": "^0.4.3" + }, + "dependencies": { + "clone": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/clone/-/clone-0.2.0.tgz", + "integrity": "sha1-xhJqkK1Pctv1rNskPMN3JP6T/B8=", + "dev": true + }, + "object-assign": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-2.1.1.tgz", + "integrity": "sha1-Q8NuXVaf+OSBbE76i+AtJpZ8GKo=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": ">=1.0.33-1 <1.1.0-0", + "xtend": ">=4.0.0 <4.1.0-0" + } + }, + "vinyl": { + "version": "0.4.6", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-0.4.6.tgz", + "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", + "dev": true, + "requires": { + "clone": "^0.2.0", + "clone-stats": "^0.0.1" + } + } + } + }, + "decompress-unzip": { + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/decompress-unzip/-/decompress-unzip-3.4.0.tgz", + "integrity": "sha1-YUdbQVIGa74/7hL51inRX+ZHjus=", + "dev": true, + "requires": { + "is-zip": "^1.0.0", + "read-all-stream": "^3.0.0", + "stat-mode": "^0.2.0", + "strip-dirs": "^1.0.0", + "through2": "^2.0.0", + "vinyl": "^1.0.0", + "yauzl": "^2.2.1" + }, + "dependencies": { + "vinyl": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", + "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", + "dev": true, + "requires": { + "clone": "^1.0.0", + "clone-stats": "^0.0.1", + "replace-ext": "0.0.1" + } + } + } + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==", + "dev": true + }, "deep-is": { "version": "0.1.3", "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", @@ -1551,7 +2448,17 @@ "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730=", "dev": true, "requires": { - "clone": "1.0.4" + "clone": "^1.0.2" + } + }, + "define-properties": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.2.tgz", + "integrity": "sha1-g6c/L+pWmJj7c3GTyPhzyvbUXJQ=", + "dev": true, + "requires": { + "foreach": "^2.0.5", + "object-keys": "^1.0.8" } }, "define-property": { @@ -1560,8 +2467,8 @@ "integrity": "sha1-1Flono1lS6d+AqgX+HENcCyxbp0=", "dev": true, "requires": { - "is-descriptor": "1.0.2", - "isobject": "3.0.1" + "is-descriptor": "^1.0.2", + "isobject": "^3.0.1" } }, "defined": { @@ -1612,10 +2519,338 @@ "integrity": "sha1-ViromZ9Evl6jB29UGdzVnrQ6yVs=", "dev": true, "requires": { - "custom-event": "1.0.1", - "ent": "2.2.0", - "extend": "3.0.1", - "void-elements": "2.0.1" + "custom-event": "~1.0.0", + "ent": "~2.2.0", + "extend": "^3.0.0", + "void-elements": "^2.0.0" + } + }, + "dom-serializer": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.1.0.tgz", + "integrity": "sha1-BzxpdUbOB4DOI75KKOKT5AvDDII=", + "dev": true, + "optional": true, + "requires": { + "domelementtype": "~1.1.1", + "entities": "~1.1.1" + }, + "dependencies": { + "domelementtype": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.1.3.tgz", + "integrity": "sha1-vSh3PiZCiBrsUVRJJCmcXNgiGFs=", + "dev": true, + "optional": true + } + } + }, + "domelementtype": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.0.tgz", + "integrity": "sha1-sXrtguirWeUt2cGbF1bg/BhyBMI=", + "dev": true, + "optional": true + }, + "domutils": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.5.1.tgz", + "integrity": "sha1-3NhIiib1Y9YQeeSMn3t+Mjc2gs8=", + "dev": true, + "optional": true, + "requires": { + "dom-serializer": "0", + "domelementtype": "1" + } + }, + "download": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/download/-/download-4.4.3.tgz", + "integrity": "sha1-qlX9rTktldS2jowr4D4MKqIbqaw=", + "dev": true, + "requires": { + "caw": "^1.0.1", + "concat-stream": "^1.4.7", + "each-async": "^1.0.0", + "filenamify": "^1.0.1", + "got": "^5.0.0", + "gulp-decompress": "^1.2.0", + "gulp-rename": "^1.2.0", + "is-url": "^1.2.0", + "object-assign": "^4.0.1", + "read-all-stream": "^3.0.0", + "readable-stream": "^2.0.2", + "stream-combiner2": "^1.1.1", + "vinyl": "^1.0.0", + "vinyl-fs": "^2.2.0", + "ware": "^1.2.0" + }, + "dependencies": { + "arr-diff": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-2.0.0.tgz", + "integrity": "sha1-jzuCf5Vai9ZpaX5KQlasPOrjVs8=", + "dev": true, + "requires": { + "arr-flatten": "^1.0.1" + } + }, + "array-unique": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.2.1.tgz", + "integrity": "sha1-odl8yvy8JiXMcPrc6zalDFiwGlM=", + "dev": true + }, + "braces": { + "version": "1.8.5", + "resolved": "https://registry.npmjs.org/braces/-/braces-1.8.5.tgz", + "integrity": "sha1-uneWLhLf+WnWt2cR6RS3N4V79qc=", + "dev": true, + "requires": { + "expand-range": "^1.8.1", + "preserve": "^0.2.0", + "repeat-element": "^1.1.2" + } + }, + "expand-brackets": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-0.1.5.tgz", + "integrity": "sha1-3wcoTjQqgHzXM6xa9yQR5YHRF3s=", + "dev": true, + "requires": { + "is-posix-bracket": "^0.1.0" + } + }, + "extglob": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/extglob/-/extglob-0.3.2.tgz", + "integrity": "sha1-Lhj/PS9JqydlzskCPwEdqo2DSaE=", + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } + }, + "glob": { + "version": "5.0.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-5.0.15.tgz", + "integrity": "sha1-G8k2ueAvSmA/zCIuz3Yz0wuLk7E=", + "dev": true, + "requires": { + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "2 || 3", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "glob-stream": { + "version": "5.3.5", + "resolved": "https://registry.npmjs.org/glob-stream/-/glob-stream-5.3.5.tgz", + "integrity": "sha1-pVZlqajM3EGRWofHAeMtTgFvrSI=", + "dev": true, + "requires": { + "extend": "^3.0.0", + "glob": "^5.0.3", + "glob-parent": "^3.0.0", + "micromatch": "^2.3.7", + "ordered-read-streams": "^0.3.0", + "through2": "^0.6.0", + "to-absolute-glob": "^0.1.1", + "unique-stream": "^2.0.2" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=", + "dev": true + }, + "readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=", + "dev": true + }, + "through2": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz", + "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", + "dev": true, + "requires": { + "readable-stream": ">=1.0.33-1 <1.1.0-0", + "xtend": ">=4.0.0 <4.1.0-0" + } + } + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, + "is-extglob": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-1.0.0.tgz", + "integrity": "sha1-rEaBd8SUNAWgkvyPKXYMb/xiBsA=", + "dev": true + }, + "is-glob": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-2.0.1.tgz", + "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", + "dev": true, + "requires": { + "is-extglob": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", + "dev": true, + "requires": { + "is-buffer": "^1.1.5" + } + }, + "micromatch": { + "version": "2.3.11", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-2.3.11.tgz", + "integrity": "sha1-hmd8l9FyCzY0MdBNDRUpO9OMFWU=", + "dev": true, + "requires": { + "arr-diff": "^2.0.0", + "array-unique": "^0.2.1", + "braces": "^1.8.2", + "expand-brackets": "^0.1.4", + "extglob": "^0.3.1", + "filename-regex": "^2.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.1", + "kind-of": "^3.0.2", + "normalize-path": "^2.0.1", + "object.omit": "^2.0.0", + "parse-glob": "^3.0.4", + "regex-cache": "^0.4.2" + } + }, + "ordered-read-streams": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/ordered-read-streams/-/ordered-read-streams-0.3.0.tgz", + "integrity": "sha1-cTfmmzKYuzQiR6G77jiByA4v14s=", + "dev": true, + "requires": { + "is-stream": "^1.0.1", + "readable-stream": "^2.0.1" + } + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "^0.2.0" + } + }, + "strip-bom-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-bom-stream/-/strip-bom-stream-1.0.0.tgz", + "integrity": "sha1-5xRDmFd9Uaa+0PoZlPoF9D/ZiO4=", + "dev": true, + "requires": { + "first-chunk-stream": "^1.0.0", + "strip-bom": "^2.0.0" + } + }, + "unique-stream": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/unique-stream/-/unique-stream-2.2.1.tgz", + "integrity": "sha1-WqADz76Uxf+GbE59ZouxxNuts2k=", + "dev": true, + "requires": { + "json-stable-stringify": "^1.0.0", + "through2-filter": "^2.0.0" + } + }, + "vinyl": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", + "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", + "dev": true, + "requires": { + "clone": "^1.0.0", + "clone-stats": "^0.0.1", + "replace-ext": "0.0.1" + } + }, + "vinyl-fs": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/vinyl-fs/-/vinyl-fs-2.4.4.tgz", + "integrity": "sha1-vm/zJwy1Xf19MGNkDegfJddTIjk=", + "dev": true, + "requires": { + "duplexify": "^3.2.0", + "glob-stream": "^5.3.2", + "graceful-fs": "^4.0.0", + "gulp-sourcemaps": "1.6.0", + "is-valid-glob": "^0.3.0", + "lazystream": "^1.0.0", + "lodash.isequal": "^4.0.0", + "merge-stream": "^1.0.0", + "mkdirp": "^0.5.0", + "object-assign": "^4.0.0", + "readable-stream": "^2.0.4", + "strip-bom": "^2.0.0", + "strip-bom-stream": "^1.0.0", + "through2": "^2.0.0", + "through2-filter": "^2.0.0", + "vali-date": "^1.0.0", + "vinyl": "^1.0.0" + } + } } }, "duplexer": { @@ -1630,7 +2865,70 @@ "integrity": "sha1-xhTc9n4vsUmVqRcR5aYX6KYKMds=", "dev": true, "requires": { - "readable-stream": "1.1.14" + "readable-stream": "~1.1.9" + } + }, + "duplexify": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.6.0.tgz", + "integrity": "sha512-fO3Di4tBKJpYTFHAxTU00BcfWMY9w24r/x21a6rZRbsD/ToUgGxsMbiGRmB7uVAXeGKXD9MwiLZa5E97EVgIRQ==", + "dev": true, + "requires": { + "end-of-stream": "^1.0.0", + "inherits": "^2.0.1", + "readable-stream": "^2.0.0", + "stream-shift": "^1.0.0" + }, + "dependencies": { + "end-of-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "each-async": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/each-async/-/each-async-1.1.1.tgz", + "integrity": "sha1-3uUim98KtrogEqOV4bhpq/iBNHM=", + "dev": true, + "requires": { + "onetime": "^1.0.0", + "set-immediate-shim": "^1.0.0" } }, "ecc-jsbn": { @@ -1640,7 +2938,7 @@ "dev": true, "optional": true, "requires": { - "jsbn": "0.1.1" + "jsbn": "~0.1.0" } }, "ee-first": { @@ -1667,7 +2965,7 @@ "integrity": "sha1-jhdyBsPICDfYVjLouTWd/osvbq8=", "dev": true, "requires": { - "once": "1.3.3" + "once": "~1.3.0" }, "dependencies": { "once": { @@ -1676,7 +2974,7 @@ "integrity": "sha1-suJhVXzkwxTsgwTz+oJmPkKXyiA=", "dev": true, "requires": { - "wrappy": "1.0.2" + "wrappy": "1" } } } @@ -1701,7 +2999,7 @@ "integrity": "sha1-w8p0NJOGSMPg2cHjKN1otiLChMo=", "dev": true, "requires": { - "mime-types": "2.1.18", + "mime-types": "~2.1.11", "negotiator": "0.6.1" } }, @@ -1791,6 +3089,13 @@ "integrity": "sha1-6WQhkyWiHQX0RGai9obtbOX13R0=", "dev": true }, + "entities": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/entities/-/entities-1.1.1.tgz", + "integrity": "sha1-blwtClYhtdra7O+AuQ7ftc13cvA=", + "dev": true, + "optional": true + }, "errno": { "version": "0.1.7", "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.7.tgz", @@ -1798,7 +3103,7 @@ "dev": true, "optional": true, "requires": { - "prr": "1.0.1" + "prr": "~1.0.1" } }, "error-ex": { @@ -1807,7 +3112,7 @@ "integrity": "sha1-+FWobOYa3E6GIcPNoh56dhLDqNw=", "dev": true, "requires": { - "is-arrayish": "0.2.1" + "is-arrayish": "^0.2.1" } }, "errorhandler": { @@ -1816,8 +3121,8 @@ "integrity": "sha1-t7cO2PNZ6duICS8tIMD4MUIK2D8=", "dev": true, "requires": { - "accepts": "1.3.5", - "escape-html": "1.0.3" + "accepts": "~1.3.0", + "escape-html": "~1.0.3" }, "dependencies": { "accepts": { @@ -1826,7 +3131,7 @@ "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", "dev": true, "requires": { - "mime-types": "2.1.18", + "mime-types": "~2.1.18", "negotiator": "0.6.1" } }, @@ -1838,6 +3143,30 @@ } } }, + "es-abstract": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.12.0.tgz", + "integrity": "sha512-C8Fx/0jFmV5IPoMOFPA9P9G5NtqW+4cOPit3MIuvR2t7Ag2K15EJTpxnHAYTzL+aYQJIESYeXZmDBfOBE1HcpA==", + "dev": true, + "requires": { + "es-to-primitive": "^1.1.1", + "function-bind": "^1.1.1", + "has": "^1.0.1", + "is-callable": "^1.1.3", + "is-regex": "^1.0.4" + } + }, + "es-to-primitive": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.1.1.tgz", + "integrity": "sha1-RTVSSKiJeQNLZ5Lhm7gfK3l13Q0=", + "dev": true, + "requires": { + "is-callable": "^1.1.1", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.1" + } + }, "es6-promise": { "version": "3.3.1", "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz", @@ -1862,11 +3191,11 @@ "integrity": "sha1-264X75bI5L7bE1b0UE+kzC98t+I=", "dev": true, "requires": { - "esprima": "3.1.3", - "estraverse": "4.2.0", - "esutils": "2.0.2", - "optionator": "0.8.2", - "source-map": "0.6.1" + "esprima": "^3.1.3", + "estraverse": "^4.2.0", + "esutils": "^2.0.2", + "optionator": "^0.8.1", + "source-map": "~0.6.1" }, "dependencies": { "esprima": { @@ -1896,8 +3225,8 @@ "integrity": "sha1-FxSp1GGQc4rJWLyv1J4CnNpWo54=", "dev": true, "requires": { - "esprima": "2.7.3", - "estraverse": "4.2.0" + "esprima": "^2.7.2", + "estraverse": "^4.1.1" } }, "estraverse": { @@ -1924,13 +3253,13 @@ "integrity": "sha1-SrTJoPWlTbkzi0w02Gv86PSzVXE=", "dev": true, "requires": { - "duplexer": "0.1.1", - "from": "0.1.7", - "map-stream": "0.1.0", + "duplexer": "~0.1.1", + "from": "~0", + "map-stream": "~0.1.0", "pause-stream": "0.0.11", - "split": "0.3.3", - "stream-combiner": "0.0.4", - "through": "2.3.8" + "split": "0.3", + "stream-combiner": "~0.0.4", + "through": "~2.3.1" } }, "eventemitter3": { @@ -1939,15 +3268,75 @@ "integrity": "sha1-HIaZHYFq0eUEdQ5zh0Ik7PO+xQg=", "dev": true }, + "exec-buffer": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/exec-buffer/-/exec-buffer-3.2.0.tgz", + "integrity": "sha512-wsiD+2Tp6BWHoVv3B+5Dcx6E7u5zky+hUwOHjuH2hKSLR3dvRmX8fk8UD8uqQixHs4Wk6eDmiegVrMPjKj7wpA==", + "dev": true, + "optional": true, + "requires": { + "execa": "^0.7.0", + "p-finally": "^1.0.0", + "pify": "^3.0.0", + "rimraf": "^2.5.4", + "tempfile": "^2.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true, + "optional": true + } + } + }, + "exec-series": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/exec-series/-/exec-series-1.0.3.tgz", + "integrity": "sha1-bSV6m+rEgqhyx3g7yGFYOfx3FDo=", + "dev": true, + "optional": true, + "requires": { + "async-each-series": "^1.1.0", + "object-assign": "^4.1.0" + } + }, + "execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "dev": true, + "optional": true, + "requires": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "executable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/executable/-/executable-1.1.0.tgz", + "integrity": "sha1-h3mA6REvM5EGbaNyZd562ENKtNk=", + "dev": true, + "optional": true, + "requires": { + "meow": "^3.1.0" + } + }, "expand-braces": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/expand-braces/-/expand-braces-0.1.2.tgz", "integrity": "sha1-SIsdHSRRyz06axks/AMPRMWFX+o=", "dev": true, "requires": { - "array-slice": "0.2.3", - "array-unique": "0.2.1", - "braces": "0.1.5" + "array-slice": "^0.2.3", + "array-unique": "^0.2.1", + "braces": "^0.1.2" }, "dependencies": { "array-slice": { @@ -1968,7 +3357,7 @@ "integrity": "sha1-wIVxEIUpHYt1/ddOqw+FlygHEeY=", "dev": true, "requires": { - "expand-range": "0.1.1" + "expand-range": "^0.1.0" } }, "expand-range": { @@ -1977,8 +3366,8 @@ "integrity": "sha1-TLjtoJk8pW+k9B/ELzy7TMrf8EQ=", "dev": true, "requires": { - "is-number": "0.1.1", - "repeat-string": "0.2.2" + "is-number": "^0.1.1", + "repeat-string": "^0.2.2" } }, "is-number": { @@ -2001,13 +3390,13 @@ "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI=", "dev": true, "requires": { - "debug": "2.6.9", - "define-property": "0.2.5", - "extend-shallow": "2.0.1", - "posix-character-classes": "0.1.1", - "regex-not": "1.0.2", - "snapdragon": "0.8.2", - "to-regex": "3.0.2" + "debug": "^2.3.3", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "posix-character-classes": "^0.1.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" }, "dependencies": { "define-property": { @@ -2016,7 +3405,7 @@ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "0.1.6" + "is-descriptor": "^0.1.0" } }, "extend-shallow": { @@ -2025,7 +3414,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "0.1.1" + "is-extendable": "^0.1.0" } }, "is-accessor-descriptor": { @@ -2034,7 +3423,7 @@ "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", "dev": true, "requires": { - "kind-of": "3.2.2" + "kind-of": "^3.0.2" }, "dependencies": { "kind-of": { @@ -2043,7 +3432,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "^1.1.5" } } } @@ -2054,7 +3443,7 @@ "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", "dev": true, "requires": { - "kind-of": "3.2.2" + "kind-of": "^3.0.2" }, "dependencies": { "kind-of": { @@ -2063,7 +3452,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "^1.1.5" } } } @@ -2074,9 +3463,9 @@ "integrity": "sha1-Nm2CQN3kh8pRgjsaufB6EKeCUco=", "dev": true, "requires": { - "is-accessor-descriptor": "0.1.6", - "is-data-descriptor": "0.1.4", - "kind-of": "5.1.0" + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" } }, "kind-of": { @@ -2093,7 +3482,7 @@ "integrity": "sha1-opnv/TNf4nIeuujiV+x5ZE/IUzc=", "dev": true, "requires": { - "fill-range": "2.2.3" + "fill-range": "^2.1.0" }, "dependencies": { "fill-range": { @@ -2102,11 +3491,11 @@ "integrity": "sha1-ULd9/X5Gm8dJJHCWNpn+eoSFpyM=", "dev": true, "requires": { - "is-number": "2.1.0", - "isobject": "2.1.0", - "randomatic": "1.1.7", - "repeat-element": "1.1.2", - "repeat-string": "1.6.1" + "is-number": "^2.1.0", + "isobject": "^2.0.0", + "randomatic": "^1.1.3", + "repeat-element": "^1.1.2", + "repeat-string": "^1.5.2" } }, "is-number": { @@ -2115,7 +3504,7 @@ "integrity": "sha1-Afy7s5NGOlSPL0ZszhbezknbkI8=", "dev": true, "requires": { - "kind-of": "3.2.2" + "kind-of": "^3.0.2" } }, "isarray": { @@ -2139,7 +3528,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "^1.1.5" } } } @@ -2150,7 +3539,7 @@ "integrity": "sha1-l+gBqgUt8CRU3kawK/YhZCzchQI=", "dev": true, "requires": { - "homedir-polyfill": "1.0.1" + "homedir-polyfill": "^1.0.1" } }, "express-session": { @@ -2162,11 +3551,11 @@ "cookie": "0.1.3", "cookie-signature": "1.0.6", "crc": "3.3.0", - "debug": "2.2.0", - "depd": "1.0.1", - "on-headers": "1.0.1", - "parseurl": "1.3.2", - "uid-safe": "2.0.0", + "debug": "~2.2.0", + "depd": "~1.0.1", + "on-headers": "~1.0.0", + "parseurl": "~1.3.0", + "uid-safe": "~2.0.0", "utils-merge": "1.0.0" }, "dependencies": { @@ -2208,8 +3597,8 @@ "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg=", "dev": true, "requires": { - "assign-symbols": "1.0.0", - "is-extendable": "1.0.1" + "assign-symbols": "^1.0.0", + "is-extendable": "^1.0.1" }, "dependencies": { "is-extendable": { @@ -2218,7 +3607,7 @@ "integrity": "sha1-p0cPnkJnM9gb2B4RVSZOOjUHyrQ=", "dev": true, "requires": { - "is-plain-object": "2.0.4" + "is-plain-object": "^2.0.4" } } } @@ -2229,14 +3618,14 @@ "integrity": "sha1-rQD+TcYSqSMuhxhxHcXLWrAoVUM=", "dev": true, "requires": { - "array-unique": "0.3.2", - "define-property": "1.0.0", - "expand-brackets": "2.1.4", - "extend-shallow": "2.0.1", - "fragment-cache": "0.2.1", - "regex-not": "1.0.2", - "snapdragon": "0.8.2", - "to-regex": "3.0.2" + "array-unique": "^0.3.2", + "define-property": "^1.0.0", + "expand-brackets": "^2.1.4", + "extend-shallow": "^2.0.1", + "fragment-cache": "^0.2.1", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" }, "dependencies": { "define-property": { @@ -2245,7 +3634,7 @@ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", "dev": true, "requires": { - "is-descriptor": "1.0.2" + "is-descriptor": "^1.0.0" } }, "extend-shallow": { @@ -2254,7 +3643,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "0.1.1" + "is-extendable": "^0.1.0" } } } @@ -2294,9 +3683,9 @@ "integrity": "sha1-9BEl49hPLn2JpD0G2VjI94vha+E=", "dev": true, "requires": { - "ansi-gray": "0.1.1", - "color-support": "1.1.3", - "time-stamp": "1.1.0" + "ansi-gray": "^0.1.1", + "color-support": "^1.1.3", + "time-stamp": "^1.0.0" } }, "fast-levenshtein": { @@ -2311,7 +3700,7 @@ "integrity": "sha1-TkkvjQTftviQA1B/btvy1QHnxvQ=", "dev": true, "requires": { - "websocket-driver": "0.7.0" + "websocket-driver": ">=0.5.1" } }, "fd-slicer": { @@ -2320,25 +3709,59 @@ "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=", "dev": true, "requires": { - "pend": "1.2.0" + "pend": "~1.2.0" } }, + "figures": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-1.7.0.tgz", + "integrity": "sha1-y+Hjr/zxzUS4DK3+0o3Hk6lwHS4=", + "dev": true, + "optional": true, + "requires": { + "escape-string-regexp": "^1.0.5", + "object-assign": "^4.1.0" + } + }, + "file-type": { + "version": "4.4.0", + "resolved": "https://registry.npmjs.org/file-type/-/file-type-4.4.0.tgz", + "integrity": "sha1-G2AOX8ofvcboDApwxxyNul95BsU=", + "dev": true + }, "filename-regex": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/filename-regex/-/filename-regex-2.0.1.tgz", "integrity": "sha1-wcS5vuPglyXdsQa3XB4wH+LxiyY=", "dev": true }, + "filename-reserved-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/filename-reserved-regex/-/filename-reserved-regex-1.0.0.tgz", + "integrity": "sha1-5hz4BfDeHJhFZ9A4bcXfUO5a9+Q=", + "dev": true + }, + "filenamify": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/filenamify/-/filenamify-1.2.1.tgz", + "integrity": "sha1-qfL/0RxQO+0wABUCknI3jx8TZaU=", + "dev": true, + "requires": { + "filename-reserved-regex": "^1.0.0", + "strip-outer": "^1.0.0", + "trim-repeated": "^1.0.0" + } + }, "fill-range": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz", "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc=", "dev": true, "requires": { - "extend-shallow": "2.0.1", - "is-number": "3.0.0", - "repeat-string": "1.6.1", - "to-regex-range": "2.1.1" + "extend-shallow": "^2.0.1", + "is-number": "^3.0.0", + "repeat-string": "^1.6.1", + "to-regex-range": "^2.1.0" }, "dependencies": { "extend-shallow": { @@ -2347,7 +3770,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "0.1.1" + "is-extendable": "^0.1.0" } } } @@ -2358,10 +3781,10 @@ "integrity": "sha1-llpS2ejQXSuFdUhUH7ibU6JJfZs=", "dev": true, "requires": { - "debug": "2.2.0", + "debug": "~2.2.0", "escape-html": "1.0.2", - "on-finished": "2.3.0", - "unpipe": "1.0.0" + "on-finished": "~2.3.0", + "unpipe": "~1.0.0" }, "dependencies": { "debug": { @@ -2399,8 +3822,21 @@ "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", "dev": true, "requires": { - "path-exists": "2.1.0", - "pinkie-promise": "2.0.1" + "path-exists": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "find-versions": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/find-versions/-/find-versions-1.2.1.tgz", + "integrity": "sha1-y96fEuOFdaCvG+G5osXV/Y8Ya2I=", + "dev": true, + "optional": true, + "requires": { + "array-uniq": "^1.0.0", + "get-stdin": "^4.0.1", + "meow": "^3.5.0", + "semver-regex": "^1.0.0" } }, "findup-sync": { @@ -2409,10 +3845,10 @@ "integrity": "sha1-kyaxSIwi0aYIhlCoaQGy2akKLLw=", "dev": true, "requires": { - "detect-file": "1.0.0", - "is-glob": "3.1.0", - "micromatch": "3.1.10", - "resolve-dir": "1.0.1" + "detect-file": "^1.0.0", + "is-glob": "^3.1.0", + "micromatch": "^3.0.4", + "resolve-dir": "^1.0.1" } }, "fined": { @@ -2421,11 +3857,11 @@ "integrity": "sha1-s33IRLdqL15wgeiE98CuNE8VNHY=", "dev": true, "requires": { - "expand-tilde": "2.0.2", - "is-plain-object": "2.0.4", - "object.defaults": "1.1.0", - "object.pick": "1.3.0", - "parse-filepath": "1.0.2" + "expand-tilde": "^2.0.2", + "is-plain-object": "^2.0.3", + "object.defaults": "^1.1.0", + "object.pick": "^1.2.0", + "parse-filepath": "^1.0.1" } }, "first-chunk-stream": { @@ -2458,9 +3894,15 @@ "integrity": "sha1-xjMy9BXO3EsE2/5wz4NklMU8tEs=", "dev": true, "requires": { - "for-in": "1.0.2" + "for-in": "^1.0.1" } }, + "foreach": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/foreach/-/foreach-2.0.5.tgz", + "integrity": "sha1-C+4AUBiusmDQo6865ljdATbsG5k=", + "dev": true + }, "forever-agent": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", @@ -2473,9 +3915,9 @@ "integrity": "sha1-M8GDrPGTJ27KqYFDpp6Uv+4XUNE=", "dev": true, "requires": { - "asynckit": "0.4.0", - "combined-stream": "1.0.6", - "mime-types": "2.1.18" + "asynckit": "^0.4.0", + "combined-stream": "^1.0.5", + "mime-types": "^2.1.12" } }, "fragment-cache": { @@ -2484,7 +3926,7 @@ "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk=", "dev": true, "requires": { - "map-cache": "0.2.2" + "map-cache": "^0.2.2" } }, "fresh": { @@ -2499,15 +3941,21 @@ "integrity": "sha1-g8YK/Fi5xWmXAH7Rp2izqzA6RP4=", "dev": true }, + "fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "dev": true + }, "fs-extra": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-1.0.0.tgz", "integrity": "sha1-zTzl9+fLYUWIP8rjGR6Yd/hYeVA=", "dev": true, "requires": { - "graceful-fs": "4.1.11", - "jsonfile": "2.4.0", - "klaw": "1.3.1" + "graceful-fs": "^4.1.2", + "jsonfile": "^2.1.0", + "klaw": "^1.0.0" }, "dependencies": { "graceful-fs": { @@ -2524,7 +3972,7 @@ "integrity": "sha1-gAI4I5gfn//+AWCei+Zo9prknnA=", "dev": true, "requires": { - "graceful-fs": "4.1.11" + "graceful-fs": "^4.1.2" }, "dependencies": { "graceful-fs": { @@ -2541,6 +3989,535 @@ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", "dev": true }, + "fsevents": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.4.tgz", + "integrity": "sha512-z8H8/diyk76B7q5wg+Ud0+CqzcAF3mBBI/bA5ne5zrRUUIvNkJY//D3BqyH571KuAC4Nr7Rw7CjWX4r0y9DvNg==", + "dev": true, + "optional": true, + "requires": { + "nan": "^2.9.2", + "node-pre-gyp": "^0.10.0" + }, + "dependencies": { + "abbrev": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "ansi-regex": { + "version": "2.1.1", + "bundled": true, + "dev": true + }, + "aproba": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + }, + "are-we-there-yet": { + "version": "1.1.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "balanced-match": { + "version": "1.0.0", + "bundled": true, + "dev": true + }, + "brace-expansion": { + "version": "1.1.11", + "bundled": true, + "dev": true, + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "chownr": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "code-point-at": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "concat-map": { + "version": "0.0.1", + "bundled": true, + "dev": true + }, + "console-control-strings": { + "version": "1.1.0", + "bundled": true, + "dev": true + }, + "core-util-is": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "debug": { + "version": "2.6.9", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ms": "2.0.0" + } + }, + "deep-extend": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "optional": true + }, + "delegates": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "detect-libc": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "fs-minipass": { + "version": "1.2.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "fs.realpath": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "gauge": { + "version": "2.7.4", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "glob": { + "version": "7.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "has-unicode": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "iconv-lite": { + "version": "0.4.21", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safer-buffer": "^2.1.0" + } + }, + "ignore-walk": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minimatch": "^3.0.4" + } + }, + "inflight": { + "version": "1.0.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "bundled": true, + "dev": true + }, + "ini": { + "version": "1.3.5", + "bundled": true, + "dev": true, + "optional": true + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "isarray": { + "version": "1.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "minimatch": { + "version": "3.0.4", + "bundled": true, + "dev": true, + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "bundled": true, + "dev": true + }, + "minipass": { + "version": "2.2.4", + "bundled": true, + "dev": true, + "requires": { + "safe-buffer": "^5.1.1", + "yallist": "^3.0.0" + } + }, + "minizlib": { + "version": "1.1.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "minipass": "^2.2.1" + } + }, + "mkdirp": { + "version": "0.5.1", + "bundled": true, + "dev": true, + "requires": { + "minimist": "0.0.8" + } + }, + "ms": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "needle": { + "version": "2.2.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "debug": "^2.1.2", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + } + }, + "node-pre-gyp": { + "version": "0.10.0", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.0", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.1.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4" + } + }, + "nopt": { + "version": "4.0.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "npm-bundled": { + "version": "1.0.3", + "bundled": true, + "dev": true, + "optional": true + }, + "npm-packlist": { + "version": "1.1.10", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" + } + }, + "npmlog": { + "version": "4.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "bundled": true, + "dev": true + }, + "object-assign": { + "version": "4.1.1", + "bundled": true, + "dev": true, + "optional": true + }, + "once": { + "version": "1.4.0", + "bundled": true, + "dev": true, + "requires": { + "wrappy": "1" + } + }, + "os-homedir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "os-tmpdir": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "osenv": { + "version": "0.1.5", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "path-is-absolute": { + "version": "1.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "process-nextick-args": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "rc": { + "version": "1.2.7", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "deep-extend": "^0.5.1", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "bundled": true, + "dev": true, + "optional": true + } + } + }, + "readable-stream": { + "version": "2.3.6", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "rimraf": { + "version": "2.6.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "glob": "^7.0.5" + } + }, + "safe-buffer": { + "version": "5.1.1", + "bundled": true, + "dev": true + }, + "safer-buffer": { + "version": "2.1.2", + "bundled": true, + "dev": true, + "optional": true + }, + "sax": { + "version": "1.2.4", + "bundled": true, + "dev": true, + "optional": true + }, + "semver": { + "version": "5.5.0", + "bundled": true, + "dev": true, + "optional": true + }, + "set-blocking": { + "version": "2.0.0", + "bundled": true, + "dev": true, + "optional": true + }, + "signal-exit": { + "version": "3.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "string-width": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "bundled": true, + "dev": true, + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "bundled": true, + "dev": true, + "optional": true + }, + "tar": { + "version": "4.4.1", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "chownr": "^1.0.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.2.4", + "minizlib": "^1.1.0", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.1", + "yallist": "^3.0.2" + } + }, + "util-deprecate": { + "version": "1.0.2", + "bundled": true, + "dev": true, + "optional": true + }, + "wide-align": { + "version": "1.1.2", + "bundled": true, + "dev": true, + "optional": true, + "requires": { + "string-width": "^1.0.2" + } + }, + "wrappy": { + "version": "1.0.2", + "bundled": true, + "dev": true + }, + "yallist": { + "version": "3.0.2", + "bundled": true, + "dev": true + } + } + }, "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", @@ -2553,7 +4530,16 @@ "integrity": "sha1-QLcJU30k0dRXZ9takIaJ3+aaxE8=", "dev": true, "requires": { - "globule": "0.1.0" + "globule": "~0.1.0" + } + }, + "get-proxy": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/get-proxy/-/get-proxy-1.1.0.tgz", + "integrity": "sha1-iUhUSRvFkbDxR9euVw9cZ4tyVus=", + "dev": true, + "requires": { + "rc": "^1.1.2" } }, "get-stdin": { @@ -2562,6 +4548,13 @@ "integrity": "sha1-uWjGsKBDhDJJAui/Gl3zJXmkUP4=", "dev": true }, + "get-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=", + "dev": true, + "optional": true + }, "get-value": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz", @@ -2574,7 +4567,7 @@ "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", "dev": true, "requires": { - "assert-plus": "1.0.0" + "assert-plus": "^1.0.0" }, "dependencies": { "assert-plus": { @@ -2585,18 +4578,30 @@ } } }, + "gifsicle": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/gifsicle/-/gifsicle-3.0.4.tgz", + "integrity": "sha1-9Fy17RAWW2ZdySng6TKLbIId+js=", + "dev": true, + "optional": true, + "requires": { + "bin-build": "^2.0.0", + "bin-wrapper": "^3.0.0", + "logalot": "^2.0.0" + } + }, "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", "dev": true, "requires": { - "fs.realpath": "1.0.0", - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "3.0.4", - "once": "1.4.0", - "path-is-absolute": "1.0.1" + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" } }, "glob-base": { @@ -2605,8 +4610,8 @@ "integrity": "sha1-27Fk9iIbHAscz4Kuoyi0l98Oo8Q=", "dev": true, "requires": { - "glob-parent": "2.0.0", - "is-glob": "2.0.1" + "glob-parent": "^2.0.0", + "is-glob": "^2.0.0" }, "dependencies": { "glob-parent": { @@ -2615,7 +4620,7 @@ "integrity": "sha1-gTg9ctsFT8zPUzbaqQLxgvbtuyg=", "dev": true, "requires": { - "is-glob": "2.0.1" + "is-glob": "^2.0.0" } }, "is-extglob": { @@ -2630,7 +4635,7 @@ "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", "dev": true, "requires": { - "is-extglob": "1.0.0" + "is-extglob": "^1.0.0" } } } @@ -2641,8 +4646,8 @@ "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4=", "dev": true, "requires": { - "is-glob": "3.1.0", - "path-dirname": "1.0.2" + "is-glob": "^3.1.0", + "path-dirname": "^1.0.0" } }, "glob-stream": { @@ -2651,12 +4656,12 @@ "integrity": "sha1-kXCl8St5Awb9/lmPMT+PeVT9FDs=", "dev": true, "requires": { - "glob": "4.5.3", - "glob2base": "0.0.12", - "minimatch": "2.0.10", - "ordered-read-streams": "0.1.0", - "through2": "0.6.5", - "unique-stream": "1.0.0" + "glob": "^4.3.1", + "glob2base": "^0.0.12", + "minimatch": "^2.0.1", + "ordered-read-streams": "^0.1.0", + "through2": "^0.6.1", + "unique-stream": "^1.0.0" }, "dependencies": { "glob": { @@ -2665,10 +4670,10 @@ "integrity": "sha1-xstz0yJsHv7wTePFbQEvAzd+4V8=", "dev": true, "requires": { - "inflight": "1.0.6", - "inherits": "2.0.3", - "minimatch": "2.0.10", - "once": "1.4.0" + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^2.0.1", + "once": "^1.3.0" } }, "minimatch": { @@ -2677,7 +4682,7 @@ "integrity": "sha1-jQh8OcazjAAbl/ynzm0OHoCvusc=", "dev": true, "requires": { - "brace-expansion": "1.1.11" + "brace-expansion": "^1.0.0" } }, "readable-stream": { @@ -2686,10 +4691,10 @@ "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", "isarray": "0.0.1", - "string_decoder": "0.10.31" + "string_decoder": "~0.10.x" } }, "through2": { @@ -2698,8 +4703,8 @@ "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", "dev": true, "requires": { - "readable-stream": "1.0.34", - "xtend": "4.0.1" + "readable-stream": ">=1.0.33-1 <1.1.0-0", + "xtend": ">=4.0.0 <4.1.0-0" } } } @@ -2710,7 +4715,7 @@ "integrity": "sha1-uVtKjfdLOcgymLDAXJeLTZo7cQs=", "dev": true, "requires": { - "gaze": "0.5.2" + "gaze": "^0.5.1" } }, "glob2base": { @@ -2719,7 +4724,7 @@ "integrity": "sha1-nUGbPijxLoOjYhZKJ3BVkiycDVY=", "dev": true, "requires": { - "find-index": "0.1.1" + "find-index": "^0.1.1" } }, "global-modules": { @@ -2728,9 +4733,9 @@ "integrity": "sha1-bXcPDrUjrHgWTXK15xqIdyZcw+o=", "dev": true, "requires": { - "global-prefix": "1.0.2", - "is-windows": "1.0.2", - "resolve-dir": "1.0.1" + "global-prefix": "^1.0.1", + "is-windows": "^1.0.1", + "resolve-dir": "^1.0.0" } }, "global-prefix": { @@ -2739,11 +4744,24 @@ "integrity": "sha1-2/dDxsFJklk8ZVVoy2btMsASLr4=", "dev": true, "requires": { - "expand-tilde": "2.0.2", - "homedir-polyfill": "1.0.1", - "ini": "1.3.5", - "is-windows": "1.0.2", - "which": "1.3.0" + "expand-tilde": "^2.0.2", + "homedir-polyfill": "^1.0.1", + "ini": "^1.3.4", + "is-windows": "^1.0.1", + "which": "^1.2.14" + } + }, + "globby": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz", + "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw=", + "dev": true, + "requires": { + "array-union": "^1.0.1", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" } }, "globule": { @@ -2752,9 +4770,9 @@ "integrity": "sha1-2cjt3h2nnRJaFRt5UzuXhnY0auU=", "dev": true, "requires": { - "glob": "3.1.21", - "lodash": "1.0.2", - "minimatch": "0.2.14" + "glob": "~3.1.21", + "lodash": "~1.0.1", + "minimatch": "~0.2.11" }, "dependencies": { "glob": { @@ -2763,9 +4781,9 @@ "integrity": "sha1-0p4KBV3qUTj00H7UDomC6DwgZs0=", "dev": true, "requires": { - "graceful-fs": "1.2.3", - "inherits": "1.0.2", - "minimatch": "0.2.14" + "graceful-fs": "~1.2.0", + "inherits": "1", + "minimatch": "~0.2.11" } }, "graceful-fs": { @@ -2792,8 +4810,8 @@ "integrity": "sha1-x054BXT2PG+aCQ6Q775u9TpqdWo=", "dev": true, "requires": { - "lru-cache": "2.7.3", - "sigmund": "1.0.1" + "lru-cache": "2", + "sigmund": "~1.0.0" } } } @@ -2804,7 +4822,71 @@ "integrity": "sha1-3PdY5EeJzD89MsHzVio2duajSBA=", "dev": true, "requires": { - "sparkles": "1.0.0" + "sparkles": "^1.0.0" + } + }, + "got": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/got/-/got-5.7.1.tgz", + "integrity": "sha1-X4FjWmHkplifGAVp6k44FoClHzU=", + "dev": true, + "requires": { + "create-error-class": "^3.0.1", + "duplexer2": "^0.1.4", + "is-redirect": "^1.0.0", + "is-retry-allowed": "^1.0.0", + "is-stream": "^1.0.0", + "lowercase-keys": "^1.0.0", + "node-status-codes": "^1.0.0", + "object-assign": "^4.0.1", + "parse-json": "^2.1.0", + "pinkie-promise": "^2.0.0", + "read-all-stream": "^3.0.0", + "readable-stream": "^2.0.5", + "timed-out": "^3.0.0", + "unzip-response": "^1.0.2", + "url-parse-lax": "^1.0.0" + }, + "dependencies": { + "duplexer2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", + "dev": true, + "requires": { + "readable-stream": "^2.0.2" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } } }, "graceful-fs": { @@ -2813,28 +4895,34 @@ "integrity": "sha1-dhPHeKGv6mLyXGMKCG1/Osu92Bg=", "dev": true, "requires": { - "natives": "1.1.2" + "natives": "^1.1.0" } }, + "graceful-readlink": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/graceful-readlink/-/graceful-readlink-1.0.1.tgz", + "integrity": "sha1-TK+tdrxi8C+gObL5Tpo906ORpyU=", + "dev": true + }, "gulp": { "version": "3.9.1", "resolved": "https://registry.npmjs.org/gulp/-/gulp-3.9.1.tgz", "integrity": "sha1-VxzkWSjdQK9lFPxAEYZgFsE4RbQ=", "dev": true, "requires": { - "archy": "1.0.0", - "chalk": "1.1.3", - "deprecated": "0.0.1", - "gulp-util": "3.0.8", - "interpret": "1.1.0", - "liftoff": "2.5.0", - "minimist": "1.2.0", - "orchestrator": "0.3.8", - "pretty-hrtime": "1.0.3", - "semver": "4.3.6", - "tildify": "1.2.0", - "v8flags": "2.1.1", - "vinyl-fs": "0.3.14" + "archy": "^1.0.0", + "chalk": "^1.0.0", + "deprecated": "^0.0.1", + "gulp-util": "^3.0.0", + "interpret": "^1.0.0", + "liftoff": "^2.1.0", + "minimist": "^1.1.0", + "orchestrator": "^0.3.0", + "pretty-hrtime": "^1.0.0", + "semver": "^4.1.0", + "tildify": "^1.0.0", + "v8flags": "^2.0.2", + "vinyl-fs": "^0.3.0" }, "dependencies": { "minimist": { @@ -2851,9 +4939,9 @@ "integrity": "sha1-Yz0WyV2IUEYorQJmVmPO5aR5M1M=", "dev": true, "requires": { - "concat-with-sourcemaps": "1.0.5", - "through2": "2.0.3", - "vinyl": "2.1.0" + "concat-with-sourcemaps": "^1.0.0", + "through2": "^2.0.0", + "vinyl": "^2.0.0" }, "dependencies": { "clone": { @@ -2880,12 +4968,12 @@ "integrity": "sha1-Ah+cLPlR1rk5lDyJ617lrdT9kkw=", "dev": true, "requires": { - "clone": "2.1.2", - "clone-buffer": "1.0.0", - "clone-stats": "1.0.0", - "cloneable-readable": "1.1.2", - "remove-trailing-separator": "1.1.0", - "replace-ext": "1.0.0" + "clone": "^2.1.1", + "clone-buffer": "^1.0.0", + "clone-stats": "^1.0.0", + "cloneable-readable": "^1.0.0", + "remove-trailing-separator": "^1.0.1", + "replace-ext": "^1.0.0" } } } @@ -2896,11 +4984,111 @@ "integrity": "sha1-8v3zBq6RFGg2jCKF8teC8T7dr04=", "dev": true, "requires": { - "connect": "2.30.2", - "connect-livereload": "0.5.4", - "event-stream": "3.3.4", - "gulp-util": "3.0.8", - "tiny-lr": "0.2.1" + "connect": "^2.30.0", + "connect-livereload": "^0.5.4", + "event-stream": "^3.3.2", + "gulp-util": "^3.0.6", + "tiny-lr": "^0.2.1" + } + }, + "gulp-decompress": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gulp-decompress/-/gulp-decompress-1.2.0.tgz", + "integrity": "sha1-jutlpeAV+O2FMsr+KEVJYGJvDcc=", + "dev": true, + "requires": { + "archive-type": "^3.0.0", + "decompress": "^3.0.0", + "gulp-util": "^3.0.1", + "readable-stream": "^2.0.2" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "gulp-imagemin": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/gulp-imagemin/-/gulp-imagemin-4.1.0.tgz", + "integrity": "sha512-6nWkrMNY5ub+34+DwlgQdWg21Z4DWAOARLpnyuZ773pGPJrfiyQrkOzdz9DgQSGBQjU1zuw6gd+9clLi6eicuw==", + "dev": true, + "requires": { + "chalk": "^2.1.0", + "fancy-log": "^1.3.2", + "imagemin": "^5.3.1", + "imagemin-gifsicle": "^5.2.0", + "imagemin-jpegtran": "^5.0.2", + "imagemin-optipng": "^5.2.1", + "imagemin-svgo": "^6.0.0", + "plugin-error": "^0.1.2", + "plur": "^2.1.2", + "pretty-bytes": "^4.0.2", + "through2-concurrent": "^1.1.1" + }, + "dependencies": { + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dev": true, + "requires": { + "color-convert": "^1.9.0" + } + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "dev": true, + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=", + "dev": true + }, + "supports-color": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.4.0.tgz", + "integrity": "sha512-zjaXglF5nnWpsq470jSv6P9DwPvgLkuapYmfDm3JWOm0vkNTVF2tI4UrN2r6jH1qM/uc/WtxYY1hYoA2dOKj5w==", + "dev": true, + "requires": { + "has-flag": "^3.0.0" + } + } } }, "gulp-less": { @@ -2909,13 +5097,13 @@ "integrity": "sha1-gBT0ad38ZUTX3aUAmN7wNxu7T3g=", "dev": true, "requires": { - "accord": "0.28.0", - "less": "2.7.3", - "object-assign": "4.1.1", - "plugin-error": "0.1.2", - "replace-ext": "1.0.0", - "through2": "2.0.3", - "vinyl-sourcemaps-apply": "0.2.1" + "accord": "^0.28.0", + "less": "2.6.x || ^2.7.1", + "object-assign": "^4.0.1", + "plugin-error": "^0.1.2", + "replace-ext": "^1.0.0", + "through2": "^2.0.0", + "vinyl-sourcemaps-apply": "^0.2.0" }, "dependencies": { "replace-ext": { @@ -2932,8 +5120,8 @@ "integrity": "sha1-J7Z6Ql6zh1ImNFq4lgTXN/Y1fCE=", "dev": true, "requires": { - "angular": "1.3.20", - "angular-animate": "1.3.20", + "angular": "~1.3.1", + "angular-animate": "~1.3.1", "canonical-path": "0.0.2", "extend": "1.3.0", "gulp-util": "3.0.0", @@ -2964,11 +5152,11 @@ "integrity": "sha1-Zjs6ZItotV0EaQ1JFnqoN4WPIXQ=", "dev": true, "requires": { - "ansi-styles": "1.1.0", - "escape-string-regexp": "1.0.5", - "has-ansi": "0.1.0", - "strip-ansi": "0.3.0", - "supports-color": "0.2.0" + "ansi-styles": "^1.1.0", + "escape-string-regexp": "^1.0.0", + "has-ansi": "^0.1.0", + "strip-ansi": "^0.3.0", + "supports-color": "^0.2.0" } }, "clone": { @@ -2983,8 +5171,8 @@ "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=", "dev": true, "requires": { - "get-stdin": "4.0.1", - "meow": "3.7.0" + "get-stdin": "^4.0.1", + "meow": "^3.3.0" } }, "extend": { @@ -2999,15 +5187,15 @@ "integrity": "sha1-b+7cR9aXKCO6zplH/F9GvYo0Zuc=", "dev": true, "requires": { - "chalk": "0.5.1", - "dateformat": "1.0.12", - "lodash": "2.4.1", - "lodash._reinterpolate": "2.4.1", - "lodash.template": "2.4.1", - "minimist": "0.2.0", - "multipipe": "0.1.2", - "through2": "0.5.1", - "vinyl": "0.2.3" + "chalk": "^0.5.0", + "dateformat": "^1.0.7-1.2.3", + "lodash": "^2.4.1", + "lodash._reinterpolate": "^2.4.1", + "lodash.template": "^2.4.1", + "minimist": "^0.2.0", + "multipipe": "^0.1.0", + "through2": "^0.5.0", + "vinyl": "^0.2.1" }, "dependencies": { "through2": { @@ -3016,8 +5204,8 @@ "integrity": "sha1-390BLrnHAOIyP9M084rGIqs3Lac=", "dev": true, "requires": { - "readable-stream": "1.0.34", - "xtend": "3.0.0" + "readable-stream": "~1.0.17", + "xtend": "~3.0.0" } } } @@ -3028,7 +5216,7 @@ "integrity": "sha1-hPJlqujA5qiKEtcCKJS3VoiUxi4=", "dev": true, "requires": { - "ansi-regex": "0.2.1" + "ansi-regex": "^0.2.0" } }, "lodash": { @@ -3049,8 +5237,8 @@ "integrity": "sha1-p+iIXwXmiFEUS24SqPNngCa8TFQ=", "dev": true, "requires": { - "lodash._objecttypes": "2.4.1", - "lodash.keys": "2.4.1" + "lodash._objecttypes": "~2.4.1", + "lodash.keys": "~2.4.1" } }, "lodash.escape": { @@ -3059,9 +5247,9 @@ "integrity": "sha1-LOEsXghNsKV92l5dHu659dF1o7Q=", "dev": true, "requires": { - "lodash._escapehtmlchar": "2.4.1", - "lodash._reunescapedhtml": "2.4.1", - "lodash.keys": "2.4.1" + "lodash._escapehtmlchar": "~2.4.1", + "lodash._reunescapedhtml": "~2.4.1", + "lodash.keys": "~2.4.1" } }, "lodash.keys": { @@ -3070,9 +5258,9 @@ "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", "dev": true, "requires": { - "lodash._isnative": "2.4.1", - "lodash._shimkeys": "2.4.1", - "lodash.isobject": "2.4.1" + "lodash._isnative": "~2.4.1", + "lodash._shimkeys": "~2.4.1", + "lodash.isobject": "~2.4.1" } }, "lodash.template": { @@ -3081,13 +5269,13 @@ "integrity": "sha1-nmEQB+32KRKal0qzxIuBez4c8g0=", "dev": true, "requires": { - "lodash._escapestringchar": "2.4.1", - "lodash._reinterpolate": "2.4.1", - "lodash.defaults": "2.4.1", - "lodash.escape": "2.4.1", - "lodash.keys": "2.4.1", - "lodash.templatesettings": "2.4.1", - "lodash.values": "2.4.1" + "lodash._escapestringchar": "~2.4.1", + "lodash._reinterpolate": "~2.4.1", + "lodash.defaults": "~2.4.1", + "lodash.escape": "~2.4.1", + "lodash.keys": "~2.4.1", + "lodash.templatesettings": "~2.4.1", + "lodash.values": "~2.4.1" } }, "lodash.templatesettings": { @@ -3096,8 +5284,8 @@ "integrity": "sha1-6nbHXRHrhtTb6JqDiTu4YZKaxpk=", "dev": true, "requires": { - "lodash._reinterpolate": "2.4.1", - "lodash.escape": "2.4.1" + "lodash._reinterpolate": "~2.4.1", + "lodash.escape": "~2.4.1" } }, "merge-stream": { @@ -3106,7 +5294,7 @@ "integrity": "sha1-5oIPet267gA/SMpKWMfFolPV4Fw=", "dev": true, "requires": { - "through2": "0.5.1" + "through2": "^0.5.1" }, "dependencies": { "through2": { @@ -3115,8 +5303,8 @@ "integrity": "sha1-390BLrnHAOIyP9M084rGIqs3Lac=", "dev": true, "requires": { - "readable-stream": "1.0.34", - "xtend": "3.0.0" + "readable-stream": "~1.0.17", + "xtend": "~3.0.0" } } } @@ -3133,10 +5321,10 @@ "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", "isarray": "0.0.1", - "string_decoder": "0.10.31" + "string_decoder": "~0.10.x" } }, "strip-ansi": { @@ -3145,7 +5333,7 @@ "integrity": "sha1-JfSOoiynkYfzF0pNuHWTR7sSYiA=", "dev": true, "requires": { - "ansi-regex": "0.2.1" + "ansi-regex": "^0.2.1" } }, "supports-color": { @@ -3160,8 +5348,8 @@ "integrity": "sha1-90KzKJPovSYUbnieT9LMssB6cX4=", "dev": true, "requires": { - "readable-stream": "1.0.34", - "xtend": "4.0.1" + "readable-stream": ">=1.0.27-1 <1.1.0-0", + "xtend": ">=4.0.0 <4.1.0-0" }, "dependencies": { "xtend": { @@ -3178,7 +5366,7 @@ "integrity": "sha1-vKk4IJWC7FpJrVOKAPofEl5RMlI=", "dev": true, "requires": { - "clone-stats": "0.0.1" + "clone-stats": "~0.0.1" } }, "vinyl-fs": { @@ -3187,14 +5375,14 @@ "integrity": "sha1-LiXP5t9cgIGPl/9Be/XCGkHkpJs=", "dev": true, "requires": { - "glob-stream": "3.1.18", - "glob-watcher": "0.0.6", - "graceful-fs": "3.0.11", - "lodash": "2.4.1", - "mkdirp": "0.5.1", - "strip-bom": "1.0.0", - "through2": "0.6.1", - "vinyl": "0.4.6" + "glob-stream": "^3.1.5", + "glob-watcher": "^0.0.6", + "graceful-fs": "^3.0.0", + "lodash": "^2.4.1", + "mkdirp": "^0.5.0", + "strip-bom": "^1.0.0", + "through2": "^0.6.1", + "vinyl": "^0.4.0" }, "dependencies": { "vinyl": { @@ -3203,8 +5391,8 @@ "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", "dev": true, "requires": { - "clone": "0.2.0", - "clone-stats": "0.0.1" + "clone": "^0.2.0", + "clone-stats": "^0.0.1" } } } @@ -3223,10 +5411,10 @@ "integrity": "sha1-rAHu6JjXenrAgS+tTz1T0IaH1Bw=", "dev": true, "requires": { - "colors": "1.2.1", + "colors": "^1.1.2", "open": "0.0.5", - "plugin-log": "0.1.0", - "through2": "2.0.3" + "plugin-log": "^0.1.0", + "through2": "^2.0.1" } }, "gulp-postcss": { @@ -3235,10 +5423,10 @@ "integrity": "sha1-eKMuPIeqbNzsWuHJBeGW1HjoxdU=", "dev": true, "requires": { - "gulp-util": "3.0.8", - "postcss": "5.2.18", - "postcss-load-config": "1.2.0", - "vinyl-sourcemaps-apply": "0.2.1" + "gulp-util": "^3.0.8", + "postcss": "^5.2.12", + "postcss-load-config": "^1.2.0", + "vinyl-sourcemaps-apply": "^0.2.1" } }, "gulp-rename": { @@ -3253,7 +5441,48 @@ "integrity": "sha1-xnYqLx8N4KP8WVohWZ0/rI26Gso=", "dev": true, "requires": { - "through2": "2.0.3" + "through2": "^2.0.1" + } + }, + "gulp-sourcemaps": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/gulp-sourcemaps/-/gulp-sourcemaps-1.6.0.tgz", + "integrity": "sha1-uG/zSdgBzrVuHZ59x7vLS33uYAw=", + "dev": true, + "requires": { + "convert-source-map": "^1.1.1", + "graceful-fs": "^4.1.2", + "strip-bom": "^2.0.0", + "through2": "^2.0.0", + "vinyl": "^1.0.0" + }, + "dependencies": { + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=", + "dev": true + }, + "strip-bom": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", + "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", + "dev": true, + "requires": { + "is-utf8": "^0.2.0" + } + }, + "vinyl": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/vinyl/-/vinyl-1.2.0.tgz", + "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", + "dev": true, + "requires": { + "clone": "^1.0.0", + "clone-stats": "^0.0.1", + "replace-ext": "0.0.1" + } + } } }, "gulp-util": { @@ -3262,24 +5491,24 @@ "integrity": "sha1-AFTh50RQLifATBh8PsxQXdVLu08=", "dev": true, "requires": { - "array-differ": "1.0.0", - "array-uniq": "1.0.3", - "beeper": "1.1.1", - "chalk": "1.1.3", - "dateformat": "2.2.0", - "fancy-log": "1.3.2", - "gulplog": "1.0.0", - "has-gulplog": "0.1.0", - "lodash._reescape": "3.0.0", - "lodash._reevaluate": "3.0.0", - "lodash._reinterpolate": "3.0.0", - "lodash.template": "3.6.2", - "minimist": "1.2.0", - "multipipe": "0.1.2", - "object-assign": "3.0.0", + "array-differ": "^1.0.0", + "array-uniq": "^1.0.2", + "beeper": "^1.0.0", + "chalk": "^1.0.0", + "dateformat": "^2.0.0", + "fancy-log": "^1.1.0", + "gulplog": "^1.0.0", + "has-gulplog": "^0.1.0", + "lodash._reescape": "^3.0.0", + "lodash._reevaluate": "^3.0.0", + "lodash._reinterpolate": "^3.0.0", + "lodash.template": "^3.0.0", + "minimist": "^1.1.0", + "multipipe": "^0.1.2", + "object-assign": "^3.0.0", "replace-ext": "0.0.1", - "through2": "2.0.3", - "vinyl": "0.5.3" + "through2": "^2.0.0", + "vinyl": "^0.5.0" }, "dependencies": { "minimist": { @@ -3302,16 +5531,16 @@ "integrity": "sha1-Fi/FY96fx3DpH5p845VVE6mhGMA=", "dev": true, "requires": { - "anymatch": "1.3.2", - "chokidar": "1.7.0", - "glob-parent": "3.1.0", - "gulp-util": "3.0.8", - "object-assign": "4.1.1", - "path-is-absolute": "1.0.1", - "readable-stream": "2.3.5", - "slash": "1.0.0", - "vinyl": "1.2.0", - "vinyl-file": "2.0.0" + "anymatch": "^1.3.0", + "chokidar": "^1.6.1", + "glob-parent": "^3.0.1", + "gulp-util": "^3.0.7", + "object-assign": "^4.1.0", + "path-is-absolute": "^1.0.1", + "readable-stream": "^2.2.2", + "slash": "^1.0.0", + "vinyl": "^1.2.0", + "vinyl-file": "^2.0.0" }, "dependencies": { "isarray": { @@ -3326,13 +5555,13 @@ "integrity": "sha1-tPhQA6k4y7bsvOKhJPsQEr0ag40=", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "2.0.0", - "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.0.3", + "util-deprecate": "~1.0.1" } }, "string_decoder": { @@ -3341,7 +5570,7 @@ "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", "dev": true, "requires": { - "safe-buffer": "5.1.1" + "safe-buffer": "~5.1.0" } }, "vinyl": { @@ -3350,8 +5579,8 @@ "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", "dev": true, "requires": { - "clone": "1.0.4", - "clone-stats": "0.0.1", + "clone": "^1.0.0", + "clone-stats": "^0.0.1", "replace-ext": "0.0.1" } } @@ -3363,16 +5592,16 @@ "integrity": "sha1-kPsLSieiZkM4Mv98YSLbXB7olMY=", "dev": true, "requires": { - "consolidate": "0.14.5", - "es6-promise": "3.3.1", - "fs-readfile-promise": "2.0.1", - "gulp-util": "3.0.8", - "js-yaml": "3.7.0", - "lodash": "4.17.5", - "node.extend": "1.1.6", - "through2": "2.0.3", - "tryit": "1.0.3", - "vinyl-bufferstream": "1.0.1" + "consolidate": "^0.14.1", + "es6-promise": "^3.1.2", + "fs-readfile-promise": "^2.0.1", + "gulp-util": "^3.0.3", + "js-yaml": "^3.2.6", + "lodash": "^4.11.1", + "node.extend": "^1.1.2", + "through2": "^2.0.1", + "tryit": "^1.0.1", + "vinyl-bufferstream": "^1.0.1" } }, "gulp-wrap-js": { @@ -3381,12 +5610,12 @@ "integrity": "sha1-3uYqpISqupVHqT0f9c0MPQvtwDE=", "dev": true, "requires": { - "escodegen": "1.9.1", - "esprima": "2.7.3", - "estemplate": "0.5.1", - "gulp-util": "3.0.8", - "through2": "2.0.3", - "vinyl-sourcemaps-apply": "0.1.4" + "escodegen": "^1.6.1", + "esprima": "^2.3.0", + "estemplate": "*", + "gulp-util": "~3.0.5", + "through2": "*", + "vinyl-sourcemaps-apply": "^0.1.4" }, "dependencies": { "source-map": { @@ -3395,7 +5624,7 @@ "integrity": "sha1-wkvBRspRfBRx9drL4lcbK3+eM0Y=", "dev": true, "requires": { - "amdefine": "1.0.1" + "amdefine": ">=0.0.4" } }, "vinyl-sourcemaps-apply": { @@ -3404,7 +5633,7 @@ "integrity": "sha1-xfy9Q+LyOEI8LcmL3db3m3K8NFs=", "dev": true, "requires": { - "source-map": "0.1.43" + "source-map": "^0.1.39" } } } @@ -3415,7 +5644,7 @@ "integrity": "sha1-4oxNRdBey77YGDY86PnFkmIp/+U=", "dev": true, "requires": { - "glogg": "1.0.1" + "glogg": "^1.0.0" } }, "har-schema": { @@ -3430,8 +5659,8 @@ "integrity": "sha1-M0gdDxu/9gDdID11gSpqX7oALio=", "dev": true, "requires": { - "ajv": "4.11.8", - "har-schema": "1.0.5" + "ajv": "^4.9.1", + "har-schema": "^1.0.5" } }, "has": { @@ -3440,7 +5669,7 @@ "integrity": "sha1-hGFzP1OLCDfJNh45qauelwTcLyg=", "dev": true, "requires": { - "function-bind": "1.1.1" + "function-bind": "^1.0.2" } }, "has-ansi": { @@ -3449,7 +5678,7 @@ "integrity": "sha1-NPUEnOHs3ysGSa8+8k5F7TVBbZE=", "dev": true, "requires": { - "ansi-regex": "2.1.1" + "ansi-regex": "^2.0.0" } }, "has-binary": { @@ -3479,7 +5708,7 @@ "integrity": "sha1-ZBTIKRNpfaUVkDl9r7EvIpZ4Ec4=", "dev": true, "requires": { - "sparkles": "1.0.0" + "sparkles": "^1.0.0" } }, "has-value": { @@ -3488,9 +5717,9 @@ "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc=", "dev": true, "requires": { - "get-value": "2.0.6", - "has-values": "1.0.0", - "isobject": "3.0.1" + "get-value": "^2.0.6", + "has-values": "^1.0.0", + "isobject": "^3.0.0" } }, "has-values": { @@ -3499,8 +5728,8 @@ "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8=", "dev": true, "requires": { - "is-number": "3.0.0", - "kind-of": "4.0.0" + "is-number": "^3.0.0", + "kind-of": "^4.0.0" }, "dependencies": { "kind-of": { @@ -3509,7 +5738,7 @@ "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "^1.1.5" } } } @@ -3520,8 +5749,8 @@ "integrity": "sha1-eNfL/B5tZjA/55g3NlmEUXsvbuE=", "dev": true, "requires": { - "is-stream": "1.1.0", - "pinkie-promise": "2.0.1" + "is-stream": "^1.0.1", + "pinkie-promise": "^2.0.0" } }, "hawk": { @@ -3530,10 +5759,10 @@ "integrity": "sha1-B4REvXwWQLD+VA0sm3PVlnjo4cQ=", "dev": true, "requires": { - "boom": "2.10.1", - "cryptiles": "2.0.5", - "hoek": "2.16.3", - "sntp": "1.0.9" + "boom": "2.x.x", + "cryptiles": "2.x.x", + "hoek": "2.x.x", + "sntp": "1.x.x" } }, "hoek": { @@ -3548,7 +5777,7 @@ "integrity": "sha1-TCu8inWJmP7r9e1oWA921GdotLw=", "dev": true, "requires": { - "parse-passwd": "1.0.0" + "parse-passwd": "^1.0.0" } }, "hosted-git-info": { @@ -3569,8 +5798,8 @@ "integrity": "sha1-GX4izevUGYWF6GlO9nhhl7ke2UI=", "dev": true, "requires": { - "inherits": "2.0.3", - "statuses": "1.5.0" + "inherits": "~2.0.1", + "statuses": "1" } }, "http-parser-js": { @@ -3585,8 +5814,8 @@ "integrity": "sha1-Bt/ykpUr9k2+hHH6nfcwZtTzd0I=", "dev": true, "requires": { - "eventemitter3": "1.2.0", - "requires-port": "1.0.0" + "eventemitter3": "1.x.x", + "requires-port": "1.x.x" } }, "http-signature": { @@ -3595,9 +5824,9 @@ "integrity": "sha1-33LiZwZs0Kxn+3at+OE0qPvPkb8=", "dev": true, "requires": { - "assert-plus": "0.2.0", - "jsprim": "1.4.1", - "sshpk": "1.14.1" + "assert-plus": "^0.2.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" } }, "iconv-lite": { @@ -3613,13 +5842,166 @@ "dev": true, "optional": true }, + "imagemin": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/imagemin/-/imagemin-5.3.1.tgz", + "integrity": "sha1-8Zwu7h5xumxlWMUV+fyWaAGJptQ=", + "dev": true, + "requires": { + "file-type": "^4.1.0", + "globby": "^6.1.0", + "make-dir": "^1.0.0", + "p-pipe": "^1.1.0", + "pify": "^2.3.0", + "replace-ext": "^1.0.0" + }, + "dependencies": { + "replace-ext": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/replace-ext/-/replace-ext-1.0.0.tgz", + "integrity": "sha1-3mMSg3P8v3w8z6TeWkgMRaZ5WOs=", + "dev": true + } + } + }, + "imagemin-gifsicle": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/imagemin-gifsicle/-/imagemin-gifsicle-5.2.0.tgz", + "integrity": "sha512-K01m5QuPK+0en8oVhiOOAicF7KjrHlCZxS++mfLI2mV/Ksfq/Y9nCXCWDz6jRv13wwlqe5T7hXT+ji2DnLc2yQ==", + "dev": true, + "optional": true, + "requires": { + "exec-buffer": "^3.0.0", + "gifsicle": "^3.0.0", + "is-gif": "^1.0.0" + } + }, + "imagemin-jpegtran": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/imagemin-jpegtran/-/imagemin-jpegtran-5.0.2.tgz", + "integrity": "sha1-5ogiY7j3kW/duABkDPddLpcNKtY=", + "dev": true, + "optional": true, + "requires": { + "exec-buffer": "^3.0.0", + "is-jpg": "^1.0.0", + "jpegtran-bin": "^3.0.0" + } + }, + "imagemin-optipng": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/imagemin-optipng/-/imagemin-optipng-5.2.1.tgz", + "integrity": "sha1-0i2kEsCfX/AKQzmWC5ioix2+hpU=", + "dev": true, + "optional": true, + "requires": { + "exec-buffer": "^3.0.0", + "is-png": "^1.0.0", + "optipng-bin": "^3.0.0" + } + }, + "imagemin-svgo": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/imagemin-svgo/-/imagemin-svgo-6.0.0.tgz", + "integrity": "sha512-xwjBZQKpbkklHtJYnCOwRJjTRJA/nR0hQzKMh+CUZRvm/L0QwKKPJQ9tkPWQHrg+cydPu2i1vLgHuy2E0hKEkg==", + "dev": true, + "optional": true, + "requires": { + "buffer-from": "^0.1.1", + "is-svg": "^2.0.0", + "svgo": "^1.0.0" + }, + "dependencies": { + "coa": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/coa/-/coa-2.0.1.tgz", + "integrity": "sha512-5wfTTO8E2/ja4jFSxePXlG5nRu5bBtL/r1HCIpJW/lzT6yDtKl0u0Z4o/Vpz32IpKmBn7HerheEZQgA9N2DarQ==", + "dev": true, + "optional": true, + "requires": { + "q": "^1.1.2" + } + }, + "colors": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.1.2.tgz", + "integrity": "sha1-FopHAXVran9RoSzgyXv6KMCE7WM=", + "dev": true, + "optional": true + }, + "csso": { + "version": "3.5.1", + "resolved": "https://registry.npmjs.org/csso/-/csso-3.5.1.tgz", + "integrity": "sha512-vrqULLffYU1Q2tLdJvaCYbONStnfkfimRxXNaGjxMldI0C7JPBC4rB1RyjhfdZ4m1frm8pM9uRPKH3d2knZ8gg==", + "dev": true, + "optional": true, + "requires": { + "css-tree": "1.0.0-alpha.29" + }, + "dependencies": { + "css-tree": { + "version": "1.0.0-alpha.29", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.29.tgz", + "integrity": "sha512-sRNb1XydwkW9IOci6iB2xmy8IGCj6r/fr+JWitvJ2JxQRPzN3T4AGGVWCMlVmVwM1gtgALJRmGIlWv5ppnGGkg==", + "dev": true, + "optional": true, + "requires": { + "mdn-data": "~1.1.0", + "source-map": "^0.5.3" + } + } + } + }, + "esprima": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.0.tgz", + "integrity": "sha512-oftTcaMu/EGrEIu904mWteKIv8vMuOgGYo7EhVJJN00R/EED9DCua/xxHRdYnKtcECzVg7xOWhflvJMnqcFZjw==", + "dev": true, + "optional": true + }, + "js-yaml": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.10.0.tgz", + "integrity": "sha512-O2v52ffjLa9VeM43J4XocZE//WT9N0IiwDa3KSHH7Tu8CtH+1qM8SIZvnsTh6v+4yFy5KUY3BHUVwjpfAWsjIA==", + "dev": true, + "optional": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "svgo": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.0.5.tgz", + "integrity": "sha512-nYrifviB77aNKDNKKyuay3M9aYiK6Hv5gJVDdjj2ZXTQmI8WZc8+UPLR5IpVlktJfSu3co/4XcWgrgI6seGBPg==", + "dev": true, + "optional": true, + "requires": { + "coa": "~2.0.1", + "colors": "~1.1.2", + "css-select": "~1.3.0-rc0", + "css-select-base-adapter": "~0.1.0", + "css-tree": "1.0.0-alpha25", + "css-url-regex": "^1.1.0", + "csso": "^3.5.0", + "js-yaml": "~3.10.0", + "mkdirp": "~0.5.1", + "object.values": "^1.0.4", + "sax": "~1.2.4", + "stable": "~0.1.6", + "unquote": "~1.1.1", + "util.promisify": "~1.0.0" + } + } + } + }, "indent-string": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-2.1.0.tgz", "integrity": "sha1-ji1INIdCEhtKghi3oTfppSBJ3IA=", "dev": true, "requires": { - "repeating": "2.0.1" + "repeating": "^2.0.0" } }, "indexes-of": { @@ -3646,8 +6028,8 @@ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", "dev": true, "requires": { - "once": "1.4.0", - "wrappy": "1.0.2" + "once": "^1.3.0", + "wrappy": "1" } }, "inherits": { @@ -3668,6 +6050,19 @@ "integrity": "sha1-ftGxQQxqDg94z5XTuEQMY/eLhhQ=", "dev": true }, + "ip-regex": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-1.0.3.tgz", + "integrity": "sha1-3FiQdvZZ9BnCIgOaMzFvHHOH7/0=", + "dev": true, + "optional": true + }, + "irregular-plurals": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/irregular-plurals/-/irregular-plurals-1.4.0.tgz", + "integrity": "sha1-LKmwM2UREYVUEvFr5dd8YqRYp2Y=", + "dev": true + }, "is": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/is/-/is-3.2.1.tgz", @@ -3680,8 +6075,8 @@ "integrity": "sha1-OV4a6EsR8mrReV5zwXN45IowFXY=", "dev": true, "requires": { - "is-relative": "1.0.0", - "is-windows": "1.0.2" + "is-relative": "^1.0.0", + "is-windows": "^1.0.1" } }, "is-absolute-url": { @@ -3696,7 +6091,7 @@ "integrity": "sha1-FpwvbT3x+ZJhgHI2XJsOofaHhlY=", "dev": true, "requires": { - "kind-of": "6.0.2" + "kind-of": "^6.0.0" } }, "is-arrayish": { @@ -3711,7 +6106,7 @@ "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg=", "dev": true, "requires": { - "binary-extensions": "1.11.0" + "binary-extensions": "^1.0.0" } }, "is-buffer": { @@ -3726,27 +6121,45 @@ "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", "dev": true, "requires": { - "builtin-modules": "1.1.1" + "builtin-modules": "^1.0.0" } }, + "is-bzip2": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-bzip2/-/is-bzip2-1.0.0.tgz", + "integrity": "sha1-XuWOqlounIDiFAe+3yOuWsCRs/w=", + "dev": true + }, + "is-callable": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.3.tgz", + "integrity": "sha1-hut1OSgF3cM69xySoO7fdO52BLI=", + "dev": true + }, "is-data-descriptor": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz", "integrity": "sha1-2Eh2Mh0Oet0DmQQGq7u9NrqSaMc=", "dev": true, "requires": { - "kind-of": "6.0.2" + "kind-of": "^6.0.0" } }, + "is-date-object": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.1.tgz", + "integrity": "sha1-mqIOtq7rv/d/vTPnTKAbM1gdOhY=", + "dev": true + }, "is-descriptor": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz", "integrity": "sha1-OxWXRqZmBLBPjIFSS6NlxfFNhuw=", "dev": true, "requires": { - "is-accessor-descriptor": "1.0.0", - "is-data-descriptor": "1.0.0", - "kind-of": "6.0.2" + "is-accessor-descriptor": "^1.0.0", + "is-data-descriptor": "^1.0.0", + "kind-of": "^6.0.2" } }, "is-directory": { @@ -3767,7 +6180,7 @@ "integrity": "sha1-IjgJj8Ih3gvPpdnqxMRdY4qhxTQ=", "dev": true, "requires": { - "is-primitive": "2.0.0" + "is-primitive": "^2.0.0" } }, "is-extendable": { @@ -3788,25 +6201,51 @@ "integrity": "sha1-zGZ3aVYCvlUO8R6LSqYwU0K20Ko=", "dev": true, "requires": { - "number-is-nan": "1.0.1" + "number-is-nan": "^1.0.0" } }, + "is-gif": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-gif/-/is-gif-1.0.0.tgz", + "integrity": "sha1-ptKumIkwB7/6l6HYwB1jIFgyCX4=", + "dev": true, + "optional": true + }, "is-glob": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz", "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo=", "dev": true, "requires": { - "is-extglob": "2.1.1" + "is-extglob": "^2.1.0" } }, + "is-gzip": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-gzip/-/is-gzip-1.0.0.tgz", + "integrity": "sha1-bKiwe5nHeZgCWQDlVc7Y7YCHmoM=", + "dev": true + }, + "is-jpg": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-jpg/-/is-jpg-1.0.1.tgz", + "integrity": "sha1-KW1X/dmc4BBDSnKD40armhA16XU=", + "dev": true, + "optional": true + }, + "is-natural-number": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-natural-number/-/is-natural-number-2.1.1.tgz", + "integrity": "sha1-fUxXKDd+84bD4ZSpkRv1fG3DNec=", + "dev": true + }, "is-number": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz", "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU=", "dev": true, "requires": { - "kind-of": "3.2.2" + "kind-of": "^3.0.2" }, "dependencies": { "kind-of": { @@ -3815,18 +6254,24 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "^1.1.5" } } } }, + "is-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz", + "integrity": "sha1-PkcprB9f3gJc19g6iW2rn09n2w8=", + "dev": true + }, "is-odd": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/is-odd/-/is-odd-2.0.0.tgz", "integrity": "sha1-dkZiRnH9fqVYzNmieVGC8pWPGyQ=", "dev": true, "requires": { - "is-number": "4.0.0" + "is-number": "^4.0.0" }, "dependencies": { "is-number": { @@ -3849,9 +6294,16 @@ "integrity": "sha1-LBY7P6+xtgbZ0Xko8FwqHDjgdnc=", "dev": true, "requires": { - "isobject": "3.0.1" + "isobject": "^3.0.1" } }, + "is-png": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-png/-/is-png-1.1.0.tgz", + "integrity": "sha1-1XSxK/J1wDUEVVcLDltXqwYgd84=", + "dev": true, + "optional": true + }, "is-posix-bracket": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/is-posix-bracket/-/is-posix-bracket-0.1.1.tgz", @@ -3864,15 +6316,36 @@ "integrity": "sha1-IHurkWOEmcB7Kt8kCkGochADRXU=", "dev": true }, + "is-redirect": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-redirect/-/is-redirect-1.0.0.tgz", + "integrity": "sha1-HQPd7VO9jbDzDCbk+V02/HyH3CQ=", + "dev": true + }, + "is-regex": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.4.tgz", + "integrity": "sha1-VRdIm1RwkbCTDglWVM7SXul+lJE=", + "dev": true, + "requires": { + "has": "^1.0.1" + } + }, "is-relative": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-1.0.0.tgz", "integrity": "sha1-obtpNc6MXboei5dUubLcwCDiJg0=", "dev": true, "requires": { - "is-unc-path": "1.0.0" + "is-unc-path": "^1.0.0" } }, + "is-retry-allowed": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-retry-allowed/-/is-retry-allowed-1.1.0.tgz", + "integrity": "sha1-EaBgVotnM5REAz0BJaYaINVk+zQ=", + "dev": true + }, "is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", @@ -3885,9 +6358,21 @@ "integrity": "sha1-z2EJDaDZ77yrhyLeum8DIgjbsOk=", "dev": true, "requires": { - "html-comment-regex": "1.1.1" + "html-comment-regex": "^1.1.0" } }, + "is-symbol": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.1.tgz", + "integrity": "sha1-PMWfAAJRlLarLjjbrmaJJWtmBXI=", + "dev": true + }, + "is-tar": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-tar/-/is-tar-1.0.0.tgz", + "integrity": "sha1-L2suF5LB9bs2UZrKqdZcDSb+hT0=", + "dev": true + }, "is-typedarray": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", @@ -3900,21 +6385,39 @@ "integrity": "sha1-1zHoiY7QkKEsNSrS6u1Qla0yLJ0=", "dev": true, "requires": { - "unc-path-regex": "0.1.2" + "unc-path-regex": "^0.1.2" } }, + "is-url": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/is-url/-/is-url-1.2.4.tgz", + "integrity": "sha512-ITvGim8FhRiYe4IQ5uHSkj7pVaPDrCTkNd3yq3cV7iZAcJdHTUMPMEHcqSOy9xZ9qFenQCvi+2wjH9a1nXqHww==", + "dev": true + }, "is-utf8": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", "integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=", "dev": true }, + "is-valid-glob": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/is-valid-glob/-/is-valid-glob-0.3.0.tgz", + "integrity": "sha1-1LVcafUYhvm2XHDWwmItN+KfSP4=", + "dev": true + }, "is-windows": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz", "integrity": "sha1-0YUOuXkezRjmGCzhKjDzlmNLsZ0=", "dev": true }, + "is-zip": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-zip/-/is-zip-1.0.0.tgz", + "integrity": "sha1-R7Co/004p2QxzP2ZqOFaTIa6IyU=", + "dev": true + }, "isarray": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", @@ -3951,6 +6454,18 @@ "integrity": "sha1-b2G9eQYeJ/Q+b5NV5Es8bKtv8pc=", "dev": true }, + "jpegtran-bin": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jpegtran-bin/-/jpegtran-bin-3.2.0.tgz", + "integrity": "sha1-9g7PSumZwL2tLp+83ytvCYHnops=", + "dev": true, + "optional": true, + "requires": { + "bin-build": "^2.0.0", + "bin-wrapper": "^3.0.0", + "logalot": "^2.0.0" + } + }, "js-base64": { "version": "2.4.3", "resolved": "https://registry.npmjs.org/js-base64/-/js-base64-2.4.3.tgz", @@ -3963,8 +6478,8 @@ "integrity": "sha1-XJZ93YN6m/3KXy3oQlOr6KHAO4A=", "dev": true, "requires": { - "argparse": "1.0.10", - "esprima": "2.7.3" + "argparse": "^1.0.7", + "esprima": "^2.6.0" } }, "jsbn": { @@ -3986,7 +6501,7 @@ "integrity": "sha1-mnWdOcXy/1A/1TAGRu1EX4jE+a8=", "dev": true, "requires": { - "jsonify": "0.0.0" + "jsonify": "~0.0.0" } }, "json-stringify-safe": { @@ -4007,7 +6522,7 @@ "integrity": "sha1-NzaitCi4e72gzIO1P6PWM6NcKug=", "dev": true, "requires": { - "graceful-fs": "4.1.11" + "graceful-fs": "^4.1.6" }, "dependencies": { "graceful-fs": { @@ -4051,33 +6566,33 @@ "integrity": "sha1-hcwI6eCiLXzpzKN8ShvoJPaisa4=", "dev": true, "requires": { - "bluebird": "3.5.1", - "body-parser": "1.18.2", - "chokidar": "1.7.0", - "colors": "1.2.1", - "combine-lists": "1.0.1", - "connect": "3.6.6", - "core-js": "2.5.4", - "di": "0.0.1", - "dom-serialize": "2.2.1", - "expand-braces": "0.1.2", - "glob": "7.1.2", - "graceful-fs": "4.1.11", - "http-proxy": "1.16.2", - "isbinaryfile": "3.0.2", - "lodash": "3.10.1", - "log4js": "0.6.38", - "mime": "1.3.4", - "minimatch": "3.0.4", - "optimist": "0.6.1", - "qjobs": "1.2.0", - "range-parser": "1.2.0", - "rimraf": "2.6.2", - "safe-buffer": "5.1.1", + "bluebird": "^3.3.0", + "body-parser": "^1.16.1", + "chokidar": "^1.4.1", + "colors": "^1.1.0", + "combine-lists": "^1.0.0", + "connect": "^3.6.0", + "core-js": "^2.2.0", + "di": "^0.0.1", + "dom-serialize": "^2.2.0", + "expand-braces": "^0.1.1", + "glob": "^7.1.1", + "graceful-fs": "^4.1.2", + "http-proxy": "^1.13.0", + "isbinaryfile": "^3.0.0", + "lodash": "^3.8.0", + "log4js": "^0.6.31", + "mime": "^1.3.4", + "minimatch": "^3.0.2", + "optimist": "^0.6.1", + "qjobs": "^1.1.4", + "range-parser": "^1.2.0", + "rimraf": "^2.6.0", + "safe-buffer": "^5.0.1", "socket.io": "1.7.3", - "source-map": "0.5.7", + "source-map": "^0.5.3", "tmp": "0.0.31", - "useragent": "2.3.0" + "useragent": "^2.1.12" }, "dependencies": { "body-parser": { @@ -4087,15 +6602,15 @@ "dev": true, "requires": { "bytes": "3.0.0", - "content-type": "1.0.4", + "content-type": "~1.0.4", "debug": "2.6.9", - "depd": "1.1.2", - "http-errors": "1.6.2", + "depd": "~1.1.1", + "http-errors": "~1.6.2", "iconv-lite": "0.4.19", - "on-finished": "2.3.0", + "on-finished": "~2.3.0", "qs": "6.5.1", "raw-body": "2.3.2", - "type-is": "1.6.16" + "type-is": "~1.6.15" } }, "bytes": { @@ -4112,7 +6627,7 @@ "requires": { "debug": "2.6.9", "finalhandler": "1.1.0", - "parseurl": "1.3.2", + "parseurl": "~1.3.2", "utils-merge": "1.0.1" } }, @@ -4129,12 +6644,12 @@ "dev": true, "requires": { "debug": "2.6.9", - "encodeurl": "1.0.2", - "escape-html": "1.0.3", - "on-finished": "2.3.0", - "parseurl": "1.3.2", - "statuses": "1.3.1", - "unpipe": "1.0.0" + "encodeurl": "~1.0.1", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", + "statuses": "~1.3.1", + "unpipe": "~1.0.0" }, "dependencies": { "statuses": { @@ -4160,7 +6675,7 @@ "depd": "1.1.1", "inherits": "2.0.3", "setprototypeof": "1.0.3", - "statuses": "1.5.0" + "statuses": ">= 1.3.1 < 2" }, "dependencies": { "depd": { @@ -4227,8 +6742,8 @@ "integrity": "sha1-0jyjSAG9qYY60xjju0vUBisTrNI=", "dev": true, "requires": { - "lodash": "4.17.5", - "phantomjs-prebuilt": "2.1.16" + "lodash": "^4.0.1", + "phantomjs-prebuilt": "^2.1.7" } }, "kew": { @@ -4249,7 +6764,7 @@ "integrity": "sha1-QIhDO0azsbolnXh4XY6W9zugJDk=", "dev": true, "requires": { - "graceful-fs": "4.1.11" + "graceful-fs": "^4.1.9" }, "dependencies": { "graceful-fs": { @@ -4267,20 +6782,68 @@ "integrity": "sha1-odePw6UEdMuAhF07O24dpJpEbo4=", "dev": true }, + "lazy-req": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/lazy-req/-/lazy-req-1.1.0.tgz", + "integrity": "sha1-va6+rTD42CQDnODOFJ1Nqge6H6w=", + "dev": true, + "optional": true + }, + "lazystream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.0.tgz", + "integrity": "sha1-9plf4PggOS9hOWvolGJAe7dxaOQ=", + "dev": true, + "requires": { + "readable-stream": "^2.0.5" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, "less": { "version": "2.7.3", "resolved": "https://registry.npmjs.org/less/-/less-2.7.3.tgz", "integrity": "sha1-zBJg9RyQCp7A2R+2mYE54CUHtjs=", "dev": true, "requires": { - "errno": "0.1.7", - "graceful-fs": "4.1.11", - "image-size": "0.5.5", - "mime": "1.3.4", - "mkdirp": "0.5.1", - "promise": "7.3.1", + "errno": "^0.1.1", + "graceful-fs": "^4.1.2", + "image-size": "~0.5.0", + "mime": "^1.2.11", + "mkdirp": "^0.5.0", + "promise": "^7.1.1", "request": "2.81.0", - "source-map": "0.5.7" + "source-map": "^0.5.3" }, "dependencies": { "graceful-fs": { @@ -4298,8 +6861,8 @@ "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", "dev": true, "requires": { - "prelude-ls": "1.1.2", - "type-check": "0.3.2" + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" } }, "liftoff": { @@ -4308,14 +6871,14 @@ "integrity": "sha1-IAkpG7Mc6oYbvxCnwVooyvdcMew=", "dev": true, "requires": { - "extend": "3.0.1", - "findup-sync": "2.0.0", - "fined": "1.1.0", - "flagged-respawn": "1.0.0", - "is-plain-object": "2.0.4", - "object.map": "1.0.1", - "rechoir": "0.6.2", - "resolve": "1.6.0" + "extend": "^3.0.0", + "findup-sync": "^2.0.0", + "fined": "^1.0.1", + "flagged-respawn": "^1.0.0", + "is-plain-object": "^2.0.4", + "object.map": "^1.0.0", + "rechoir": "^0.6.2", + "resolve": "^1.1.7" } }, "livereload-js": { @@ -4330,11 +6893,11 @@ "integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", "dev": true, "requires": { - "graceful-fs": "4.1.11", - "parse-json": "2.2.0", - "pify": "2.3.0", - "pinkie-promise": "2.0.1", - "strip-bom": "2.0.0" + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0" }, "dependencies": { "graceful-fs": { @@ -4349,7 +6912,7 @@ "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", "dev": true, "requires": { - "is-utf8": "0.2.1" + "is-utf8": "^0.2.0" } } } @@ -4384,7 +6947,7 @@ "integrity": "sha1-32fDu2t+jh6DGrSL+geVuSr+iZ0=", "dev": true, "requires": { - "lodash._htmlescapes": "2.4.1" + "lodash._htmlescapes": "~2.4.1" } }, "lodash._escapestringchar": { @@ -4447,8 +7010,8 @@ "integrity": "sha1-dHxPxAED6zu4oJduVx96JlnpO6c=", "dev": true, "requires": { - "lodash._htmlescapes": "2.4.1", - "lodash.keys": "2.4.1" + "lodash._htmlescapes": "~2.4.1", + "lodash.keys": "~2.4.1" }, "dependencies": { "lodash.keys": { @@ -4457,9 +7020,9 @@ "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", "dev": true, "requires": { - "lodash._isnative": "2.4.1", - "lodash._shimkeys": "2.4.1", - "lodash.isobject": "2.4.1" + "lodash._isnative": "~2.4.1", + "lodash._shimkeys": "~2.4.1", + "lodash.isobject": "~2.4.1" } } } @@ -4476,7 +7039,7 @@ "integrity": "sha1-bpzJZm/wgfC1psl4uD4kLmlJ0gM=", "dev": true, "requires": { - "lodash._objecttypes": "2.4.1" + "lodash._objecttypes": "~2.4.1" } }, "lodash.clone": { @@ -4497,7 +7060,7 @@ "integrity": "sha1-mV7g3BjBtIzJLv+ucaEKq1tIdpg=", "dev": true, "requires": { - "lodash._root": "3.0.1" + "lodash._root": "^3.0.0" } }, "lodash.flatten": { @@ -4518,13 +7081,19 @@ "integrity": "sha1-eeTriMNqgSKvhvhEqpvNhRtfu1U=", "dev": true }, + "lodash.isequal": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz", + "integrity": "sha1-QVxEePK8wwEgwizhDtMib30+GOA=", + "dev": true + }, "lodash.isobject": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/lodash.isobject/-/lodash.isobject-2.4.1.tgz", "integrity": "sha1-Wi5H/mmVPx7mMafrof5k0tBlWPU=", "dev": true, "requires": { - "lodash._objecttypes": "2.4.1" + "lodash._objecttypes": "~2.4.1" } }, "lodash.keys": { @@ -4533,9 +7102,9 @@ "integrity": "sha1-TbwEcrFWvlCgsoaFXRvQsMZWCYo=", "dev": true, "requires": { - "lodash._getnative": "3.9.1", - "lodash.isarguments": "3.1.0", - "lodash.isarray": "3.0.4" + "lodash._getnative": "^3.0.0", + "lodash.isarguments": "^3.0.0", + "lodash.isarray": "^3.0.0" } }, "lodash.memoize": { @@ -4574,15 +7143,15 @@ "integrity": "sha1-+M3sxhaaJVvpCYrosMU9N4kx0U8=", "dev": true, "requires": { - "lodash._basecopy": "3.0.1", - "lodash._basetostring": "3.0.1", - "lodash._basevalues": "3.0.0", - "lodash._isiterateecall": "3.0.9", - "lodash._reinterpolate": "3.0.0", - "lodash.escape": "3.2.0", - "lodash.keys": "3.1.2", - "lodash.restparam": "3.6.1", - "lodash.templatesettings": "3.1.1" + "lodash._basecopy": "^3.0.0", + "lodash._basetostring": "^3.0.0", + "lodash._basevalues": "^3.0.0", + "lodash._isiterateecall": "^3.0.0", + "lodash._reinterpolate": "^3.0.0", + "lodash.escape": "^3.0.0", + "lodash.keys": "^3.0.0", + "lodash.restparam": "^3.0.0", + "lodash.templatesettings": "^3.0.0" } }, "lodash.templatesettings": { @@ -4591,8 +7160,8 @@ "integrity": "sha1-+zB4RHU7Zrnxr6VOJix0UwfbqOU=", "dev": true, "requires": { - "lodash._reinterpolate": "3.0.0", - "lodash.escape": "3.2.0" + "lodash._reinterpolate": "^3.0.0", + "lodash.escape": "^3.0.0" } }, "lodash.uniq": { @@ -4607,7 +7176,7 @@ "integrity": "sha1-q/UUQ2s8twUAFieXjLzzCxKA7qQ=", "dev": true, "requires": { - "lodash.keys": "2.4.1" + "lodash.keys": "~2.4.1" }, "dependencies": { "lodash.keys": { @@ -4616,9 +7185,9 @@ "integrity": "sha1-SN6kbfj/djKxDXBrissmWR4rNyc=", "dev": true, "requires": { - "lodash._isnative": "2.4.1", - "lodash._shimkeys": "2.4.1", - "lodash.isobject": "2.4.1" + "lodash._isnative": "~2.4.1", + "lodash._shimkeys": "~2.4.1", + "lodash.isobject": "~2.4.1" } } } @@ -4629,8 +7198,8 @@ "integrity": "sha1-LElBFmldb7JUgJQ9P8hy5mKlIv0=", "dev": true, "requires": { - "readable-stream": "1.0.34", - "semver": "4.3.6" + "readable-stream": "~1.0.2", + "semver": "~4.3.3" }, "dependencies": { "readable-stream": { @@ -4639,14 +7208,25 @@ "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", "isarray": "0.0.1", - "string_decoder": "0.10.31" + "string_decoder": "~0.10.x" } } } }, + "logalot": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/logalot/-/logalot-2.1.0.tgz", + "integrity": "sha1-X46MkNME7fElMJUaVVSruMXj9VI=", + "dev": true, + "optional": true, + "requires": { + "figures": "^1.3.5", + "squeak": "^1.0.0" + } + }, "longest": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", @@ -4659,8 +7239,27 @@ "integrity": "sha1-W0b4AUft7leIcPCG0Eghz5mOVR8=", "dev": true, "requires": { - "currently-unhandled": "0.4.1", - "signal-exit": "3.0.2" + "currently-unhandled": "^0.4.1", + "signal-exit": "^3.0.0" + } + }, + "lowercase-keys": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-1.0.1.tgz", + "integrity": "sha512-G2Lj61tXDnVFFOi8VZds+SoQjtQC3dgokKdDG2mTm1tx4m50NUHBOZSBwQQHyy0V12A0JTG4icfZQH+xPyh8VA==", + "dev": true + }, + "lpad-align": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/lpad-align/-/lpad-align-1.1.2.tgz", + "integrity": "sha1-IfYArBwwlcPG5JfuZyce4ISB/p4=", + "dev": true, + "optional": true, + "requires": { + "get-stdin": "^4.0.1", + "indent-string": "^2.1.0", + "longest": "^1.0.0", + "meow": "^3.3.0" } }, "lru-cache": { @@ -4675,13 +7274,30 @@ "integrity": "sha1-WQTcU3w57G2+/q6QIycTX6hRHxI=", "dev": true }, + "make-dir": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-1.3.0.tgz", + "integrity": "sha512-2w31R7SJtieJJnQtGc7RVL2StM2vGYVfqUOvUDxH6bC6aJTxPxTF0GnIgCyu7tjockiUWAYQRbxa7vKn34s5sQ==", + "dev": true, + "requires": { + "pify": "^3.0.0" + }, + "dependencies": { + "pify": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz", + "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=", + "dev": true + } + } + }, "make-iterator": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/make-iterator/-/make-iterator-1.0.0.tgz", "integrity": "sha1-V7713IXSOSO6I3ZzJNjo+PPZaUs=", "dev": true, "requires": { - "kind-of": "3.2.2" + "kind-of": "^3.1.0" }, "dependencies": { "kind-of": { @@ -4690,7 +7306,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "^1.1.5" } } } @@ -4719,7 +7335,7 @@ "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48=", "dev": true, "requires": { - "object-visit": "1.0.1" + "object-visit": "^1.0.0" } }, "marked": { @@ -4734,6 +7350,12 @@ "integrity": "sha1-3oGf282E3M2PrlnGrreWFbnSZqw=", "dev": true }, + "mdn-data": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-1.1.4.tgz", + "integrity": "sha512-FSYbp3lyKjyj3E7fMl6rYvUdX0FBXaluGqlFoYESWQlyUTq8R+wp0rkFxoYFqZlHCvsUXGjyJmLQSnXToYhOSA==", + "dev": true + }, "media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -4746,16 +7368,16 @@ "integrity": "sha1-cstmi0JSKCkKu/qFaJJYcwioAfs=", "dev": true, "requires": { - "camelcase-keys": "2.1.0", - "decamelize": "1.2.0", - "loud-rejection": "1.6.0", - "map-obj": "1.0.1", - "minimist": "1.2.0", - "normalize-package-data": "2.4.0", - "object-assign": "4.1.1", - "read-pkg-up": "1.0.1", - "redent": "1.0.0", - "trim-newlines": "1.0.0" + "camelcase-keys": "^2.0.0", + "decamelize": "^1.1.2", + "loud-rejection": "^1.0.0", + "map-obj": "^1.0.1", + "minimist": "^1.1.3", + "normalize-package-data": "^2.3.4", + "object-assign": "^4.0.1", + "read-pkg-up": "^1.0.1", + "redent": "^1.0.0", + "trim-newlines": "^1.0.0" }, "dependencies": { "minimist": { @@ -4772,7 +7394,7 @@ "integrity": "sha1-QEEgLVCKNCugAXQAjfDCUbjBNeE=", "dev": true, "requires": { - "readable-stream": "2.3.5" + "readable-stream": "^2.0.1" }, "dependencies": { "isarray": { @@ -4787,13 +7409,13 @@ "integrity": "sha1-tPhQA6k4y7bsvOKhJPsQEr0ag40=", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "2.0.0", - "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.0.3", + "util-deprecate": "~1.0.1" } }, "string_decoder": { @@ -4802,7 +7424,7 @@ "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", "dev": true, "requires": { - "safe-buffer": "5.1.1" + "safe-buffer": "~5.1.0" } } } @@ -4814,9 +7436,9 @@ "dev": true, "requires": { "debug": "2.6.9", - "methods": "1.1.2", - "parseurl": "1.3.2", - "vary": "1.1.2" + "methods": "~1.1.2", + "parseurl": "~1.3.2", + "vary": "~1.1.2" }, "dependencies": { "vary": { @@ -4839,19 +7461,19 @@ "integrity": "sha1-cIWbyVyYQJUvNZoGij/En57PrCM=", "dev": true, "requires": { - "arr-diff": "4.0.0", - "array-unique": "0.3.2", - "braces": "2.3.1", - "define-property": "2.0.2", - "extend-shallow": "3.0.2", - "extglob": "2.0.4", - "fragment-cache": "0.2.1", - "kind-of": "6.0.2", - "nanomatch": "1.2.9", - "object.pick": "1.3.0", - "regex-not": "1.0.2", - "snapdragon": "0.8.2", - "to-regex": "3.0.2" + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "braces": "^2.3.1", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "extglob": "^2.0.4", + "fragment-cache": "^0.2.1", + "kind-of": "^6.0.2", + "nanomatch": "^1.2.9", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.2" } }, "mime": { @@ -4872,7 +7494,7 @@ "integrity": "sha1-bzI/YKg9ERRvgx/xH9ZuL+VQO7g=", "dev": true, "requires": { - "mime-db": "1.33.0" + "mime-db": "~1.33.0" } }, "minimatch": { @@ -4881,7 +7503,7 @@ "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", "dev": true, "requires": { - "brace-expansion": "1.1.11" + "brace-expansion": "^1.1.7" } }, "minimist": { @@ -4896,8 +7518,8 @@ "integrity": "sha1-pJ5yaNzhoNlpjkUybFYm3zVD0P4=", "dev": true, "requires": { - "for-in": "1.0.2", - "is-extendable": "1.0.1" + "for-in": "^1.0.2", + "is-extendable": "^1.0.1" }, "dependencies": { "is-extendable": { @@ -4906,7 +7528,7 @@ "integrity": "sha1-p0cPnkJnM9gb2B4RVSZOOjUHyrQ=", "dev": true, "requires": { - "is-plain-object": "2.0.4" + "is-plain-object": "^2.0.4" } } } @@ -4926,11 +7548,11 @@ "integrity": "sha1-X9gYOYxoGcuiinzWZk8pL+HAu/I=", "dev": true, "requires": { - "basic-auth": "1.0.4", - "debug": "2.2.0", - "depd": "1.0.1", - "on-finished": "2.3.0", - "on-headers": "1.0.1" + "basic-auth": "~1.0.3", + "debug": "~2.2.0", + "depd": "~1.0.1", + "on-finished": "~2.3.0", + "on-headers": "~1.0.0" }, "dependencies": { "debug": { @@ -4962,8 +7584,8 @@ "integrity": "sha1-Nd5oBNwZZD5SSfPT473GyM4wHT8=", "dev": true, "requires": { - "readable-stream": "1.1.14", - "stream-counter": "0.2.0" + "readable-stream": "~1.1.9", + "stream-counter": "~0.2.0" } }, "multipipe": { @@ -4975,24 +7597,31 @@ "duplexer2": "0.0.2" } }, + "nan": { + "version": "2.10.0", + "resolved": "https://registry.npmjs.org/nan/-/nan-2.10.0.tgz", + "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==", + "dev": true, + "optional": true + }, "nanomatch": { "version": "1.2.9", "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.9.tgz", "integrity": "sha1-h59xUMstq3pHElkGbBBO7m4Pp8I=", "dev": true, "requires": { - "arr-diff": "4.0.0", - "array-unique": "0.3.2", - "define-property": "2.0.2", - "extend-shallow": "3.0.2", - "fragment-cache": "0.2.1", - "is-odd": "2.0.0", - "is-windows": "1.0.2", - "kind-of": "6.0.2", - "object.pick": "1.3.0", - "regex-not": "1.0.2", - "snapdragon": "0.8.2", - "to-regex": "3.0.2" + "arr-diff": "^4.0.0", + "array-unique": "^0.3.2", + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "fragment-cache": "^0.2.1", + "is-odd": "^2.0.0", + "is-windows": "^1.0.2", + "kind-of": "^6.0.2", + "object.pick": "^1.3.0", + "regex-not": "^1.0.0", + "snapdragon": "^0.8.1", + "to-regex": "^3.0.1" } }, "natives": { @@ -5013,13 +7642,19 @@ "integrity": "sha1-MjI8zLRsn78PwRgS1FAhzDHTJbs=", "dev": true }, + "node-status-codes": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/node-status-codes/-/node-status-codes-1.0.0.tgz", + "integrity": "sha1-WuVUHQJGRdMqWPzdyc7s6nrjrC8=", + "dev": true + }, "node.extend": { "version": "1.1.6", "resolved": "https://registry.npmjs.org/node.extend/-/node.extend-1.1.6.tgz", "integrity": "sha1-p7iCyC1sk6SGOlUEvV3o7IYli5Y=", "dev": true, "requires": { - "is": "3.2.1" + "is": "^3.1.0" } }, "nopt": { @@ -5028,7 +7663,7 @@ "integrity": "sha1-xkZdvwirzU2zWTF/eaxopkayj/k=", "dev": true, "requires": { - "abbrev": "1.1.1" + "abbrev": "1" } }, "normalize-package-data": { @@ -5037,10 +7672,10 @@ "integrity": "sha1-EvlaMH1YNSB1oEkHuErIvpisAS8=", "dev": true, "requires": { - "hosted-git-info": "2.6.0", - "is-builtin-module": "1.0.0", - "semver": "4.3.6", - "validate-npm-package-license": "3.0.3" + "hosted-git-info": "^2.1.4", + "is-builtin-module": "^1.0.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" } }, "normalize-path": { @@ -5049,7 +7684,7 @@ "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk=", "dev": true, "requires": { - "remove-trailing-separator": "1.1.0" + "remove-trailing-separator": "^1.0.1" } }, "normalize-range": { @@ -5064,10 +7699,30 @@ "integrity": "sha1-LMDWazHqIwNkWENuNiDYWVTGbDw=", "dev": true, "requires": { - "object-assign": "4.1.1", - "prepend-http": "1.0.4", - "query-string": "4.3.4", - "sort-keys": "1.1.2" + "object-assign": "^4.0.1", + "prepend-http": "^1.0.0", + "query-string": "^4.1.0", + "sort-keys": "^1.0.0" + } + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "dev": true, + "optional": true, + "requires": { + "path-key": "^2.0.0" + } + }, + "nth-check": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.1.tgz", + "integrity": "sha1-mSms32KPwsQQmN6rgqxYDPFJquQ=", + "dev": true, + "optional": true, + "requires": { + "boolbase": "~1.0.0" } }, "num2fraction": { @@ -5106,9 +7761,9 @@ "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw=", "dev": true, "requires": { - "copy-descriptor": "0.1.1", - "define-property": "0.2.5", - "kind-of": "3.2.2" + "copy-descriptor": "^0.1.0", + "define-property": "^0.2.5", + "kind-of": "^3.0.3" }, "dependencies": { "define-property": { @@ -5117,7 +7772,7 @@ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "0.1.6" + "is-descriptor": "^0.1.0" } }, "is-accessor-descriptor": { @@ -5126,7 +7781,7 @@ "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", "dev": true, "requires": { - "kind-of": "3.2.2" + "kind-of": "^3.0.2" } }, "is-data-descriptor": { @@ -5135,7 +7790,7 @@ "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", "dev": true, "requires": { - "kind-of": "3.2.2" + "kind-of": "^3.0.2" } }, "is-descriptor": { @@ -5144,9 +7799,9 @@ "integrity": "sha1-Nm2CQN3kh8pRgjsaufB6EKeCUco=", "dev": true, "requires": { - "is-accessor-descriptor": "0.1.6", - "is-data-descriptor": "0.1.4", - "kind-of": "5.1.0" + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" }, "dependencies": { "kind-of": { @@ -5163,18 +7818,24 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "^1.1.5" } } } }, + "object-keys": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.0.11.tgz", + "integrity": "sha1-xUYBd4rVYPEULODgG8yotW0TQm0=", + "dev": true + }, "object-visit": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz", "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs=", "dev": true, "requires": { - "isobject": "3.0.1" + "isobject": "^3.0.0" } }, "object.defaults": { @@ -5183,10 +7844,21 @@ "integrity": "sha1-On+GgzS0B96gbaFtiNXNKeQ1/s8=", "dev": true, "requires": { - "array-each": "1.0.1", - "array-slice": "1.1.0", - "for-own": "1.0.0", - "isobject": "3.0.1" + "array-each": "^1.0.1", + "array-slice": "^1.0.0", + "for-own": "^1.0.0", + "isobject": "^3.0.0" + } + }, + "object.getownpropertydescriptors": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.0.3.tgz", + "integrity": "sha1-h1jIRvW0B62rDyNuCYbxSwUcqhY=", + "dev": true, + "optional": true, + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.5.1" } }, "object.map": { @@ -5195,8 +7867,8 @@ "integrity": "sha1-z4Plncj8wK1fQlDh94s7gb2AHTc=", "dev": true, "requires": { - "for-own": "1.0.0", - "make-iterator": "1.0.0" + "for-own": "^1.0.0", + "make-iterator": "^1.0.0" } }, "object.omit": { @@ -5205,8 +7877,8 @@ "integrity": "sha1-Gpx0SCnznbuFjHbKNXmuKlTr0fo=", "dev": true, "requires": { - "for-own": "0.1.5", - "is-extendable": "0.1.1" + "for-own": "^0.1.4", + "is-extendable": "^0.1.1" }, "dependencies": { "for-own": { @@ -5215,7 +7887,7 @@ "integrity": "sha1-UmXGgaTylNq78XyVCbZ2OqhFEM4=", "dev": true, "requires": { - "for-in": "1.0.2" + "for-in": "^1.0.1" } } } @@ -5226,7 +7898,20 @@ "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c=", "dev": true, "requires": { - "isobject": "3.0.1" + "isobject": "^3.0.1" + } + }, + "object.values": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.0.4.tgz", + "integrity": "sha1-5STaCbT2b/Bd9FdUbscqyZ8TBpo=", + "dev": true, + "optional": true, + "requires": { + "define-properties": "^1.1.2", + "es-abstract": "^1.6.1", + "function-bind": "^1.1.0", + "has": "^1.0.1" } }, "on-finished": { @@ -5250,9 +7935,15 @@ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", "dev": true, "requires": { - "wrappy": "1.0.2" + "wrappy": "1" } }, + "onetime": { + "version": "1.1.0", + "resolved": "http://registry.npmjs.org/onetime/-/onetime-1.1.0.tgz", + "integrity": "sha1-ofeDj4MUxRbwXs78vEzP4EtO14k=", + "dev": true + }, "open": { "version": "0.0.5", "resolved": "https://registry.npmjs.org/open/-/open-0.0.5.tgz", @@ -5265,8 +7956,8 @@ "integrity": "sha1-2j6nRob6IaGaERwybpDrFaAZZoY=", "dev": true, "requires": { - "minimist": "0.0.8", - "wordwrap": "0.0.2" + "minimist": "~0.0.1", + "wordwrap": "~0.0.2" } }, "optionator": { @@ -5275,12 +7966,12 @@ "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", "dev": true, "requires": { - "deep-is": "0.1.3", - "fast-levenshtein": "2.0.6", - "levn": "0.3.0", - "prelude-ls": "1.1.2", - "type-check": "0.3.2", - "wordwrap": "1.0.0" + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.4", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "wordwrap": "~1.0.0" }, "dependencies": { "wordwrap": { @@ -5297,15 +7988,27 @@ "integrity": "sha1-7CLTEoBrtT5zF3Pnza788cZDEo8=", "dev": true }, + "optipng-bin": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/optipng-bin/-/optipng-bin-3.1.4.tgz", + "integrity": "sha1-ldNPLEiHBPb9cGBr/qDGWfHZXYQ=", + "dev": true, + "optional": true, + "requires": { + "bin-build": "^2.0.0", + "bin-wrapper": "^3.0.0", + "logalot": "^2.0.0" + } + }, "orchestrator": { "version": "0.3.8", "resolved": "https://registry.npmjs.org/orchestrator/-/orchestrator-0.3.8.tgz", "integrity": "sha1-FOfp4nZPcxX7rBhOUGx6pt+UrX4=", "dev": true, "requires": { - "end-of-stream": "0.1.5", - "sequencify": "0.0.7", - "stream-consume": "0.1.1" + "end-of-stream": "~0.1.5", + "sequencify": "~0.0.7", + "stream-consume": "~0.1.0" } }, "ordered-read-streams": { @@ -5314,6 +8017,13 @@ "integrity": "sha1-/VZamvjrRHO6abbtijQ1LLVS8SY=", "dev": true }, + "os-filter-obj": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/os-filter-obj/-/os-filter-obj-1.0.3.tgz", + "integrity": "sha1-WRUzDZDs7VV9LZOKMcbdIU2cY60=", + "dev": true, + "optional": true + }, "os-homedir": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", @@ -5326,15 +8036,27 @@ "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=", "dev": true }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=", + "dev": true + }, + "p-pipe": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/p-pipe/-/p-pipe-1.2.0.tgz", + "integrity": "sha1-SxoROZoRUgpneQ7loMHViB1r7+k=", + "dev": true + }, "parse-filepath": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/parse-filepath/-/parse-filepath-1.0.2.tgz", "integrity": "sha1-pjISf1Oq89FYdvWHLz/6x2PWyJE=", "dev": true, "requires": { - "is-absolute": "1.0.0", - "map-cache": "0.2.2", - "path-root": "0.1.1" + "is-absolute": "^1.0.0", + "map-cache": "^0.2.0", + "path-root": "^0.1.1" } }, "parse-glob": { @@ -5343,10 +8065,10 @@ "integrity": "sha1-ssN2z7EfNVE7rdFz7wu246OIORw=", "dev": true, "requires": { - "glob-base": "0.3.0", - "is-dotfile": "1.0.3", - "is-extglob": "1.0.0", - "is-glob": "2.0.1" + "glob-base": "^0.3.0", + "is-dotfile": "^1.0.0", + "is-extglob": "^1.0.0", + "is-glob": "^2.0.0" }, "dependencies": { "is-extglob": { @@ -5361,7 +8083,7 @@ "integrity": "sha1-0Jb5JqPe1WAPP9/ZEZjLCIjC2GM=", "dev": true, "requires": { - "is-extglob": "1.0.0" + "is-extglob": "^1.0.0" } } } @@ -5372,7 +8094,7 @@ "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", "dev": true, "requires": { - "error-ex": "1.3.1" + "error-ex": "^1.2.0" } }, "parse-passwd": { @@ -5387,7 +8109,7 @@ "integrity": "sha1-q343WfIJ7OmUN5c/fQ8fZK4OZKs=", "dev": true, "requires": { - "better-assert": "1.0.2" + "better-assert": "~1.0.0" } }, "parseqs": { @@ -5396,7 +8118,7 @@ "integrity": "sha1-1SCKNzjkZ2bikbouoXNoSSGouJ0=", "dev": true, "requires": { - "better-assert": "1.0.2" + "better-assert": "~1.0.0" } }, "parseuri": { @@ -5405,7 +8127,7 @@ "integrity": "sha1-gCBKUNTbt3m/3G6+J3jZDkvOMgo=", "dev": true, "requires": { - "better-assert": "1.0.2" + "better-assert": "~1.0.0" } }, "parseurl": { @@ -5438,7 +8160,7 @@ "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", "dev": true, "requires": { - "pinkie-promise": "2.0.1" + "pinkie-promise": "^2.0.0" } }, "path-is-absolute": { @@ -5447,6 +8169,13 @@ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=", "dev": true }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=", + "dev": true, + "optional": true + }, "path-parse": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.5.tgz", @@ -5459,7 +8188,7 @@ "integrity": "sha1-mkpoFMrBwM1zNgqV8yCDyOpHRbc=", "dev": true, "requires": { - "path-root-regex": "0.1.2" + "path-root-regex": "^0.1.0" } }, "path-root-regex": { @@ -5474,9 +8203,9 @@ "integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=", "dev": true, "requires": { - "graceful-fs": "4.1.11", - "pify": "2.3.0", - "pinkie-promise": "2.0.1" + "graceful-fs": "^4.1.2", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" }, "dependencies": { "graceful-fs": { @@ -5499,7 +8228,7 @@ "integrity": "sha1-/lo0sMvOErWqaitAPuLnO2AvFEU=", "dev": true, "requires": { - "through": "2.3.8" + "through": "~2.3" } }, "pend": { @@ -5520,15 +8249,15 @@ "integrity": "sha1-79ISpKOWbTZHaE6ouniFSb4q7+8=", "dev": true, "requires": { - "es6-promise": "4.2.4", - "extract-zip": "1.6.6", - "fs-extra": "1.0.0", - "hasha": "2.2.0", - "kew": "0.7.0", - "progress": "1.1.8", - "request": "2.81.0", - "request-progress": "2.0.1", - "which": "1.3.0" + "es6-promise": "^4.0.3", + "extract-zip": "^1.6.5", + "fs-extra": "^1.0.0", + "hasha": "^2.2.0", + "kew": "^0.7.0", + "progress": "^1.1.8", + "request": "^2.81.0", + "request-progress": "^2.0.1", + "which": "^1.2.10" }, "dependencies": { "es6-promise": { @@ -5557,7 +8286,7 @@ "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", "dev": true, "requires": { - "pinkie": "2.0.4" + "pinkie": "^2.0.0" } }, "plugin-error": { @@ -5566,11 +8295,11 @@ "integrity": "sha1-O5uzM1zPAPQl4HQ34ZJ2ln2kes4=", "dev": true, "requires": { - "ansi-cyan": "0.1.1", - "ansi-red": "0.1.1", - "arr-diff": "1.1.0", - "arr-union": "2.1.0", - "extend-shallow": "1.1.4" + "ansi-cyan": "^0.1.1", + "ansi-red": "^0.1.1", + "arr-diff": "^1.0.1", + "arr-union": "^2.0.1", + "extend-shallow": "^1.1.2" }, "dependencies": { "arr-diff": { @@ -5579,8 +8308,8 @@ "integrity": "sha1-aHwydYFjWI/vfeezb6vklesaOZo=", "dev": true, "requires": { - "arr-flatten": "1.1.0", - "array-slice": "0.2.3" + "arr-flatten": "^1.0.1", + "array-slice": "^0.2.3" } }, "arr-union": { @@ -5601,7 +8330,7 @@ "integrity": "sha1-Gda/lN/AnXa6cR85uHLSH/TdkHE=", "dev": true, "requires": { - "kind-of": "1.1.0" + "kind-of": "^1.1.0" } }, "kind-of": { @@ -5618,8 +8347,8 @@ "integrity": "sha1-hgSc9qsQgzOYqTHzaJy67nteEzM=", "dev": true, "requires": { - "chalk": "1.1.3", - "dateformat": "1.0.12" + "chalk": "^1.1.1", + "dateformat": "^1.0.11" }, "dependencies": { "dateformat": { @@ -5628,12 +8357,21 @@ "integrity": "sha1-nxJLZ1lMk3/3BpMuSmQsyo27/uk=", "dev": true, "requires": { - "get-stdin": "4.0.1", - "meow": "3.7.0" + "get-stdin": "^4.0.1", + "meow": "^3.3.0" } } } }, + "plur": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/plur/-/plur-2.1.2.tgz", + "integrity": "sha1-dIJFLBoPUI4+NE6uwxLJHCncZVo=", + "dev": true, + "requires": { + "irregular-plurals": "^1.0.0" + } + }, "posix-character-classes": { "version": "0.1.1", "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz", @@ -5646,10 +8384,10 @@ "integrity": "sha1-ut+hSX1GJE9jkPWLMZgw2RB4U8U=", "dev": true, "requires": { - "chalk": "1.1.3", - "js-base64": "2.4.3", - "source-map": "0.5.7", - "supports-color": "3.2.3" + "chalk": "^1.1.3", + "js-base64": "^2.1.9", + "source-map": "^0.5.6", + "supports-color": "^3.2.3" } }, "postcss-calc": { @@ -5658,9 +8396,9 @@ "integrity": "sha1-d7rnypKK2FcW4v2kLyYb98HWW14=", "dev": true, "requires": { - "postcss": "5.2.18", - "postcss-message-helpers": "2.0.0", - "reduce-css-calc": "1.3.0" + "postcss": "^5.0.2", + "postcss-message-helpers": "^2.0.0", + "reduce-css-calc": "^1.2.6" } }, "postcss-colormin": { @@ -5669,9 +8407,9 @@ "integrity": "sha1-ZjFBfV8OkJo9fsJrJMio0eT5bks=", "dev": true, "requires": { - "colormin": "1.1.2", - "postcss": "5.2.18", - "postcss-value-parser": "3.3.0" + "colormin": "^1.0.5", + "postcss": "^5.0.13", + "postcss-value-parser": "^3.2.3" } }, "postcss-convert-values": { @@ -5680,8 +8418,8 @@ "integrity": "sha1-u9hZPFwf0uPRwyK7kl3K6Nrk1i0=", "dev": true, "requires": { - "postcss": "5.2.18", - "postcss-value-parser": "3.3.0" + "postcss": "^5.0.11", + "postcss-value-parser": "^3.1.2" } }, "postcss-discard-comments": { @@ -5690,7 +8428,7 @@ "integrity": "sha1-vv6J+v1bPazlzM5Rt2uBUUvgDj0=", "dev": true, "requires": { - "postcss": "5.2.18" + "postcss": "^5.0.14" } }, "postcss-discard-duplicates": { @@ -5699,7 +8437,7 @@ "integrity": "sha1-uavye4isGIFYpesSq8riAmO5GTI=", "dev": true, "requires": { - "postcss": "5.2.18" + "postcss": "^5.0.4" } }, "postcss-discard-empty": { @@ -5708,7 +8446,7 @@ "integrity": "sha1-0rS9nVztXr2Nyt52QMfXzX9PkrU=", "dev": true, "requires": { - "postcss": "5.2.18" + "postcss": "^5.0.14" } }, "postcss-discard-overridden": { @@ -5717,7 +8455,7 @@ "integrity": "sha1-ix6vVU9ob7KIzYdMVWZ7CqNmjVg=", "dev": true, "requires": { - "postcss": "5.2.18" + "postcss": "^5.0.16" } }, "postcss-discard-unused": { @@ -5726,8 +8464,8 @@ "integrity": "sha1-vOMLLMWR/8Y0Mitfs0ZLbZNPRDM=", "dev": true, "requires": { - "postcss": "5.2.18", - "uniqs": "2.0.0" + "postcss": "^5.0.14", + "uniqs": "^2.0.0" } }, "postcss-filter-plugins": { @@ -5736,8 +8474,8 @@ "integrity": "sha1-bYWGJTTXNaxCDkqFgG4fXUKG2Ew=", "dev": true, "requires": { - "postcss": "5.2.18", - "uniqid": "4.1.1" + "postcss": "^5.0.4", + "uniqid": "^4.0.0" } }, "postcss-load-config": { @@ -5746,10 +8484,10 @@ "integrity": "sha1-U56a/J3chiASHr+djDZz4M5Q0oo=", "dev": true, "requires": { - "cosmiconfig": "2.2.2", - "object-assign": "4.1.1", - "postcss-load-options": "1.2.0", - "postcss-load-plugins": "2.3.0" + "cosmiconfig": "^2.1.0", + "object-assign": "^4.1.0", + "postcss-load-options": "^1.2.0", + "postcss-load-plugins": "^2.3.0" } }, "postcss-load-options": { @@ -5758,8 +8496,8 @@ "integrity": "sha1-sJixVZ3awt8EvAuzdfmaXP4rbYw=", "dev": true, "requires": { - "cosmiconfig": "2.2.2", - "object-assign": "4.1.1" + "cosmiconfig": "^2.1.0", + "object-assign": "^4.1.0" } }, "postcss-load-plugins": { @@ -5768,8 +8506,8 @@ "integrity": "sha1-dFdoEWWZrKLwCfrUJrABdQSdjZI=", "dev": true, "requires": { - "cosmiconfig": "2.2.2", - "object-assign": "4.1.1" + "cosmiconfig": "^2.1.1", + "object-assign": "^4.1.0" } }, "postcss-merge-idents": { @@ -5778,9 +8516,9 @@ "integrity": "sha1-TFUwMTwI4dWzu/PSu8dH4njuonA=", "dev": true, "requires": { - "has": "1.0.1", - "postcss": "5.2.18", - "postcss-value-parser": "3.3.0" + "has": "^1.0.1", + "postcss": "^5.0.10", + "postcss-value-parser": "^3.1.1" } }, "postcss-merge-longhand": { @@ -5789,7 +8527,7 @@ "integrity": "sha1-I9kM0Sewp3mUkVMyc5A0oaTz1lg=", "dev": true, "requires": { - "postcss": "5.2.18" + "postcss": "^5.0.4" } }, "postcss-merge-rules": { @@ -5798,11 +8536,11 @@ "integrity": "sha1-0d9d+qexrMO+VT8OnhDofGG19yE=", "dev": true, "requires": { - "browserslist": "1.7.7", - "caniuse-api": "1.6.1", - "postcss": "5.2.18", - "postcss-selector-parser": "2.2.3", - "vendors": "1.0.1" + "browserslist": "^1.5.2", + "caniuse-api": "^1.5.2", + "postcss": "^5.0.4", + "postcss-selector-parser": "^2.2.2", + "vendors": "^1.0.0" } }, "postcss-message-helpers": { @@ -5817,9 +8555,9 @@ "integrity": "sha1-S1jttWZB66fIR0qzUmyv17vey2k=", "dev": true, "requires": { - "object-assign": "4.1.1", - "postcss": "5.2.18", - "postcss-value-parser": "3.3.0" + "object-assign": "^4.0.1", + "postcss": "^5.0.4", + "postcss-value-parser": "^3.0.2" } }, "postcss-minify-gradients": { @@ -5828,8 +8566,8 @@ "integrity": "sha1-Xb2hE3NwP4PPtKPqOIHY11/15uE=", "dev": true, "requires": { - "postcss": "5.2.18", - "postcss-value-parser": "3.3.0" + "postcss": "^5.0.12", + "postcss-value-parser": "^3.3.0" } }, "postcss-minify-params": { @@ -5838,10 +8576,10 @@ "integrity": "sha1-rSzgcTc7lDs9kwo/pZo1jCjW8fM=", "dev": true, "requires": { - "alphanum-sort": "1.0.2", - "postcss": "5.2.18", - "postcss-value-parser": "3.3.0", - "uniqs": "2.0.0" + "alphanum-sort": "^1.0.1", + "postcss": "^5.0.2", + "postcss-value-parser": "^3.0.2", + "uniqs": "^2.0.0" } }, "postcss-minify-selectors": { @@ -5850,10 +8588,10 @@ "integrity": "sha1-ssapjAByz5G5MtGkllCBFDEXNb8=", "dev": true, "requires": { - "alphanum-sort": "1.0.2", - "has": "1.0.1", - "postcss": "5.2.18", - "postcss-selector-parser": "2.2.3" + "alphanum-sort": "^1.0.2", + "has": "^1.0.1", + "postcss": "^5.0.14", + "postcss-selector-parser": "^2.0.0" } }, "postcss-normalize-charset": { @@ -5862,7 +8600,7 @@ "integrity": "sha1-757nEhLX/nWceO0WL2HtYrXLk/E=", "dev": true, "requires": { - "postcss": "5.2.18" + "postcss": "^5.0.5" } }, "postcss-normalize-url": { @@ -5871,10 +8609,10 @@ "integrity": "sha1-EI90s/L82viRov+j6kWSJ5/HgiI=", "dev": true, "requires": { - "is-absolute-url": "2.1.0", - "normalize-url": "1.9.1", - "postcss": "5.2.18", - "postcss-value-parser": "3.3.0" + "is-absolute-url": "^2.0.0", + "normalize-url": "^1.4.0", + "postcss": "^5.0.14", + "postcss-value-parser": "^3.2.3" } }, "postcss-ordered-values": { @@ -5883,8 +8621,8 @@ "integrity": "sha1-7sbCpntsQSqNsgQud/6NpD+VwR0=", "dev": true, "requires": { - "postcss": "5.2.18", - "postcss-value-parser": "3.3.0" + "postcss": "^5.0.4", + "postcss-value-parser": "^3.0.1" } }, "postcss-reduce-idents": { @@ -5893,8 +8631,8 @@ "integrity": "sha1-wsbSDMlYKE9qv75j92Cb9AkFmtM=", "dev": true, "requires": { - "postcss": "5.2.18", - "postcss-value-parser": "3.3.0" + "postcss": "^5.0.4", + "postcss-value-parser": "^3.0.2" } }, "postcss-reduce-initial": { @@ -5903,7 +8641,7 @@ "integrity": "sha1-aPgGlfBF0IJjqHmtJA343WT2ROo=", "dev": true, "requires": { - "postcss": "5.2.18" + "postcss": "^5.0.4" } }, "postcss-reduce-transforms": { @@ -5912,9 +8650,9 @@ "integrity": "sha1-/3b02CEkN7McKYpC0uFEQCV3GuE=", "dev": true, "requires": { - "has": "1.0.1", - "postcss": "5.2.18", - "postcss-value-parser": "3.3.0" + "has": "^1.0.1", + "postcss": "^5.0.8", + "postcss-value-parser": "^3.0.1" } }, "postcss-selector-parser": { @@ -5923,9 +8661,9 @@ "integrity": "sha1-+UN3iGBsPJrO4W/+jYsWKX8nu5A=", "dev": true, "requires": { - "flatten": "1.0.2", - "indexes-of": "1.0.1", - "uniq": "1.0.1" + "flatten": "^1.0.2", + "indexes-of": "^1.0.1", + "uniq": "^1.0.1" } }, "postcss-svgo": { @@ -5934,10 +8672,10 @@ "integrity": "sha1-tt8YqmE7Zm4TPwittSGcJoSsEI0=", "dev": true, "requires": { - "is-svg": "2.1.0", - "postcss": "5.2.18", - "postcss-value-parser": "3.3.0", - "svgo": "0.7.2" + "is-svg": "^2.0.0", + "postcss": "^5.0.14", + "postcss-value-parser": "^3.2.3", + "svgo": "^0.7.0" } }, "postcss-unique-selectors": { @@ -5946,9 +8684,9 @@ "integrity": "sha1-mB1X0p3csz57Hf4f1DuGSfkzyh0=", "dev": true, "requires": { - "alphanum-sort": "1.0.2", - "postcss": "5.2.18", - "uniqs": "2.0.0" + "alphanum-sort": "^1.0.1", + "postcss": "^5.0.4", + "uniqs": "^2.0.0" } }, "postcss-value-parser": { @@ -5963,9 +8701,9 @@ "integrity": "sha1-0hCd3AVbka9n/EyzsCWUZjnSryI=", "dev": true, "requires": { - "has": "1.0.1", - "postcss": "5.2.18", - "uniqs": "2.0.0" + "has": "^1.0.1", + "postcss": "^5.0.4", + "uniqs": "^2.0.0" } }, "prelude-ls": { @@ -5986,6 +8724,12 @@ "integrity": "sha1-gV7R9uvGWSb4ZbMQwHE7yzMVzks=", "dev": true }, + "pretty-bytes": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-4.0.2.tgz", + "integrity": "sha1-sr+C5zUNZcbDOqlaqlpPYyf2HNk=", + "dev": true + }, "pretty-hrtime": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz", @@ -6011,7 +8755,7 @@ "dev": true, "optional": true, "requires": { - "asap": "2.0.6" + "asap": "~2.0.3" } }, "prr": { @@ -6057,8 +8801,8 @@ "integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s=", "dev": true, "requires": { - "object-assign": "4.1.1", - "strict-uri-encode": "1.1.0" + "object-assign": "^4.1.0", + "strict-uri-encode": "^1.0.0" } }, "random-bytes": { @@ -6073,8 +8817,8 @@ "integrity": "sha1-x6vpzIuHwLqodrGf3oP9RkeX44w=", "dev": true, "requires": { - "is-number": "3.0.0", - "kind-of": "4.0.0" + "is-number": "^3.0.0", + "kind-of": "^4.0.0" }, "dependencies": { "kind-of": { @@ -6083,7 +8827,7 @@ "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "^1.1.5" } } } @@ -6119,15 +8863,77 @@ } } }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "dev": true, + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "read-all-stream": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/read-all-stream/-/read-all-stream-3.1.0.tgz", + "integrity": "sha1-NcPhd/IHjveJ7kv6+kNzB06u9Po=", + "dev": true, + "requires": { + "pinkie-promise": "^2.0.0", + "readable-stream": "^2.0.0" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, "read-pkg": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz", "integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=", "dev": true, "requires": { - "load-json-file": "1.1.0", - "normalize-package-data": "2.4.0", - "path-type": "1.1.0" + "load-json-file": "^1.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^1.0.0" } }, "read-pkg-up": { @@ -6136,8 +8942,8 @@ "integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", "dev": true, "requires": { - "find-up": "1.1.2", - "read-pkg": "1.1.0" + "find-up": "^1.0.0", + "read-pkg": "^1.0.0" } }, "readable-stream": { @@ -6146,10 +8952,10 @@ "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", "isarray": "0.0.1", - "string_decoder": "0.10.31" + "string_decoder": "~0.10.x" } }, "readdirp": { @@ -6158,10 +8964,10 @@ "integrity": "sha1-TtCtBg3zBzMAxIRANz9y0cxkLXg=", "dev": true, "requires": { - "graceful-fs": "4.1.11", - "minimatch": "3.0.4", - "readable-stream": "2.3.5", - "set-immediate-shim": "1.0.1" + "graceful-fs": "^4.1.2", + "minimatch": "^3.0.2", + "readable-stream": "^2.0.2", + "set-immediate-shim": "^1.0.1" }, "dependencies": { "graceful-fs": { @@ -6182,13 +8988,13 @@ "integrity": "sha1-tPhQA6k4y7bsvOKhJPsQEr0ag40=", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "2.0.0", - "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.0.3", + "util-deprecate": "~1.0.1" } }, "string_decoder": { @@ -6197,7 +9003,7 @@ "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", "dev": true, "requires": { - "safe-buffer": "5.1.1" + "safe-buffer": "~5.1.0" } } } @@ -6208,7 +9014,7 @@ "integrity": "sha1-hSBLVNuoLVdC4oyWdW70OvUOM4Q=", "dev": true, "requires": { - "resolve": "1.6.0" + "resolve": "^1.1.6" } }, "redent": { @@ -6217,8 +9023,8 @@ "integrity": "sha1-z5Fqsf1fHxbfsggi3W7H9zDCr94=", "dev": true, "requires": { - "indent-string": "2.1.0", - "strip-indent": "1.0.1" + "indent-string": "^2.1.0", + "strip-indent": "^1.0.1" } }, "reduce-css-calc": { @@ -6227,9 +9033,9 @@ "integrity": "sha1-dHyRTgSWFKTJz7umKYca0dKSdxY=", "dev": true, "requires": { - "balanced-match": "0.4.2", - "math-expression-evaluator": "1.2.17", - "reduce-function-call": "1.0.2" + "balanced-match": "^0.4.2", + "math-expression-evaluator": "^1.2.14", + "reduce-function-call": "^1.0.1" }, "dependencies": { "balanced-match": { @@ -6246,7 +9052,7 @@ "integrity": "sha1-WiAL+S4ON3UXUv5FsKszD9S2vpk=", "dev": true, "requires": { - "balanced-match": "0.4.2" + "balanced-match": "^0.4.2" }, "dependencies": { "balanced-match": { @@ -6263,7 +9069,7 @@ "integrity": "sha1-db3FiioUls7EihKDW8VMjVYjNt0=", "dev": true, "requires": { - "is-equal-shallow": "0.1.3" + "is-equal-shallow": "^0.1.3" } }, "regex-not": { @@ -6272,8 +9078,8 @@ "integrity": "sha1-H07OJ+ALC2XgJHpoEOaoXYOldSw=", "dev": true, "requires": { - "extend-shallow": "3.0.2", - "safe-regex": "1.1.0" + "extend-shallow": "^3.0.2", + "safe-regex": "^1.1.0" } }, "remove-trailing-separator": { @@ -6300,7 +9106,7 @@ "integrity": "sha1-UhTFOpJtNVJwdSf7q0FdvAjQbdo=", "dev": true, "requires": { - "is-finite": "1.0.2" + "is-finite": "^1.0.0" } }, "replace-ext": { @@ -6315,28 +9121,28 @@ "integrity": "sha1-xpKJRqDgbF+Nb4qTM0af/aRimKA=", "dev": true, "requires": { - "aws-sign2": "0.6.0", - "aws4": "1.6.0", - "caseless": "0.12.0", - "combined-stream": "1.0.6", - "extend": "3.0.1", - "forever-agent": "0.6.1", - "form-data": "2.1.4", - "har-validator": "4.2.1", - "hawk": "3.1.3", - "http-signature": "1.1.1", - "is-typedarray": "1.0.0", - "isstream": "0.1.2", - "json-stringify-safe": "5.0.1", - "mime-types": "2.1.18", - "oauth-sign": "0.8.2", - "performance-now": "0.2.0", - "qs": "6.4.0", - "safe-buffer": "5.1.1", - "stringstream": "0.0.5", - "tough-cookie": "2.3.4", - "tunnel-agent": "0.6.0", - "uuid": "3.2.1" + "aws-sign2": "~0.6.0", + "aws4": "^1.2.1", + "caseless": "~0.12.0", + "combined-stream": "~1.0.5", + "extend": "~3.0.0", + "forever-agent": "~0.6.1", + "form-data": "~2.1.1", + "har-validator": "~4.2.1", + "hawk": "~3.1.3", + "http-signature": "~1.1.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.7", + "oauth-sign": "~0.8.1", + "performance-now": "^0.2.0", + "qs": "~6.4.0", + "safe-buffer": "^5.0.1", + "stringstream": "~0.0.4", + "tough-cookie": "~2.3.0", + "tunnel-agent": "^0.6.0", + "uuid": "^3.0.0" }, "dependencies": { "qs": { @@ -6353,7 +9159,7 @@ "integrity": "sha1-XTa7V5YcZzqlt4jbyBQf3yO0Tgg=", "dev": true, "requires": { - "throttleit": "1.0.0" + "throttleit": "^1.0.0" } }, "require-from-string": { @@ -6374,7 +9180,7 @@ "integrity": "sha1-D70hJ4sntABEgcOVNJ56umCp/1w=", "dev": true, "requires": { - "path-parse": "1.0.5" + "path-parse": "^1.0.5" } }, "resolve-dir": { @@ -6383,8 +9189,8 @@ "integrity": "sha1-eaQGRMNivoLybv/nOcm7U4IEb0M=", "dev": true, "requires": { - "expand-tilde": "2.0.2", - "global-modules": "1.0.0" + "expand-tilde": "^2.0.0", + "global-modules": "^1.0.0" } }, "resolve-url": { @@ -6399,8 +9205,8 @@ "integrity": "sha1-/6cbq5UtYvfB1Jt0NDVfvGjf/Fo=", "dev": true, "requires": { - "depd": "1.1.2", - "on-headers": "1.0.1" + "depd": "~1.1.0", + "on-headers": "~1.0.1" }, "dependencies": { "depd": { @@ -6423,7 +9229,7 @@ "integrity": "sha1-YTObci/mo1FWiSENJOFMlhSGE+8=", "dev": true, "requires": { - "align-text": "0.1.4" + "align-text": "^0.1.1" } }, "rimraf": { @@ -6432,7 +9238,7 @@ "integrity": "sha1-LtgVDSShbqhlHm1u8PR8QVjOejY=", "dev": true, "requires": { - "glob": "7.1.2" + "glob": "^7.0.5" } }, "rndm": { @@ -6447,9 +9253,9 @@ "integrity": "sha1-HOZD2jb9jH6n4akynaM/wriJhJU=", "dev": true, "requires": { - "chalk": "1.1.3", - "fancy-log": "1.3.2", - "plugin-error": "0.1.2" + "chalk": "^1.1.3", + "fancy-log": "^1.3.2", + "plugin-error": "^0.1.2" } }, "safe-buffer": { @@ -6464,7 +9270,7 @@ "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4=", "dev": true, "requires": { - "ret": "0.1.15" + "ret": "~0.1.10" } }, "sax": { @@ -6473,30 +9279,65 @@ "integrity": "sha1-KBYjTiN4vdxOU1T6tcqold9xANk=", "dev": true }, + "seek-bzip": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/seek-bzip/-/seek-bzip-1.0.5.tgz", + "integrity": "sha1-z+kXyz0nS8/6x5J1ivUxc+sfq9w=", + "dev": true, + "requires": { + "commander": "~2.8.1" + } + }, "semver": { "version": "4.3.6", "resolved": "https://registry.npmjs.org/semver/-/semver-4.3.6.tgz", "integrity": "sha1-MAvG4OhjdPe6YQaLWx7NV/xlMto=", "dev": true }, + "semver-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/semver-regex/-/semver-regex-1.0.0.tgz", + "integrity": "sha1-kqSWkGX5xwxpR1PVUkj8aPj2Usk=", + "dev": true, + "optional": true + }, + "semver-truncate": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/semver-truncate/-/semver-truncate-1.1.2.tgz", + "integrity": "sha1-V/Qd5pcHpicJp+AQS6IRcQnqR+g=", + "dev": true, + "optional": true, + "requires": { + "semver": "^5.3.0" + }, + "dependencies": { + "semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-4SJ3dm0WAwWy/NVeioZh5AntkdJoWKxHxcmyP622fOkgHa4z3R0TdBJICINyaSDE6uNwVc8gZr+ZinwZAH4xIA==", + "dev": true, + "optional": true + } + } + }, "send": { "version": "0.13.2", "resolved": "https://registry.npmjs.org/send/-/send-0.13.2.tgz", "integrity": "sha1-dl52B8gFVFK7pvCwUllTUJhgNt4=", "dev": true, "requires": { - "debug": "2.2.0", - "depd": "1.1.2", - "destroy": "1.0.4", - "escape-html": "1.0.3", - "etag": "1.7.0", + "debug": "~2.2.0", + "depd": "~1.1.0", + "destroy": "~1.0.4", + "escape-html": "~1.0.3", + "etag": "~1.7.0", "fresh": "0.3.0", - "http-errors": "1.3.1", + "http-errors": "~1.3.1", "mime": "1.3.4", "ms": "0.7.1", - "on-finished": "2.3.0", - "range-parser": "1.0.3", - "statuses": "1.2.1" + "on-finished": "~2.3.0", + "range-parser": "~1.0.3", + "statuses": "~1.2.1" }, "dependencies": { "debug": { @@ -6540,10 +9381,10 @@ "integrity": "sha1-3UGeJo3gEqtysxnTN/IQUBP5OB8=", "dev": true, "requires": { - "etag": "1.7.0", + "etag": "~1.7.0", "fresh": "0.3.0", "ms": "0.7.2", - "parseurl": "1.3.2" + "parseurl": "~1.3.1" }, "dependencies": { "ms": { @@ -6560,13 +9401,13 @@ "integrity": "sha1-egV/xu4o3GP2RWbl+lexEahq7NI=", "dev": true, "requires": { - "accepts": "1.2.13", + "accepts": "~1.2.13", "batch": "0.5.3", - "debug": "2.2.0", - "escape-html": "1.0.3", - "http-errors": "1.3.1", - "mime-types": "2.1.18", - "parseurl": "1.3.2" + "debug": "~2.2.0", + "escape-html": "~1.0.3", + "http-errors": "~1.3.1", + "mime-types": "~2.1.9", + "parseurl": "~1.3.1" }, "dependencies": { "debug": { @@ -6592,8 +9433,8 @@ "integrity": "sha1-zlpuzTEB/tXsCYJ9rCKpwpv7BTU=", "dev": true, "requires": { - "escape-html": "1.0.3", - "parseurl": "1.3.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.1", "send": "0.13.2" } }, @@ -6609,10 +9450,10 @@ "integrity": "sha1-ca5KiPD+77v1LR6mBPP7MV67YnQ=", "dev": true, "requires": { - "extend-shallow": "2.0.1", - "is-extendable": "0.1.1", - "is-plain-object": "2.0.4", - "split-string": "3.1.0" + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.3", + "split-string": "^3.0.1" }, "dependencies": { "extend-shallow": { @@ -6621,7 +9462,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "0.1.1" + "is-extendable": "^0.1.0" } } } @@ -6632,6 +9473,23 @@ "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=", "dev": true }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "dev": true, + "optional": true, + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=", + "dev": true, + "optional": true + }, "sigmund": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", @@ -6656,14 +9514,14 @@ "integrity": "sha1-ZJIufFZbDhQgS6GqfWlkJ40lGC0=", "dev": true, "requires": { - "base": "0.11.2", - "debug": "2.6.9", - "define-property": "0.2.5", - "extend-shallow": "2.0.1", - "map-cache": "0.2.2", - "source-map": "0.5.7", - "source-map-resolve": "0.5.1", - "use": "3.1.0" + "base": "^0.11.1", + "debug": "^2.2.0", + "define-property": "^0.2.5", + "extend-shallow": "^2.0.1", + "map-cache": "^0.2.2", + "source-map": "^0.5.6", + "source-map-resolve": "^0.5.0", + "use": "^3.1.0" }, "dependencies": { "define-property": { @@ -6672,7 +9530,7 @@ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "0.1.6" + "is-descriptor": "^0.1.0" } }, "extend-shallow": { @@ -6681,7 +9539,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "0.1.1" + "is-extendable": "^0.1.0" } }, "is-accessor-descriptor": { @@ -6690,7 +9548,7 @@ "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", "dev": true, "requires": { - "kind-of": "3.2.2" + "kind-of": "^3.0.2" }, "dependencies": { "kind-of": { @@ -6699,7 +9557,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "^1.1.5" } } } @@ -6710,7 +9568,7 @@ "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", "dev": true, "requires": { - "kind-of": "3.2.2" + "kind-of": "^3.0.2" }, "dependencies": { "kind-of": { @@ -6719,7 +9577,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "^1.1.5" } } } @@ -6730,9 +9588,9 @@ "integrity": "sha1-Nm2CQN3kh8pRgjsaufB6EKeCUco=", "dev": true, "requires": { - "is-accessor-descriptor": "0.1.6", - "is-data-descriptor": "0.1.4", - "kind-of": "5.1.0" + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" } }, "kind-of": { @@ -6749,9 +9607,9 @@ "integrity": "sha1-bBdfhv8UvbByRWPo88GwIaKGhTs=", "dev": true, "requires": { - "define-property": "1.0.0", - "isobject": "3.0.1", - "snapdragon-util": "3.0.1" + "define-property": "^1.0.0", + "isobject": "^3.0.0", + "snapdragon-util": "^3.0.1" }, "dependencies": { "define-property": { @@ -6760,7 +9618,7 @@ "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY=", "dev": true, "requires": { - "is-descriptor": "1.0.2" + "is-descriptor": "^1.0.0" } } } @@ -6771,7 +9629,7 @@ "integrity": "sha1-+VZHlIbyrNeXAGk/b3uAXkWrVuI=", "dev": true, "requires": { - "kind-of": "3.2.2" + "kind-of": "^3.2.0" }, "dependencies": { "kind-of": { @@ -6780,7 +9638,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "^1.1.5" } } } @@ -6791,7 +9649,7 @@ "integrity": "sha1-ZUEYTMkK7qbG57NeJlkIJEPGYZg=", "dev": true, "requires": { - "hoek": "2.16.3" + "hoek": "2.x.x" } }, "socket.io": { @@ -6936,7 +9794,7 @@ "integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0=", "dev": true, "requires": { - "is-plain-obj": "1.1.0" + "is-plain-obj": "^1.0.0" } }, "source-map": { @@ -6951,11 +9809,11 @@ "integrity": "sha1-etD1k/IoFZjoVN+A8ZquS5LXoRo=", "dev": true, "requires": { - "atob": "2.1.0", - "decode-uri-component": "0.2.0", - "resolve-url": "0.2.1", - "source-map-url": "0.4.0", - "urix": "0.1.0" + "atob": "^2.0.0", + "decode-uri-component": "^0.2.0", + "resolve-url": "^0.2.1", + "source-map-url": "^0.4.0", + "urix": "^0.1.0" } }, "source-map-url": { @@ -6976,8 +9834,8 @@ "integrity": "sha1-BaW01xU6GVvJLDxCW2nzsqlSTII=", "dev": true, "requires": { - "spdx-expression-parse": "3.0.0", - "spdx-license-ids": "3.0.0" + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" } }, "spdx-exceptions": { @@ -6992,8 +9850,8 @@ "integrity": "sha1-meEZt6XaAOBUkcn6M4t5BII7QdA=", "dev": true, "requires": { - "spdx-exceptions": "2.1.0", - "spdx-license-ids": "3.0.0" + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" } }, "spdx-license-ids": { @@ -7008,7 +9866,7 @@ "integrity": "sha1-zQ7qXmOiEd//frDwkcQTPi0N0o8=", "dev": true, "requires": { - "through": "2.3.8" + "through": "2" } }, "split-string": { @@ -7017,7 +9875,7 @@ "integrity": "sha1-fLCd2jqGWFcFxks5pkZgOGguj+I=", "dev": true, "requires": { - "extend-shallow": "3.0.2" + "extend-shallow": "^3.0.0" } }, "sprintf-js": { @@ -7026,20 +9884,32 @@ "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", "dev": true }, + "squeak": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/squeak/-/squeak-1.3.0.tgz", + "integrity": "sha1-MwRQN7ZDiLVnZ0uEMiplIQc5FsM=", + "dev": true, + "optional": true, + "requires": { + "chalk": "^1.0.0", + "console-stream": "^0.1.1", + "lpad-align": "^1.0.1" + } + }, "sshpk": { "version": "1.14.1", "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.14.1.tgz", "integrity": "sha1-Ew9Zde3a2WPx1W+SuaxsUfqfg+s=", "dev": true, "requires": { - "asn1": "0.2.3", - "assert-plus": "1.0.0", - "bcrypt-pbkdf": "1.0.1", - "dashdash": "1.14.1", - "ecc-jsbn": "0.1.1", - "getpass": "0.1.7", - "jsbn": "0.1.1", - "tweetnacl": "0.14.5" + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "tweetnacl": "~0.14.0" }, "dependencies": { "assert-plus": { @@ -7050,14 +9920,27 @@ } } }, + "stable": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", + "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", + "dev": true, + "optional": true + }, + "stat-mode": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/stat-mode/-/stat-mode-0.2.2.tgz", + "integrity": "sha1-5sgLYjEj19gM8TLOU480YokHJQI=", + "dev": true + }, "static-extend": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz", "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY=", "dev": true, "requires": { - "define-property": "0.2.5", - "object-copy": "0.1.0" + "define-property": "^0.2.5", + "object-copy": "^0.1.0" }, "dependencies": { "define-property": { @@ -7066,7 +9949,7 @@ "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY=", "dev": true, "requires": { - "is-descriptor": "0.1.6" + "is-descriptor": "^0.1.0" } }, "is-accessor-descriptor": { @@ -7075,7 +9958,7 @@ "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY=", "dev": true, "requires": { - "kind-of": "3.2.2" + "kind-of": "^3.0.2" }, "dependencies": { "kind-of": { @@ -7084,7 +9967,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "^1.1.5" } } } @@ -7095,7 +9978,7 @@ "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y=", "dev": true, "requires": { - "kind-of": "3.2.2" + "kind-of": "^3.0.2" }, "dependencies": { "kind-of": { @@ -7104,7 +9987,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "^1.1.5" } } } @@ -7115,9 +9998,9 @@ "integrity": "sha1-Nm2CQN3kh8pRgjsaufB6EKeCUco=", "dev": true, "requires": { - "is-accessor-descriptor": "0.1.6", - "is-data-descriptor": "0.1.4", - "kind-of": "5.1.0" + "is-accessor-descriptor": "^0.1.6", + "is-data-descriptor": "^0.1.4", + "kind-of": "^5.0.0" } }, "kind-of": { @@ -7140,7 +10023,58 @@ "integrity": "sha1-TV5DPBhSYd3mI8o/RMWGvPXErRQ=", "dev": true, "requires": { - "duplexer": "0.1.1" + "duplexer": "~0.1.1" + } + }, + "stream-combiner2": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/stream-combiner2/-/stream-combiner2-1.1.1.tgz", + "integrity": "sha1-+02KFCDqNidk4hrUeAOXvry0HL4=", + "dev": true, + "requires": { + "duplexer2": "~0.1.0", + "readable-stream": "^2.0.2" + }, + "dependencies": { + "duplexer2": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/duplexer2/-/duplexer2-0.1.4.tgz", + "integrity": "sha1-ixLauHjA1p4+eJEFFmKjL8a93ME=", + "dev": true, + "requires": { + "readable-stream": "^2.0.2" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } } }, "stream-consume": { @@ -7155,9 +10089,15 @@ "integrity": "sha1-3tJmVWMZyLDiIoErnPOyb6fZR94=", "dev": true, "requires": { - "readable-stream": "1.1.14" + "readable-stream": "~1.1.8" } }, + "stream-shift": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.0.tgz", + "integrity": "sha1-1cdSgl5TZ+eG944Y5EXqIjoVWVI=", + "dev": true + }, "strict-uri-encode": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz", @@ -7182,7 +10122,7 @@ "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", "dev": true, "requires": { - "ansi-regex": "2.1.1" + "ansi-regex": "^2.0.0" } }, "strip-bom": { @@ -7191,8 +10131,8 @@ "integrity": "sha1-hbiGLzhEtabV7IRnqTWYFzo295Q=", "dev": true, "requires": { - "first-chunk-stream": "1.0.0", - "is-utf8": "0.2.1" + "first-chunk-stream": "^1.0.0", + "is-utf8": "^0.2.0" } }, "strip-bom-stream": { @@ -7201,8 +10141,8 @@ "integrity": "sha1-+H217yYT9paKpUWr/h7HKLaoKco=", "dev": true, "requires": { - "first-chunk-stream": "2.0.0", - "strip-bom": "2.0.0" + "first-chunk-stream": "^2.0.0", + "strip-bom": "^2.0.0" }, "dependencies": { "first-chunk-stream": { @@ -7211,7 +10151,7 @@ "integrity": "sha1-G97NuOCDwGZLkZRVgVd6Q6nzHXA=", "dev": true, "requires": { - "readable-stream": "2.3.5" + "readable-stream": "^2.0.2" } }, "isarray": { @@ -7226,13 +10166,13 @@ "integrity": "sha1-tPhQA6k4y7bsvOKhJPsQEr0ag40=", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "2.0.0", - "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.0.3", + "util-deprecate": "~1.0.1" } }, "string_decoder": { @@ -7241,7 +10181,7 @@ "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", "dev": true, "requires": { - "safe-buffer": "5.1.1" + "safe-buffer": "~5.1.0" } }, "strip-bom": { @@ -7250,18 +10190,86 @@ "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", "dev": true, "requires": { - "is-utf8": "0.2.1" + "is-utf8": "^0.2.0" } } } }, + "strip-dirs": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/strip-dirs/-/strip-dirs-1.1.1.tgz", + "integrity": "sha1-lgu9EoeETzl1pFWKoQOoJV4kVqA=", + "dev": true, + "requires": { + "chalk": "^1.0.0", + "get-stdin": "^4.0.1", + "is-absolute": "^0.1.5", + "is-natural-number": "^2.0.0", + "minimist": "^1.1.0", + "sum-up": "^1.0.1" + }, + "dependencies": { + "is-absolute": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/is-absolute/-/is-absolute-0.1.7.tgz", + "integrity": "sha1-hHSREZ/MtftDYhfMc39/qtUPYD8=", + "dev": true, + "requires": { + "is-relative": "^0.1.0" + } + }, + "is-relative": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/is-relative/-/is-relative-0.1.3.tgz", + "integrity": "sha1-kF/uiuhvRbPsYUvDwVyGnfCHboI=", + "dev": true + }, + "minimist": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=", + "dev": true + } + } + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=", + "dev": true, + "optional": true + }, "strip-indent": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-1.0.1.tgz", "integrity": "sha1-DHlipq3vp7vUrDZkYKY4VSrhoKI=", "dev": true, "requires": { - "get-stdin": "4.0.1" + "get-stdin": "^4.0.1" + } + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=", + "dev": true + }, + "strip-outer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/strip-outer/-/strip-outer-1.0.1.tgz", + "integrity": "sha512-k55yxKHwaXnpYGsOzg4Vl8+tDrWylxDEpknGjhTiZB8dFRU5rTo9CAzeycivxV3s+zlTKwrs6WxMxR95n26kwg==", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.2" + } + }, + "sum-up": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sum-up/-/sum-up-1.0.3.tgz", + "integrity": "sha1-HGYfZnBX9jvLeHWqFDi8FiUlFW4=", + "dev": true, + "requires": { + "chalk": "^1.0.0" } }, "supports-color": { @@ -7270,7 +10278,7 @@ "integrity": "sha1-ZawFBLOVQXHYpklGsq48u4pfVPY=", "dev": true, "requires": { - "has-flag": "1.0.0" + "has-flag": "^1.0.0" } }, "svgo": { @@ -7279,13 +10287,13 @@ "integrity": "sha1-n1dyQTlSE1xv779Ar+ak+qiLS7U=", "dev": true, "requires": { - "coa": "1.0.4", - "colors": "1.1.2", - "csso": "2.3.2", - "js-yaml": "3.7.0", - "mkdirp": "0.5.1", - "sax": "1.2.4", - "whet.extend": "0.9.9" + "coa": "~1.0.1", + "colors": "~1.1.2", + "csso": "~2.3.1", + "js-yaml": "~3.7.0", + "mkdirp": "~0.5.1", + "sax": "~1.2.1", + "whet.extend": "~0.9.9" }, "dependencies": { "colors": { @@ -7296,6 +10304,80 @@ } } }, + "tar-stream": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-1.6.1.tgz", + "integrity": "sha512-IFLM5wp3QrJODQFPm6/to3LJZrONdBY/otxcvDIQzu217zKye6yVR3hhi9lAjrC2Z+m/j5oDxMPb1qcd8cIvpA==", + "dev": true, + "requires": { + "bl": "^1.0.0", + "buffer-alloc": "^1.1.0", + "end-of-stream": "^1.0.0", + "fs-constants": "^1.0.0", + "readable-stream": "^2.3.0", + "to-buffer": "^1.1.0", + "xtend": "^4.0.0" + }, + "dependencies": { + "end-of-stream": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.1.tgz", + "integrity": "sha512-1MkrZNvWTKCaigbn+W15elq2BB/L22nqrSY5DKlo3X6+vclJm8Bb5djXJBmEX6fS3+zCh/F4VBK5Z2KxJt4s2Q==", + "dev": true, + "requires": { + "once": "^1.4.0" + } + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, + "temp-dir": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/temp-dir/-/temp-dir-1.0.0.tgz", + "integrity": "sha1-CnwOom06Oa+n4OvqnB/AvE2qAR0=", + "dev": true, + "optional": true + }, + "tempfile": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/tempfile/-/tempfile-2.0.0.tgz", + "integrity": "sha1-awRGhWqbERTRhW/8vlCczLCXcmU=", + "dev": true, + "optional": true, + "requires": { + "temp-dir": "^1.0.0", + "uuid": "^3.0.1" + } + }, "throttleit": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.0.tgz", @@ -7314,8 +10396,8 @@ "integrity": "sha1-AARWmzfHx0ujnEPzzteNGtlBQL4=", "dev": true, "requires": { - "readable-stream": "2.3.5", - "xtend": "4.0.1" + "readable-stream": "^2.1.5", + "xtend": "~4.0.1" }, "dependencies": { "isarray": { @@ -7330,13 +10412,13 @@ "integrity": "sha1-tPhQA6k4y7bsvOKhJPsQEr0ag40=", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", - "isarray": "1.0.0", - "process-nextick-args": "2.0.0", - "safe-buffer": "5.1.1", - "string_decoder": "1.0.3", - "util-deprecate": "1.0.2" + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.0.3", + "util-deprecate": "~1.0.1" } }, "string_decoder": { @@ -7345,18 +10427,37 @@ "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", "dev": true, "requires": { - "safe-buffer": "5.1.1" + "safe-buffer": "~5.1.0" } } } }, + "through2-concurrent": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/through2-concurrent/-/through2-concurrent-1.1.1.tgz", + "integrity": "sha1-EctOpMnjG8puTB5tukjRxyjDUks=", + "dev": true, + "requires": { + "through2": "^2.0.0" + } + }, + "through2-filter": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/through2-filter/-/through2-filter-2.0.0.tgz", + "integrity": "sha1-YLxVoNrLdghdsfna6Zq0P4PWIuw=", + "dev": true, + "requires": { + "through2": "~2.0.0", + "xtend": "~4.0.0" + } + }, "tildify": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/tildify/-/tildify-1.2.0.tgz", "integrity": "sha1-3OwD9V3Km3qj5bBPIYF+tW5jWIo=", "dev": true, "requires": { - "os-homedir": "1.0.2" + "os-homedir": "^1.0.0" } }, "time-stamp": { @@ -7365,18 +10466,24 @@ "integrity": "sha1-dkpaEa9QVhkhsTPztE5hhofg9cM=", "dev": true }, + "timed-out": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/timed-out/-/timed-out-3.1.3.tgz", + "integrity": "sha1-lYYL/MXHbCd/j4Mm/Q9bLiDrohc=", + "dev": true + }, "tiny-lr": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/tiny-lr/-/tiny-lr-0.2.1.tgz", "integrity": "sha1-s/26gC5dVqM8L28QeUsy5Hescp0=", "dev": true, "requires": { - "body-parser": "1.14.2", - "debug": "2.2.0", - "faye-websocket": "0.10.0", - "livereload-js": "2.3.0", - "parseurl": "1.3.2", - "qs": "5.1.0" + "body-parser": "~1.14.0", + "debug": "~2.2.0", + "faye-websocket": "~0.10.0", + "livereload-js": "^2.2.0", + "parseurl": "~1.3.0", + "qs": "~5.1.0" }, "dependencies": { "body-parser": { @@ -7386,15 +10493,15 @@ "dev": true, "requires": { "bytes": "2.2.0", - "content-type": "1.0.4", - "debug": "2.2.0", - "depd": "1.1.2", - "http-errors": "1.3.1", + "content-type": "~1.0.1", + "debug": "~2.2.0", + "depd": "~1.1.0", + "http-errors": "~1.3.1", "iconv-lite": "0.4.13", - "on-finished": "2.3.0", + "on-finished": "~2.3.0", "qs": "5.2.0", - "raw-body": "2.1.7", - "type-is": "1.6.16" + "raw-body": "~2.1.5", + "type-is": "~1.6.10" }, "dependencies": { "qs": { @@ -7452,7 +10559,27 @@ "integrity": "sha1-jzirlDjhcxXl29izZX6L+yd65Kc=", "dev": true, "requires": { - "os-tmpdir": "1.0.2" + "os-tmpdir": "~1.0.1" + } + }, + "to-absolute-glob": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/to-absolute-glob/-/to-absolute-glob-0.1.1.tgz", + "integrity": "sha1-HN+kcqnvUMI57maZm2YsoOs5k38=", + "dev": true, + "requires": { + "extend-shallow": "^2.0.1" + }, + "dependencies": { + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "dev": true, + "requires": { + "is-extendable": "^0.1.0" + } + } } }, "to-array": { @@ -7461,13 +10588,19 @@ "integrity": "sha1-F+bBH3PdTz10zaek/zI46a2b+JA=", "dev": true }, + "to-buffer": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.1.1.tgz", + "integrity": "sha512-lx9B5iv7msuFYE3dytT+KE5tap+rNYw+K4jVkb9R/asAb+pbBSM17jtunHplhBe6RRJdZx3Pn2Jph24O32mOVg==", + "dev": true + }, "to-object-path": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz", "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68=", "dev": true, "requires": { - "kind-of": "3.2.2" + "kind-of": "^3.0.2" }, "dependencies": { "kind-of": { @@ -7476,7 +10609,7 @@ "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ=", "dev": true, "requires": { - "is-buffer": "1.1.6" + "is-buffer": "^1.1.5" } } } @@ -7487,10 +10620,10 @@ "integrity": "sha1-E8/dmzNlUvMLUfM6iuG0Knp1mc4=", "dev": true, "requires": { - "define-property": "2.0.2", - "extend-shallow": "3.0.2", - "regex-not": "1.0.2", - "safe-regex": "1.1.0" + "define-property": "^2.0.2", + "extend-shallow": "^3.0.2", + "regex-not": "^1.0.2", + "safe-regex": "^1.1.0" } }, "to-regex-range": { @@ -7499,8 +10632,8 @@ "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg=", "dev": true, "requires": { - "is-number": "3.0.0", - "repeat-string": "1.6.1" + "is-number": "^3.0.0", + "repeat-string": "^1.6.1" } }, "tough-cookie": { @@ -7509,7 +10642,7 @@ "integrity": "sha1-7GDO44rGdQY//JelwYlwV47oNlU=", "dev": true, "requires": { - "punycode": "1.4.1" + "punycode": "^1.4.1" } }, "trim-newlines": { @@ -7518,6 +10651,15 @@ "integrity": "sha1-WIeWa7WCpFA6QetST301ARgVphM=", "dev": true }, + "trim-repeated": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/trim-repeated/-/trim-repeated-1.0.0.tgz", + "integrity": "sha1-42RqLqTokTEr9+rObPsFOAvAHCE=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.2" + } + }, "tryit": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/tryit/-/tryit-1.0.3.tgz", @@ -7536,7 +10678,7 @@ "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", "dev": true, "requires": { - "safe-buffer": "5.1.1" + "safe-buffer": "^5.0.1" } }, "tweetnacl": { @@ -7552,7 +10694,7 @@ "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", "dev": true, "requires": { - "prelude-ls": "1.1.2" + "prelude-ls": "~1.1.2" } }, "type-is": { @@ -7562,7 +10704,7 @@ "dev": true, "requires": { "media-typer": "0.3.0", - "mime-types": "2.1.18" + "mime-types": "~2.1.18" } }, "typedarray": { @@ -7577,9 +10719,9 @@ "integrity": "sha1-KcVzMUgFe7Th913zW3qcty5qWd0=", "dev": true, "requires": { - "source-map": "0.5.7", - "uglify-to-browserify": "1.0.2", - "yargs": "3.10.0" + "source-map": "~0.5.1", + "uglify-to-browserify": "~1.0.0", + "yargs": "~3.10.0" } }, "uglify-to-browserify": { @@ -7595,7 +10737,7 @@ "integrity": "sha1-Otbzg2jG1MjHXsF2I/t5qh0HHYE=", "dev": true, "requires": { - "random-bytes": "1.0.0" + "random-bytes": "~1.0.0" } }, "ultron": { @@ -7616,10 +10758,10 @@ "integrity": "sha1-XHHDTLW61dzr4+oM0IIHulqhrqQ=", "dev": true, "requires": { - "arr-union": "3.1.0", - "get-value": "2.0.6", - "is-extendable": "0.1.1", - "set-value": "0.4.3" + "arr-union": "^3.1.0", + "get-value": "^2.0.6", + "is-extendable": "^0.1.1", + "set-value": "^0.4.3" }, "dependencies": { "extend-shallow": { @@ -7628,7 +10770,7 @@ "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", "dev": true, "requires": { - "is-extendable": "0.1.1" + "is-extendable": "^0.1.0" } }, "set-value": { @@ -7637,10 +10779,10 @@ "integrity": "sha1-fbCPnT0i3H945Trzw79GZuzfzPE=", "dev": true, "requires": { - "extend-shallow": "2.0.1", - "is-extendable": "0.1.1", - "is-plain-object": "2.0.4", - "to-object-path": "0.3.0" + "extend-shallow": "^2.0.1", + "is-extendable": "^0.1.1", + "is-plain-object": "^2.0.1", + "to-object-path": "^0.3.0" } } } @@ -7657,7 +10799,7 @@ "integrity": "sha1-iSIN32t1GuUrX3JISGNShZa7hME=", "dev": true, "requires": { - "macaddress": "0.2.8" + "macaddress": "^0.2.8" } }, "uniqs": { @@ -7678,14 +10820,21 @@ "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=", "dev": true }, + "unquote": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/unquote/-/unquote-1.1.1.tgz", + "integrity": "sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ=", + "dev": true, + "optional": true + }, "unset-value": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz", "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk=", "dev": true, "requires": { - "has-value": "0.3.1", - "isobject": "3.0.1" + "has-value": "^0.3.1", + "isobject": "^3.0.0" }, "dependencies": { "has-value": { @@ -7694,9 +10843,9 @@ "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8=", "dev": true, "requires": { - "get-value": "2.0.6", - "has-values": "0.1.4", - "isobject": "2.1.0" + "get-value": "^2.0.3", + "has-values": "^0.1.4", + "isobject": "^2.0.0" }, "dependencies": { "isobject": { @@ -7724,19 +10873,44 @@ } } }, + "unzip-response": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unzip-response/-/unzip-response-1.0.2.tgz", + "integrity": "sha1-uYTwh3/AqJwsdzzB73tbIytbBv4=", + "dev": true + }, "urix": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz", "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI=", "dev": true }, + "url-parse-lax": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/url-parse-lax/-/url-parse-lax-1.0.0.tgz", + "integrity": "sha1-evjzA2Rem9eaJy56FKxovAYJ2nM=", + "dev": true, + "requires": { + "prepend-http": "^1.0.1" + } + }, + "url-regex": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/url-regex/-/url-regex-3.2.0.tgz", + "integrity": "sha1-260eDJ4p4QXdCx8J9oYvf9tIJyQ=", + "dev": true, + "optional": true, + "requires": { + "ip-regex": "^1.0.1" + } + }, "use": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/use/-/use-3.1.0.tgz", "integrity": "sha1-FHFr8D/f79AwQK71jYtLhfOnxUQ=", "dev": true, "requires": { - "kind-of": "6.0.2" + "kind-of": "^6.0.2" } }, "user-home": { @@ -7751,8 +10925,8 @@ "integrity": "sha1-IX+UOtVAyyEoZYqyP8lg9qiMmXI=", "dev": true, "requires": { - "lru-cache": "4.1.2", - "tmp": "0.0.31" + "lru-cache": "4.1.x", + "tmp": "0.0.x" }, "dependencies": { "lru-cache": { @@ -7761,8 +10935,8 @@ "integrity": "sha1-RSNLLm4vKzPaElYkxGZJKaAiTD8=", "dev": true, "requires": { - "pseudomap": "1.0.2", - "yallist": "2.1.2" + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" } } } @@ -7773,6 +10947,17 @@ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=", "dev": true }, + "util.promisify": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz", + "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==", + "dev": true, + "optional": true, + "requires": { + "define-properties": "^1.1.2", + "object.getownpropertydescriptors": "^2.0.3" + } + }, "utils-merge": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.0.tgz", @@ -7791,17 +10976,23 @@ "integrity": "sha1-qrGh+jDUX4jdMhFIh1rALAtV5bQ=", "dev": true, "requires": { - "user-home": "1.1.1" + "user-home": "^1.1.1" } }, + "vali-date": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/vali-date/-/vali-date-1.0.0.tgz", + "integrity": "sha1-G5BKWWCfsyjvB4E4Qgk09rhnCaY=", + "dev": true + }, "validate-npm-package-license": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz", "integrity": "sha1-gWQ7y+8b3+zUYjeT3EZIlIupgzg=", "dev": true, "requires": { - "spdx-correct": "3.0.0", - "spdx-expression-parse": "3.0.0" + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" } }, "vary": { @@ -7822,9 +11013,9 @@ "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", "dev": true, "requires": { - "assert-plus": "1.0.0", + "assert-plus": "^1.0.0", "core-util-is": "1.0.2", - "extsprintf": "1.3.0" + "extsprintf": "^1.2.0" }, "dependencies": { "assert-plus": { @@ -7847,11 +11038,53 @@ "integrity": "sha1-sEVbOPxeDPMNQyUTLkYZcMIJHN4=", "dev": true, "requires": { - "clone": "1.0.4", - "clone-stats": "0.0.1", + "clone": "^1.0.0", + "clone-stats": "^0.0.1", "replace-ext": "0.0.1" } }, + "vinyl-assign": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/vinyl-assign/-/vinyl-assign-1.2.1.tgz", + "integrity": "sha1-TRmIkbVRWRHXcajNnFSApGoHSkU=", + "dev": true, + "requires": { + "object-assign": "^4.0.1", + "readable-stream": "^2.0.0" + }, + "dependencies": { + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=", + "dev": true + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "dev": true, + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dev": true, + "requires": { + "safe-buffer": "~5.1.0" + } + } + } + }, "vinyl-bufferstream": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/vinyl-bufferstream/-/vinyl-bufferstream-1.0.1.tgz", @@ -7867,12 +11100,12 @@ "integrity": "sha1-p+v1/779obfRjRQPyweyI++2dRo=", "dev": true, "requires": { - "graceful-fs": "4.1.11", - "pify": "2.3.0", - "pinkie-promise": "2.0.1", - "strip-bom": "2.0.0", - "strip-bom-stream": "2.0.0", - "vinyl": "1.2.0" + "graceful-fs": "^4.1.2", + "pify": "^2.3.0", + "pinkie-promise": "^2.0.0", + "strip-bom": "^2.0.0", + "strip-bom-stream": "^2.0.0", + "vinyl": "^1.1.0" }, "dependencies": { "graceful-fs": { @@ -7887,7 +11120,7 @@ "integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", "dev": true, "requires": { - "is-utf8": "0.2.1" + "is-utf8": "^0.2.0" } }, "vinyl": { @@ -7896,8 +11129,8 @@ "integrity": "sha1-XIgDbPVl5d8FVYv8kR+GVt8hiIQ=", "dev": true, "requires": { - "clone": "1.0.4", - "clone-stats": "0.0.1", + "clone": "^1.0.0", + "clone-stats": "^0.0.1", "replace-ext": "0.0.1" } } @@ -7909,14 +11142,14 @@ "integrity": "sha1-mmhRzhysHBzqX+hsCTHWIMLPqeY=", "dev": true, "requires": { - "defaults": "1.0.3", - "glob-stream": "3.1.18", - "glob-watcher": "0.0.6", - "graceful-fs": "3.0.11", - "mkdirp": "0.5.1", - "strip-bom": "1.0.0", - "through2": "0.6.5", - "vinyl": "0.4.6" + "defaults": "^1.0.0", + "glob-stream": "^3.1.5", + "glob-watcher": "^0.0.6", + "graceful-fs": "^3.0.0", + "mkdirp": "^0.5.0", + "strip-bom": "^1.0.0", + "through2": "^0.6.1", + "vinyl": "^0.4.0" }, "dependencies": { "clone": { @@ -7931,10 +11164,10 @@ "integrity": "sha1-Elgg40vIQtLyqq+v5MKRbuMsFXw=", "dev": true, "requires": { - "core-util-is": "1.0.2", - "inherits": "2.0.3", + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", "isarray": "0.0.1", - "string_decoder": "0.10.31" + "string_decoder": "~0.10.x" } }, "through2": { @@ -7943,8 +11176,8 @@ "integrity": "sha1-QaucZ7KdVyCQcUEOHXp6lozTrUg=", "dev": true, "requires": { - "readable-stream": "1.0.34", - "xtend": "4.0.1" + "readable-stream": ">=1.0.33-1 <1.1.0-0", + "xtend": ">=4.0.0 <4.1.0-0" } }, "vinyl": { @@ -7953,8 +11186,8 @@ "integrity": "sha1-LzVsh6VQolVGHza76ypbqL94SEc=", "dev": true, "requires": { - "clone": "0.2.0", - "clone-stats": "0.0.1" + "clone": "^0.2.0", + "clone-stats": "^0.0.1" } } } @@ -7965,7 +11198,7 @@ "integrity": "sha1-q2VJ1h0XLCsbh75cUI0jnI74dwU=", "dev": true, "requires": { - "source-map": "0.5.7" + "source-map": "^0.5.1" } }, "void-elements": { @@ -7974,14 +11207,23 @@ "integrity": "sha1-wGavtYK7HLQSjWDqkjkulNXp2+w=", "dev": true }, + "ware": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ware/-/ware-1.3.0.tgz", + "integrity": "sha1-0bFPOdLiy0q4xAmPdW/ksWTkc9Q=", + "dev": true, + "requires": { + "wrap-fn": "^0.1.0" + } + }, "websocket-driver": { "version": "0.7.0", "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.0.tgz", "integrity": "sha1-DK+dLXVdk67gSdS90NP+LMoqJOs=", "dev": true, "requires": { - "http-parser-js": "0.4.11", - "websocket-extensions": "0.1.3" + "http-parser-js": ">=0.4.0", + "websocket-extensions": ">=0.1.1" } }, "websocket-extensions": { @@ -8008,7 +11250,7 @@ "integrity": "sha1-/wS9/AEO5UfXgL7DjhrBwnd9JTo=", "dev": true, "requires": { - "isexe": "2.0.0" + "isexe": "^2.0.0" } }, "window-size": { @@ -8023,6 +11265,23 @@ "integrity": "sha1-t5Zpu0LstAn4PVg8rVLKF+qhZD8=", "dev": true }, + "wrap-fn": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/wrap-fn/-/wrap-fn-0.1.5.tgz", + "integrity": "sha1-8htuQQFv9KfjFyDbxjoJAWvfmEU=", + "dev": true, + "requires": { + "co": "3.1.0" + }, + "dependencies": { + "co": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/co/-/co-3.1.0.tgz", + "integrity": "sha1-TqVOpaCJOBUxheFSEMaNkJK8G3g=", + "dev": true + } + } + }, "wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -8035,8 +11294,8 @@ "integrity": "sha1-iiRPoFJAHgjJiGz0SoUYnh/UBn8=", "dev": true, "requires": { - "options": "0.0.6", - "ultron": "1.0.2" + "options": ">=0.0.5", + "ultron": "1.0.x" } }, "wtf-8": { @@ -8069,9 +11328,9 @@ "integrity": "sha1-9+572FfdfB0tOMDnTvvWgdFDH9E=", "dev": true, "requires": { - "camelcase": "1.2.1", - "cliui": "2.1.0", - "decamelize": "1.2.0", + "camelcase": "^1.0.2", + "cliui": "^2.1.0", + "decamelize": "^1.0.0", "window-size": "0.1.0" } }, @@ -8081,7 +11340,7 @@ "integrity": "sha1-lSj0QtqxsihOWLQ3m7GU4i4MQAU=", "dev": true, "requires": { - "fd-slicer": "1.0.1" + "fd-slicer": "~1.0.1" } }, "yeast": { diff --git a/src/Umbraco.Web.UI.Client/src/canvasdesigner.loader.js b/src/Umbraco.Web.UI.Client/src/canvasdesigner.loader.js index 1281443952..8c0ec78025 100644 --- a/src/Umbraco.Web.UI.Client/src/canvasdesigner.loader.js +++ b/src/Umbraco.Web.UI.Client/src/canvasdesigner.loader.js @@ -7,7 +7,7 @@ LazyLoad.js([ '../js/app.js', '../js/umbraco.resources.js', '../js/umbraco.services.js', - '../js/umbraco.security.js', + '../js/umbraco.interceptors.js', '../ServerVariables', '../lib/signalr/jquery.signalR.js', '/umbraco/BackOffice/signalr/hubs', diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js index a4fa759aa6..6eaac473af 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/content/edit.controller.js @@ -286,7 +286,7 @@ contentResource.unPublish($scope.content.id, culture) .then(function (data) { - formHelper.resetForm({ scope: $scope, notifications: data.notifications }); + formHelper.resetForm({ scope: $scope }); contentEditingHelper.handleSuccessfulSave({ scope: $scope, @@ -301,7 +301,6 @@ $scope.page.buttonGroupState = "success"; }, function (err) { - formHelper.showNotifications(err.data); $scope.page.buttonGroupState = 'error'; }); } @@ -367,12 +366,12 @@ } } else { - return performSave({ saveMethod: contentResource.publish, action: "publish" }); + return performSave({ saveMethod: contentResource.publish, action: "publish" }).catch(angular.noop);; } }; $scope.save = function () { - return performSave({ saveMethod: $scope.saveMethod(), action: "save" }); + return performSave({ saveMethod: $scope.saveMethod(), action: "save" }).catch(angular.noop); }; $scope.preview = function (content) { @@ -396,7 +395,7 @@ else { $scope.save().then(function (data) { previewWindow.location.href = redirect; - }); + }).catch(angular.noop); } } }; diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/html/umbcontrolgroup.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/html/umbcontrolgroup.directive.js index bd2f0ca0b3..886f7be4af 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/html/umbcontrolgroup.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/html/umbcontrolgroup.directive.js @@ -14,7 +14,7 @@ angular.module("umbraco.directives.html") labelFor: "@", required: "@?" }, - require: '?^form', + require: '?^^form', transclude: true, restrict: 'E', replace: true, diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/components/property/umbpropertyeditor.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/components/property/umbpropertyeditor.directive.js index 5500f954b1..ea73004a3f 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/components/property/umbpropertyeditor.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/components/property/umbpropertyeditor.directive.js @@ -15,7 +15,7 @@ var _umbPropertyEditor = function (umbPropEditorHelper) { preview: "@" }, - require: "^form", + require: "^^form", restrict: 'E', replace: true, templateUrl: 'views/components/property/umb-property-editor.html', @@ -37,4 +37,4 @@ var _umbPropertyEditor = function (umbPropEditorHelper) { }; }; -angular.module("umbraco.directives").directive('umbPropertyEditor', _umbPropertyEditor); \ No newline at end of file +angular.module("umbraco.directives").directive('umbPropertyEditor', _umbPropertyEditor); diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/validation/umbsetdirtyonchange.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/validation/umbsetdirtyonchange.directive.js index 0c2339dd5c..86cb3614dd 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/validation/umbsetdirtyonchange.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/validation/umbsetdirtyonchange.directive.js @@ -25,7 +25,7 @@ } var directive = { - require: "^form", + require: "^^form", restrict: 'A', link: link }; diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valcompare.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valcompare.directive.js index 195c70ce0f..fc419a0b97 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valcompare.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valcompare.directive.js @@ -1,7 +1,7 @@ angular.module('umbraco.directives.validation') .directive('valCompare',function () { return { - require: ["ngModel", "^form"], + require: ["ngModel", "^^form"], link: function (scope, elem, attrs, ctrls) { var ctrl = ctrls[0]; @@ -23,4 +23,4 @@ angular.module('umbraco.directives.validation') }); } }; -}); \ No newline at end of file +}); diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valformmanager.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valformmanager.directive.js index 9d01b41190..194565476d 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valformmanager.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valformmanager.directive.js @@ -13,6 +13,11 @@ * be marked with the 'error' css class. This ensures that labels included in that control group are styled correctly. **/ function valFormManager(serverValidationManager, $rootScope, $log, $timeout, notificationsService, eventsService, $routeParams) { + + var SHOW_VALIDATION_CLASS_NAME = "show-validation"; + var SAVING_EVENT_NAME = "formSubmitting"; + var SAVED_EVENT_NAME = "formSubmitted"; + return { require: "form", restrict: "A", @@ -39,14 +44,22 @@ function valFormManager(serverValidationManager, $rootScope, $log, $timeout, not }, link: function (scope, element, attr, formCtrl) { - - /* - FIXME: This is commented out because it caused this error - http://uixdk.com/angular/docs/error/ng/cpws - resulting in an endless digest loop for all editors - + //watch the list of validation errors to notify the application of any validation changes scope.$watch(function () { - return formCtrl.$error; + //the validators are in the $error collection: https://docs.angularjs.org/api/ng/type/form.FormController#$error + //since each key is the validator name (i.e. 'required') we can't just watch the number of keys, we need to watch + //the sum of the items inside of each key + + //get the lengths of each array for each key in the $error collection + var validatorLengths = _.map(formCtrl.$error, function (val, key) { + return val.length; + }); + //sum up all numbers in the resulting array + var sum = _.reduce(validatorLengths, function (memo, num) { + return memo + num; + }, 0); + //this is the value we watch to notify of any validation changes on the form + return sum; }, function (e) { scope.$broadcast("valStatusChanged", { form: formCtrl }); @@ -58,11 +71,7 @@ function valFormManager(serverValidationManager, $rootScope, $log, $timeout, not var noInError = element.find(".control-group .ng-valid").closest(".control-group").not(inError); noInError.removeClass("error"); - }, true); - - var className = attr.valShowValidation ? attr.valShowValidation : "show-validation"; - var savingEventName = attr.savingEvent ? attr.savingEvent : "formSubmitting"; - var savedEvent = attr.savedEvent ? attr.savingEvent : "formSubmitted"; + }); //This tracks if the user is currently saving a new item, we use this to determine // if we should display the warning dialog that they are leaving the page - if a new item @@ -72,23 +81,23 @@ function valFormManager(serverValidationManager, $rootScope, $log, $timeout, not //we should show validation if there are any msgs in the server validation collection if (serverValidationManager.items.length > 0) { - element.addClass(className); + element.addClass(SHOW_VALIDATION_CLASS_NAME); } var unsubscribe = []; //listen for the forms saving event - unsubscribe.push(scope.$on(savingEventName, function(ev, args) { - element.addClass(className); + unsubscribe.push(scope.$on(SAVING_EVENT_NAME, function(ev, args) { + element.addClass(SHOW_VALIDATION_CLASS_NAME); //set the flag so we can check to see if we should display the error. isSavingNewItem = $routeParams.create; })); //listen for the forms saved event - unsubscribe.push(scope.$on(savedEvent, function(ev, args) { + unsubscribe.push(scope.$on(SAVED_EVENT_NAME, function(ev, args) { //remove validation class - element.removeClass(className); + element.removeClass(SHOW_VALIDATION_CLASS_NAME); //clear form state as at this point we retrieve new data from the server //and all validation will have cleared at this point @@ -133,8 +142,8 @@ function valFormManager(serverValidationManager, $rootScope, $log, $timeout, not $timeout(function(){ formCtrl.$setPristine(); }, 1000); - */ + } }; } -angular.module('umbraco.directives.validation').directive("valFormManager", valFormManager); \ No newline at end of file +angular.module('umbraco.directives.validation').directive("valFormManager", valFormManager); diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valpropertymsg.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valpropertymsg.directive.js index be5da51702..71c59860df 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valpropertymsg.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valpropertymsg.directive.js @@ -7,7 +7,7 @@ * @description This directive is used to control the display of the property level validation message. * We will listen for server side validation changes * and when an error is detected for this property we'll show the error message. -* In order for this directive to work, the valStatusChanged directive must be placed on the containing form. +* In order for this directive to work, the valFormManager directive must be placed on the containing form. **/ function valPropertyMsg(serverValidationManager) { @@ -15,16 +15,18 @@ function valPropertyMsg(serverValidationManager) { scope: { property: "=" }, - require: "^form", //require that this directive is contained within an ngForm - replace: true, //replace the element with the template - restrict: "E", //restrict to element + require: ['^^form', '^^valFormManager'], + replace: true, + restrict: "E", template: "
                {{errorMsg}}
                ", - /** - Our directive requries a reference to a form controller - which gets passed in to this parameter - */ - link: function (scope, element, attrs, formCtrl) { + link: function (scope, element, attrs, ctrl) { + + //the property form controller api + var formCtrl = ctrl[0]; + + //the valFormManager controller api + var valFormManager = ctrl[1]; var watcher = null; @@ -39,10 +41,12 @@ function valPropertyMsg(serverValidationManager) { return err.errorMsg; } else { + //TODO: localize return scope.property.propertyErrorMessage ? scope.property.propertyErrorMessage : "Property has errors"; } } + //TODO: localize return "Property has errors"; } @@ -98,18 +102,19 @@ function valPropertyMsg(serverValidationManager) { var unsubscribe = []; - //listen for form error changes - unsubscribe.push(scope.$on("valStatusChanged", function(evt, args) { - if (args.form.$invalid) { - + //listen for form validation changes. + //The alternative is to add a watch to formCtrl.$invalid but that would lead to many more watches then + // subscribing to this single watch. + valFormManager.onValidationStatusChanged(function (evt, args) { + if (formCtrl.$invalid) { //first we need to check if the valPropertyMsg validity is invalid if (formCtrl.$error.valPropertyMsg && formCtrl.$error.valPropertyMsg.length > 0) { //since we already have an error we'll just return since this means we've already set the // hasError and errorMsg properties which occurs below in the serverValidationManager.subscribe return; } - else if (element.closest(".umb-control-group").find(".ng-invalid").length > 0) { - //check if it's one of the properties that is invalid in the current content property + //if there are any errors in the current property form that are not valPropertyMsg + else if (_.without(_.keys(formCtrl.$error), "valPropertyMsg").length > 0) { hasError = true; //update the validation message if we don't already have one assigned. if (showValidation && scope.errorMsg === "") { @@ -125,7 +130,7 @@ function valPropertyMsg(serverValidationManager) { hasError = false; scope.errorMsg = ""; } - }, true)); + }); //listen for the forms saving event unsubscribe.push(scope.$on("formSubmitting", function(ev, args) { @@ -193,4 +198,4 @@ function valPropertyMsg(serverValidationManager) { }; } -angular.module('umbraco.directives.validation').directive("valPropertyMsg", valPropertyMsg); \ No newline at end of file +angular.module('umbraco.directives.validation').directive("valPropertyMsg", valPropertyMsg); diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valserverfield.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valserverfield.directive.js index 1b3e59717e..29fd94ff5b 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valserverfield.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valserverfield.directive.js @@ -2,8 +2,9 @@ * @ngdoc directive * @name umbraco.directives.directive:valServerField * @restrict A - * @description This directive is used to associate a content field (not user defined) with a server-side validation response + * @description This directive is used to associate a field with a server-side validation response * so that the validators in angular are updated based on server-side feedback. + * (For validation of user defined content properties on content/media/members, the valServer directive is used) **/ function valServerField(serverValidationManager) { return { diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valsubview.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valsubview.directive.js index 98c4c6768f..ca571d3954 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valsubview.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valsubview.directive.js @@ -41,7 +41,7 @@ } var directive = { - require: ['?^form', '?^valFormManager'], + require: ['?^^form', '?^^valFormManager'], restrict: "A", link: link }; diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valtab.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valtab.directive.js index 8d1fc60083..39b94742ec 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valtab.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valtab.directive.js @@ -8,7 +8,7 @@ **/ function valTab() { return { - require: ['^form', '^valFormManager'], + require: ['^^form', '^^valFormManager'], restrict: "A", link: function (scope, element, attr, ctrs) { @@ -35,4 +35,4 @@ function valTab() { } }; } -angular.module('umbraco.directives.validation').directive("valTab", valTab); \ No newline at end of file +angular.module('umbraco.directives.validation').directive("valTab", valTab); diff --git a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valtogglemsg.directive.js b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valtogglemsg.directive.js index 304f151274..1d64175f33 100644 --- a/src/Umbraco.Web.UI.Client/src/common/directives/validation/valtogglemsg.directive.js +++ b/src/Umbraco.Web.UI.Client/src/common/directives/validation/valtogglemsg.directive.js @@ -1,6 +1,6 @@ function valToggleMsg(serverValidationManager) { return { - require: "^form", + require: "^^form", restrict: "A", /** @@ -87,4 +87,4 @@ function valToggleMsg(serverValidationManager) { * @requires formController * @description This directive will show/hide an error based on: is the value + the given validator invalid? AND, has the form been submitted ? **/ -angular.module('umbraco.directives.validation').directive("valToggleMsg", valToggleMsg); \ No newline at end of file +angular.module('umbraco.directives.validation').directive("valToggleMsg", valToggleMsg); diff --git a/src/Umbraco.Web.UI.Client/src/common/interceptors/_module.js b/src/Umbraco.Web.UI.Client/src/common/interceptors/_module.js new file mode 100644 index 0000000000..765f44a636 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/interceptors/_module.js @@ -0,0 +1,9 @@ +angular.module('umbraco.interceptors', []) + // We have to add the interceptor to the queue as a string because the interceptor depends upon service instances that are not available in the config block. + .config(['$httpProvider', function($httpProvider) { + $httpProvider.defaults.xsrfHeaderName = 'X-UMB-XSRF-TOKEN'; + $httpProvider.defaults.xsrfCookieName = 'UMB-XSRF-TOKEN'; + + $httpProvider.interceptors.push('securityInterceptor'); + $httpProvider.interceptors.push('debugRequestInterceptor'); + }]); diff --git a/src/Umbraco.Web.UI.Client/src/common/interceptors/debugrequest.interceptor.js b/src/Umbraco.Web.UI.Client/src/common/interceptors/debugrequest.interceptor.js new file mode 100644 index 0000000000..9fe0afd481 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/interceptors/debugrequest.interceptor.js @@ -0,0 +1,25 @@ +(function() { + 'use strict'; + + /** + * Used to set debug headers on all requests where necessary + * @param {any} $q + * @param {any} urlHelper + */ + function debugRequestInterceptor($q, urlHelper) { + return { + //dealing with requests: + 'request': function(config) { + var queryStrings = urlHelper.getQueryStringParams(); + if (queryStrings.umbDebug === "true" || queryStrings.umbdebug === "true") { + config.headers["X-UMB-DEBUG"] = "true"; + } + return config; + } + }; + } + + angular.module('umbraco.interceptors').factory('debugRequestInterceptor', debugRequestInterceptor); + + +})(); diff --git a/src/Umbraco.Web.UI.Client/src/common/interceptors/requestinterceptorfilter.value.js b/src/Umbraco.Web.UI.Client/src/common/interceptors/requestinterceptorfilter.value.js new file mode 100644 index 0000000000..1a7ba54327 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/interceptors/requestinterceptorfilter.value.js @@ -0,0 +1,11 @@ +(function() { + 'use strict'; + + /** Used to filter the request interceptor */ + function requestInterceptorFilter() { + return ["www.gravatar.com"]; + } + + angular.module('umbraco.interceptors').value('requestInterceptorFilter', requestInterceptorFilter); + +})(); diff --git a/src/Umbraco.Web.UI.Client/src/common/security/securityinterceptor.js b/src/Umbraco.Web.UI.Client/src/common/interceptors/security.interceptor.js similarity index 71% rename from src/Umbraco.Web.UI.Client/src/common/security/securityinterceptor.js rename to src/Umbraco.Web.UI.Client/src/common/interceptors/security.interceptor.js index 9976502b88..221e71eb8c 100644 --- a/src/Umbraco.Web.UI.Client/src/common/security/securityinterceptor.js +++ b/src/Umbraco.Web.UI.Client/src/common/interceptors/security.interceptor.js @@ -1,9 +1,19 @@ -angular.module('umbraco.security.interceptor') - // This http interceptor listens for authentication successes and failures - .factory('securityInterceptor', ['$injector', 'securityRetryQueue', 'notificationsService', 'eventsService', 'requestInterceptorFilter', function ($injector, queue, notifications, eventsService, requestInterceptorFilter) { - return { +(function () { + 'use strict'; - 'response': function(response) { + /** + * This http interceptor listens for authentication successes and failures + * @param {any} $q + * @param {any} $injector + * @param {any} requestRetryQueue + * @param {any} notificationsService + * @param {any} eventsService + * @param {any} requestInterceptorFilter + */ + function securityInterceptor($q, $injector, requestRetryQueue, notificationsService, eventsService, requestInterceptorFilter) { + return { + + 'response': function (response) { // Intercept successful requests //Here we'll check if our custom header is in the response which indicates how many seconds the user's session has before it //expires. Then we'll update the user in the user service accordingly. @@ -14,7 +24,7 @@ angular.module('umbraco.security.interceptor') var userService = $injector.get('userService'); userService.setUserTimeout(headers["x-umb-user-seconds"]); } - + //this checks if the user's values have changed, in which case we need to update the user details throughout //the back office similar to how we do when a user logs in if (headers["x-umb-user-modified"]) { @@ -23,8 +33,8 @@ angular.module('umbraco.security.interceptor') return response; }, - - 'responseError': function(rejection) { + + 'responseError': function (rejection) { // Intercept failed requests // Make sure we have the configuration of the request (don't we always?) @@ -36,13 +46,13 @@ angular.module('umbraco.security.interceptor') //Here we'll check if we should ignore the error (either based on the original header set or the request configuration) if (headers["x-umb-ignore-error"] === "ignore" || config.umbIgnoreErrors === true || (angular.isArray(config.umbIgnoreStatus) && config.umbIgnoreStatus.indexOf(rejection.status) !== -1)) { //exit/ignore - return promise; + return $q.reject(rejection); } var filtered = _.find(requestInterceptorFilter(), function (val) { return config.url.indexOf(val) > 0; }); if (filtered) { - return promise; + return $q.reject(rejection); } //A 401 means that the user is not logged in @@ -51,11 +61,11 @@ angular.module('umbraco.security.interceptor') var userService = $injector.get('userService'); // see above //Associate the user name with the retry to ensure we retry for the right user - promise = userService.getCurrentUser() + return userService.getCurrentUser() .then(function (user) { var userName = user ? user.name : null; //The request bounced because it was not authorized - add a new request to the retry queue - return queue.pushRetryFn('unauthorized-server', userName, function retryRequest() { + return requestRetryQueue.pushRetryFn('unauthorized-server', userName, function retryRequest() { // We must use $injector to get the $http service to prevent circular dependency return $injector.get('$http')(rejection.config); }); @@ -74,9 +84,9 @@ angular.module('umbraco.security.interceptor') errMsg += "
                with data:
                " + angular.toJson(rejection.config.data) + "
                Contact your administrator for information."; } - notifications.error( + notificationsService.error( "Request error", - errMsg); + errMsg); } else if (rejection.status === 403) { @@ -94,35 +104,15 @@ angular.module('umbraco.security.interceptor') msg += "
                with data:
                " + angular.toJson(rejection.config.data) + "
                Contact your administrator for information."; } - notifications.error("Authorization error", msg); + notificationsService.error("Authorization error", msg); } return $q.reject(rejection); } }; - }]) - //used to set headers on all requests where necessary - .factory('umbracoRequestInterceptor', function ($q, urlHelper) { - return { - //dealing with requests: - 'request': function (config) { - var queryStrings = urlHelper.getQueryStringParams(); - if (queryStrings.umbDebug === "true" || queryStrings.umbdebug === "true") { - config.headers["X-UMB-DEBUG"] = "true"; - } - return config; - } - }; - }) - .value('requestInterceptorFilter', function () { - return ["www.gravatar.com"]; - }) + } - // We have to add the interceptor to the queue as a string because the interceptor depends upon service instances that are not available in the config block. - .config(['$httpProvider', function ($httpProvider) { - $httpProvider.defaults.xsrfHeaderName = 'X-UMB-XSRF-TOKEN'; - $httpProvider.defaults.xsrfCookieName = 'UMB-XSRF-TOKEN'; + angular.module('umbraco.interceptors').factory('securityInterceptor', securityInterceptor); - $httpProvider.interceptors.push('securityInterceptor'); - $httpProvider.interceptors.push('umbracoRequestInterceptor'); - }]); + +})(); diff --git a/src/Umbraco.Web.UI.Client/src/common/security/_module.js b/src/Umbraco.Web.UI.Client/src/common/security/_module.js deleted file mode 100644 index c8289c754e..0000000000 --- a/src/Umbraco.Web.UI.Client/src/common/security/_module.js +++ /dev/null @@ -1,4 +0,0 @@ -//TODO: This is silly and unecessary to have a separate module for this -angular.module('umbraco.security.retryQueue', []); -angular.module('umbraco.security.interceptor', ['umbraco.security.retryQueue']); -angular.module('umbraco.security', ['umbraco.security.retryQueue', 'umbraco.security.interceptor']); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/common/security/retryqueue.js b/src/Umbraco.Web.UI.Client/src/common/security/retryqueue.js deleted file mode 100644 index 755e179527..0000000000 --- a/src/Umbraco.Web.UI.Client/src/common/security/retryqueue.js +++ /dev/null @@ -1,90 +0,0 @@ -//TODO: This is silly and unecessary to have a separate module for this -angular.module('umbraco.security.retryQueue', []) - -// This is a generic retry queue for security failures. Each item is expected to expose two functions: retry and cancel. -.factory('securityRetryQueue', ['$q', '$log', function ($q, $log) { - - var retryQueue = []; - var retryUser = null; - - var service = { - // The security service puts its own handler in here! - onItemAddedCallbacks: [], - - hasMore: function() { - return retryQueue.length > 0; - }, - push: function(retryItem) { - retryQueue.push(retryItem); - // Call all the onItemAdded callbacks - angular.forEach(service.onItemAddedCallbacks, function(cb) { - try { - cb(retryItem); - } catch(e) { - $log.error('securityRetryQueue.push(retryItem): callback threw an error' + e); - } - }); - }, - pushRetryFn: function(reason, userName, retryFn) { - // The reason parameter is optional - if ( arguments.length === 2) { - retryFn = userName; - userName = reason; - reason = undefined; - } - - if ((retryUser && retryUser !== userName) || userName === null) { - throw new Error('invalid user'); - } - - retryUser = userName; - - // The deferred object that will be resolved or rejected by calling retry or cancel - var deferred = $q.defer(); - var retryItem = { - reason: reason, - retry: function() { - // Wrap the result of the retryFn into a promise if it is not already - $q.when(retryFn()).then(function(value) { - // If it was successful then resolve our deferred - deferred.resolve(value); - }, function(value) { - // Othewise reject it - deferred.reject(value); - }); - }, - cancel: function() { - // Give up on retrying and reject our deferred - deferred.reject(); - } - }; - service.push(retryItem); - return deferred.promise; - }, - retryReason: function() { - return service.hasMore() && retryQueue[0].reason; - }, - cancelAll: function() { - while(service.hasMore()) { - retryQueue.shift().cancel(); - } - retryUser = null; - }, - retryAll: function (userName) { - - if (retryUser == null) { - return; - } - - if (retryUser !== userName) { - service.cancelAll(); - return; - } - - while(service.hasMore()) { - retryQueue.shift().retry(); - } - } - }; - return service; -}]); \ No newline at end of file diff --git a/src/Umbraco.Web.UI.Client/src/common/services/_module.js b/src/Umbraco.Web.UI.Client/src/common/services/_module.js index a3ffbeb28b..87f6bcec4b 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/_module.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/_module.js @@ -1 +1 @@ -angular.module("umbraco.services", ["umbraco.security", "umbraco.resources"]); +angular.module("umbraco.services", ["umbraco.interceptors", "umbraco.resources"]); diff --git a/src/Umbraco.Web.UI.Client/src/common/services/angularhelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/angularhelper.service.js index 6a1b4916b7..5abacc2a80 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/angularhelper.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/angularhelper.service.js @@ -54,7 +54,7 @@ function angularHelper($log, $q) { * This checks if a digest/apply is already occuring, if not it will force an apply call */ safeApply: function (scope, fn) { - if (scope.$$phase || scope.$root.$$phase) { + if (scope.$$phase || (scope.$root && scope.$root.$$phase)) { if (angular.isFunction(fn)) { fn(); } diff --git a/src/Umbraco.Web.UI.Client/src/common/services/contenteditinghelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/contenteditinghelper.service.js index 6c3f1054f7..4b77d28aee 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/contenteditinghelper.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/contenteditinghelper.service.js @@ -29,7 +29,8 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, notifica return { /** Used by the content editor and mini content editor to perform saving operations */ - //TODO: Make this a more helpful/reusable method for other form operations! we can simplify this form most forms + //TODO: Make this a more helpful/reusable method for other form operations! we can simplify this form most forms + // = this is already done in the formhelper service contentEditorPerformSave: function (args) { if (!angular.isObject(args)) { throw "args must be an object"; @@ -59,7 +60,7 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, notifica return args.saveMethod(args.content, $routeParams.create, fileManager.getFiles()) .then(function (data) { - formHelper.resetForm({ scope: args.scope, notifications: data.notifications }); + formHelper.resetForm({ scope: args.scope }); self.handleSuccessfulSave({ scope: args.scope, @@ -71,7 +72,7 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, notifica }); args.scope.busy = false; - return $q.when(data); + return $q.resolve(data); }, function (err) { self.handleSaveError({ @@ -81,12 +82,7 @@ function contentEditingHelper(fileManager, $q, $location, $routeParams, notifica rebindCallback.apply(self, [args.content, err.data]); } }); - //show any notifications - if (angular.isArray(err.data.notifications)) { - for (var i = 0; i < err.data.notifications.length; i++) { - notificationsService.showNotification(err.data.notifications[i]); - } - } + args.scope.busy = false; return $q.reject(err); }); diff --git a/src/Umbraco.Web.UI.Client/src/common/services/formhelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/formhelper.service.js index 801fc7675c..7d34309396 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/formhelper.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/formhelper.service.js @@ -7,7 +7,7 @@ * A utility class used to streamline how forms are developed, to ensure that validation is check and displayed consistently and to ensure that the correct events * fire when they need to. */ -function formHelper(angularHelper, serverValidationManager, $timeout, notificationsService, dialogService, localizationService) { +function formHelper(angularHelper, serverValidationManager, $timeout, notificationsService, dialogService) { return { /** @@ -64,8 +64,7 @@ function formHelper(angularHelper, serverValidationManager, $timeout, notificati * @function * * @description - * Called by controllers when a form has been successfully submitted. the correct events execute - * and that the notifications are displayed if there are any. + * Called by controllers when a form has been successfully submitted, this ensures the correct events are raised. * * @param {object} args An object containing arguments for form submission */ @@ -77,8 +76,6 @@ function formHelper(angularHelper, serverValidationManager, $timeout, notificati throw "args.scope cannot be null"; } - this.showNotifications(args); - args.scope.$broadcast("formSubmitted", { scope: args.scope }); }, diff --git a/src/Umbraco.Web.UI.Client/src/common/services/retryqueue.service.js b/src/Umbraco.Web.UI.Client/src/common/services/retryqueue.service.js new file mode 100644 index 0000000000..16ced17075 --- /dev/null +++ b/src/Umbraco.Web.UI.Client/src/common/services/retryqueue.service.js @@ -0,0 +1,97 @@ +(function () { + 'use strict'; + + /** + * A service normally used to recover from session expiry + * @param {any} $q + * @param {any} $log + */ + function requestRetryQueue($q, $log) { + + var retryQueue = []; + var retryUser = null; + + var service = { + // The security service puts its own handler in here! + onItemAddedCallbacks: [], + + hasMore: function () { + return retryQueue.length > 0; + }, + push: function (retryItem) { + retryQueue.push(retryItem); + // Call all the onItemAdded callbacks + angular.forEach(service.onItemAddedCallbacks, function (cb) { + try { + cb(retryItem); + } catch (e) { + $log.error('requestRetryQueue.push(retryItem): callback threw an error' + e); + } + }); + }, + pushRetryFn: function (reason, userName, retryFn) { + // The reason parameter is optional + if (arguments.length === 2) { + retryFn = userName; + userName = reason; + reason = undefined; + } + + if ((retryUser && retryUser !== userName) || userName === null) { + throw new Error('invalid user'); + } + + retryUser = userName; + + // The deferred object that will be resolved or rejected by calling retry or cancel + var deferred = $q.defer(); + var retryItem = { + reason: reason, + retry: function () { + // Wrap the result of the retryFn into a promise if it is not already + $q.when(retryFn()).then(function (value) { + // If it was successful then resolve our deferred + deferred.resolve(value); + }, function (value) { + // Othewise reject it + deferred.reject(value); + }); + }, + cancel: function () { + // Give up on retrying and reject our deferred + deferred.reject(); + } + }; + service.push(retryItem); + return deferred.promise; + }, + retryReason: function () { + return service.hasMore() && retryQueue[0].reason; + }, + cancelAll: function () { + while (service.hasMore()) { + retryQueue.shift().cancel(); + } + retryUser = null; + }, + retryAll: function (userName) { + + if (retryUser == null) { + return; + } + + if (retryUser !== userName) { + service.cancelAll(); + return; + } + + while (service.hasMore()) { + retryQueue.shift().retry(); + } + } + }; + return service; + + } + angular.module('umbraco.services').factory('requestRetryQueue', requestRetryQueue); +})(); diff --git a/src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js b/src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js index c98ce34c76..26271ade2f 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/umbrequesthelper.service.js @@ -3,7 +3,8 @@ * @name umbraco.services.umbRequestHelper * @description A helper object used for sending requests to the server **/ -function umbRequestHelper($http, $q, umbDataFormatter, angularHelper, dialogService, notificationsService, eventsService) { +function umbRequestHelper($http, $q, umbDataFormatter, angularHelper, dialogService, notificationsService, eventsService, formHelper) { + return { /** @@ -24,7 +25,7 @@ function umbRequestHelper($http, $q, umbDataFormatter, angularHelper, dialogServ if (!virtualPath.startsWith("~/")) { throw "The path " + virtualPath + " is not a virtual path"; } - if (!Umbraco.Sys.ServerVariables.application.applicationPath) { + if (!Umbraco.Sys.ServerVariables.application.applicationPath) { throw "No applicationPath defined in Umbraco.ServerVariables.application.applicationPath"; } return Umbraco.Sys.ServerVariables.application.applicationPath + virtualPath.trimStart("~/"); @@ -42,7 +43,7 @@ function umbRequestHelper($http, $q, umbDataFormatter, angularHelper, dialogServ * @param {Array} queryStrings An array of key/value pairs */ dictionaryToQueryString: function (queryStrings) { - + if (angular.isArray(queryStrings)) { return _.map(queryStrings, function (item) { var key = null; @@ -63,7 +64,7 @@ function umbRequestHelper($http, $q, umbDataFormatter, angularHelper, dialogServ //this allows for a normal object to be passed in (ie. a dictionary) return decodeURIComponent($.param(queryStrings)); } - + throw "The queryString parameter is not an array or object of key value pairs"; }, @@ -116,12 +117,10 @@ function umbRequestHelper($http, $q, umbDataFormatter, angularHelper, dialogServ * The error callback must return an object containing: {errorMsg: errorMessage, data: originalData, status: status } */ resourcePromise: function (httpPromise, opts) { - var deferred = $q.defer(); - + /** The default success callback used if one is not supplied in the opts */ function defaultSuccess(data, status, headers, config) { //when it's successful, just return the data - console.log("succes promise", data); return data; } @@ -141,13 +140,15 @@ function umbRequestHelper($http, $q, umbDataFormatter, angularHelper, dialogServ error: ((!opts || !opts.error) ? defaultError : opts.error) }; - httpPromise.then(function (response) { + return httpPromise.then(function (response) { //invoke the callback var result = callbacks.success.apply(this, [response.data, response.status, response.headers, response.config]); + + formHelper.showNotifications(response.data); //when it's successful, just return the data - deferred.resolve(result); + return $q.resolve(result); }, function (response) { @@ -169,24 +170,23 @@ function umbRequestHelper($http, $q, umbDataFormatter, angularHelper, dialogServ //show a simple error notification notificationsService.error("Server error", "Contact administrator, see log for full details.
                " + result.errorMsg + ""); } - + + } + else { + formHelper.showNotifications(result.data); } //return an error object including the error message for UI - deferred.reject({ + return $q.reject({ errorMsg: result.errorMsg, data: result.data, status: result.status - }); - - + }) }); - return deferred.promise; - }, - /** Used for saving media/content specifically */ + /** Used for saving content/media/members specifically */ postSaveContent: function (args) { if (!args.restApiUrl) { @@ -204,10 +204,7 @@ function umbRequestHelper($http, $q, umbDataFormatter, angularHelper, dialogServ if (!args.dataFormatter) { throw "args.dataFormatter is a required argument"; } - - - var deferred = $q.defer(); - + //save the active tab id so we can set it when the data is returned. var activeTab = _.find(args.content.tabs, function (item) { return item.active; @@ -215,9 +212,10 @@ function umbRequestHelper($http, $q, umbDataFormatter, angularHelper, dialogServ var activeTabIndex = (activeTab === undefined ? 0 : _.indexOf(args.content.tabs, activeTab)); //save the data - this.postMultiPartRequest( + return this.postMultiPartRequest( args.restApiUrl, { key: "contentItem", value: args.dataFormatter(args.content, args.action) }, + //data transform callback: function (data, formData) { //now add all of the assigned files for (var f in args.files) { @@ -225,64 +223,63 @@ function umbRequestHelper($http, $q, umbDataFormatter, angularHelper, dialogServ // so we know which property it belongs to on the server side formData.append("file_" + args.files[f].alias, args.files[f].file); } - - }, - function (data, status, headers, config) { + }).then(function (response) { //success callback //reset the tabs and set the active one - if(data.tabs && data.tabs.length > 0) { - _.each(data.tabs, function (item) { + if (response.data.tabs && response.data.tabs.length > 0) { + _.each(response.data.tabs, function (item) { item.active = false; }); - data.tabs[activeTabIndex].active = true; + response.data.tabs[activeTabIndex].active = true; } + + formHelper.showNotifications(response.data); //the data returned is the up-to-date data so the UI will refresh - deferred.resolve(data); - }, - function (data, status, headers, config) { + return $q.resolve(response.data); + }, function (response) { //failure callback //when there's a 500 (unhandled) error show a YSOD overlay if debugging is enabled. - if (status >= 500 && status < 600) { + if (response.status >= 500 && response.status < 600) { //This is a bit of a hack to check if the error is due to a file being uploaded that is too large, // we have to just check for the existence of a string value but currently that is the best way to // do this since it's very hacky/difficult to catch this on the server - if (typeof data !== "undefined" && typeof data.indexOf === "function" && data.indexOf("Maximum request length exceeded") >= 0) { + if (typeof response.data !== "undefined" && typeof response.data.indexOf === "function" && response.data.indexOf("Maximum request length exceeded") >= 0) { notificationsService.error("Server error", "The uploaded file was too large, check with your site administrator to adjust the maximum size allowed"); - } + } else if (Umbraco.Sys.ServerVariables["isDebuggingEnabled"] === true) { //show a ysod dialog eventsService.emit('app.ysod', { errorMsg: 'An error occured', - data: data + data: response.data }); } else { //show a simple error notification - notificationsService.error("Server error", "Contact administrator, see log for full details.
                " + data.ExceptionMessage + ""); + notificationsService.error("Server error", "Contact administrator, see log for full details.
                " + response.data.ExceptionMessage + ""); } - + } - + else { + formHelper.showNotifications(response.data); + } + //return an error object including the error message for UI - deferred.reject({ + return $q.reject({ errorMsg: 'An error occurred', - data: data, - status: status + data: response.data, + status: response.status }); - }); - - return deferred.promise; }, /** Posts a multi-part mime request to the server */ - postMultiPartRequest: function (url, jsonData, transformCallback, successCallback, failureCallback) { + postMultiPartRequest: function (url, jsonData, transformCallback) { //validate input, jsonData can be an array of key/value pairs or just one key/value pair. if (!jsonData) { throw "jsonData cannot be null"; } @@ -293,9 +290,8 @@ function umbRequestHelper($http, $q, umbDataFormatter, angularHelper, dialogServ }); } else if (!jsonData.key || !jsonData.value) { throw "jsonData object must have both a key and a value property"; } - - - $http({ + + return $http({ method: 'POST', url: url, //IMPORTANT!!! You might think this should be set to 'multipart/form-data' but this is not true because when we are sending up files @@ -303,11 +299,11 @@ function umbRequestHelper($http, $q, umbDataFormatter, angularHelper, dialogServ // and setting the Content-type manually will not set this boundary parameter. For whatever reason, setting the Content-type to 'undefined' // will force the request to automatically populate the headers properly including the boundary parameter. headers: { 'Content-Type': undefined }, - transformRequest: function (data) { + transformRequest: function(data) { var formData = new FormData(); //add the json data if (angular.isArray(data)) { - _.each(data, function (item) { + _.each(data, function(item) { formData.append(item.key, !angular.isString(item.value) ? angular.toJson(item.value) : item.value); }); } @@ -323,16 +319,10 @@ function umbRequestHelper($http, $q, umbDataFormatter, angularHelper, dialogServ return formData; }, data: jsonData - }). - then(function (response) { - if (successCallback) { - successCallback.apply(this, [response.data, response.status, response.headers, response.config]); - } - }). - catch(function (response) { - if (failureCallback) { - failureCallback.apply(this, [response.data, response.status, response.headers, response.config]); - } + }).then(function(response) { + return $q.resolve(response); + }, function(response) { + return $q.reject(response); }); }, @@ -343,17 +333,15 @@ function umbRequestHelper($http, $q, umbDataFormatter, angularHelper, dialogServ */ downloadFile : function (httpPath) { - var deferred = $q.defer(); - // Use an arraybuffer - $http.get(httpPath, { responseType: 'arraybuffer' }) - .success(function (data, status, headers) { - + return $http.get(httpPath, { responseType: 'arraybuffer' }) + .then(function (response) { + var octetStreamMime = 'application/octet-stream'; var success = false; // Get the headers - headers = headers(); + var headers = response.headers(); // Get the filename from the x-filename header or default to "download.bin" var filename = headers['x-filename'] || 'download.bin'; @@ -363,8 +351,7 @@ function umbRequestHelper($http, $q, umbDataFormatter, angularHelper, dialogServ try { // Try using msSaveBlob if supported - console.log("Trying saveBlob method ..."); - var blob = new Blob([data], { type: contentType }); + var blob = new Blob([response.data], { type: contentType }); if (navigator.msSaveBlob) navigator.msSaveBlob(blob, filename); else { @@ -373,7 +360,6 @@ function umbRequestHelper($http, $q, umbDataFormatter, angularHelper, dialogServ if (saveBlob === undefined) throw "Not supported"; saveBlob(blob, filename); } - console.log("saveBlob succeeded"); success = true; } catch (ex) { console.log("saveBlob method failed with the following exception:"); @@ -390,8 +376,7 @@ function umbRequestHelper($http, $q, umbDataFormatter, angularHelper, dialogServ // Try to simulate a click try { // Prepare a blob URL - console.log("Trying download link method with simulated click ..."); - var blob = new Blob([data], { type: contentType }); + var blob = new Blob([response.data], { type: contentType }); var url = urlCreator.createObjectURL(blob); link.setAttribute('href', url); @@ -402,7 +387,6 @@ function umbRequestHelper($http, $q, umbDataFormatter, angularHelper, dialogServ var event = document.createEvent('MouseEvents'); event.initMouseEvent('click', true, true, window, 1, 0, 0, 0, 0, false, false, false, false, 0, null); link.dispatchEvent(event); - console.log("Download link method with simulated click succeeded"); success = true; } catch (ex) { @@ -416,11 +400,9 @@ function umbRequestHelper($http, $q, umbDataFormatter, angularHelper, dialogServ try { // Prepare a blob URL // Use application/octet-stream when using window.location to force download - console.log("Trying download link method with window.location ..."); - var blob = new Blob([data], { type: octetStreamMime }); + var blob = new Blob([response.data], { type: octetStreamMime }); var url = urlCreator.createObjectURL(blob); window.location = url; - console.log("Download link method with window.location succeeded"); success = true; } catch (ex) { console.log("Download link method with window.location failed with the following exception:"); @@ -433,23 +415,19 @@ function umbRequestHelper($http, $q, umbDataFormatter, angularHelper, dialogServ if (!success) { // Fallback to window.open method - console.log("No methods worked for saving the arraybuffer, using last resort window.open"); window.open(httpPath, '_blank', ''); } - deferred.resolve(); - }) - .error(function (data, status) { - console.log("Request failed with status: " + status); + return $q.resolve(); - deferred.reject({ + }, function (response) { + + return $q.reject({ errorMsg: "An error occurred downloading the file", - data: data, - status: status + data: response.data, + status: response.status }); }); - - return deferred.promise; } }; } diff --git a/src/Umbraco.Web.UI.Client/src/common/services/user.service.js b/src/Umbraco.Web.UI.Client/src/common/services/user.service.js index 34aa6295b9..13743e01f3 100644 --- a/src/Umbraco.Web.UI.Client/src/common/services/user.service.js +++ b/src/Umbraco.Web.UI.Client/src/common/services/user.service.js @@ -1,5 +1,5 @@ angular.module('umbraco.services') - .factory('userService', function ($rootScope, eventsService, $q, $location, $log, securityRetryQueue, authResource, dialogService, $timeout, angularHelper, $http) { + .factory('userService', function ($rootScope, eventsService, $q, $location, $log, requestRetryQueue, authResource, dialogService, $timeout, angularHelper, $http) { var currentUser = null; var lastUserId = null; @@ -32,10 +32,10 @@ angular.module('umbraco.services') loginDialog = null; if (success) { - securityRetryQueue.retryAll(currentUser.name); + requestRetryQueue.retryAll(currentUser.name); } else { - securityRetryQueue.cancelAll(); + requestRetryQueue.cancelAll(); $location.path('/'); } } @@ -172,8 +172,8 @@ angular.module('umbraco.services') } // Register a handler for when an item is added to the retry queue - securityRetryQueue.onItemAddedCallbacks.push(function (retryItem) { - if (securityRetryQueue.hasMore()) { + requestRetryQueue.onItemAddedCallbacks.push(function (retryItem) { + if (requestRetryQueue.hasMore()) { userAuthExpired(); } }); @@ -260,10 +260,10 @@ angular.module('umbraco.services') } setCurrentUser(data); - + return $q.when(currentUser); }, function () { - //it failed, so they are not logged in + //it failed, so they are not logged in return $q.reject(currentUser); }); diff --git a/src/Umbraco.Web.UI.Client/src/loader.dev.js b/src/Umbraco.Web.UI.Client/src/loader.dev.js index 6fa09f00d9..c702966b4b 100644 --- a/src/Umbraco.Web.UI.Client/src/loader.dev.js +++ b/src/Umbraco.Web.UI.Client/src/loader.dev.js @@ -35,7 +35,7 @@ LazyLoad.js( 'js/umbraco.filters.js', 'js/umbraco.resources.js', 'js/umbraco.services.js', - 'js/umbraco.security.js', + 'js/umbraco.interceptors.js', 'js/umbraco.controllers.js', 'js/routes.js', 'js/init.js' @@ -46,4 +46,4 @@ LazyLoad.js( angular.bootstrap(document, ['umbraco']); }); } -); \ No newline at end of file +); diff --git a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/login.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/login.controller.js index 62fc5779c7..7116a6e6e2 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/dialogs/login.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/dialogs/login.controller.js @@ -144,7 +144,7 @@ .then(function (data) { //success - formHelper.resetForm({ scope: $scope, notifications: data.notifications }); + formHelper.resetForm({ scope: $scope }); $scope.invitedUserPasswordModel.buttonState = "success"; //set the user and set them as logged in $scope.invitedUser = data; diff --git a/src/Umbraco.Web.UI.Client/src/views/common/overlays/publish/publish.html b/src/Umbraco.Web.UI.Client/src/views/common/overlays/publish/publish.html index 38a460801e..f2d1921e1f 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/overlays/publish/publish.html +++ b/src/Umbraco.Web.UI.Client/src/views/common/overlays/publish/publish.html @@ -10,9 +10,9 @@
                -
                +
                -

                diff --git a/src/Umbraco.Web.UI.Client/src/views/common/overlays/user/user.controller.js b/src/Umbraco.Web.UI.Client/src/views/common/overlays/user/user.controller.js index 108a7589f6..3147989821 100644 --- a/src/Umbraco.Web.UI.Client/src/views/common/overlays/user/user.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/common/overlays/user/user.controller.js @@ -147,7 +147,7 @@ angular.module("umbraco") $scope.changePasswordModel.value.generatedPassword = data.value; } - formHelper.resetForm({ scope: $scope, notifications: data.notifications }); + formHelper.resetForm({ scope: $scope }); $scope.changePasswordButtonState = "success"; $timeout(function() { diff --git a/src/Umbraco.Web.UI.Client/src/views/content/content.copy.controller.js b/src/Umbraco.Web.UI.Client/src/views/content/content.copy.controller.js index e8b5bbf2c3..f456d7f13e 100644 --- a/src/Umbraco.Web.UI.Client/src/views/content/content.copy.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/content/content.copy.controller.js @@ -100,13 +100,7 @@ angular.module("umbraco").controller("Umbraco.Editors.Content.CopyController", }, function (err) { $scope.success = false; $scope.error = err; - $scope.busy = false; - //show any notifications - if (angular.isArray(err.data.notifications)) { - for (var i = 0; i < err.data.notifications.length; i++) { - notificationsService.showNotification(err.data.notifications[i]); - } - } + $scope.busy = false; }); }; diff --git a/src/Umbraco.Web.UI.Client/src/views/content/content.createblueprint.controller.js b/src/Umbraco.Web.UI.Client/src/views/content/content.createblueprint.controller.js index 7769c39ad3..361ce36b72 100644 --- a/src/Umbraco.Web.UI.Client/src/views/content/content.createblueprint.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/content/content.createblueprint.controller.js @@ -33,7 +33,7 @@ contentResource.createBlueprintFromContent($scope.currentNode.id, $scope.message.name) .then(function(data) { - formHelper.resetForm({ scope: $scope, notifications: data.notifications }); + formHelper.resetForm({ scope: $scope }); navigationService.hideMenu(); }, diff --git a/src/Umbraco.Web.UI.Client/src/views/content/content.delete.controller.js b/src/Umbraco.Web.UI.Client/src/views/content/content.delete.controller.js index b0b7fc2312..863d06444c 100644 --- a/src/Umbraco.Web.UI.Client/src/views/content/content.delete.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/content/content.delete.controller.js @@ -54,12 +54,6 @@ function ContentDeleteController($scope, contentResource, treeService, navigatio if (err.status && err.status >= 500) { dialogService.ysodDialog(err); } - - if (err.data && angular.isArray(err.data.notifications)) { - for (var i = 0; i < err.data.notifications.length; i++) { - notificationsService.showNotification(err.data.notifications[i]); - } - } }); }; diff --git a/src/Umbraco.Web.UI.Client/src/views/content/content.emptyrecyclebin.controller.js b/src/Umbraco.Web.UI.Client/src/views/content/content.emptyrecyclebin.controller.js index 9077598424..23b872674b 100644 --- a/src/Umbraco.Web.UI.Client/src/views/content/content.emptyrecyclebin.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/content/content.emptyrecyclebin.controller.js @@ -20,14 +20,7 @@ function ContentEmptyRecycleBinController($scope, contentResource, treeService, $scope.busy = false; $scope.currentNode.loading = false; - - //show any notifications - if (angular.isArray(result.notifications)) { - for (var i = 0; i < result.notifications.length; i++) { - notificationsService.showNotification(result.notifications[i]); - } - } - + treeService.removeChildNodes($scope.currentNode); navigationService.hideMenu(); diff --git a/src/Umbraco.Web.UI.Client/src/views/content/content.move.controller.js b/src/Umbraco.Web.UI.Client/src/views/content/content.move.controller.js index d978d1673c..d6b5c44523 100644 --- a/src/Umbraco.Web.UI.Client/src/views/content/content.move.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/content/content.move.controller.js @@ -102,12 +102,7 @@ angular.module("umbraco").controller("Umbraco.Editors.Content.MoveController", $scope.success = false; $scope.error = err; $scope.busy = false; - //show any notifications - if (angular.isArray(err.data.notifications)) { - for (var i = 0; i < err.data.notifications.length; i++) { - notificationsService.showNotification(err.data.notifications[i]); - } - } + }); }; diff --git a/src/Umbraco.Web.UI.Client/src/views/datatypes/datatype.edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/datatypes/datatype.edit.controller.js index ffee603bc2..7c231e6120 100644 --- a/src/Umbraco.Web.UI.Client/src/views/datatypes/datatype.edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/datatypes/datatype.edit.controller.js @@ -143,7 +143,7 @@ function DataTypeEditController($scope, $routeParams, $location, appState, navig dataTypeResource.save($scope.content, $scope.preValues, $routeParams.create) .then(function(data) { - formHelper.resetForm({ scope: $scope, notifications: data.notifications }); + formHelper.resetForm({ scope: $scope }); contentEditingHelper.handleSuccessfulSave({ scope: $scope, diff --git a/src/Umbraco.Web.UI.Client/src/views/datatypes/move.controller.js b/src/Umbraco.Web.UI.Client/src/views/datatypes/move.controller.js index 66863e6e87..a5daf0cb98 100644 --- a/src/Umbraco.Web.UI.Client/src/views/datatypes/move.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/datatypes/move.controller.js @@ -51,12 +51,7 @@ angular.module("umbraco") $scope.success = false; $scope.error = err; $scope.busy = false; - //show any notifications - if (angular.isArray(err.data.notifications)) { - for (var i = 0; i < err.data.notifications.length; i++) { - notificationsService.showNotification(err.data.notifications[i]); - } - } + }); }; diff --git a/src/Umbraco.Web.UI.Client/src/views/documenttypes/copy.controller.js b/src/Umbraco.Web.UI.Client/src/views/documenttypes/copy.controller.js index 11af7448d1..3dd5b0f0bc 100644 --- a/src/Umbraco.Web.UI.Client/src/views/documenttypes/copy.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/documenttypes/copy.controller.js @@ -46,12 +46,7 @@ angular.module("umbraco") $scope.success = false; $scope.error = err; $scope.busy = false; - //show any notifications - if (angular.isArray(err.data.notifications)) { - for (var i = 0; i < err.data.notifications.length; i++) { - notificationsService.showNotification(err.data.notifications[i]); - } - } + }); }; diff --git a/src/Umbraco.Web.UI.Client/src/views/documenttypes/create.controller.js b/src/Umbraco.Web.UI.Client/src/views/documenttypes/create.controller.js index 8d7d7d7839..10e04c0384 100644 --- a/src/Umbraco.Web.UI.Client/src/views/documenttypes/create.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/documenttypes/create.controller.js @@ -40,9 +40,7 @@ function DocumentTypesCreateController($scope, $location, navigationService, con activate: true }); - formHelper.resetForm({ - scope: $scope - }); + formHelper.resetForm({ scope: $scope }); var section = appState.getSectionState("currentSection"); @@ -50,12 +48,6 @@ function DocumentTypesCreateController($scope, $location, navigationService, con $scope.error = err; - //show any notifications - if (angular.isArray(err.data.notifications)) { - for (var i = 0; i < err.data.notifications.length; i++) { - notificationsService.showNotification(err.data.notifications[i]); - } - } }); } }; diff --git a/src/Umbraco.Web.UI.Client/src/views/documenttypes/move.controller.js b/src/Umbraco.Web.UI.Client/src/views/documenttypes/move.controller.js index 1ae38920d8..d3965ea576 100644 --- a/src/Umbraco.Web.UI.Client/src/views/documenttypes/move.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/documenttypes/move.controller.js @@ -51,12 +51,7 @@ angular.module("umbraco") $scope.success = false; $scope.error = err; $scope.busy = false; - //show any notifications - if (angular.isArray(err.data.notifications)) { - for (var i = 0; i < err.data.notifications.length; i++) { - notificationsService.showNotification(err.data.notifications[i]); - } - } + }); }; diff --git a/src/Umbraco.Web.UI.Client/src/views/documenttypes/rename.controller.js b/src/Umbraco.Web.UI.Client/src/views/documenttypes/rename.controller.js index 49e9591496..bcfa9e7ec7 100644 --- a/src/Umbraco.Web.UI.Client/src/views/documenttypes/rename.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/documenttypes/rename.controller.js @@ -1,12 +1,6 @@ angular.module("umbraco") .controller("Umbraco.Editors.ContentTypeContainers.RenameController", - [ - "$scope", - "$injector", - "navigationService", - "notificationsService", - "localizationService", - function (scope, injector, navigationService, notificationsService, localizationService) { + function(scope, injector, navigationService, notificationsService, localizationService) { var notificationHeader; function reportSuccessAndClose(treeName) { @@ -25,7 +19,7 @@ localizationService.localize( "renamecontainer_folderWasRenamed", [scope.currentNode.name, scope.model.folderName]) - .then(function (msg) { + .then(function(msg) { notificationsService.showNotification({ type: 0, header: notificationHeader, @@ -37,27 +31,21 @@ } localizationService.localize("renamecontainer_renamed") - .then(function (s) { notificationHeader = s; }); + .then(function(s) { notificationHeader = s; }); scope.model = { folderName: scope.currentNode.name } - scope.renameContainer = function (resourceKey, treeName) { + scope.renameContainer = function(resourceKey, treeName) { var resource = injector.get(resourceKey); resource.renameContainer(scope.currentNode.id, scope.model.folderName) - .then(function () { + .then(function() { reportSuccessAndClose(treeName); - }, function (err) { + }, function(err) { scope.error = err; - - if (angular.isArray(err.data.notifications)) { - for (var i = 0; i < err.data.notifications.length; i++) { - notificationsService.showNotification(err.data.notifications[i]); - } - } }); } } - ]); \ No newline at end of file + ); diff --git a/src/Umbraco.Web.UI.Client/src/views/languages/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/languages/edit.controller.js index 1bbbfd0ab4..8b6a6f8ef9 100644 --- a/src/Umbraco.Web.UI.Client/src/views/languages/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/languages/edit.controller.js @@ -85,9 +85,7 @@ languageResource.save(vm.language).then(function (lang) { - formHelper.resetForm({ - scope: $scope - }); + formHelper.resetForm({ scope: $scope }); vm.language = lang; vm.page.saveButtonState = "success"; @@ -108,12 +106,6 @@ formHelper.handleError(err); - //show any notifications - if (angular.isArray(err.data.notifications)) { - for (var i = 0; i < err.data.notifications.length; i++) { - notificationsService.showNotification(err.data.notifications[i]); - } - } }); } diff --git a/src/Umbraco.Web.UI.Client/src/views/languages/overview.controller.js b/src/Umbraco.Web.UI.Client/src/views/languages/overview.controller.js index de05ac7079..c81f93c7d6 100644 --- a/src/Umbraco.Web.UI.Client/src/views/languages/overview.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/languages/overview.controller.js @@ -70,12 +70,6 @@ }, function (err) { language.deleteButtonState = "error"; - //show any notifications - if (angular.isArray(err.data.notifications)) { - for (var i = 0; i < err.data.notifications.length; i++) { - notificationsService.showNotification(err.data.notifications[i]); - } - } }); } diff --git a/src/Umbraco.Web.UI.Client/src/views/media/media.delete.controller.js b/src/Umbraco.Web.UI.Client/src/views/media/media.delete.controller.js index a8be3d0be5..b0498fcb32 100644 --- a/src/Umbraco.Web.UI.Client/src/views/media/media.delete.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/media/media.delete.controller.js @@ -56,11 +56,6 @@ function MediaDeleteController($scope, mediaResource, treeService, navigationSer dialogService.ysodDialog(err); } - if (err.data && angular.isArray(err.data.notifications)) { - for (var i = 0; i < err.data.notifications.length; i++) { - notificationsService.showNotification(err.data.notifications[i]); - } - } }); }; diff --git a/src/Umbraco.Web.UI.Client/src/views/media/media.edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/media/media.edit.controller.js index 49f65b4579..2e5f0a5319 100644 --- a/src/Umbraco.Web.UI.Client/src/views/media/media.edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/media/media.edit.controller.js @@ -191,7 +191,7 @@ function mediaEditController($scope, $routeParams, appState, mediaResource, enti mediaResource.save($scope.content, create, fileManager.getFiles()) .then(function(data) { - formHelper.resetForm({ scope: $scope, notifications: data.notifications }); + formHelper.resetForm({ scope: $scope }); contentEditingHelper.handleSuccessfulSave({ scope: $scope, @@ -226,13 +226,6 @@ function mediaEditController($scope, $routeParams, appState, mediaResource, enti rebindCallback: contentEditingHelper.reBindChangedProperties($scope.content, err.data) }); - //show any notifications - if (angular.isArray(err.data.notifications)) { - for (var i = 0; i < err.data.notifications.length; i++) { - notificationsService.showNotification(err.data.notifications[i]); - } - } - editorState.set($scope.content); $scope.busy = false; $scope.page.saveButtonState = "error"; diff --git a/src/Umbraco.Web.UI.Client/src/views/media/media.emptyrecyclebin.controller.js b/src/Umbraco.Web.UI.Client/src/views/media/media.emptyrecyclebin.controller.js index 218654b464..64dd8678c5 100644 --- a/src/Umbraco.Web.UI.Client/src/views/media/media.emptyrecyclebin.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/media/media.emptyrecyclebin.controller.js @@ -21,13 +21,6 @@ function MediaEmptyRecycleBinController($scope, mediaResource, treeService, navi $scope.busy = false; $scope.currentNode.loading = false; - //show any notifications - if (angular.isArray(result.notifications)) { - for (var i = 0; i < result.notifications.length; i++) { - notificationsService.showNotification(result.notifications[i]); - } - } - treeService.removeChildNodes($scope.currentNode); navigationService.hideMenu(); diff --git a/src/Umbraco.Web.UI.Client/src/views/mediatypes/copy.controller.js b/src/Umbraco.Web.UI.Client/src/views/mediatypes/copy.controller.js index 62d7a6be35..b1fb85d31d 100644 --- a/src/Umbraco.Web.UI.Client/src/views/mediatypes/copy.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/mediatypes/copy.controller.js @@ -46,12 +46,7 @@ angular.module("umbraco") $scope.success = false; $scope.error = err; $scope.busy = false; - //show any notifications - if (angular.isArray(err.data.notifications)) { - for (var i = 0; i < err.data.notifications.length; i++) { - notificationsService.showNotification(err.data.notifications[i]); - } - } + }); }; diff --git a/src/Umbraco.Web.UI.Client/src/views/mediatypes/move.controller.js b/src/Umbraco.Web.UI.Client/src/views/mediatypes/move.controller.js index d2990c0c9d..f0be370634 100644 --- a/src/Umbraco.Web.UI.Client/src/views/mediatypes/move.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/mediatypes/move.controller.js @@ -52,12 +52,7 @@ angular.module("umbraco") $scope.success = false; $scope.error = err; $scope.busy = false; - //show any notifications - if (angular.isArray(err.data.notifications)) { - for (var i = 0; i < err.data.notifications.length; i++) { - notificationsService.showNotification(err.data.notifications[i]); - } - } + }); }; diff --git a/src/Umbraco.Web.UI.Client/src/views/member/member.edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/member/member.edit.controller.js index 33fceb4c4f..cd086d575f 100644 --- a/src/Umbraco.Web.UI.Client/src/views/member/member.edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/member/member.edit.controller.js @@ -134,7 +134,7 @@ function MemberEditController($scope, $routeParams, $location, $q, $window, appS memberResource.save($scope.content, $routeParams.create, fileManager.getFiles()) .then(function(data) { - formHelper.resetForm({ scope: $scope, notifications: data.notifications }); + formHelper.resetForm({ scope: $scope }); contentEditingHelper.handleSuccessfulSave({ scope: $scope, diff --git a/src/Umbraco.Web.UI.Client/src/views/membergroups/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/membergroups/edit.controller.js index bcfedb01a7..c963d5c0c4 100644 --- a/src/Umbraco.Web.UI.Client/src/views/membergroups/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/membergroups/edit.controller.js @@ -67,7 +67,7 @@ function MemberGroupsEditController($scope, $routeParams, appState, navigationSe memberGroupResource.save($scope.content, $scope.preValues, $routeParams.create) .then(function (data) { - formHelper.resetForm({ scope: $scope, notifications: data.notifications }); + formHelper.resetForm({ scope: $scope }); contentEditingHelper.handleSuccessfulSave({ scope: $scope, diff --git a/src/Umbraco.Web.UI.Client/src/views/partialviewmacros/create.controller.js b/src/Umbraco.Web.UI.Client/src/views/partialviewmacros/create.controller.js index 5e08e4d4da..c72df3c15e 100644 --- a/src/Umbraco.Web.UI.Client/src/views/partialviewmacros/create.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/partialviewmacros/create.controller.js @@ -45,18 +45,14 @@ activate: true }); - formHelper.resetForm({ - scope: $scope - }); + formHelper.resetForm({ scope: $scope }); var section = appState.getSectionState("currentSection"); }, function (err) { vm.createFolderError = err; - - //show any notifications - formHelper.showNotifications(err.data); + }); } } diff --git a/src/Umbraco.Web.UI.Client/src/views/partialviewmacros/edit.controller.js b/src/Umbraco.Web.UI.Client/src/views/partialviewmacros/edit.controller.js index 9176adf66a..00551ff8ba 100644 --- a/src/Umbraco.Web.UI.Client/src/views/partialviewmacros/edit.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/partialviewmacros/edit.controller.js @@ -71,11 +71,7 @@ if($routeParams.create && $routeParams.nomacro !== "true") { macroResource.createPartialViewMacroWithFile(saved.virtualPath, saved.name).then(function(created) { completeSave(saved); - }, function(err) { - //show any notifications - formHelper.showNotifications(err.data); - - }); + }, angular.noop); } else { completeSave(saved); } diff --git a/src/Umbraco.Web.UI.Client/src/views/partialviews/create.controller.js b/src/Umbraco.Web.UI.Client/src/views/partialviews/create.controller.js index b37cd918c1..1600d88d46 100644 --- a/src/Umbraco.Web.UI.Client/src/views/partialviews/create.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/partialviews/create.controller.js @@ -55,17 +55,13 @@ activate: true }); - formHelper.resetForm({ - scope: $scope - }); + formHelper.resetForm({ scope: $scope }); var section = appState.getSectionState("currentSection"); }, function(err) { vm.createFolderError = err; - - formHelper.showNotifications(err.data); }); } } diff --git a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.controller.js b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.controller.js index 41c8216a77..21434fb826 100644 --- a/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/propertyeditors/listview/listview.controller.js @@ -216,12 +216,8 @@ function listViewController($rootScope, $scope, $routeParams, $injector, notific if (reload === true) { $scope.reloadView($scope.contentId, true); } - - if (err.data && angular.isArray(err.data.notifications)) { - for (var i = 0; i < err.data.notifications.length; i++) { - notificationsService.showNotification(err.data.notifications[i]); - } - } else if (successMsg) { + + if (successMsg) { localizationService.localize("bulk_done") .then(function(v) { notificationsService.success(v, successMsg); diff --git a/src/Umbraco.Web.UI.Client/src/views/scripts/create.controller.js b/src/Umbraco.Web.UI.Client/src/views/scripts/create.controller.js index a1fb7d6573..be196c5f64 100644 --- a/src/Umbraco.Web.UI.Client/src/views/scripts/create.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/scripts/create.controller.js @@ -39,16 +39,13 @@ activate: true }); - formHelper.resetForm({ - scope: $scope - }); + formHelper.resetForm({ scope: $scope }); var section = appState.getSectionState("currentSection"); }, function(err) { vm.createFolderError = err; - formHelper.showNotifications(err.data); }); } diff --git a/src/Umbraco.Web.UI.Client/src/views/users/user.controller.js b/src/Umbraco.Web.UI.Client/src/views/users/user.controller.js index 2f7e69e312..c9a0c48d8c 100644 --- a/src/Umbraco.Web.UI.Client/src/views/users/user.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/users/user.controller.js @@ -138,11 +138,8 @@ //if the user saved, then try to execute all extended save options extendedSave(saved).then(function(result) { //if all is good, then reset the form - formHelper.resetForm({ scope: $scope, notifications: saved.notifications }); - }, function(err) { - //otherwise show the notifications for the user being saved - formHelper.showNotifications(saved); - }); + formHelper.resetForm({ scope: $scope }); + }, angular.noop); vm.user = _.omit(saved, "navigation"); //restore @@ -162,10 +159,7 @@ redirectOnFailure: false, err: err }); - //show any notifications - if (err.data) { - formHelper.showNotifications(err.data); - } + vm.page.saveButtonState = "error"; }); } @@ -319,10 +313,10 @@ vm.user.userState = 1; setUserDisplayState(); vm.disableUserButtonState = "success"; - formHelper.showNotifications(data); + }, function (error) { vm.disableUserButtonState = "error"; - formHelper.showNotifications(error.data); + }); } @@ -332,10 +326,8 @@ vm.user.userState = 0; setUserDisplayState(); vm.enableUserButtonState = "success"; - formHelper.showNotifications(data); }, function (error) { vm.enableUserButtonState = "error"; - formHelper.showNotifications(error.data); }); } @@ -345,10 +337,8 @@ vm.user.userState = 0; setUserDisplayState(); vm.unlockUserButtonState = "success"; - formHelper.showNotifications(data); }, function (error) { vm.unlockUserButtonState = "error"; - formHelper.showNotifications(error.data); }); } diff --git a/src/Umbraco.Web.UI.Client/src/views/users/views/groups/groups.controller.js b/src/Umbraco.Web.UI.Client/src/views/users/views/groups/groups.controller.js index f636347b84..bcfb7df258 100644 --- a/src/Umbraco.Web.UI.Client/src/views/users/views/groups/groups.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/users/views/groups/groups.controller.js @@ -96,10 +96,7 @@ userGroupsResource.deleteUserGroups(vm.selection).then(function (data) { clearSelection(); onInit(); - formHelper.showNotifications(data); - }, function(error) { - formHelper.showNotifications(error.data); - }); + }, angular.noop); } }); diff --git a/src/Umbraco.Web.UI.Client/src/views/users/views/users/users.controller.js b/src/Umbraco.Web.UI.Client/src/views/users/views/users/users.controller.js index 2235f333c8..c3cee9292c 100644 --- a/src/Umbraco.Web.UI.Client/src/views/users/views/users/users.controller.js +++ b/src/Umbraco.Web.UI.Client/src/views/users/views/users/users.controller.js @@ -250,14 +250,11 @@ // show the correct badges setUserDisplayState(vm.users); - formHelper.showNotifications(data); - vm.disableUserButtonState = "init"; clearSelection(); }, function (error) { vm.disableUserButtonState = "error"; - formHelper.showNotifications(error.data); }); } @@ -273,13 +270,10 @@ }); // show the correct badges setUserDisplayState(vm.users); - // show notification - formHelper.showNotifications(data); vm.enableUserButtonState = "init"; clearSelection(); }, function (error) { vm.enableUserButtonState = "error"; - formHelper.showNotifications(error.data); }); } @@ -295,13 +289,10 @@ }); // show the correct badges setUserDisplayState(vm.users); - // show notification - formHelper.showNotifications(data); vm.unlockUserButtonState = "init"; clearSelection(); }, function (error) { vm.unlockUserButtonState = "error"; - formHelper.showNotifications(error.data); }); } @@ -334,11 +325,8 @@ vm.selectedBulkUserGroups = []; vm.userGroupPicker.show = false; vm.userGroupPicker = null; - formHelper.showNotifications(data); clearSelection(); - }, function (error) { - formHelper.showNotifications(error.data); - }); + }, angular.noop); }, close: function (oldModel) { vm.selectedBulkUserGroups = []; diff --git a/src/Umbraco.Web.UI.Client/test/config/app.unit.js b/src/Umbraco.Web.UI.Client/test/config/app.unit.js index 0f6a57d369..accf467fdc 100644 --- a/src/Umbraco.Web.UI.Client/test/config/app.unit.js +++ b/src/Umbraco.Web.UI.Client/test/config/app.unit.js @@ -4,11 +4,11 @@ var app = angular.module('umbraco', [ 'umbraco.resources', 'umbraco.services', 'umbraco.mocks', - 'umbraco.security', + 'umbraco.interceptors', 'ngCookies', 'LocalStorageModule' ]); /* For Angular 1.2: we need to load in Routing separately 'ngRoute' -*/ \ No newline at end of file +*/ diff --git a/src/Umbraco.Web/UI/JavaScript/JsInitialize.js b/src/Umbraco.Web/UI/JavaScript/JsInitialize.js index d03f825dc5..84b5591ec3 100644 --- a/src/Umbraco.Web/UI/JavaScript/JsInitialize.js +++ b/src/Umbraco.Web/UI/JavaScript/JsInitialize.js @@ -38,7 +38,7 @@ 'js/umbraco.directives.js', 'js/umbraco.filters.js', 'js/umbraco.services.js', - 'js/umbraco.security.js', + 'js/umbraco.interceptors.js', 'js/umbraco.controllers.js', 'js/routes.js', 'js/init.js' From feb16f901fab856abf45841d1be0fada7d22b304 Mon Sep 17 00:00:00 2001 From: Shannon Date: Fri, 15 Jun 2018 11:42:43 +1000 Subject: [PATCH 087/115] Updates some JS dependencies, moves more dependencies to bower instead of having them committed, ensures angular locales are workgin with 1.7, upgrades to angular 1.7.2 --- src/Umbraco.Web.UI.Client/bower.json | 31 +- src/Umbraco.Web.UI.Client/gulpfile.js | 2 +- .../lib/angular/1.1.5/angular-cookies.js | 185 - .../lib/angular/1.1.5/angular-cookies.min.js | 7 - .../lib/angular/1.1.5/angular-loader.js | 304 - .../lib/angular/1.1.5/angular-loader.min.js | 7 - .../lib/angular/1.1.5/angular-mobile.js | 462 - .../lib/angular/1.1.5/angular-mobile.min.js | 11 - .../lib/angular/1.1.5/angular-mocks.js | 1886 - .../lib/angular/1.1.5/angular-resource.js | 537 - .../lib/angular/1.1.5/angular-resource.min.js | 11 - .../lib/angular/1.1.5/angular-sanitize.js | 558 - .../lib/angular/1.1.5/angular-sanitize.min.js | 13 - .../lib/angular/1.1.5/angular-scenario.js | 28463 ---------------- .../lib/angular/1.1.5/angular.js | 16882 --------- .../lib/angular/1.1.5/angular.min.js | 178 - .../1.1.5/i18n/angular-locale_af-na.js | 98 - .../1.1.5/i18n/angular-locale_af-za.js | 98 - .../angular/1.1.5/i18n/angular-locale_af.js | 98 - .../1.1.5/i18n/angular-locale_am-et.js | 98 - .../angular/1.1.5/i18n/angular-locale_am.js | 98 - .../1.1.5/i18n/angular-locale_ar-001.js | 98 - .../1.1.5/i18n/angular-locale_ar-ae.js | 98 - .../1.1.5/i18n/angular-locale_ar-bh.js | 98 - .../1.1.5/i18n/angular-locale_ar-dz.js | 98 - .../1.1.5/i18n/angular-locale_ar-eg.js | 98 - .../1.1.5/i18n/angular-locale_ar-iq.js | 98 - .../1.1.5/i18n/angular-locale_ar-jo.js | 98 - .../1.1.5/i18n/angular-locale_ar-kw.js | 98 - .../1.1.5/i18n/angular-locale_ar-lb.js | 98 - .../1.1.5/i18n/angular-locale_ar-ly.js | 98 - .../1.1.5/i18n/angular-locale_ar-ma.js | 98 - .../1.1.5/i18n/angular-locale_ar-om.js | 98 - .../1.1.5/i18n/angular-locale_ar-qa.js | 98 - .../1.1.5/i18n/angular-locale_ar-sa.js | 98 - .../1.1.5/i18n/angular-locale_ar-sd.js | 98 - .../1.1.5/i18n/angular-locale_ar-sy.js | 98 - .../1.1.5/i18n/angular-locale_ar-tn.js | 98 - .../1.1.5/i18n/angular-locale_ar-ye.js | 98 - .../angular/1.1.5/i18n/angular-locale_ar.js | 98 - .../1.1.5/i18n/angular-locale_bg-bg.js | 98 - .../angular/1.1.5/i18n/angular-locale_bg.js | 98 - .../1.1.5/i18n/angular-locale_bn-bd.js | 98 - .../1.1.5/i18n/angular-locale_bn-in.js | 98 - .../angular/1.1.5/i18n/angular-locale_bn.js | 98 - .../1.1.5/i18n/angular-locale_ca-ad.js | 98 - .../1.1.5/i18n/angular-locale_ca-es.js | 98 - .../angular/1.1.5/i18n/angular-locale_ca.js | 98 - .../angular/1.1.5/i18n/angular-locale_chr.js | 4 - .../1.1.5/i18n/angular-locale_cs-cz.js | 98 - .../angular/1.1.5/i18n/angular-locale_cs.js | 98 - .../angular/1.1.5/i18n/angular-locale_cy.js | 4 - .../1.1.5/i18n/angular-locale_da-dk.js | 98 - .../angular/1.1.5/i18n/angular-locale_da.js | 98 - .../1.1.5/i18n/angular-locale_de-at.js | 98 - .../1.1.5/i18n/angular-locale_de-be.js | 98 - .../1.1.5/i18n/angular-locale_de-ch.js | 98 - .../1.1.5/i18n/angular-locale_de-de.js | 98 - .../1.1.5/i18n/angular-locale_de-li.js | 98 - .../1.1.5/i18n/angular-locale_de-lu.js | 98 - .../angular/1.1.5/i18n/angular-locale_de.js | 98 - .../1.1.5/i18n/angular-locale_el-cy.js | 98 - .../1.1.5/i18n/angular-locale_el-gr.js | 98 - .../1.1.5/i18n/angular-locale_el-polyton.js | 4 - .../angular/1.1.5/i18n/angular-locale_el.js | 98 - .../1.1.5/i18n/angular-locale_en-as.js | 98 - .../1.1.5/i18n/angular-locale_en-au.js | 98 - .../1.1.5/i18n/angular-locale_en-bb.js | 98 - .../1.1.5/i18n/angular-locale_en-be.js | 98 - .../1.1.5/i18n/angular-locale_en-bm.js | 98 - .../1.1.5/i18n/angular-locale_en-bw.js | 98 - .../1.1.5/i18n/angular-locale_en-bz.js | 98 - .../1.1.5/i18n/angular-locale_en-ca.js | 98 - .../1.1.5/i18n/angular-locale_en-dsrt-us.js | 98 - .../1.1.5/i18n/angular-locale_en-dsrt.js | 98 - .../1.1.5/i18n/angular-locale_en-fm.js | 98 - .../1.1.5/i18n/angular-locale_en-gb.js | 98 - .../1.1.5/i18n/angular-locale_en-gu.js | 98 - .../1.1.5/i18n/angular-locale_en-gy.js | 98 - .../1.1.5/i18n/angular-locale_en-hk.js | 98 - .../1.1.5/i18n/angular-locale_en-ie.js | 98 - .../1.1.5/i18n/angular-locale_en-in.js | 98 - .../1.1.5/i18n/angular-locale_en-iso.js | 98 - .../1.1.5/i18n/angular-locale_en-jm.js | 98 - .../1.1.5/i18n/angular-locale_en-mh.js | 98 - .../1.1.5/i18n/angular-locale_en-mp.js | 98 - .../1.1.5/i18n/angular-locale_en-mt.js | 98 - .../1.1.5/i18n/angular-locale_en-mu.js | 98 - .../1.1.5/i18n/angular-locale_en-na.js | 98 - .../1.1.5/i18n/angular-locale_en-nz.js | 98 - .../1.1.5/i18n/angular-locale_en-ph.js | 98 - .../1.1.5/i18n/angular-locale_en-pk.js | 98 - .../1.1.5/i18n/angular-locale_en-pr.js | 98 - .../1.1.5/i18n/angular-locale_en-pw.js | 98 - .../1.1.5/i18n/angular-locale_en-sg.js | 98 - .../1.1.5/i18n/angular-locale_en-tc.js | 98 - .../1.1.5/i18n/angular-locale_en-tt.js | 98 - .../1.1.5/i18n/angular-locale_en-um.js | 98 - .../1.1.5/i18n/angular-locale_en-us.js | 98 - .../1.1.5/i18n/angular-locale_en-vg.js | 98 - .../1.1.5/i18n/angular-locale_en-vi.js | 98 - .../1.1.5/i18n/angular-locale_en-za.js | 98 - .../1.1.5/i18n/angular-locale_en-zw.js | 98 - .../1.1.5/i18n/angular-locale_en-zz.js | 4 - .../angular/1.1.5/i18n/angular-locale_en.js | 98 - .../1.1.5/i18n/angular-locale_es-419.js | 98 - .../1.1.5/i18n/angular-locale_es-ar.js | 98 - .../1.1.5/i18n/angular-locale_es-bo.js | 98 - .../1.1.5/i18n/angular-locale_es-cl.js | 98 - .../1.1.5/i18n/angular-locale_es-co.js | 98 - .../1.1.5/i18n/angular-locale_es-cr.js | 98 - .../1.1.5/i18n/angular-locale_es-do.js | 98 - .../1.1.5/i18n/angular-locale_es-ea.js | 98 - .../1.1.5/i18n/angular-locale_es-ec.js | 98 - .../1.1.5/i18n/angular-locale_es-es.js | 98 - .../1.1.5/i18n/angular-locale_es-gq.js | 98 - .../1.1.5/i18n/angular-locale_es-gt.js | 98 - .../1.1.5/i18n/angular-locale_es-hn.js | 98 - .../1.1.5/i18n/angular-locale_es-ic.js | 98 - .../1.1.5/i18n/angular-locale_es-mx.js | 98 - .../1.1.5/i18n/angular-locale_es-ni.js | 98 - .../1.1.5/i18n/angular-locale_es-pa.js | 98 - .../1.1.5/i18n/angular-locale_es-pe.js | 98 - .../1.1.5/i18n/angular-locale_es-pr.js | 98 - .../1.1.5/i18n/angular-locale_es-py.js | 98 - .../1.1.5/i18n/angular-locale_es-sv.js | 98 - .../1.1.5/i18n/angular-locale_es-us.js | 98 - .../1.1.5/i18n/angular-locale_es-uy.js | 98 - .../1.1.5/i18n/angular-locale_es-ve.js | 98 - .../angular/1.1.5/i18n/angular-locale_es.js | 98 - .../1.1.5/i18n/angular-locale_et-ee.js | 98 - .../angular/1.1.5/i18n/angular-locale_et.js | 98 - .../1.1.5/i18n/angular-locale_eu-es.js | 98 - .../angular/1.1.5/i18n/angular-locale_eu.js | 98 - .../1.1.5/i18n/angular-locale_fa-af.js | 98 - .../1.1.5/i18n/angular-locale_fa-ir.js | 98 - .../angular/1.1.5/i18n/angular-locale_fa.js | 98 - .../1.1.5/i18n/angular-locale_fi-fi.js | 98 - .../angular/1.1.5/i18n/angular-locale_fi.js | 98 - .../1.1.5/i18n/angular-locale_fil-ph.js | 98 - .../angular/1.1.5/i18n/angular-locale_fil.js | 98 - .../1.1.5/i18n/angular-locale_fr-be.js | 98 - .../1.1.5/i18n/angular-locale_fr-bf.js | 98 - .../1.1.5/i18n/angular-locale_fr-bi.js | 98 - .../1.1.5/i18n/angular-locale_fr-bj.js | 98 - .../1.1.5/i18n/angular-locale_fr-bl.js | 98 - .../1.1.5/i18n/angular-locale_fr-ca.js | 98 - .../1.1.5/i18n/angular-locale_fr-cd.js | 98 - .../1.1.5/i18n/angular-locale_fr-cf.js | 98 - .../1.1.5/i18n/angular-locale_fr-cg.js | 98 - .../1.1.5/i18n/angular-locale_fr-ch.js | 98 - .../1.1.5/i18n/angular-locale_fr-ci.js | 98 - .../1.1.5/i18n/angular-locale_fr-cm.js | 98 - .../1.1.5/i18n/angular-locale_fr-dj.js | 98 - .../1.1.5/i18n/angular-locale_fr-fr.js | 98 - .../1.1.5/i18n/angular-locale_fr-ga.js | 98 - .../1.1.5/i18n/angular-locale_fr-gf.js | 98 - .../1.1.5/i18n/angular-locale_fr-gn.js | 98 - .../1.1.5/i18n/angular-locale_fr-gp.js | 98 - .../1.1.5/i18n/angular-locale_fr-gq.js | 98 - .../1.1.5/i18n/angular-locale_fr-km.js | 98 - .../1.1.5/i18n/angular-locale_fr-lu.js | 98 - .../1.1.5/i18n/angular-locale_fr-mc.js | 98 - .../1.1.5/i18n/angular-locale_fr-mf.js | 98 - .../1.1.5/i18n/angular-locale_fr-mg.js | 98 - .../1.1.5/i18n/angular-locale_fr-ml.js | 98 - .../1.1.5/i18n/angular-locale_fr-mq.js | 98 - .../1.1.5/i18n/angular-locale_fr-ne.js | 98 - .../1.1.5/i18n/angular-locale_fr-re.js | 98 - .../1.1.5/i18n/angular-locale_fr-rw.js | 98 - .../1.1.5/i18n/angular-locale_fr-sn.js | 98 - .../1.1.5/i18n/angular-locale_fr-td.js | 98 - .../1.1.5/i18n/angular-locale_fr-tg.js | 98 - .../1.1.5/i18n/angular-locale_fr-yt.js | 98 - .../angular/1.1.5/i18n/angular-locale_fr.js | 98 - .../1.1.5/i18n/angular-locale_gl-es.js | 98 - .../angular/1.1.5/i18n/angular-locale_gl.js | 98 - .../1.1.5/i18n/angular-locale_gsw-ch.js | 98 - .../angular/1.1.5/i18n/angular-locale_gsw.js | 98 - .../1.1.5/i18n/angular-locale_gu-in.js | 98 - .../angular/1.1.5/i18n/angular-locale_gu.js | 98 - .../angular/1.1.5/i18n/angular-locale_haw.js | 4 - .../1.1.5/i18n/angular-locale_he-il.js | 98 - .../angular/1.1.5/i18n/angular-locale_he.js | 98 - .../1.1.5/i18n/angular-locale_hi-in.js | 98 - .../angular/1.1.5/i18n/angular-locale_hi.js | 98 - .../1.1.5/i18n/angular-locale_hr-hr.js | 98 - .../angular/1.1.5/i18n/angular-locale_hr.js | 98 - .../1.1.5/i18n/angular-locale_hu-hu.js | 98 - .../angular/1.1.5/i18n/angular-locale_hu.js | 98 - .../1.1.5/i18n/angular-locale_id-id.js | 98 - .../angular/1.1.5/i18n/angular-locale_id.js | 98 - .../angular/1.1.5/i18n/angular-locale_in.js | 98 - .../1.1.5/i18n/angular-locale_is-is.js | 98 - .../angular/1.1.5/i18n/angular-locale_is.js | 98 - .../1.1.5/i18n/angular-locale_it-ch.js | 98 - .../1.1.5/i18n/angular-locale_it-it.js | 98 - .../1.1.5/i18n/angular-locale_it-sm.js | 98 - .../angular/1.1.5/i18n/angular-locale_it.js | 98 - .../angular/1.1.5/i18n/angular-locale_iw.js | 98 - .../1.1.5/i18n/angular-locale_ja-jp.js | 98 - .../angular/1.1.5/i18n/angular-locale_ja.js | 98 - .../1.1.5/i18n/angular-locale_kn-in.js | 98 - .../angular/1.1.5/i18n/angular-locale_kn.js | 98 - .../1.1.5/i18n/angular-locale_ko-kr.js | 98 - .../angular/1.1.5/i18n/angular-locale_ko.js | 98 - .../1.1.5/i18n/angular-locale_ln-cd.js | 98 - .../1.1.5/i18n/angular-locale_ln-cg.js | 98 - .../angular/1.1.5/i18n/angular-locale_ln.js | 98 - .../1.1.5/i18n/angular-locale_lt-lt.js | 98 - .../angular/1.1.5/i18n/angular-locale_lt.js | 98 - .../1.1.5/i18n/angular-locale_lv-lv.js | 98 - .../angular/1.1.5/i18n/angular-locale_lv.js | 98 - .../1.1.5/i18n/angular-locale_ml-in.js | 98 - .../angular/1.1.5/i18n/angular-locale_ml.js | 98 - .../angular/1.1.5/i18n/angular-locale_mo.js | 4 - .../1.1.5/i18n/angular-locale_mr-in.js | 98 - .../angular/1.1.5/i18n/angular-locale_mr.js | 98 - .../1.1.5/i18n/angular-locale_ms-bn.js | 98 - .../1.1.5/i18n/angular-locale_ms-my.js | 98 - .../angular/1.1.5/i18n/angular-locale_ms.js | 98 - .../1.1.5/i18n/angular-locale_mt-mt.js | 98 - .../angular/1.1.5/i18n/angular-locale_mt.js | 98 - .../1.1.5/i18n/angular-locale_nl-aw.js | 98 - .../1.1.5/i18n/angular-locale_nl-be.js | 98 - .../1.1.5/i18n/angular-locale_nl-cw.js | 98 - .../1.1.5/i18n/angular-locale_nl-nl.js | 98 - .../1.1.5/i18n/angular-locale_nl-sx.js | 98 - .../angular/1.1.5/i18n/angular-locale_nl.js | 98 - .../angular/1.1.5/i18n/angular-locale_no.js | 98 - .../1.1.5/i18n/angular-locale_or-in.js | 98 - .../angular/1.1.5/i18n/angular-locale_or.js | 98 - .../1.1.5/i18n/angular-locale_pl-pl.js | 98 - .../angular/1.1.5/i18n/angular-locale_pl.js | 98 - .../1.1.5/i18n/angular-locale_pt-ao.js | 98 - .../1.1.5/i18n/angular-locale_pt-br.js | 98 - .../1.1.5/i18n/angular-locale_pt-gw.js | 98 - .../1.1.5/i18n/angular-locale_pt-mz.js | 98 - .../1.1.5/i18n/angular-locale_pt-pt.js | 98 - .../1.1.5/i18n/angular-locale_pt-st.js | 98 - .../angular/1.1.5/i18n/angular-locale_pt.js | 98 - .../1.1.5/i18n/angular-locale_ro-md.js | 98 - .../1.1.5/i18n/angular-locale_ro-ro.js | 98 - .../angular/1.1.5/i18n/angular-locale_ro.js | 98 - .../1.1.5/i18n/angular-locale_ru-md.js | 98 - .../1.1.5/i18n/angular-locale_ru-ru.js | 98 - .../1.1.5/i18n/angular-locale_ru-ua.js | 98 - .../angular/1.1.5/i18n/angular-locale_ru.js | 98 - .../1.1.5/i18n/angular-locale_sk-sk.js | 98 - .../angular/1.1.5/i18n/angular-locale_sk.js | 98 - .../1.1.5/i18n/angular-locale_sl-si.js | 98 - .../angular/1.1.5/i18n/angular-locale_sl.js | 98 - .../1.1.5/i18n/angular-locale_sq-al.js | 98 - .../angular/1.1.5/i18n/angular-locale_sq.js | 98 - .../1.1.5/i18n/angular-locale_sr-cyrl-ba.js | 98 - .../1.1.5/i18n/angular-locale_sr-cyrl-me.js | 98 - .../1.1.5/i18n/angular-locale_sr-cyrl-rs.js | 98 - .../1.1.5/i18n/angular-locale_sr-cyrl.js | 98 - .../1.1.5/i18n/angular-locale_sr-latn-ba.js | 98 - .../1.1.5/i18n/angular-locale_sr-latn-me.js | 98 - .../1.1.5/i18n/angular-locale_sr-latn-rs.js | 98 - .../1.1.5/i18n/angular-locale_sr-latn.js | 98 - .../1.1.5/i18n/angular-locale_sr-rs.js | 4 - .../angular/1.1.5/i18n/angular-locale_sr.js | 98 - .../1.1.5/i18n/angular-locale_sv-fi.js | 98 - .../1.1.5/i18n/angular-locale_sv-se.js | 98 - .../angular/1.1.5/i18n/angular-locale_sv.js | 98 - .../1.1.5/i18n/angular-locale_sw-ke.js | 98 - .../1.1.5/i18n/angular-locale_sw-tz.js | 98 - .../angular/1.1.5/i18n/angular-locale_sw.js | 98 - .../1.1.5/i18n/angular-locale_ta-in.js | 98 - .../1.1.5/i18n/angular-locale_ta-lk.js | 98 - .../angular/1.1.5/i18n/angular-locale_ta.js | 98 - .../1.1.5/i18n/angular-locale_te-in.js | 98 - .../angular/1.1.5/i18n/angular-locale_te.js | 98 - .../1.1.5/i18n/angular-locale_th-th.js | 98 - .../angular/1.1.5/i18n/angular-locale_th.js | 98 - .../1.1.5/i18n/angular-locale_tl-ph.js | 4 - .../angular/1.1.5/i18n/angular-locale_tl.js | 98 - .../1.1.5/i18n/angular-locale_tr-tr.js | 98 - .../angular/1.1.5/i18n/angular-locale_tr.js | 98 - .../1.1.5/i18n/angular-locale_uk-ua.js | 98 - .../angular/1.1.5/i18n/angular-locale_uk.js | 98 - .../1.1.5/i18n/angular-locale_ur-in.js | 98 - .../1.1.5/i18n/angular-locale_ur-pk.js | 98 - .../angular/1.1.5/i18n/angular-locale_ur.js | 98 - .../1.1.5/i18n/angular-locale_vi-vn.js | 98 - .../angular/1.1.5/i18n/angular-locale_vi.js | 98 - .../1.1.5/i18n/angular-locale_zh-cn.js | 98 - .../1.1.5/i18n/angular-locale_zh-hans-cn.js | 98 - .../1.1.5/i18n/angular-locale_zh-hans-hk.js | 98 - .../1.1.5/i18n/angular-locale_zh-hans-mo.js | 98 - .../1.1.5/i18n/angular-locale_zh-hans-sg.js | 98 - .../1.1.5/i18n/angular-locale_zh-hans.js | 98 - .../1.1.5/i18n/angular-locale_zh-hant-hk.js | 98 - .../1.1.5/i18n/angular-locale_zh-hant-mo.js | 98 - .../1.1.5/i18n/angular-locale_zh-hant-tw.js | 98 - .../1.1.5/i18n/angular-locale_zh-hant.js | 98 - .../1.1.5/i18n/angular-locale_zh-hk.js | 98 - .../1.1.5/i18n/angular-locale_zh-tw.js | 98 - .../angular/1.1.5/i18n/angular-locale_zh.js | 98 - .../1.1.5/i18n/angular-locale_zu-za.js | 98 - .../angular/1.1.5/i18n/angular-locale_zu.js | 98 - .../lib/angular/angular-ui-sortable.js | 262 - src/Umbraco.Web.UI.Client/package-lock.json | 74 +- .../src/controllers/main.controller.js | 2 +- .../src/install.loader.js | 4 +- src/Umbraco.Web.UI.Client/src/loader.dev.js | 2 +- src/Umbraco.Web/UI/JavaScript/JsInitialize.js | 6 +- 309 files changed, 63 insertions(+), 77198 deletions(-) delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/angular-cookies.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/angular-cookies.min.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/angular-loader.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/angular-loader.min.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/angular-mobile.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/angular-mobile.min.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/angular-mocks.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/angular-resource.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/angular-resource.min.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/angular-sanitize.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/angular-sanitize.min.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/angular-scenario.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/angular.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/angular.min.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_af-na.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_af-za.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_af.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_am-et.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_am.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_ar-001.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_ar-ae.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_ar-bh.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_ar-dz.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_ar-eg.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_ar-iq.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_ar-jo.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_ar-kw.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_ar-lb.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_ar-ly.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_ar-ma.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_ar-om.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_ar-qa.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_ar-sa.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_ar-sd.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_ar-sy.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_ar-tn.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_ar-ye.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_ar.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_bg-bg.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_bg.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_bn-bd.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_bn-in.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_bn.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_ca-ad.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_ca-es.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_ca.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_chr.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_cs-cz.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_cs.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_cy.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_da-dk.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_da.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_de-at.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_de-be.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_de-ch.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_de-de.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_de-li.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_de-lu.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_de.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_el-cy.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_el-gr.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_el-polyton.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_el.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_en-as.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_en-au.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_en-bb.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_en-be.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_en-bm.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_en-bw.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_en-bz.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_en-ca.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_en-dsrt-us.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_en-dsrt.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_en-fm.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_en-gb.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_en-gu.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_en-gy.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_en-hk.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_en-ie.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_en-in.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_en-iso.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_en-jm.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_en-mh.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_en-mp.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_en-mt.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_en-mu.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_en-na.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_en-nz.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_en-ph.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_en-pk.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_en-pr.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_en-pw.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_en-sg.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_en-tc.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_en-tt.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_en-um.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_en-us.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_en-vg.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_en-vi.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_en-za.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_en-zw.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_en-zz.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_en.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_es-419.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_es-ar.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_es-bo.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_es-cl.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_es-co.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_es-cr.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_es-do.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_es-ea.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_es-ec.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_es-es.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_es-gq.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_es-gt.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_es-hn.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_es-ic.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_es-mx.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_es-ni.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_es-pa.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_es-pe.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_es-pr.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_es-py.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_es-sv.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_es-us.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_es-uy.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_es-ve.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_es.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_et-ee.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_et.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_eu-es.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_eu.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_fa-af.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_fa-ir.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_fa.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_fi-fi.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_fi.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_fil-ph.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_fil.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_fr-be.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_fr-bf.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_fr-bi.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_fr-bj.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_fr-bl.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_fr-ca.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_fr-cd.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_fr-cf.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_fr-cg.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_fr-ch.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_fr-ci.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_fr-cm.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_fr-dj.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_fr-fr.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_fr-ga.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_fr-gf.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_fr-gn.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_fr-gp.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_fr-gq.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_fr-km.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_fr-lu.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_fr-mc.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_fr-mf.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_fr-mg.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_fr-ml.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_fr-mq.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_fr-ne.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_fr-re.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_fr-rw.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_fr-sn.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_fr-td.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_fr-tg.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_fr-yt.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_fr.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_gl-es.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_gl.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_gsw-ch.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_gsw.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_gu-in.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_gu.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_haw.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_he-il.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_he.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_hi-in.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_hi.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_hr-hr.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_hr.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_hu-hu.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_hu.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_id-id.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_id.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_in.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_is-is.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_is.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_it-ch.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_it-it.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_it-sm.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_it.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_iw.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_ja-jp.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_ja.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_kn-in.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_kn.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_ko-kr.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_ko.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_ln-cd.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_ln-cg.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_ln.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_lt-lt.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_lt.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_lv-lv.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_lv.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_ml-in.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_ml.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_mo.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_mr-in.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_mr.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_ms-bn.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_ms-my.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_ms.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_mt-mt.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_mt.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_nl-aw.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_nl-be.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_nl-cw.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_nl-nl.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_nl-sx.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_nl.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_no.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_or-in.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_or.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_pl-pl.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_pl.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_pt-ao.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_pt-br.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_pt-gw.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_pt-mz.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_pt-pt.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_pt-st.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_pt.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_ro-md.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_ro-ro.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_ro.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_ru-md.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_ru-ru.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_ru-ua.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_ru.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_sk-sk.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_sk.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_sl-si.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_sl.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_sq-al.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_sq.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_sr-cyrl-ba.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_sr-cyrl-me.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_sr-cyrl-rs.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_sr-cyrl.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_sr-latn-ba.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_sr-latn-me.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_sr-latn-rs.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_sr-latn.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_sr-rs.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_sr.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_sv-fi.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_sv-se.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_sv.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_sw-ke.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_sw-tz.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_sw.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_ta-in.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_ta-lk.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_ta.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_te-in.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_te.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_th-th.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_th.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_tl-ph.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_tl.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_tr-tr.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_tr.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_uk-ua.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_uk.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_ur-in.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_ur-pk.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_ur.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_vi-vn.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_vi.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_zh-cn.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_zh-hans-cn.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_zh-hans-hk.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_zh-hans-mo.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_zh-hans-sg.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_zh-hans.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_zh-hant-hk.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_zh-hant-mo.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_zh-hant-tw.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_zh-hant.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_zh-hk.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_zh-tw.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_zh.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_zu-za.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/1.1.5/i18n/angular-locale_zu.js delete mode 100644 src/Umbraco.Web.UI.Client/lib/angular/angular-ui-sortable.js diff --git a/src/Umbraco.Web.UI.Client/bower.json b/src/Umbraco.Web.UI.Client/bower.json index 97a21bc5d3..d9a5c366a6 100644 --- a/src/Umbraco.Web.UI.Client/bower.json +++ b/src/Umbraco.Web.UI.Client/bower.json @@ -16,37 +16,40 @@ "tests" ], "dependencies": { - "angular": "1.7.0", - "angular-cookies": "1.7.0", - "angular-sanitize": "1.7.0", - "angular-touch": "1.7.0", - "angular-route": "1.7.0", - "angular-animate": "1.7.0", + "angular": "~1.7.2", + "angular-cookies": "~1.7.2", + "angular-sanitize": "~1.7.2", + "angular-touch": "~1.7.2", + "angular-route": "~1.7.2", + "angular-animate": "~1.7.2", + "angular-i18n": "~1.7.2", "signalr": "^2.2.1", "typeahead.js": "~0.10.5", "underscore": "~1.7.0", "rgrove-lazyload": "*", "bootstrap-social": "~4.8.0", "jquery": "2.2.4", - "jquery-ui": "1.11.4", + "jquery-ui": "~1.12.0", "jquery-migrate": "1.4.0", - "angular-dynamic-locale": "0.1.28", + "angular-dynamic-locale": "~0.1.36", "ng-file-upload": "~12.2.13", "tinymce": "~4.7.1", "codemirror": "~5.3.0", "angular-local-storage": "~0.7.1", "moment": "~2.10.3", - "ace-builds": "^1.2.3", - "clipboard": "1.7.1", + "ace-builds": "~1.3.0", + "clipboard": "~2.0.0", "font-awesome": "~4.2", - "animejs": "^2.2.0" + "animejs": "^2.2.0", + "angular-ui-sortable": "0.14.3" }, "install": { "path": "lib-bower", "ignore": [ "font-awesome", "bootstrap", - "codemirror" + "codemirror", + "ace-builds" ], "sources": { "moment": [ @@ -74,6 +77,7 @@ "tinymce": [ "bower_components/tinymce/tinymce.min.js" ], + "angular-i18n": "bower_components/angular-i18n/angular-locale_*.js", "typeahead.js": "bower_components/typeahead.js/dist/typeahead.bundle.min.js", "rgrove-lazyload": "bower_components/rgrove-lazyload/lazyload.js", "ng-file-upload": "bower_components/ng-file-upload/ng-file-upload.min.js", @@ -82,5 +86,8 @@ "clipboard": "bower_components/clipboard/dist/clipboard.min.js", "animejs": "bower_components/animejs/anime.min.js" } + }, + "devDependencies": { + "angular-mocks": "~1.7.2" } } diff --git a/src/Umbraco.Web.UI.Client/gulpfile.js b/src/Umbraco.Web.UI.Client/gulpfile.js index 15f908a9e8..e7ca996d9f 100644 --- a/src/Umbraco.Web.UI.Client/gulpfile.js +++ b/src/Umbraco.Web.UI.Client/gulpfile.js @@ -140,7 +140,7 @@ gulp.task('dependencies', function () { //as we do multiple things in this task, we merge the multiple streams var stream = new MergeStream(); - //Tinymce + //Tinymce plugins/themes stream.add( gulp.src(["./bower_components/tinymce/plugins/**", "./bower_components/tinymce/themes/**"], diff --git a/src/Umbraco.Web.UI.Client/lib/angular/1.1.5/angular-cookies.js b/src/Umbraco.Web.UI.Client/lib/angular/1.1.5/angular-cookies.js deleted file mode 100644 index b6a86bb4f6..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/angular/1.1.5/angular-cookies.js +++ /dev/null @@ -1,185 +0,0 @@ -/** - * @license AngularJS v1.1.5 - * (c) 2010-2012 Google, Inc. http://angularjs.org - * License: MIT - */ -(function(window, angular, undefined) { -'use strict'; - -/** - * @ngdoc overview - * @name ngCookies - */ - - -angular.module('ngCookies', ['ng']). - /** - * @ngdoc object - * @name ngCookies.$cookies - * @requires $browser - * - * @description - * Provides read/write access to browser's cookies. - * - * Only a simple Object is exposed and by adding or removing properties to/from - * this object, new cookies are created/deleted at the end of current $eval. - * - * @example - - - - - - */ - factory('$cookies', ['$rootScope', '$browser', function ($rootScope, $browser) { - var cookies = {}, - lastCookies = {}, - lastBrowserCookies, - runEval = false, - copy = angular.copy, - isUndefined = angular.isUndefined; - - //creates a poller fn that copies all cookies from the $browser to service & inits the service - $browser.addPollFn(function() { - var currentCookies = $browser.cookies(); - if (lastBrowserCookies != currentCookies) { //relies on browser.cookies() impl - lastBrowserCookies = currentCookies; - copy(currentCookies, lastCookies); - copy(currentCookies, cookies); - if (runEval) $rootScope.$apply(); - } - })(); - - runEval = true; - - //at the end of each eval, push cookies - //TODO: this should happen before the "delayed" watches fire, because if some cookies are not - // strings or browser refuses to store some cookies, we update the model in the push fn. - $rootScope.$watch(push); - - return cookies; - - - /** - * Pushes all the cookies from the service to the browser and verifies if all cookies were stored. - */ - function push() { - var name, - value, - browserCookies, - updated; - - //delete any cookies deleted in $cookies - for (name in lastCookies) { - if (isUndefined(cookies[name])) { - $browser.cookies(name, undefined); - } - } - - //update all cookies updated in $cookies - for(name in cookies) { - value = cookies[name]; - if (!angular.isString(value)) { - if (angular.isDefined(lastCookies[name])) { - cookies[name] = lastCookies[name]; - } else { - delete cookies[name]; - } - } else if (value !== lastCookies[name]) { - $browser.cookies(name, value); - updated = true; - } - } - - //verify what was actually stored - if (updated){ - updated = false; - browserCookies = $browser.cookies(); - - for (name in cookies) { - if (cookies[name] !== browserCookies[name]) { - //delete or reset all cookies that the browser dropped from $cookies - if (isUndefined(browserCookies[name])) { - delete cookies[name]; - } else { - cookies[name] = browserCookies[name]; - } - updated = true; - } - } - } - } - }]). - - - /** - * @ngdoc object - * @name ngCookies.$cookieStore - * @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. - * @example - */ - factory('$cookieStore', ['$cookies', function($cookies) { - - return { - /** - * @ngdoc method - * @name ngCookies.$cookieStore#get - * @methodOf ngCookies.$cookieStore - * - * @description - * Returns the value of given cookie key - * - * @param {string} key Id to use for lookup. - * @returns {Object} Deserialized cookie value. - */ - get: function(key) { - var value = $cookies[key]; - return value ? angular.fromJson(value) : value; - }, - - /** - * @ngdoc method - * @name ngCookies.$cookieStore#put - * @methodOf ngCookies.$cookieStore - * - * @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[key] = angular.toJson(value); - }, - - /** - * @ngdoc method - * @name ngCookies.$cookieStore#remove - * @methodOf ngCookies.$cookieStore - * - * @description - * Remove given cookie - * - * @param {string} key Id of the key-value pair to delete. - */ - remove: function(key) { - delete $cookies[key]; - } - }; - - }]); - - -})(window, window.angular); diff --git a/src/Umbraco.Web.UI.Client/lib/angular/1.1.5/angular-cookies.min.js b/src/Umbraco.Web.UI.Client/lib/angular/1.1.5/angular-cookies.min.js deleted file mode 100644 index 276bce05b1..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/angular/1.1.5/angular-cookies.min.js +++ /dev/null @@ -1,7 +0,0 @@ -/* - AngularJS v1.1.5 - (c) 2010-2012 Google, Inc. http://angularjs.org - License: MIT -*/ -(function(m,f,l){'use strict';f.module("ngCookies",["ng"]).factory("$cookies",["$rootScope","$browser",function(d,b){var c={},g={},h,i=!1,j=f.copy,k=f.isUndefined;b.addPollFn(function(){var a=b.cookies();h!=a&&(h=a,j(a,g),j(a,c),i&&d.$apply())})();i=!0;d.$watch(function(){var a,e,d;for(a in g)k(c[a])&&b.cookies(a,l);for(a in c)e=c[a],f.isString(e)?e!==g[a]&&(b.cookies(a,e),d=!0):f.isDefined(g[a])?c[a]=g[a]:delete c[a];if(d)for(a in e=b.cookies(),c)c[a]!==e[a]&&(k(e[a])?delete c[a]:c[a]=e[a])});return c}]).factory("$cookieStore", -["$cookies",function(d){return{get:function(b){return(b=d[b])?f.fromJson(b):b},put:function(b,c){d[b]=f.toJson(c)},remove:function(b){delete d[b]}}}])})(window,window.angular); diff --git a/src/Umbraco.Web.UI.Client/lib/angular/1.1.5/angular-loader.js b/src/Umbraco.Web.UI.Client/lib/angular/1.1.5/angular-loader.js deleted file mode 100644 index e4c31614c6..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/angular/1.1.5/angular-loader.js +++ /dev/null @@ -1,304 +0,0 @@ -/** - * @license AngularJS v1.1.5 - * (c) 2010-2012 Google, Inc. http://angularjs.org - * License: MIT - */ - -( - -/** - * @ngdoc interface - * @name angular.Module - * @description - * - * Interface for configuring angular {@link angular.module modules}. - */ - -function setupModuleLoader(window) { - - function ensure(obj, name, factory) { - return obj[name] || (obj[name] = factory()); - } - - return ensure(ensure(window, 'angular', Object), 'module', function() { - /** @type {Object.} */ - var modules = {}; - - /** - * @ngdoc function - * @name angular.module - * @description - * - * The `angular.module` is a global place for creating and registering Angular modules. All - * modules (angular core or 3rd party) that should be available to an application must be - * registered using this mechanism. - * - * - * # Module - * - * A module is a collocation of services, directives, filters, and configuration information. Module - * is used to configure the {@link AUTO.$injector $injector}. - * - *
                -     * // Create a new module
                -     * var myModule = angular.module('myModule', []);
                -     *
                -     * // register a new service
                -     * myModule.value('appName', 'MyCoolApp');
                -     *
                -     * // configure existing services inside initialization blocks.
                -     * myModule.config(function($locationProvider) {
                -'use strict';
                -     *   // Configure existing providers
                -     *   $locationProvider.hashPrefix('!');
                -     * });
                -     * 
                - * - * Then you can create an injector and load your modules like this: - * - *
                -     * var injector = angular.injector(['ng', 'MyModule'])
                -     * 
                - * - * However it's more likely that you'll just use - * {@link ng.directive:ngApp ngApp} or - * {@link angular.bootstrap} to simplify this process for you. - * - * @param {!string} name The name of the module to create or retrieve. - * @param {Array.=} requires If specified then new module is being created. If unspecified then the - * the module is being retrieved for further configuration. - * @param {Function} configFn Optional configuration function for the module. Same as - * {@link angular.Module#config Module#config()}. - * @returns {module} new module with the {@link angular.Module} api. - */ - return function module(name, requires, configFn) { - if (requires && modules.hasOwnProperty(name)) { - modules[name] = null; - } - return ensure(modules, name, function() { - if (!requires) { - throw Error('No module: ' + name); - } - - /** @type {!Array.>} */ - var invokeQueue = []; - - /** @type {!Array.} */ - var runBlocks = []; - - var config = invokeLater('$injector', 'invoke'); - - /** @type {angular.Module} */ - var moduleInstance = { - // Private state - _invokeQueue: invokeQueue, - _runBlocks: runBlocks, - - /** - * @ngdoc property - * @name angular.Module#requires - * @propertyOf angular.Module - * @returns {Array.} List of module names which must be loaded before this module. - * @description - * Holds the list of modules which the injector will load before the current module is loaded. - */ - requires: requires, - - /** - * @ngdoc property - * @name angular.Module#name - * @propertyOf angular.Module - * @returns {string} Name of the module. - * @description - */ - name: name, - - - /** - * @ngdoc method - * @name angular.Module#provider - * @methodOf angular.Module - * @param {string} name service name - * @param {Function} providerType Construction function for creating new instance of the service. - * @description - * See {@link AUTO.$provide#provider $provide.provider()}. - */ - provider: invokeLater('$provide', 'provider'), - - /** - * @ngdoc method - * @name angular.Module#factory - * @methodOf angular.Module - * @param {string} name service name - * @param {Function} providerFunction Function for creating new instance of the service. - * @description - * See {@link AUTO.$provide#factory $provide.factory()}. - */ - factory: invokeLater('$provide', 'factory'), - - /** - * @ngdoc method - * @name angular.Module#service - * @methodOf angular.Module - * @param {string} name service name - * @param {Function} constructor A constructor function that will be instantiated. - * @description - * See {@link AUTO.$provide#service $provide.service()}. - */ - service: invokeLater('$provide', 'service'), - - /** - * @ngdoc method - * @name angular.Module#value - * @methodOf angular.Module - * @param {string} name service name - * @param {*} object Service instance object. - * @description - * See {@link AUTO.$provide#value $provide.value()}. - */ - value: invokeLater('$provide', 'value'), - - /** - * @ngdoc method - * @name angular.Module#constant - * @methodOf angular.Module - * @param {string} name constant name - * @param {*} object Constant value. - * @description - * Because the constant are fixed, they get applied before other provide methods. - * See {@link AUTO.$provide#constant $provide.constant()}. - */ - constant: invokeLater('$provide', 'constant', 'unshift'), - - /** - * @ngdoc method - * @name angular.Module#animation - * @methodOf angular.Module - * @param {string} name animation name - * @param {Function} animationFactory Factory function for creating new instance of an animation. - * @description - * - * Defines an animation hook that can be later used with {@link ng.directive:ngAnimate ngAnimate} - * alongside {@link ng.directive:ngAnimate#Description common ng directives} as well as custom directives. - *
                -           * module.animation('animation-name', function($inject1, $inject2) {
                -           *   return {
                -           *     //this gets called in preparation to setup an animation
                -           *     setup : function(element) { ... },
                -           *
                -           *     //this gets called once the animation is run
                -           *     start : function(element, done, memo) { ... }
                -           *   }
                -           * })
                -           * 
                - * - * See {@link ng.$animationProvider#register $animationProvider.register()} and - * {@link ng.directive:ngAnimate ngAnimate} for more information. - */ - animation: invokeLater('$animationProvider', 'register'), - - /** - * @ngdoc method - * @name angular.Module#filter - * @methodOf angular.Module - * @param {string} name Filter name. - * @param {Function} filterFactory Factory function for creating new instance of filter. - * @description - * See {@link ng.$filterProvider#register $filterProvider.register()}. - */ - filter: invokeLater('$filterProvider', 'register'), - - /** - * @ngdoc method - * @name angular.Module#controller - * @methodOf angular.Module - * @param {string} name Controller name. - * @param {Function} constructor Controller constructor function. - * @description - * See {@link ng.$controllerProvider#register $controllerProvider.register()}. - */ - controller: invokeLater('$controllerProvider', 'register'), - - /** - * @ngdoc method - * @name angular.Module#directive - * @methodOf angular.Module - * @param {string} name directive name - * @param {Function} directiveFactory Factory function for creating new instance of - * directives. - * @description - * See {@link ng.$compileProvider#directive $compileProvider.directive()}. - */ - directive: invokeLater('$compileProvider', 'directive'), - - /** - * @ngdoc method - * @name angular.Module#config - * @methodOf angular.Module - * @param {Function} configFn Execute this function on module load. Useful for service - * configuration. - * @description - * Use this method to register work which needs to be performed on module loading. - */ - config: config, - - /** - * @ngdoc method - * @name angular.Module#run - * @methodOf angular.Module - * @param {Function} initializationFn Execute this function after injector creation. - * Useful for application initialization. - * @description - * Use this method to register work which should be performed when the injector is done - * loading all modules. - */ - run: function(block) { - runBlocks.push(block); - return this; - } - }; - - if (configFn) { - config(configFn); - } - - return moduleInstance; - - /** - * @param {string} provider - * @param {string} method - * @param {String=} insertMethod - * @returns {angular.Module} - */ - function invokeLater(provider, method, insertMethod) { - return function() { - invokeQueue[insertMethod || 'push']([provider, method, arguments]); - return moduleInstance; - } - } - }); - }; - }); - -} - -)(window); - -/** - * Closure compiler type information - * - * @typedef { { - * requires: !Array., - * invokeQueue: !Array.>, - * - * service: function(string, Function):angular.Module, - * factory: function(string, Function):angular.Module, - * value: function(string, *):angular.Module, - * - * filter: function(string, Function):angular.Module, - * - * init: function(Function):angular.Module - * } } - */ -angular.Module; - diff --git a/src/Umbraco.Web.UI.Client/lib/angular/1.1.5/angular-loader.min.js b/src/Umbraco.Web.UI.Client/lib/angular/1.1.5/angular-loader.min.js deleted file mode 100644 index 5d1e2538ee..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/angular/1.1.5/angular-loader.min.js +++ /dev/null @@ -1,7 +0,0 @@ -/* - AngularJS v1.1.5 - (c) 2010-2012 Google, Inc. http://angularjs.org - License: MIT -*/ -(function(i){'use strict';function d(c,b,e){return c[b]||(c[b]=e())}return d(d(i,"angular",Object),"module",function(){var c={};return function(b,e,f){e&&c.hasOwnProperty(b)&&(c[b]=null);return d(c,b,function(){function a(a,b,d){return function(){c[d||"push"]([a,b,arguments]);return g}}if(!e)throw Error("No module: "+b);var c=[],d=[],h=a("$injector","invoke"),g={_invokeQueue:c,_runBlocks:d,requires:e,name:b,provider:a("$provide","provider"),factory:a("$provide","factory"),service:a("$provide","service"), -value:a("$provide","value"),constant:a("$provide","constant","unshift"),animation:a("$animationProvider","register"),filter:a("$filterProvider","register"),controller:a("$controllerProvider","register"),directive:a("$compileProvider","directive"),config:h,run:function(a){d.push(a);return this}};f&&h(f);return g})}})})(window); diff --git a/src/Umbraco.Web.UI.Client/lib/angular/1.1.5/angular-mobile.js b/src/Umbraco.Web.UI.Client/lib/angular/1.1.5/angular-mobile.js deleted file mode 100644 index d335dcbd9b..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/angular/1.1.5/angular-mobile.js +++ /dev/null @@ -1,462 +0,0 @@ -/** - * @license AngularJS v1.1.5 - * (c) 2010-2012 Google, Inc. http://angularjs.org - * License: MIT - */ -(function(window, angular, undefined) { -'use strict'; - -/** - * @ngdoc overview - * @name ngMobile - * @description - * Touch events and other mobile helpers. - * Based on jQuery Mobile touch event handling (jquerymobile.com) - */ - -// define ngMobile module -var ngMobile = angular.module('ngMobile', []); - -/** - * @ngdoc directive - * @name ngMobile.directive:ngClick - * - * @description - * A more powerful replacement for the default ngClick designed to be used on touchscreen - * devices. Most mobile browsers wait about 300ms after a tap-and-release before sending - * the click event. This version handles them immediately, and then prevents the - * following click event from propagating. - * - * This directive can fall back to using an ordinary click event, and so works on desktop - * browsers as well as mobile. - * - * This directive also sets the CSS class `ng-click-active` while the element is being held - * down (by a mouse click or touch) so you can restyle the depressed element if you wish. - * - * @element ANY - * @param {expression} ngClick {@link guide/expression Expression} to evaluate - * upon tap. (Event object is available as `$event`) - * - * @example - - - - count: {{ count }} - - - */ - -ngMobile.config(['$provide', function($provide) { - $provide.decorator('ngClickDirective', ['$delegate', function($delegate) { - // drop the default ngClick directive - $delegate.shift(); - return $delegate; - }]); -}]); - -ngMobile.directive('ngClick', ['$parse', '$timeout', '$rootElement', - function($parse, $timeout, $rootElement) { - var TAP_DURATION = 750; // Shorter than 750ms is a tap, longer is a taphold or drag. - var MOVE_TOLERANCE = 12; // 12px seems to work in most mobile browsers. - var PREVENT_DURATION = 2500; // 2.5 seconds maximum from preventGhostClick call to click - var CLICKBUSTER_THRESHOLD = 25; // 25 pixels in any dimension is the limit for busting clicks. - - var ACTIVE_CLASS_NAME = 'ng-click-active'; - var lastPreventedTime; - var touchCoordinates; - - - // TAP EVENTS AND GHOST CLICKS - // - // Why tap events? - // Mobile browsers detect a tap, then wait a moment (usually ~300ms) to see if you're - // double-tapping, and then fire a click event. - // - // This delay sucks and makes mobile apps feel unresponsive. - // So we detect touchstart, touchmove, touchcancel and touchend ourselves and determine when - // the user has tapped on something. - // - // What happens when the browser then generates a click event? - // The browser, of course, also detects the tap and fires a click after a delay. This results in - // tapping/clicking twice. So we do "clickbusting" to prevent it. - // - // How does it work? - // We attach global touchstart and click handlers, that run during the capture (early) phase. - // So the sequence for a tap is: - // - global touchstart: Sets an "allowable region" at the point touched. - // - element's touchstart: Starts a touch - // (- touchmove or touchcancel ends the touch, no click follows) - // - element's touchend: Determines if the tap is valid (didn't move too far away, didn't hold - // too long) and fires the user's tap handler. The touchend also calls preventGhostClick(). - // - preventGhostClick() removes the allowable region the global touchstart created. - // - The browser generates a click event. - // - The global click handler catches the click, and checks whether it was in an allowable region. - // - If preventGhostClick was called, the region will have been removed, the click is busted. - // - If the region is still there, the click proceeds normally. Therefore clicks on links and - // other elements without ngTap on them work normally. - // - // This is an ugly, terrible hack! - // Yeah, tell me about it. The alternatives are using the slow click events, or making our users - // deal with the ghost clicks, so I consider this the least of evils. Fortunately Angular - // encapsulates this ugly logic away from the user. - // - // Why not just put click handlers on the element? - // We do that too, just to be sure. The problem is that the tap event might have caused the DOM - // to change, so that the click fires in the same position but something else is there now. So - // the handlers are global and care only about coordinates and not elements. - - // Checks if the coordinates are close enough to be within the region. - function hit(x1, y1, x2, y2) { - return Math.abs(x1 - x2) < CLICKBUSTER_THRESHOLD && Math.abs(y1 - y2) < CLICKBUSTER_THRESHOLD; - } - - // Checks a list of allowable regions against a click location. - // Returns true if the click should be allowed. - // Splices out the allowable region from the list after it has been used. - function checkAllowableRegions(touchCoordinates, x, y) { - for (var i = 0; i < touchCoordinates.length; i += 2) { - if (hit(touchCoordinates[i], touchCoordinates[i+1], x, y)) { - touchCoordinates.splice(i, i + 2); - return true; // allowable region - } - } - return false; // No allowable region; bust it. - } - - // Global click handler that prevents the click if it's in a bustable zone and preventGhostClick - // was called recently. - function onClick(event) { - if (Date.now() - lastPreventedTime > PREVENT_DURATION) { - return; // Too old. - } - - var touches = event.touches && event.touches.length ? event.touches : [event]; - var x = touches[0].clientX; - var y = touches[0].clientY; - // Work around desktop Webkit quirk where clicking a label will fire two clicks (on the label - // and on the input element). Depending on the exact browser, this second click we don't want - // to bust has either (0,0) or negative coordinates. - if (x < 1 && y < 1) { - return; // offscreen - } - - // Look for an allowable region containing this click. - // If we find one, that means it was created by touchstart and not removed by - // preventGhostClick, so we don't bust it. - if (checkAllowableRegions(touchCoordinates, x, y)) { - return; - } - - // If we didn't find an allowable region, bust the click. - event.stopPropagation(); - event.preventDefault(); - } - - - // Global touchstart handler that creates an allowable region for a click event. - // This allowable region can be removed by preventGhostClick if we want to bust it. - function onTouchStart(event) { - var touches = event.touches && event.touches.length ? event.touches : [event]; - var x = touches[0].clientX; - var y = touches[0].clientY; - touchCoordinates.push(x, y); - - $timeout(function() { - // Remove the allowable region. - for (var i = 0; i < touchCoordinates.length; i += 2) { - if (touchCoordinates[i] == x && touchCoordinates[i+1] == y) { - touchCoordinates.splice(i, i + 2); - return; - } - } - }, PREVENT_DURATION, false); - } - - // On the first call, attaches some event handlers. Then whenever it gets called, it creates a - // zone around the touchstart where clicks will get busted. - function preventGhostClick(x, y) { - if (!touchCoordinates) { - $rootElement[0].addEventListener('click', onClick, true); - $rootElement[0].addEventListener('touchstart', onTouchStart, true); - touchCoordinates = []; - } - - lastPreventedTime = Date.now(); - - checkAllowableRegions(touchCoordinates, x, y); - } - - // Actual linking function. - return function(scope, element, attr) { - var clickHandler = $parse(attr.ngClick), - tapping = false, - tapElement, // Used to blur the element after a tap. - startTime, // Used to check if the tap was held too long. - touchStartX, - touchStartY; - - function resetState() { - tapping = false; - element.removeClass(ACTIVE_CLASS_NAME); - } - - element.bind('touchstart', function(event) { - tapping = true; - tapElement = event.target ? event.target : event.srcElement; // IE uses srcElement. - // Hack for Safari, which can target text nodes instead of containers. - if(tapElement.nodeType == 3) { - tapElement = tapElement.parentNode; - } - - element.addClass(ACTIVE_CLASS_NAME); - - startTime = Date.now(); - - var touches = event.touches && event.touches.length ? event.touches : [event]; - var e = touches[0].originalEvent || touches[0]; - touchStartX = e.clientX; - touchStartY = e.clientY; - }); - - element.bind('touchmove', function(event) { - resetState(); - }); - - element.bind('touchcancel', function(event) { - resetState(); - }); - - element.bind('touchend', function(event) { - var diff = Date.now() - startTime; - - var touches = (event.changedTouches && event.changedTouches.length) ? event.changedTouches : - ((event.touches && event.touches.length) ? event.touches : [event]); - var e = touches[0].originalEvent || touches[0]; - var x = e.clientX; - var y = e.clientY; - var dist = Math.sqrt( Math.pow(x - touchStartX, 2) + Math.pow(y - touchStartY, 2) ); - - if (tapping && diff < TAP_DURATION && dist < MOVE_TOLERANCE) { - // Call preventGhostClick so the clickbuster will catch the corresponding click. - preventGhostClick(x, y); - - // Blur the focused element (the button, probably) before firing the callback. - // This doesn't work perfectly on Android Chrome, but seems to work elsewhere. - // I couldn't get anything to work reliably on Android Chrome. - if (tapElement) { - tapElement.blur(); - } - - scope.$apply(function() { - // TODO(braden): This is sending the touchend, not a tap or click. Is that kosher? - clickHandler(scope, {$event: event}); - }); - } - - resetState(); - }); - - // Hack for iOS Safari's benefit. It goes searching for onclick handlers and is liable to click - // something else nearby. - element.onclick = function(event) { }; - - // Fallback click handler. - // Busted clicks don't get this far, and adding this handler allows ng-tap to be used on - // desktop as well, to allow more portable sites. - element.bind('click', function(event) { - scope.$apply(function() { - clickHandler(scope, {$event: event}); - }); - }); - -/* - element.bind('mousedown', function(event) { - element.addClass(ACTIVE_CLASS_NAME); - }); - - element.bind('mousemove mouseup', function(event) { - element.removeClass(ACTIVE_CLASS_NAME); - }); -*/ - - }; -}]); - -/** - * @ngdoc directive - * @name ngMobile.directive:ngSwipeLeft - * - * @description - * Specify custom behavior when an element is swiped to the left on a touchscreen device. - * A leftward swipe is a quick, right-to-left slide of the finger. - * Though ngSwipeLeft is designed for touch-based devices, it will work with a mouse click and drag too. - * - * @element ANY - * @param {expression} ngSwipeLeft {@link guide/expression Expression} to evaluate - * upon left swipe. (Event object is available as `$event`) - * - * @example - - -
                - Some list content, like an email in the inbox -
                -
                - - -
                -
                -
                - */ - -/** - * @ngdoc directive - * @name ngMobile.directive:ngSwipeRight - * - * @description - * Specify custom behavior when an element is swiped to the right on a touchscreen device. - * A rightward swipe is a quick, left-to-right slide of the finger. - * Though ngSwipeRight is designed for touch-based devices, it will work with a mouse click and drag too. - * - * @element ANY - * @param {expression} ngSwipeRight {@link guide/expression Expression} to evaluate - * upon right swipe. (Event object is available as `$event`) - * - * @example - - -
                - Some list content, like an email in the inbox -
                -
                - - -
                -
                -
                - */ - -function makeSwipeDirective(directiveName, direction) { - ngMobile.directive(directiveName, ['$parse', function($parse) { - // The maximum vertical delta for a swipe should be less than 75px. - var MAX_VERTICAL_DISTANCE = 75; - // Vertical distance should not be more than a fraction of the horizontal distance. - var MAX_VERTICAL_RATIO = 0.3; - // At least a 30px lateral motion is necessary for a swipe. - var MIN_HORIZONTAL_DISTANCE = 30; - // The total distance in any direction before we make the call on swipe vs. scroll. - var MOVE_BUFFER_RADIUS = 10; - - function getCoordinates(event) { - var touches = event.touches && event.touches.length ? event.touches : [event]; - var e = (event.changedTouches && event.changedTouches[0]) || - (event.originalEvent && event.originalEvent.changedTouches && - event.originalEvent.changedTouches[0]) || - touches[0].originalEvent || touches[0]; - - return { - x: e.clientX, - y: e.clientY - }; - } - - return function(scope, element, attr) { - var swipeHandler = $parse(attr[directiveName]); - var startCoords, valid; - var totalX, totalY; - var lastX, lastY; - - function validSwipe(event) { - // Check that it's within the coordinates. - // Absolute vertical distance must be within tolerances. - // Horizontal distance, we take the current X - the starting X. - // This is negative for leftward swipes and positive for rightward swipes. - // After multiplying by the direction (-1 for left, +1 for right), legal swipes - // (ie. same direction as the directive wants) will have a positive delta and - // illegal ones a negative delta. - // Therefore this delta must be positive, and larger than the minimum. - if (!startCoords) return false; - var coords = getCoordinates(event); - var deltaY = Math.abs(coords.y - startCoords.y); - var deltaX = (coords.x - startCoords.x) * direction; - return valid && // Short circuit for already-invalidated swipes. - deltaY < MAX_VERTICAL_DISTANCE && - deltaX > 0 && - deltaX > MIN_HORIZONTAL_DISTANCE && - deltaY / deltaX < MAX_VERTICAL_RATIO; - } - - element.bind('touchstart mousedown', function(event) { - startCoords = getCoordinates(event); - valid = true; - totalX = 0; - totalY = 0; - lastX = startCoords.x; - lastY = startCoords.y; - }); - - element.bind('touchcancel', function(event) { - valid = false; - }); - - element.bind('touchmove mousemove', function(event) { - if (!valid) return; - - // Android will send a touchcancel if it thinks we're starting to scroll. - // So when the total distance (+ or - or both) exceeds 10px in either direction, - // we either: - // - On totalX > totalY, we send preventDefault() and treat this as a swipe. - // - On totalY > totalX, we let the browser handle it as a scroll. - - // Invalidate a touch while it's in progress if it strays too far away vertically. - // We don't want a scroll down and back up while drifting sideways to be a swipe just - // because you happened to end up vertically close in the end. - if (!startCoords) return; - var coords = getCoordinates(event); - - if (Math.abs(coords.y - startCoords.y) > MAX_VERTICAL_DISTANCE) { - valid = false; - return; - } - - totalX += Math.abs(coords.x - lastX); - totalY += Math.abs(coords.y - lastY); - - lastX = coords.x; - lastY = coords.y; - - if (totalX < MOVE_BUFFER_RADIUS && totalY < MOVE_BUFFER_RADIUS) { - return; - } - - // One of totalX or totalY has exceeded the buffer, so decide on swipe vs. scroll. - if (totalY > totalX) { - valid = false; - return; - } else { - event.preventDefault(); - } - }); - - element.bind('touchend mouseup', function(event) { - if (validSwipe(event)) { - // Prevent this swipe from bubbling up to any other elements with ngSwipes. - event.stopPropagation(); - scope.$apply(function() { - swipeHandler(scope, {$event:event}); - }); - } - }); - }; - }]); -} - -// Left is negative X-coordinate, right is positive. -makeSwipeDirective('ngSwipeLeft', -1); -makeSwipeDirective('ngSwipeRight', 1); - - - -})(window, window.angular); diff --git a/src/Umbraco.Web.UI.Client/lib/angular/1.1.5/angular-mobile.min.js b/src/Umbraco.Web.UI.Client/lib/angular/1.1.5/angular-mobile.min.js deleted file mode 100644 index afac870a91..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/angular/1.1.5/angular-mobile.min.js +++ /dev/null @@ -1,11 +0,0 @@ -/* - AngularJS v1.1.5 - (c) 2010-2012 Google, Inc. http://angularjs.org - License: MIT -*/ -(function(u,s){'use strict';function k(i,t){j.directive(i,["$parse",function(l){function g(b){var h=b.touches&&b.touches.length?b.touches:[b],b=b.changedTouches&&b.changedTouches[0]||b.originalEvent&&b.originalEvent.changedTouches&&b.originalEvent.changedTouches[0]||h[0].originalEvent||h[0];return{x:b.clientX,y:b.clientY}}var m=75,j=0.3,p=30;return function(b,h,n){function o(e){if(!a)return!1;var b=g(e),e=Math.abs(b.y-a.y),b=(b.x-a.x)*t;return c&&e0&&b>p&&e/bm?c=!1:(f+=Math.abs(d.x-q),e+=Math.abs(d.y-r),q=d.x,r=d.y,f<10&&e<10||(e>f?c=!1:b.preventDefault()))}});h.bind("touchend mouseup",function(a){o(a)&&(a.stopPropagation(),b.$apply(function(){d(b,{$event:a})}))})}}])}var j=s.module("ngMobile",[]);j.config(["$provide",function(i){i.decorator("ngClickDirective",["$delegate",function(i){i.shift(); -return i}])}]);j.directive("ngClick",["$parse","$timeout","$rootElement",function(i,j,l){function g(a,c,b){for(var e=0;eb)){var c=a.touches&&a.touches.length?a.touches:[a],f=c[0].clientX,c=c[0].clientY;!(f<1&&c<1)&&!g(d,f,c)&&(a.stopPropagation(),a.preventDefault())}}function k(a){var a=a.touches&&a.touches.length?a.touches:[a],c=a[0].clientX,f=a[0].clientY;d.push(c,f);j(function(){for(var a= -0;a - * describe('$exceptionHandlerProvider', function() { - * - * it('should capture log messages and exceptions', function() { - * - * module(function($exceptionHandlerProvider) { - * $exceptionHandlerProvider.mode('log'); - * }); - * - * inject(function($log, $exceptionHandler, $timeout) { - * $timeout(function() { $log.log(1); }); - * $timeout(function() { $log.log(2); throw 'banana peel'; }); - * $timeout(function() { $log.log(3); }); - * expect($exceptionHandler.errors).toEqual([]); - * expect($log.assertEmpty()); - * $timeout.flush(); - * expect($exceptionHandler.errors).toEqual(['banana peel']); - * expect($log.log.logs).toEqual([[1], [2], [3]]); - * }); - * }); - * }); - * - */ - -angular.mock.$ExceptionHandlerProvider = function() { - var handler; - - /** - * @ngdoc method - * @name ngMock.$exceptionHandlerProvider#mode - * @methodOf ngMock.$exceptionHandlerProvider - * - * @description - * Sets the logging mode. - * - * @param {string} mode Mode of operation, defaults to `rethrow`. - * - * - `rethrow`: If any errors are passed into the handler in tests, it typically - * means that there is a bug in the application or test, so this mock will - * make these tests fail. - * - `log`: Sometimes it is desirable to test that an error is thrown, for this case the `log` mode stores an - * array of errors in `$exceptionHandler.errors`, to allow later assertion of them. - * See {@link ngMock.$log#assertEmpty assertEmpty()} and - * {@link ngMock.$log#reset reset()} - */ - this.mode = function(mode) { - switch(mode) { - case 'rethrow': - handler = function(e) { - throw e; - }; - break; - case 'log': - var errors = []; - - handler = function(e) { - if (arguments.length == 1) { - errors.push(e); - } else { - errors.push([].slice.call(arguments, 0)); - } - }; - - handler.errors = errors; - break; - default: - throw Error("Unknown mode '" + mode + "', only 'log'/'rethrow' modes are allowed!"); - } - }; - - this.$get = function() { - return handler; - }; - - this.mode('rethrow'); -}; - - -/** - * @ngdoc service - * @name ngMock.$log - * - * @description - * Mock implementation of {@link ng.$log} that gathers all logged messages in arrays - * (one array per logging level). These arrays are exposed as `logs` property of each of the - * level-specific log function, e.g. for level `error` the array is exposed as `$log.error.logs`. - * - */ -angular.mock.$LogProvider = function() { - - function concat(array1, array2, index) { - return array1.concat(Array.prototype.slice.call(array2, index)); - } - - - this.$get = function () { - var $log = { - log: function() { $log.log.logs.push(concat([], arguments, 0)); }, - warn: function() { $log.warn.logs.push(concat([], arguments, 0)); }, - info: function() { $log.info.logs.push(concat([], arguments, 0)); }, - error: function() { $log.error.logs.push(concat([], arguments, 0)); } - }; - - /** - * @ngdoc method - * @name ngMock.$log#reset - * @methodOf ngMock.$log - * - * @description - * Reset all of the logging arrays to empty. - */ - $log.reset = function () { - /** - * @ngdoc property - * @name ngMock.$log#log.logs - * @propertyOf ngMock.$log - * - * @description - * Array of messages logged using {@link ngMock.$log#log}. - * - * @example - *
                -       * $log.log('Some Log');
                -       * var first = $log.log.logs.unshift();
                -       * 
                - */ - $log.log.logs = []; - /** - * @ngdoc property - * @name ngMock.$log#warn.logs - * @propertyOf ngMock.$log - * - * @description - * Array of messages logged using {@link ngMock.$log#warn}. - * - * @example - *
                -       * $log.warn('Some Warning');
                -       * var first = $log.warn.logs.unshift();
                -       * 
                - */ - $log.warn.logs = []; - /** - * @ngdoc property - * @name ngMock.$log#info.logs - * @propertyOf ngMock.$log - * - * @description - * Array of messages logged using {@link ngMock.$log#info}. - * - * @example - *
                -       * $log.info('Some Info');
                -       * var first = $log.info.logs.unshift();
                -       * 
                - */ - $log.info.logs = []; - /** - * @ngdoc property - * @name ngMock.$log#error.logs - * @propertyOf ngMock.$log - * - * @description - * Array of messages logged using {@link ngMock.$log#error}. - * - * @example - *
                -       * $log.log('Some Error');
                -       * var first = $log.error.logs.unshift();
                -       * 
                - */ - $log.error.logs = []; - }; - - /** - * @ngdoc method - * @name ngMock.$log#assertEmpty - * @methodOf ngMock.$log - * - * @description - * Assert that the all of the logging methods have no logged messages. If messages present, an exception is thrown. - */ - $log.assertEmpty = function() { - var errors = []; - angular.forEach(['error', 'warn', 'info', 'log'], function(logLevel) { - angular.forEach($log[logLevel].logs, function(log) { - angular.forEach(log, function (logItem) { - errors.push('MOCK $log (' + logLevel + '): ' + String(logItem) + '\n' + (logItem.stack || '')); - }); - }); - }); - if (errors.length) { - errors.unshift("Expected $log to be empty! Either a message was logged unexpectedly, or an expected " + - "log message was not checked and removed:"); - errors.push(''); - throw new Error(errors.join('\n---------\n')); - } - }; - - $log.reset(); - return $log; - }; -}; - - -(function() { - var R_ISO8061_STR = /^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?:\:?(\d\d)(?:\:?(\d\d)(?:\.(\d{3}))?)?)?(Z|([+-])(\d\d):?(\d\d)))?$/; - - function jsonStringToDate(string){ - var match; - if (match = string.match(R_ISO8061_STR)) { - var date = new Date(0), - tzHour = 0, - tzMin = 0; - if (match[9]) { - tzHour = int(match[9] + match[10]); - tzMin = int(match[9] + match[11]); - } - date.setUTCFullYear(int(match[1]), int(match[2]) - 1, int(match[3])); - date.setUTCHours(int(match[4]||0) - tzHour, int(match[5]||0) - tzMin, int(match[6]||0), int(match[7]||0)); - return date; - } - return string; - } - - function int(str) { - return parseInt(str, 10); - } - - function padNumber(num, digits, trim) { - var neg = ''; - if (num < 0) { - neg = '-'; - num = -num; - } - num = '' + num; - while(num.length < digits) num = '0' + num; - if (trim) - num = num.substr(num.length - digits); - return neg + num; - } - - - /** - * @ngdoc object - * @name angular.mock.TzDate - * @description - * - * *NOTE*: this is not an injectable instance, just a globally available mock class of `Date`. - * - * Mock of the Date type which has its timezone specified via constructor arg. - * - * The main purpose is to create Date-like instances with timezone fixed to the specified timezone - * offset, so that we can test code that depends on local timezone settings without dependency on - * the time zone settings of the machine where the code is running. - * - * @param {number} offset Offset of the *desired* timezone in hours (fractions will be honored) - * @param {(number|string)} timestamp Timestamp representing the desired time in *UTC* - * - * @example - * !!!! WARNING !!!!! - * This is not a complete Date object so only methods that were implemented can be called safely. - * To make matters worse, TzDate instances inherit stuff from Date via a prototype. - * - * We do our best to intercept calls to "unimplemented" methods, but since the list of methods is - * incomplete we might be missing some non-standard methods. This can result in errors like: - * "Date.prototype.foo called on incompatible Object". - * - *
                -   * var newYearInBratislava = new TzDate(-1, '2009-12-31T23:00:00Z');
                -   * newYearInBratislava.getTimezoneOffset() => -60;
                -   * newYearInBratislava.getFullYear() => 2010;
                -   * newYearInBratislava.getMonth() => 0;
                -   * newYearInBratislava.getDate() => 1;
                -   * newYearInBratislava.getHours() => 0;
                -   * newYearInBratislava.getMinutes() => 0;
                -   * newYearInBratislava.getSeconds() => 0;
                -   * 
                - * - */ - angular.mock.TzDate = function (offset, timestamp) { - var self = new Date(0); - if (angular.isString(timestamp)) { - var tsStr = timestamp; - - self.origDate = jsonStringToDate(timestamp); - - timestamp = self.origDate.getTime(); - if (isNaN(timestamp)) - throw { - name: "Illegal Argument", - message: "Arg '" + tsStr + "' passed into TzDate constructor is not a valid date string" - }; - } else { - self.origDate = new Date(timestamp); - } - - var localOffset = new Date(timestamp).getTimezoneOffset(); - self.offsetDiff = localOffset*60*1000 - offset*1000*60*60; - self.date = new Date(timestamp + self.offsetDiff); - - self.getTime = function() { - return self.date.getTime() - self.offsetDiff; - }; - - self.toLocaleDateString = function() { - return self.date.toLocaleDateString(); - }; - - self.getFullYear = function() { - return self.date.getFullYear(); - }; - - self.getMonth = function() { - return self.date.getMonth(); - }; - - self.getDate = function() { - return self.date.getDate(); - }; - - self.getHours = function() { - return self.date.getHours(); - }; - - self.getMinutes = function() { - return self.date.getMinutes(); - }; - - self.getSeconds = function() { - return self.date.getSeconds(); - }; - - self.getMilliseconds = function() { - return self.date.getMilliseconds(); - }; - - self.getTimezoneOffset = function() { - return offset * 60; - }; - - self.getUTCFullYear = function() { - return self.origDate.getUTCFullYear(); - }; - - self.getUTCMonth = function() { - return self.origDate.getUTCMonth(); - }; - - self.getUTCDate = function() { - return self.origDate.getUTCDate(); - }; - - self.getUTCHours = function() { - return self.origDate.getUTCHours(); - }; - - self.getUTCMinutes = function() { - return self.origDate.getUTCMinutes(); - }; - - self.getUTCSeconds = function() { - return self.origDate.getUTCSeconds(); - }; - - self.getUTCMilliseconds = function() { - return self.origDate.getUTCMilliseconds(); - }; - - self.getDay = function() { - return self.date.getDay(); - }; - - // provide this method only on browsers that already have it - if (self.toISOString) { - self.toISOString = function() { - return padNumber(self.origDate.getUTCFullYear(), 4) + '-' + - padNumber(self.origDate.getUTCMonth() + 1, 2) + '-' + - padNumber(self.origDate.getUTCDate(), 2) + 'T' + - padNumber(self.origDate.getUTCHours(), 2) + ':' + - padNumber(self.origDate.getUTCMinutes(), 2) + ':' + - padNumber(self.origDate.getUTCSeconds(), 2) + '.' + - padNumber(self.origDate.getUTCMilliseconds(), 3) + 'Z' - } - } - - //hide all methods not implemented in this mock that the Date prototype exposes - var unimplementedMethods = ['getUTCDay', - 'getYear', 'setDate', 'setFullYear', 'setHours', 'setMilliseconds', - 'setMinutes', 'setMonth', 'setSeconds', 'setTime', 'setUTCDate', 'setUTCFullYear', - 'setUTCHours', 'setUTCMilliseconds', 'setUTCMinutes', 'setUTCMonth', 'setUTCSeconds', - 'setYear', 'toDateString', 'toGMTString', 'toJSON', 'toLocaleFormat', 'toLocaleString', - 'toLocaleTimeString', 'toSource', 'toString', 'toTimeString', 'toUTCString', 'valueOf']; - - angular.forEach(unimplementedMethods, function(methodName) { - self[methodName] = function() { - throw Error("Method '" + methodName + "' is not implemented in the TzDate mock"); - }; - }); - - return self; - }; - - //make "tzDateInstance instanceof Date" return true - angular.mock.TzDate.prototype = Date.prototype; -})(); - -/** - * @ngdoc function - * @name angular.mock.createMockWindow - * @description - * - * This function creates a mock window object useful for controlling access ot setTimeout, but mocking out - * sufficient window's properties to allow Angular to execute. - * - * @example - * - *
                -    beforeEach(module(function($provide) {
                -      $provide.value('$window', window = angular.mock.createMockWindow());
                -    }));
                -
                -    it('should do something', inject(function($window) {
                -      var val = null;
                -      $window.setTimeout(function() { val = 123; }, 10);
                -      expect(val).toEqual(null);
                -      window.setTimeout.expect(10).process();
                -      expect(val).toEqual(123);
                -    });
                - * 
                - * - */ -angular.mock.createMockWindow = function() { - var mockWindow = {}; - var setTimeoutQueue = []; - - mockWindow.document = window.document; - mockWindow.getComputedStyle = angular.bind(window, window.getComputedStyle); - mockWindow.scrollTo = angular.bind(window, window.scrollTo); - mockWindow.navigator = window.navigator; - mockWindow.setTimeout = function(fn, delay) { - setTimeoutQueue.push({fn: fn, delay: delay}); - }; - mockWindow.setTimeout.queue = setTimeoutQueue; - mockWindow.setTimeout.expect = function(delay) { - if (setTimeoutQueue.length > 0) { - return { - process: function() { - var tick = setTimeoutQueue.shift(); - expect(tick.delay).toEqual(delay); - tick.fn(); - } - }; - } else { - expect('SetTimoutQueue empty. Expecting delay of ').toEqual(delay); - } - }; - - return mockWindow; -}; - -/** - * @ngdoc function - * @name angular.mock.dump - * @description - * - * *NOTE*: this is not an injectable instance, just a globally available function. - * - * Method for serializing common angular objects (scope, elements, etc..) into strings, useful for debugging. - * - * This method is also available on window, where it can be used to display objects on debug console. - * - * @param {*} object - any object to turn into string. - * @return {string} a serialized string of the argument - */ -angular.mock.dump = function(object) { - return serialize(object); - - function serialize(object) { - var out; - - if (angular.isElement(object)) { - object = angular.element(object); - out = angular.element('
                '); - angular.forEach(object, function(element) { - out.append(angular.element(element).clone()); - }); - out = out.html(); - } else if (angular.isArray(object)) { - out = []; - angular.forEach(object, function(o) { - out.push(serialize(o)); - }); - out = '[ ' + out.join(', ') + ' ]'; - } else if (angular.isObject(object)) { - if (angular.isFunction(object.$eval) && angular.isFunction(object.$apply)) { - out = serializeScope(object); - } else if (object instanceof Error) { - out = object.stack || ('' + object.name + ': ' + object.message); - } else { - out = angular.toJson(object, true); - } - } else { - out = String(object); - } - - return out; - } - - function serializeScope(scope, offset) { - offset = offset || ' '; - var log = [offset + 'Scope(' + scope.$id + '): {']; - for ( var key in scope ) { - if (scope.hasOwnProperty(key) && !key.match(/^(\$|this)/)) { - log.push(' ' + key + ': ' + angular.toJson(scope[key])); - } - } - var child = scope.$$childHead; - while(child) { - log.push(serializeScope(child, offset + ' ')); - child = child.$$nextSibling; - } - log.push('}'); - return log.join('\n' + offset); - } -}; - -/** - * @ngdoc object - * @name ngMock.$httpBackend - * @description - * Fake HTTP backend implementation suitable for unit testing applications that use the - * {@link ng.$http $http service}. - * - * *Note*: For fake HTTP backend implementation suitable for end-to-end testing or backend-less - * development please see {@link ngMockE2E.$httpBackend e2e $httpBackend mock}. - * - * During unit testing, we want our unit tests to run quickly and have no external dependencies so - * we don’t want to send {@link https://developer.mozilla.org/en/xmlhttprequest XHR} or - * {@link http://en.wikipedia.org/wiki/JSONP JSONP} requests to a real server. All we really need is - * to verify whether a certain request has been sent or not, or alternatively just let the - * application make requests, respond with pre-trained responses and assert that the end result is - * what we expect it to be. - * - * This mock implementation can be used to respond with static or dynamic responses via the - * `expect` and `when` apis and their shortcuts (`expectGET`, `whenPOST`, etc). - * - * When an Angular application needs some data from a server, it calls the $http service, which - * sends the request to a real server using $httpBackend service. With dependency injection, it is - * easy to inject $httpBackend mock (which has the same API as $httpBackend) and use it to verify - * the requests and respond with some testing data without sending a request to real server. - * - * There are two ways to specify what test data should be returned as http responses by the mock - * backend when the code under test makes http requests: - * - * - `$httpBackend.expect` - specifies a request expectation - * - `$httpBackend.when` - specifies a backend definition - * - * - * # Request Expectations vs Backend Definitions - * - * Request expectations provide a way to make assertions about requests made by the application and - * to define responses for those requests. The test will fail if the expected requests are not made - * or they are made in the wrong order. - * - * Backend definitions allow you to define a fake backend for your application which doesn't assert - * if a particular request was made or not, it just returns a trained response if a request is made. - * The test will pass whether or not the request gets made during testing. - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
                Request expectationsBackend definitions
                Syntax.expect(...).respond(...).when(...).respond(...)
                Typical usagestrict unit testsloose (black-box) unit testing
                Fulfills multiple requestsNOYES
                Order of requests mattersYESNO
                Request requiredYESNO
                Response requiredoptional (see below)YES
                - * - * In cases where both backend definitions and request expectations are specified during unit - * testing, the request expectations are evaluated first. - * - * If a request expectation has no response specified, the algorithm will search your backend - * definitions for an appropriate response. - * - * If a request didn't match any expectation or if the expectation doesn't have the response - * defined, the backend definitions are evaluated in sequential order to see if any of them match - * the request. The response from the first matched definition is returned. - * - * - * # Flushing HTTP requests - * - * The $httpBackend used in production, always responds to requests with responses asynchronously. - * If we preserved this behavior in unit testing, we'd have to create async unit tests, which are - * hard to write, follow and maintain. At the same time the testing mock, can't respond - * synchronously because that would change the execution of the code under test. For this reason the - * mock $httpBackend has a `flush()` method, which allows the test to explicitly flush pending - * requests and thus preserving the async api of the backend, while allowing the test to execute - * synchronously. - * - * - * # Unit testing with mock $httpBackend - * - *
                -   // controller
                -   function MyController($scope, $http) {
                -     $http.get('/auth.py').success(function(data) {
                -       $scope.user = data;
                -     });
                -
                -     this.saveMessage = function(message) {
                -       $scope.status = 'Saving...';
                -       $http.post('/add-msg.py', message).success(function(response) {
                -         $scope.status = '';
                -       }).error(function() {
                -         $scope.status = 'ERROR!';
                -       });
                -     };
                -   }
                -
                -   // testing controller
                -   var $httpBackend;
                -
                -   beforeEach(inject(function($injector) {
                -     $httpBackend = $injector.get('$httpBackend');
                -
                -     // backend definition common for all tests
                -     $httpBackend.when('GET', '/auth.py').respond({userId: 'userX'}, {'A-Token': 'xxx'});
                -   }));
                -
                -
                -   afterEach(function() {
                -     $httpBackend.verifyNoOutstandingExpectation();
                -     $httpBackend.verifyNoOutstandingRequest();
                -   });
                -
                -
                -   it('should fetch authentication token', function() {
                -     $httpBackend.expectGET('/auth.py');
                -     var controller = scope.$new(MyController);
                -     $httpBackend.flush();
                -   });
                -
                -
                -   it('should send msg to server', function() {
                -     // now you don’t care about the authentication, but
                -     // the controller will still send the request and
                -     // $httpBackend will respond without you having to
                -     // specify the expectation and response for this request
                -     $httpBackend.expectPOST('/add-msg.py', 'message content').respond(201, '');
                -
                -     var controller = scope.$new(MyController);
                -     $httpBackend.flush();
                -     controller.saveMessage('message content');
                -     expect(controller.status).toBe('Saving...');
                -     $httpBackend.flush();
                -     expect(controller.status).toBe('');
                -   });
                -
                -
                -   it('should send auth header', function() {
                -     $httpBackend.expectPOST('/add-msg.py', undefined, function(headers) {
                -       // check if the header was send, if it wasn't the expectation won't
                -       // match the request and the test will fail
                -       return headers['Authorization'] == 'xxx';
                -     }).respond(201, '');
                -
                -     var controller = scope.$new(MyController);
                -     controller.saveMessage('whatever');
                -     $httpBackend.flush();
                -   });
                -   
                - */ -angular.mock.$HttpBackendProvider = function() { - this.$get = ['$rootScope', createHttpBackendMock]; -}; - -/** - * General factory function for $httpBackend mock. - * Returns instance for unit testing (when no arguments specified): - * - passing through is disabled - * - auto flushing is disabled - * - * Returns instance for e2e testing (when `$delegate` and `$browser` specified): - * - passing through (delegating request to real backend) is enabled - * - auto flushing is enabled - * - * @param {Object=} $delegate Real $httpBackend instance (allow passing through if specified) - * @param {Object=} $browser Auto-flushing enabled if specified - * @return {Object} Instance of $httpBackend mock - */ -function createHttpBackendMock($rootScope, $delegate, $browser) { - var definitions = [], - expectations = [], - responses = [], - responsesPush = angular.bind(responses, responses.push); - - function createResponse(status, data, headers) { - if (angular.isFunction(status)) return status; - - return function() { - return angular.isNumber(status) - ? [status, data, headers] - : [200, status, data]; - }; - } - - // TODO(vojta): change params to: method, url, data, headers, callback - function $httpBackend(method, url, data, callback, headers, timeout) { - var xhr = new MockXhr(), - expectation = expectations[0], - wasExpected = false; - - function prettyPrint(data) { - return (angular.isString(data) || angular.isFunction(data) || data instanceof RegExp) - ? data - : angular.toJson(data); - } - - function wrapResponse(wrapped) { - if (!$browser && timeout && timeout.then) timeout.then(handleTimeout); - - return handleResponse; - - function handleResponse() { - var response = wrapped.response(method, url, data, headers); - xhr.$$respHeaders = response[2]; - callback(response[0], response[1], xhr.getAllResponseHeaders()); - } - - function handleTimeout() { - for (var i = 0, ii = responses.length; i < ii; i++) { - if (responses[i] === handleResponse) { - responses.splice(i, 1); - callback(-1, undefined, ''); - break; - } - } - } - } - - if (expectation && expectation.match(method, url)) { - if (!expectation.matchData(data)) - throw Error('Expected ' + expectation + ' with different data\n' + - 'EXPECTED: ' + prettyPrint(expectation.data) + '\nGOT: ' + data); - - if (!expectation.matchHeaders(headers)) - throw Error('Expected ' + expectation + ' with different headers\n' + - 'EXPECTED: ' + prettyPrint(expectation.headers) + '\nGOT: ' + - prettyPrint(headers)); - - expectations.shift(); - - if (expectation.response) { - responses.push(wrapResponse(expectation)); - return; - } - wasExpected = true; - } - - var i = -1, definition; - while ((definition = definitions[++i])) { - if (definition.match(method, url, data, headers || {})) { - if (definition.response) { - // if $browser specified, we do auto flush all requests - ($browser ? $browser.defer : responsesPush)(wrapResponse(definition)); - } else if (definition.passThrough) { - $delegate(method, url, data, callback, headers, timeout); - } else throw Error('No response defined !'); - return; - } - } - throw wasExpected ? - Error('No response defined !') : - Error('Unexpected request: ' + method + ' ' + url + '\n' + - (expectation ? 'Expected ' + expectation : 'No more request expected')); - } - - /** - * @ngdoc method - * @name ngMock.$httpBackend#when - * @methodOf ngMock.$httpBackend - * @description - * Creates a new backend definition. - * - * @param {string} method HTTP method. - * @param {string|RegExp} url HTTP url. - * @param {(string|RegExp)=} data HTTP request body. - * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header - * object and returns true if the headers match the current definition. - * @returns {requestHandler} Returns an object with `respond` method that control how a matched - * request is handled. - * - * - respond – `{function([status,] data[, headers])|function(function(method, url, data, headers)}` - * – The respond method takes a set of static data to be returned or a function that can return - * an array containing response status (number), response data (string) and response headers - * (Object). - */ - $httpBackend.when = function(method, url, data, headers) { - var definition = new MockHttpExpectation(method, url, data, headers), - chain = { - respond: function(status, data, headers) { - definition.response = createResponse(status, data, headers); - } - }; - - if ($browser) { - chain.passThrough = function() { - definition.passThrough = true; - }; - } - - definitions.push(definition); - return chain; - }; - - /** - * @ngdoc method - * @name ngMock.$httpBackend#whenGET - * @methodOf ngMock.$httpBackend - * @description - * Creates a new backend definition for GET requests. For more info see `when()`. - * - * @param {string|RegExp} url HTTP url. - * @param {(Object|function(Object))=} headers HTTP headers. - * @returns {requestHandler} Returns an object with `respond` method that control how a matched - * request is handled. - */ - - /** - * @ngdoc method - * @name ngMock.$httpBackend#whenHEAD - * @methodOf ngMock.$httpBackend - * @description - * Creates a new backend definition for HEAD requests. For more info see `when()`. - * - * @param {string|RegExp} url HTTP url. - * @param {(Object|function(Object))=} headers HTTP headers. - * @returns {requestHandler} Returns an object with `respond` method that control how a matched - * request is handled. - */ - - /** - * @ngdoc method - * @name ngMock.$httpBackend#whenDELETE - * @methodOf ngMock.$httpBackend - * @description - * Creates a new backend definition for DELETE requests. For more info see `when()`. - * - * @param {string|RegExp} url HTTP url. - * @param {(Object|function(Object))=} headers HTTP headers. - * @returns {requestHandler} Returns an object with `respond` method that control how a matched - * request is handled. - */ - - /** - * @ngdoc method - * @name ngMock.$httpBackend#whenPOST - * @methodOf ngMock.$httpBackend - * @description - * Creates a new backend definition for POST requests. For more info see `when()`. - * - * @param {string|RegExp} url HTTP url. - * @param {(string|RegExp)=} data HTTP request body. - * @param {(Object|function(Object))=} headers HTTP headers. - * @returns {requestHandler} Returns an object with `respond` method that control how a matched - * request is handled. - */ - - /** - * @ngdoc method - * @name ngMock.$httpBackend#whenPUT - * @methodOf ngMock.$httpBackend - * @description - * Creates a new backend definition for PUT requests. For more info see `when()`. - * - * @param {string|RegExp} url HTTP url. - * @param {(string|RegExp)=} data HTTP request body. - * @param {(Object|function(Object))=} headers HTTP headers. - * @returns {requestHandler} Returns an object with `respond` method that control how a matched - * request is handled. - */ - - /** - * @ngdoc method - * @name ngMock.$httpBackend#whenJSONP - * @methodOf ngMock.$httpBackend - * @description - * Creates a new backend definition for JSONP requests. For more info see `when()`. - * - * @param {string|RegExp} url HTTP url. - * @returns {requestHandler} Returns an object with `respond` method that control how a matched - * request is handled. - */ - createShortMethods('when'); - - - /** - * @ngdoc method - * @name ngMock.$httpBackend#expect - * @methodOf ngMock.$httpBackend - * @description - * Creates a new request expectation. - * - * @param {string} method HTTP method. - * @param {string|RegExp} url HTTP url. - * @param {(string|RegExp)=} data HTTP request body. - * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header - * object and returns true if the headers match the current expectation. - * @returns {requestHandler} Returns an object with `respond` method that control how a matched - * request is handled. - * - * - respond – `{function([status,] data[, headers])|function(function(method, url, data, headers)}` - * – The respond method takes a set of static data to be returned or a function that can return - * an array containing response status (number), response data (string) and response headers - * (Object). - */ - $httpBackend.expect = function(method, url, data, headers) { - var expectation = new MockHttpExpectation(method, url, data, headers); - expectations.push(expectation); - return { - respond: function(status, data, headers) { - expectation.response = createResponse(status, data, headers); - } - }; - }; - - - /** - * @ngdoc method - * @name ngMock.$httpBackend#expectGET - * @methodOf ngMock.$httpBackend - * @description - * Creates a new request expectation for GET requests. For more info see `expect()`. - * - * @param {string|RegExp} url HTTP url. - * @param {Object=} headers HTTP headers. - * @returns {requestHandler} Returns an object with `respond` method that control how a matched - * request is handled. See #expect for more info. - */ - - /** - * @ngdoc method - * @name ngMock.$httpBackend#expectHEAD - * @methodOf ngMock.$httpBackend - * @description - * Creates a new request expectation for HEAD requests. For more info see `expect()`. - * - * @param {string|RegExp} url HTTP url. - * @param {Object=} headers HTTP headers. - * @returns {requestHandler} Returns an object with `respond` method that control how a matched - * request is handled. - */ - - /** - * @ngdoc method - * @name ngMock.$httpBackend#expectDELETE - * @methodOf ngMock.$httpBackend - * @description - * Creates a new request expectation for DELETE requests. For more info see `expect()`. - * - * @param {string|RegExp} url HTTP url. - * @param {Object=} headers HTTP headers. - * @returns {requestHandler} Returns an object with `respond` method that control how a matched - * request is handled. - */ - - /** - * @ngdoc method - * @name ngMock.$httpBackend#expectPOST - * @methodOf ngMock.$httpBackend - * @description - * Creates a new request expectation for POST requests. For more info see `expect()`. - * - * @param {string|RegExp} url HTTP url. - * @param {(string|RegExp)=} data HTTP request body. - * @param {Object=} headers HTTP headers. - * @returns {requestHandler} Returns an object with `respond` method that control how a matched - * request is handled. - */ - - /** - * @ngdoc method - * @name ngMock.$httpBackend#expectPUT - * @methodOf ngMock.$httpBackend - * @description - * Creates a new request expectation for PUT requests. For more info see `expect()`. - * - * @param {string|RegExp} url HTTP url. - * @param {(string|RegExp)=} data HTTP request body. - * @param {Object=} headers HTTP headers. - * @returns {requestHandler} Returns an object with `respond` method that control how a matched - * request is handled. - */ - - /** - * @ngdoc method - * @name ngMock.$httpBackend#expectPATCH - * @methodOf ngMock.$httpBackend - * @description - * Creates a new request expectation for PATCH requests. For more info see `expect()`. - * - * @param {string|RegExp} url HTTP url. - * @param {(string|RegExp)=} data HTTP request body. - * @param {Object=} headers HTTP headers. - * @returns {requestHandler} Returns an object with `respond` method that control how a matched - * request is handled. - */ - - /** - * @ngdoc method - * @name ngMock.$httpBackend#expectJSONP - * @methodOf ngMock.$httpBackend - * @description - * Creates a new request expectation for JSONP requests. For more info see `expect()`. - * - * @param {string|RegExp} url HTTP url. - * @returns {requestHandler} Returns an object with `respond` method that control how a matched - * request is handled. - */ - createShortMethods('expect'); - - - /** - * @ngdoc method - * @name ngMock.$httpBackend#flush - * @methodOf ngMock.$httpBackend - * @description - * Flushes all pending requests using the trained responses. - * - * @param {number=} count Number of responses to flush (in the order they arrived). If undefined, - * all pending requests will be flushed. If there are no pending requests when the flush method - * is called an exception is thrown (as this typically a sign of programming error). - */ - $httpBackend.flush = function(count) { - $rootScope.$digest(); - if (!responses.length) throw Error('No pending request to flush !'); - - if (angular.isDefined(count)) { - while (count--) { - if (!responses.length) throw Error('No more pending request to flush !'); - responses.shift()(); - } - } else { - while (responses.length) { - responses.shift()(); - } - } - $httpBackend.verifyNoOutstandingExpectation(); - }; - - - /** - * @ngdoc method - * @name ngMock.$httpBackend#verifyNoOutstandingExpectation - * @methodOf ngMock.$httpBackend - * @description - * Verifies that all of the requests defined via the `expect` api were made. If any of the - * requests were not made, verifyNoOutstandingExpectation throws an exception. - * - * Typically, you would call this method following each test case that asserts requests using an - * "afterEach" clause. - * - *
                -   *   afterEach($httpBackend.verifyExpectations);
                -   * 
                - */ - $httpBackend.verifyNoOutstandingExpectation = function() { - $rootScope.$digest(); - if (expectations.length) { - throw Error('Unsatisfied requests: ' + expectations.join(', ')); - } - }; - - - /** - * @ngdoc method - * @name ngMock.$httpBackend#verifyNoOutstandingRequest - * @methodOf ngMock.$httpBackend - * @description - * Verifies that there are no outstanding requests that need to be flushed. - * - * Typically, you would call this method following each test case that asserts requests using an - * "afterEach" clause. - * - *
                -   *   afterEach($httpBackend.verifyNoOutstandingRequest);
                -   * 
                - */ - $httpBackend.verifyNoOutstandingRequest = function() { - if (responses.length) { - throw Error('Unflushed requests: ' + responses.length); - } - }; - - - /** - * @ngdoc method - * @name ngMock.$httpBackend#resetExpectations - * @methodOf ngMock.$httpBackend - * @description - * Resets all request expectations, but preserves all backend definitions. Typically, you would - * call resetExpectations during a multiple-phase test when you want to reuse the same instance of - * $httpBackend mock. - */ - $httpBackend.resetExpectations = function() { - expectations.length = 0; - responses.length = 0; - }; - - return $httpBackend; - - - function createShortMethods(prefix) { - angular.forEach(['GET', 'DELETE', 'JSONP'], function(method) { - $httpBackend[prefix + method] = function(url, headers) { - return $httpBackend[prefix](method, url, undefined, headers) - } - }); - - angular.forEach(['PUT', 'POST', 'PATCH'], function(method) { - $httpBackend[prefix + method] = function(url, data, headers) { - return $httpBackend[prefix](method, url, data, headers) - } - }); - } -} - -function MockHttpExpectation(method, url, data, headers) { - - this.data = data; - this.headers = headers; - - this.match = function(m, u, d, h) { - if (method != m) return false; - if (!this.matchUrl(u)) return false; - if (angular.isDefined(d) && !this.matchData(d)) return false; - if (angular.isDefined(h) && !this.matchHeaders(h)) return false; - return true; - }; - - this.matchUrl = function(u) { - if (!url) return true; - if (angular.isFunction(url.test)) return url.test(u); - return url == u; - }; - - this.matchHeaders = function(h) { - if (angular.isUndefined(headers)) return true; - if (angular.isFunction(headers)) return headers(h); - return angular.equals(headers, h); - }; - - this.matchData = function(d) { - if (angular.isUndefined(data)) return true; - if (data && angular.isFunction(data.test)) return data.test(d); - if (data && !angular.isString(data)) return angular.toJson(data) == d; - return data == d; - }; - - this.toString = function() { - return method + ' ' + url; - }; -} - -function MockXhr() { - - // hack for testing $http, $httpBackend - MockXhr.$$lastInstance = this; - - this.open = function(method, url, async) { - this.$$method = method; - this.$$url = url; - this.$$async = async; - this.$$reqHeaders = {}; - this.$$respHeaders = {}; - }; - - this.send = function(data) { - this.$$data = data; - }; - - this.setRequestHeader = function(key, value) { - this.$$reqHeaders[key] = value; - }; - - this.getResponseHeader = function(name) { - // the lookup must be case insensitive, that's why we try two quick lookups and full scan at last - var header = this.$$respHeaders[name]; - if (header) return header; - - name = angular.lowercase(name); - header = this.$$respHeaders[name]; - if (header) return header; - - header = undefined; - angular.forEach(this.$$respHeaders, function(headerVal, headerName) { - if (!header && angular.lowercase(headerName) == name) header = headerVal; - }); - return header; - }; - - this.getAllResponseHeaders = function() { - var lines = []; - - angular.forEach(this.$$respHeaders, function(value, key) { - lines.push(key + ': ' + value); - }); - return lines.join('\n'); - }; - - this.abort = angular.noop; -} - - -/** - * @ngdoc function - * @name ngMock.$timeout - * @description - * - * This service is just a simple decorator for {@link ng.$timeout $timeout} service - * that adds a "flush" and "verifyNoPendingTasks" methods. - */ - -angular.mock.$TimeoutDecorator = function($delegate, $browser) { - - /** - * @ngdoc method - * @name ngMock.$timeout#flush - * @methodOf ngMock.$timeout - * @description - * - * Flushes the queue of pending tasks. - */ - $delegate.flush = function() { - $browser.defer.flush(); - }; - - /** - * @ngdoc method - * @name ngMock.$timeout#verifyNoPendingTasks - * @methodOf ngMock.$timeout - * @description - * - * Verifies that there are no pending tasks that need to be flushed. - */ - $delegate.verifyNoPendingTasks = function() { - if ($browser.deferredFns.length) { - throw Error('Deferred tasks to flush (' + $browser.deferredFns.length + '): ' + - formatPendingTasksAsString($browser.deferredFns)); - } - }; - - function formatPendingTasksAsString(tasks) { - var result = []; - angular.forEach(tasks, function(task) { - result.push('{id: ' + task.id + ', ' + 'time: ' + task.time + '}'); - }); - - return result.join(', '); - } - - return $delegate; -}; - -/** - * - */ -angular.mock.$RootElementProvider = function() { - this.$get = function() { - return angular.element('
                '); - } -}; - -/** - * @ngdoc overview - * @name ngMock - * @description - * - * The `ngMock` is an angular module which is used with `ng` module and adds unit-test configuration as well as useful - * mocks to the {@link AUTO.$injector $injector}. - */ -angular.module('ngMock', ['ng']).provider({ - $browser: angular.mock.$BrowserProvider, - $exceptionHandler: angular.mock.$ExceptionHandlerProvider, - $log: angular.mock.$LogProvider, - $httpBackend: angular.mock.$HttpBackendProvider, - $rootElement: angular.mock.$RootElementProvider -}).config(function($provide) { - $provide.decorator('$timeout', angular.mock.$TimeoutDecorator); -}); - -/** - * @ngdoc overview - * @name ngMockE2E - * @description - * - * The `ngMockE2E` is an angular module which contains mocks suitable for end-to-end testing. - * Currently there is only one mock present in this module - - * the {@link ngMockE2E.$httpBackend e2e $httpBackend} mock. - */ -angular.module('ngMockE2E', ['ng']).config(function($provide) { - $provide.decorator('$httpBackend', angular.mock.e2e.$httpBackendDecorator); -}); - -/** - * @ngdoc object - * @name ngMockE2E.$httpBackend - * @description - * Fake HTTP backend implementation suitable for end-to-end testing or backend-less development of - * applications that use the {@link ng.$http $http service}. - * - * *Note*: For fake http backend implementation suitable for unit testing please see - * {@link ngMock.$httpBackend unit-testing $httpBackend mock}. - * - * This implementation can be used to respond with static or dynamic responses via the `when` api - * and its shortcuts (`whenGET`, `whenPOST`, etc) and optionally pass through requests to the - * real $httpBackend for specific requests (e.g. to interact with certain remote apis or to fetch - * templates from a webserver). - * - * As opposed to unit-testing, in an end-to-end testing scenario or in scenario when an application - * is being developed with the real backend api replaced with a mock, it is often desirable for - * certain category of requests to bypass the mock and issue a real http request (e.g. to fetch - * templates or static files from the webserver). To configure the backend with this behavior - * use the `passThrough` request handler of `when` instead of `respond`. - * - * Additionally, we don't want to manually have to flush mocked out requests like we do during unit - * testing. For this reason the e2e $httpBackend automatically flushes mocked out requests - * automatically, closely simulating the behavior of the XMLHttpRequest object. - * - * To setup the application to run with this http backend, you have to create a module that depends - * on the `ngMockE2E` and your application modules and defines the fake backend: - * - *
                - *   myAppDev = angular.module('myAppDev', ['myApp', 'ngMockE2E']);
                - *   myAppDev.run(function($httpBackend) {
                - *     phones = [{name: 'phone1'}, {name: 'phone2'}];
                - *
                - *     // returns the current list of phones
                - *     $httpBackend.whenGET('/phones').respond(phones);
                - *
                - *     // adds a new phone to the phones array
                - *     $httpBackend.whenPOST('/phones').respond(function(method, url, data) {
                - *       phones.push(angular.fromJSON(data));
                - *     });
                - *     $httpBackend.whenGET(/^\/templates\//).passThrough();
                - *     //...
                - *   });
                - * 
                - * - * Afterwards, bootstrap your app with this new module. - */ - -/** - * @ngdoc method - * @name ngMockE2E.$httpBackend#when - * @methodOf ngMockE2E.$httpBackend - * @description - * Creates a new backend definition. - * - * @param {string} method HTTP method. - * @param {string|RegExp} url HTTP url. - * @param {(string|RegExp)=} data HTTP request body. - * @param {(Object|function(Object))=} headers HTTP headers or function that receives http header - * object and returns true if the headers match the current definition. - * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that - * control how a matched request is handled. - * - * - respond – `{function([status,] data[, headers])|function(function(method, url, data, headers)}` - * – The respond method takes a set of static data to be returned or a function that can return - * an array containing response status (number), response data (string) and response headers - * (Object). - * - passThrough – `{function()}` – Any request matching a backend definition with `passThrough` - * handler, will be pass through to the real backend (an XHR request will be made to the - * server. - */ - -/** - * @ngdoc method - * @name ngMockE2E.$httpBackend#whenGET - * @methodOf ngMockE2E.$httpBackend - * @description - * Creates a new backend definition for GET requests. For more info see `when()`. - * - * @param {string|RegExp} url HTTP url. - * @param {(Object|function(Object))=} headers HTTP headers. - * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that - * control how a matched request is handled. - */ - -/** - * @ngdoc method - * @name ngMockE2E.$httpBackend#whenHEAD - * @methodOf ngMockE2E.$httpBackend - * @description - * Creates a new backend definition for HEAD requests. For more info see `when()`. - * - * @param {string|RegExp} url HTTP url. - * @param {(Object|function(Object))=} headers HTTP headers. - * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that - * control how a matched request is handled. - */ - -/** - * @ngdoc method - * @name ngMockE2E.$httpBackend#whenDELETE - * @methodOf ngMockE2E.$httpBackend - * @description - * Creates a new backend definition for DELETE requests. For more info see `when()`. - * - * @param {string|RegExp} url HTTP url. - * @param {(Object|function(Object))=} headers HTTP headers. - * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that - * control how a matched request is handled. - */ - -/** - * @ngdoc method - * @name ngMockE2E.$httpBackend#whenPOST - * @methodOf ngMockE2E.$httpBackend - * @description - * Creates a new backend definition for POST requests. For more info see `when()`. - * - * @param {string|RegExp} url HTTP url. - * @param {(string|RegExp)=} data HTTP request body. - * @param {(Object|function(Object))=} headers HTTP headers. - * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that - * control how a matched request is handled. - */ - -/** - * @ngdoc method - * @name ngMockE2E.$httpBackend#whenPUT - * @methodOf ngMockE2E.$httpBackend - * @description - * Creates a new backend definition for PUT requests. For more info see `when()`. - * - * @param {string|RegExp} url HTTP url. - * @param {(string|RegExp)=} data HTTP request body. - * @param {(Object|function(Object))=} headers HTTP headers. - * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that - * control how a matched request is handled. - */ - -/** - * @ngdoc method - * @name ngMockE2E.$httpBackend#whenPATCH - * @methodOf ngMockE2E.$httpBackend - * @description - * Creates a new backend definition for PATCH requests. For more info see `when()`. - * - * @param {string|RegExp} url HTTP url. - * @param {(string|RegExp)=} data HTTP request body. - * @param {(Object|function(Object))=} headers HTTP headers. - * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that - * control how a matched request is handled. - */ - -/** - * @ngdoc method - * @name ngMockE2E.$httpBackend#whenJSONP - * @methodOf ngMockE2E.$httpBackend - * @description - * Creates a new backend definition for JSONP requests. For more info see `when()`. - * - * @param {string|RegExp} url HTTP url. - * @returns {requestHandler} Returns an object with `respond` and `passThrough` methods that - * control how a matched request is handled. - */ -angular.mock.e2e = {}; -angular.mock.e2e.$httpBackendDecorator = ['$rootScope', '$delegate', '$browser', createHttpBackendMock]; - - -angular.mock.clearDataCache = function() { - var key, - cache = angular.element.cache; - - for(key in cache) { - if (cache.hasOwnProperty(key)) { - var handle = cache[key].handle; - - handle && angular.element(handle.elem).unbind(); - delete cache[key]; - } - } -}; - - -window.jstestdriver && (function(window) { - /** - * Global method to output any number of objects into JSTD console. Useful for debugging. - */ - window.dump = function() { - var args = []; - angular.forEach(arguments, function(arg) { - args.push(angular.mock.dump(arg)); - }); - jstestdriver.console.log.apply(jstestdriver.console, args); - if (window.console) { - window.console.log.apply(window.console, args); - } - }; -})(window); - - -(window.jasmine || window.mocha) && (function(window) { - - var currentSpec = null; - - beforeEach(function() { - currentSpec = this; - }); - - afterEach(function() { - var injector = currentSpec.$injector; - - currentSpec.$injector = null; - currentSpec.$modules = null; - currentSpec = null; - - if (injector) { - injector.get('$rootElement').unbind(); - injector.get('$browser').pollFns.length = 0; - } - - angular.mock.clearDataCache(); - - // clean up jquery's fragment cache - angular.forEach(angular.element.fragments, function(val, key) { - delete angular.element.fragments[key]; - }); - - MockXhr.$$lastInstance = null; - - angular.forEach(angular.callbacks, function(val, key) { - delete angular.callbacks[key]; - }); - angular.callbacks.counter = 0; - }); - - function isSpecRunning() { - return currentSpec && (window.mocha || currentSpec.queue.running); - } - - /** - * @ngdoc function - * @name angular.mock.module - * @description - * - * *NOTE*: This function is also published on window for easy access.
                - * - * This function registers a module configuration code. It collects the configuration information - * which will be used when the injector is created by {@link angular.mock.inject inject}. - * - * See {@link angular.mock.inject inject} for usage example - * - * @param {...(string|Function)} fns any number of modules which are represented as string - * aliases or as anonymous module initialization functions. The modules are used to - * configure the injector. The 'ng' and 'ngMock' modules are automatically loaded. - */ - window.module = angular.mock.module = function() { - var moduleFns = Array.prototype.slice.call(arguments, 0); - return isSpecRunning() ? workFn() : workFn; - ///////////////////// - function workFn() { - if (currentSpec.$injector) { - throw Error('Injector already created, can not register a module!'); - } else { - var modules = currentSpec.$modules || (currentSpec.$modules = []); - angular.forEach(moduleFns, function(module) { - modules.push(module); - }); - } - } - }; - - /** - * @ngdoc function - * @name angular.mock.inject - * @description - * - * *NOTE*: This function is also published on window for easy access.
                - * - * The inject function wraps a function into an injectable function. The inject() creates new - * instance of {@link AUTO.$injector $injector} per test, which is then used for - * resolving references. - * - * See also {@link angular.mock.module module} - * - * Example of what a typical jasmine tests looks like with the inject method. - *
                -   *
                -   *   angular.module('myApplicationModule', [])
                -   *       .value('mode', 'app')
                -   *       .value('version', 'v1.0.1');
                -   *
                -   *
                -   *   describe('MyApp', function() {
                -   *
                -   *     // You need to load modules that you want to test,
                -   *     // it loads only the "ng" module by default.
                -   *     beforeEach(module('myApplicationModule'));
                -   *
                -   *
                -   *     // inject() is used to inject arguments of all given functions
                -   *     it('should provide a version', inject(function(mode, version) {
                -   *       expect(version).toEqual('v1.0.1');
                -   *       expect(mode).toEqual('app');
                -   *     }));
                -   *
                -   *
                -   *     // The inject and module method can also be used inside of the it or beforeEach
                -   *     it('should override a version and test the new version is injected', function() {
                -   *       // module() takes functions or strings (module aliases)
                -   *       module(function($provide) {
                -   *         $provide.value('version', 'overridden'); // override version here
                -   *       });
                -   *
                -   *       inject(function(version) {
                -   *         expect(version).toEqual('overridden');
                -   *       });
                -   *     ));
                -   *   });
                -   *
                -   * 
                - * - * @param {...Function} fns any number of functions which will be injected using the injector. - */ - window.inject = angular.mock.inject = function() { - var blockFns = Array.prototype.slice.call(arguments, 0); - var errorForStack = new Error('Declaration Location'); - return isSpecRunning() ? workFn() : workFn; - ///////////////////// - function workFn() { - var modules = currentSpec.$modules || []; - - modules.unshift('ngMock'); - modules.unshift('ng'); - var injector = currentSpec.$injector; - if (!injector) { - injector = currentSpec.$injector = angular.injector(modules); - } - for(var i = 0, ii = blockFns.length; i < ii; i++) { - try { - injector.invoke(blockFns[i] || angular.noop, this); - } catch (e) { - if(e.stack && errorForStack) e.stack += '\n' + errorForStack.stack; - throw e; - } finally { - errorForStack = null; - } - } - } - }; -})(window); diff --git a/src/Umbraco.Web.UI.Client/lib/angular/1.1.5/angular-resource.js b/src/Umbraco.Web.UI.Client/lib/angular/1.1.5/angular-resource.js deleted file mode 100644 index 2b9047ee4c..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/angular/1.1.5/angular-resource.js +++ /dev/null @@ -1,537 +0,0 @@ -/** - * @license AngularJS v1.1.5 - * (c) 2010-2012 Google, Inc. http://angularjs.org - * License: MIT - */ -(function(window, angular, undefined) { -'use strict'; - -/** - * @ngdoc overview - * @name ngResource - * @description - */ - -/** - * @ngdoc object - * @name ngResource.$resource - * @requires $http - * - * @description - * A factory which creates a resource object that lets you interact with - * [RESTful](http://en.wikipedia.org/wiki/Representational_State_Transfer) server-side data sources. - * - * The returned resource object has action methods which provide high-level behaviors without - * the need to interact with the low level {@link ng.$http $http} service. - * - * # Installation - * To use $resource make sure you have included the `angular-resource.js` that comes in Angular - * package. You can also find this file on Google CDN, bower as well as at - * {@link http://code.angularjs.org/ code.angularjs.org}. - * - * Finally load the module in your application: - * - * angular.module('app', ['ngResource']); - * - * and you are ready to get started! - * - * @param {string} url A parametrized URL template with parameters prefixed by `:` as in - * `/user/:username`. If you are using a URL with a port number (e.g. - * `http://example.com:8080/api`), you'll need to escape the colon character before the port - * number, like this: `$resource('http://example.com\\:8080/api')`. - * - * If you are using a url with a suffix, just add the suffix, like this: - * `$resource('http://example.com/resource.json')` or `$resource('http://example.com/:id.json') - * or even `$resource('http://example.com/resource/:resource_id.:format')` - * If the parameter before the suffix is empty, :resource_id in this case, then the `/.` will be - * collapsed down to a single `.`. If you need this sequence to appear and not collapse then you - * can escape it with `/\.`. - * - * @param {Object=} paramDefaults Default values for `url` parameters. These can be overridden in - * `actions` methods. If any of the parameter value is a function, it will be executed every time - * when a param value needs to be obtained for a request (unless the param was overridden). - * - * Each key value in the parameter object is first bound to url template if present and then any - * excess keys are appended to the url search query after the `?`. - * - * Given a template `/path/:verb` and parameter `{verb:'greet', salutation:'Hello'}` results in - * URL `/path/greet?salutation=Hello`. - * - * If the parameter value is prefixed with `@` then the value of that parameter is extracted from - * the data object (useful for non-GET operations). - * - * @param {Object.=} actions Hash with declaration of custom action that should extend the - * default set of resource actions. The declaration should be created in the format of {@link - * ng.$http#Parameters $http.config}: - * - * {action1: {method:?, params:?, isArray:?, headers:?, ...}, - * action2: {method:?, params:?, isArray:?, headers:?, ...}, - * ...} - * - * Where: - * - * - **`action`** – {string} – The name of action. This name becomes the name of the method on your - * resource object. - * - **`method`** – {string} – HTTP request method. Valid methods are: `GET`, `POST`, `PUT`, `DELETE`, - * and `JSONP`. - * - **`params`** – {Object=} – Optional set of pre-bound parameters for this action. If any of the - * parameter value is a function, it will be executed every time when a param value needs to be - * obtained for a request (unless the param was overridden). - * - **`url`** – {string} – action specific `url` override. The url templating is supported just like - * for the resource-level urls. - * - **`isArray`** – {boolean=} – If true then the returned object for this action is an array, see - * `returns` section. - * - **`transformRequest`** – `{function(data, headersGetter)|Array.}` – - * transform function or an array of such functions. The transform function takes the http - * request body and headers and returns its transformed (typically serialized) version. - * - **`transformResponse`** – `{function(data, headersGetter)|Array.}` – - * transform function or an array of such functions. The transform function takes the http - * response body and headers and returns its transformed (typically deserialized) version. - * - **`cache`** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the - * GET request, otherwise if a cache instance built with - * {@link ng.$cacheFactory $cacheFactory}, this cache will be used for - * caching. - * - **`timeout`** – `{number|Promise}` – timeout in milliseconds, or {@link ng.$q promise} that - * should abort the request when resolved. - * - **`withCredentials`** - `{boolean}` - whether to to set the `withCredentials` flag on the - * XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5 - * requests with credentials} for more information. - * - **`responseType`** - `{string}` - see {@link - * https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#responseType requestType}. - * - * @returns {Object} A resource "class" object with methods for the default set of resource actions - * optionally extended with custom `actions`. The default set contains these actions: - * - * { 'get': {method:'GET'}, - * 'save': {method:'POST'}, - * 'query': {method:'GET', isArray:true}, - * 'remove': {method:'DELETE'}, - * 'delete': {method:'DELETE'} }; - * - * Calling these methods invoke an {@link ng.$http} with the specified http method, - * destination and parameters. When the data is returned from the server then the object is an - * instance of the resource class. The actions `save`, `remove` and `delete` are available on it - * as methods with the `$` prefix. This allows you to easily perform CRUD operations (create, - * read, update, delete) on server-side data like this: - *
                -        var User = $resource('/user/:userId', {userId:'@id'});
                -        var user = User.get({userId:123}, function() {
                -          user.abc = true;
                -          user.$save();
                -        });
                -     
                - * - * It is important to realize that invoking a $resource object method immediately returns an - * empty reference (object or array depending on `isArray`). Once the data is returned from the - * server the existing reference is populated with the actual data. This is a useful trick since - * usually the resource is assigned to a model which is then rendered by the view. Having an empty - * object results in no rendering, once the data arrives from the server then the object is - * populated with the data and the view automatically re-renders itself showing the new data. This - * means that in most case one never has to write a callback function for the action methods. - * - * The action methods on the class object or instance object can be invoked with the following - * parameters: - * - * - HTTP GET "class" actions: `Resource.action([parameters], [success], [error])` - * - non-GET "class" actions: `Resource.action([parameters], postData, [success], [error])` - * - non-GET instance actions: `instance.$action([parameters], [success], [error])` - * - * - * The Resource instances and collection have these additional properties: - * - * - `$then`: the `then` method of a {@link ng.$q promise} derived from the underlying - * {@link ng.$http $http} call. - * - * The success callback for the `$then` method will be resolved if the underlying `$http` requests - * succeeds. - * - * The success callback is called with a single object which is the {@link ng.$http http response} - * object extended with a new property `resource`. This `resource` property is a reference to the - * result of the resource action — resource object or array of resources. - * - * The error callback is called with the {@link ng.$http http response} object when an http - * error occurs. - * - * - `$resolved`: true if the promise has been resolved (either with success or rejection); - * Knowing if the Resource has been resolved is useful in data-binding. - * - * @example - * - * # Credit card resource - * - *
                -     // Define CreditCard class
                -     var CreditCard = $resource('/user/:userId/card/:cardId',
                -      {userId:123, cardId:'@id'}, {
                -       charge: {method:'POST', params:{charge:true}}
                -      });
                -
                -     // We can retrieve a collection from the server
                -     var cards = CreditCard.query(function() {
                -       // GET: /user/123/card
                -       // server returns: [ {id:456, number:'1234', name:'Smith'} ];
                -
                -       var card = cards[0];
                -       // each item is an instance of CreditCard
                -       expect(card instanceof CreditCard).toEqual(true);
                -       card.name = "J. Smith";
                -       // non GET methods are mapped onto the instances
                -       card.$save();
                -       // POST: /user/123/card/456 {id:456, number:'1234', name:'J. Smith'}
                -       // server returns: {id:456, number:'1234', name: 'J. Smith'};
                -
                -       // our custom method is mapped as well.
                -       card.$charge({amount:9.99});
                -       // POST: /user/123/card/456?amount=9.99&charge=true {id:456, number:'1234', name:'J. Smith'}
                -     });
                -
                -     // we can create an instance as well
                -     var newCard = new CreditCard({number:'0123'});
                -     newCard.name = "Mike Smith";
                -     newCard.$save();
                -     // POST: /user/123/card {number:'0123', name:'Mike Smith'}
                -     // server returns: {id:789, number:'01234', name: 'Mike Smith'};
                -     expect(newCard.id).toEqual(789);
                - * 
                - * - * The object returned from this function execution is a resource "class" which has "static" method - * for each action in the definition. - * - * Calling these methods invoke `$http` on the `url` template with the given `method`, `params` and `headers`. - * When the data is returned from the server then the object is an instance of the resource type and - * all of the non-GET methods are available with `$` prefix. This allows you to easily support CRUD - * operations (create, read, update, delete) on server-side data. - -
                -     var User = $resource('/user/:userId', {userId:'@id'});
                -     var user = User.get({userId:123}, function() {
                -       user.abc = true;
                -       user.$save();
                -     });
                -   
                - * - * It's worth noting that the success callback for `get`, `query` and other method gets passed - * in the response that came from the server as well as $http header getter function, so one - * could rewrite the above example and get access to http headers as: - * -
                -     var User = $resource('/user/:userId', {userId:'@id'});
                -     User.get({userId:123}, function(u, getResponseHeaders){
                -       u.abc = true;
                -       u.$save(function(u, putResponseHeaders) {
                -         //u => saved user object
                -         //putResponseHeaders => $http header getter
                -       });
                -     });
                -   
                - - * # Buzz client - - Let's look at what a buzz client created with the `$resource` service looks like: - - - - -
                - - -
                -
                -

                - - {{item.actor.name}} - Expand replies: {{item.links.replies[0].count}} -

                - {{item.object.content | html}} -
                - - {{reply.actor.name}}: {{reply.content | html}} -
                -
                -
                -
                - - -
                - */ -angular.module('ngResource', ['ng']). - factory('$resource', ['$http', '$parse', function($http, $parse) { - var DEFAULT_ACTIONS = { - 'get': {method:'GET'}, - 'save': {method:'POST'}, - 'query': {method:'GET', isArray:true}, - 'remove': {method:'DELETE'}, - 'delete': {method:'DELETE'} - }; - var noop = angular.noop, - forEach = angular.forEach, - extend = angular.extend, - copy = angular.copy, - isFunction = angular.isFunction, - getter = function(obj, path) { - return $parse(path)(obj); - }; - - /** - * We need our custom method because encodeURIComponent is too aggressive and doesn't follow - * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path - * segments: - * segment = *pchar - * pchar = unreserved / pct-encoded / sub-delims / ":" / "@" - * pct-encoded = "%" HEXDIG HEXDIG - * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" - * sub-delims = "!" / "$" / "&" / "'" / "(" / ")" - * / "*" / "+" / "," / ";" / "=" - */ - function encodeUriSegment(val) { - return encodeUriQuery(val, true). - replace(/%26/gi, '&'). - replace(/%3D/gi, '='). - replace(/%2B/gi, '+'); - } - - - /** - * This method is intended for encoding *key* or *value* parts of query component. We need a custom - * method because encodeURIComponent is too aggressive and encodes stuff that doesn't have to be - * encoded per http://tools.ietf.org/html/rfc3986: - * query = *( pchar / "/" / "?" ) - * pchar = unreserved / pct-encoded / sub-delims / ":" / "@" - * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" - * pct-encoded = "%" HEXDIG HEXDIG - * sub-delims = "!" / "$" / "&" / "'" / "(" / ")" - * / "*" / "+" / "," / ";" / "=" - */ - function encodeUriQuery(val, pctEncodeSpaces) { - return encodeURIComponent(val). - replace(/%40/gi, '@'). - replace(/%3A/gi, ':'). - replace(/%24/g, '$'). - replace(/%2C/gi, ','). - replace(/%20/g, (pctEncodeSpaces ? '%20' : '+')); - } - - function Route(template, defaults) { - this.template = template; - this.defaults = defaults || {}; - this.urlParams = {}; - } - - Route.prototype = { - setUrlParams: function(config, params, actionUrl) { - var self = this, - url = actionUrl || self.template, - val, - encodedVal; - - var urlParams = self.urlParams = {}; - forEach(url.split(/\W/), function(param){ - if (param && (new RegExp("(^|[^\\\\]):" + param + "(\\W|$)").test(url))) { - urlParams[param] = true; - } - }); - url = url.replace(/\\:/g, ':'); - - params = params || {}; - forEach(self.urlParams, function(_, urlParam){ - val = params.hasOwnProperty(urlParam) ? params[urlParam] : self.defaults[urlParam]; - if (angular.isDefined(val) && val !== null) { - encodedVal = encodeUriSegment(val); - url = url.replace(new RegExp(":" + urlParam + "(\\W|$)", "g"), encodedVal + "$1"); - } else { - url = url.replace(new RegExp("(\/?):" + urlParam + "(\\W|$)", "g"), function(match, - leadingSlashes, tail) { - if (tail.charAt(0) == '/') { - return tail; - } else { - return leadingSlashes + tail; - } - }); - } - }); - - // strip trailing slashes and set the url - url = url.replace(/\/+$/, ''); - // then replace collapse `/.` if found in the last URL path segment before the query - // E.g. `http://url.com/id./format?q=x` becomes `http://url.com/id.format?q=x` - url = url.replace(/\/\.(?=\w+($|\?))/, '.'); - // replace escaped `/\.` with `/.` - config.url = url.replace(/\/\\\./, '/.'); - - - // set params - delegate param encoding to $http - forEach(params, function(value, key){ - if (!self.urlParams[key]) { - config.params = config.params || {}; - config.params[key] = value; - } - }); - } - }; - - - function ResourceFactory(url, paramDefaults, actions) { - var route = new Route(url); - - actions = extend({}, DEFAULT_ACTIONS, actions); - - function extractParams(data, actionParams){ - var ids = {}; - actionParams = extend({}, paramDefaults, actionParams); - forEach(actionParams, function(value, key){ - if (isFunction(value)) { value = value(); } - ids[key] = value && value.charAt && value.charAt(0) == '@' ? getter(data, value.substr(1)) : value; - }); - return ids; - } - - function Resource(value){ - copy(value || {}, this); - } - - forEach(actions, function(action, name) { - action.method = angular.uppercase(action.method); - var hasBody = action.method == 'POST' || action.method == 'PUT' || action.method == 'PATCH'; - Resource[name] = function(a1, a2, a3, a4) { - var params = {}; - var data; - var success = noop; - var error = null; - var promise; - - switch(arguments.length) { - case 4: - error = a4; - success = a3; - //fallthrough - case 3: - case 2: - if (isFunction(a2)) { - if (isFunction(a1)) { - success = a1; - error = a2; - break; - } - - success = a2; - error = a3; - //fallthrough - } else { - params = a1; - data = a2; - success = a3; - break; - } - case 1: - if (isFunction(a1)) success = a1; - else if (hasBody) data = a1; - else params = a1; - break; - case 0: break; - default: - throw "Expected between 0-4 arguments [params, data, success, error], got " + - arguments.length + " arguments."; - } - - var value = this instanceof Resource ? this : (action.isArray ? [] : new Resource(data)); - var httpConfig = {}, - promise; - - forEach(action, function(value, key) { - if (key != 'params' && key != 'isArray' ) { - httpConfig[key] = copy(value); - } - }); - httpConfig.data = data; - route.setUrlParams(httpConfig, extend({}, extractParams(data, action.params || {}), params), action.url); - - function markResolved() { value.$resolved = true; } - - promise = $http(httpConfig); - value.$resolved = false; - - promise.then(markResolved, markResolved); - value.$then = promise.then(function(response) { - var data = response.data; - var then = value.$then, resolved = value.$resolved; - - if (data) { - if (action.isArray) { - value.length = 0; - forEach(data, function(item) { - value.push(new Resource(item)); - }); - } else { - copy(data, value); - value.$then = then; - value.$resolved = resolved; - } - } - - (success||noop)(value, response.headers); - - response.resource = value; - return response; - }, error).then; - - return value; - }; - - - Resource.prototype['$' + name] = function(a1, a2, a3) { - var params = extractParams(this), - success = noop, - error; - - switch(arguments.length) { - case 3: params = a1; success = a2; error = a3; break; - case 2: - case 1: - if (isFunction(a1)) { - success = a1; - error = a2; - } else { - params = a1; - success = a2 || noop; - } - case 0: break; - default: - throw "Expected between 1-3 arguments [params, success, error], got " + - arguments.length + " arguments."; - } - var data = hasBody ? this : undefined; - Resource[name].call(this, params, data, success, error); - }; - }); - - Resource.bind = function(additionalParamDefaults){ - return ResourceFactory(url, extend({}, paramDefaults, additionalParamDefaults), actions); - }; - - return Resource; - } - - return ResourceFactory; - }]); - - -})(window, window.angular); diff --git a/src/Umbraco.Web.UI.Client/lib/angular/1.1.5/angular-resource.min.js b/src/Umbraco.Web.UI.Client/lib/angular/1.1.5/angular-resource.min.js deleted file mode 100644 index bdcdf0aa3b..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/angular/1.1.5/angular-resource.min.js +++ /dev/null @@ -1,11 +0,0 @@ -/* - AngularJS v1.1.5 - (c) 2010-2012 Google, Inc. http://angularjs.org - License: MIT -*/ -(function(B,f,w){'use strict';f.module("ngResource",["ng"]).factory("$resource",["$http","$parse",function(x,y){function u(b,d){this.template=b;this.defaults=d||{};this.urlParams={}}function v(b,d,e){function j(c,b){var p={},b=m({},d,b);l(b,function(a,b){k(a)&&(a=a());var g;a&&a.charAt&&a.charAt(0)=="@"?(g=a.substr(1),g=y(g)(c)):g=a;p[b]=g});return p}function c(c){t(c||{},this)}var n=new u(b),e=m({},z,e);l(e,function(b,d){b.method=f.uppercase(b.method);var p=b.method=="POST"||b.method=="PUT"||b.method== -"PATCH";c[d]=function(a,d,g,A){function f(){h.$resolved=!0}var i={},e,o=q,r=null;switch(arguments.length){case 4:r=A,o=g;case 3:case 2:if(k(d)){if(k(a)){o=a;r=d;break}o=d;r=g}else{i=a;e=d;o=g;break}case 1:k(a)?o=a:p?e=a:i=a;break;case 0:break;default:throw"Expected between 0-4 arguments [params, data, success, error], got "+arguments.length+" arguments.";}var h=this instanceof c?this:b.isArray?[]:new c(e),s={};l(b,function(a,b){b!="params"&&b!="isArray"&&(s[b]=t(a))});s.data=e;n.setUrlParams(s,m({}, -j(e,b.params||{}),i),b.url);i=x(s);h.$resolved=!1;i.then(f,f);h.$then=i.then(function(a){var d=a.data,g=h.$then,e=h.$resolved;if(d)b.isArray?(h.length=0,l(d,function(a){h.push(new c(a))})):(t(d,h),h.$then=g,h.$resolved=e);(o||q)(h,a.headers);a.resource=h;return a},r).then;return h};c.prototype["$"+d]=function(a,b,g){var e=j(this),f=q,i;switch(arguments.length){case 3:e=a;f=b;i=g;break;case 2:case 1:k(a)?(f=a,i=b):(e=a,f=b||q);case 0:break;default:throw"Expected between 1-3 arguments [params, success, error], got "+ -arguments.length+" arguments.";}c[d].call(this,e,p?this:w,f,i)}});c.bind=function(c){return v(b,m({},d,c),e)};return c}var z={get:{method:"GET"},save:{method:"POST"},query:{method:"GET",isArray:!0},remove:{method:"DELETE"},"delete":{method:"DELETE"}},q=f.noop,l=f.forEach,m=f.extend,t=f.copy,k=f.isFunction;u.prototype={setUrlParams:function(b,d,e){var j=this,c=e||j.template,n,k,m=j.urlParams={};l(c.split(/\W/),function(b){b&&RegExp("(^|[^\\\\]):"+b+"(\\W|$)").test(c)&&(m[b]=!0)});c=c.replace(/\\:/g, -":");d=d||{};l(j.urlParams,function(b,a){n=d.hasOwnProperty(a)?d[a]:j.defaults[a];f.isDefined(n)&&n!==null?(k=encodeURIComponent(n).replace(/%40/gi,"@").replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%20/g,"%20").replace(/%26/gi,"&").replace(/%3D/gi,"=").replace(/%2B/gi,"+"),c=c.replace(RegExp(":"+a+"(\\W|$)","g"),k+"$1")):c=c.replace(RegExp("(/?):"+a+"(\\W|$)","g"),function(b,a,c){return c.charAt(0)=="/"?c:a+c})});c=c.replace(/\/+$/,"");c=c.replace(/\/\.(?=\w+($|\?))/,"."); -b.url=c.replace(/\/\\\./,"/.");l(d,function(c,a){if(!j.urlParams[a])b.params=b.params||{},b.params[a]=c})}};return v}])})(window,window.angular); diff --git a/src/Umbraco.Web.UI.Client/lib/angular/1.1.5/angular-sanitize.js b/src/Umbraco.Web.UI.Client/lib/angular/1.1.5/angular-sanitize.js deleted file mode 100644 index 60d002edff..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/angular/1.1.5/angular-sanitize.js +++ /dev/null @@ -1,558 +0,0 @@ -/** - * @license AngularJS v1.1.5 - * (c) 2010-2012 Google, Inc. http://angularjs.org - * License: MIT - */ -(function(window, angular, undefined) { -'use strict'; - -/** - * @ngdoc overview - * @name ngSanitize - * @description - */ - -/* - * HTML Parser By Misko Hevery (misko@hevery.com) - * based on: HTML Parser By John Resig (ejohn.org) - * Original code by Erik Arvidsson, Mozilla Public License - * http://erik.eae.net/simplehtmlparser/simplehtmlparser.js - * - * // Use like so: - * htmlParser(htmlString, { - * start: function(tag, attrs, unary) {}, - * end: function(tag) {}, - * chars: function(text) {}, - * comment: function(text) {} - * }); - * - */ - - -/** - * @ngdoc service - * @name ngSanitize.$sanitize - * @function - * - * @description - * The input is sanitized by parsing the html into tokens. All safe tokens (from a whitelist) are - * then serialized back to properly escaped html string. This means that no unsafe input can make - * it into the returned string, however, since our parser is more strict than a typical browser - * parser, it's possible that some obscure input, which would be recognized as valid HTML by a - * browser, won't make it through the sanitizer. - * - * @param {string} html Html input. - * @returns {string} Sanitized html. - * - * @example - - - -
                - Snippet: - - - - - - - - - - - - - - - - - - - - - -
                FilterSourceRendered
                html filter -
                <div ng-bind-html="snippet">
                </div>
                -
                -
                -
                no filter
                <div ng-bind="snippet">
                </div>
                unsafe html filter
                <div ng-bind-html-unsafe="snippet">
                </div>
                -
                -
                - - it('should sanitize the html snippet ', function() { - expect(using('#html-filter').element('div').html()). - toBe('

                an html\nclick here\nsnippet

                '); - }); - - it('should escape snippet without any filter', function() { - expect(using('#escaped-html').element('div').html()). - toBe("<p style=\"color:blue\">an html\n" + - "<em onmouseover=\"this.textContent='PWN3D!'\">click here</em>\n" + - "snippet</p>"); - }); - - it('should inline raw snippet if filtered as unsafe', function() { - expect(using('#html-unsafe-filter').element("div").html()). - toBe("

                an html\n" + - "click here\n" + - "snippet

                "); - }); - - it('should update', function() { - input('snippet').enter('new text'); - expect(using('#html-filter').binding('snippet')).toBe('new text'); - expect(using('#escaped-html').element('div').html()).toBe("new <b>text</b>"); - expect(using('#html-unsafe-filter').binding("snippet")).toBe('new text'); - }); -
                -
                - */ -var $sanitize = function(html) { - var buf = []; - htmlParser(html, htmlSanitizeWriter(buf)); - return buf.join(''); -}; - - -// Regular Expressions for parsing tags and attributes -var START_TAG_REGEXP = /^<\s*([\w:-]+)((?:\s+[\w:-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)\s*>/, - END_TAG_REGEXP = /^<\s*\/\s*([\w:-]+)[^>]*>/, - ATTR_REGEXP = /([\w:-]+)(?:\s*=\s*(?:(?:"((?:[^"])*)")|(?:'((?:[^'])*)')|([^>\s]+)))?/g, - BEGIN_TAG_REGEXP = /^/g, - CDATA_REGEXP = //g, - URI_REGEXP = /^((ftp|https?):\/\/|mailto:|tel:|#)/, - NON_ALPHANUMERIC_REGEXP = /([^\#-~| |!])/g; // Match everything outside of normal chars and " (quote character) - - -// Good source of info about elements and attributes -// http://dev.w3.org/html5/spec/Overview.html#semantics -// http://simon.html5.org/html-elements - -// Safe Void Elements - HTML5 -// http://dev.w3.org/html5/spec/Overview.html#void-elements -var voidElements = makeMap("area,br,col,hr,img,wbr"); - -// Elements that you can, intentionally, leave open (and which close themselves) -// http://dev.w3.org/html5/spec/Overview.html#optional-tags -var optionalEndTagBlockElements = makeMap("colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr"), - optionalEndTagInlineElements = makeMap("rp,rt"), - optionalEndTagElements = angular.extend({}, optionalEndTagInlineElements, optionalEndTagBlockElements); - -// Safe Block Elements - HTML5 -var blockElements = angular.extend({}, optionalEndTagBlockElements, makeMap("address,article,aside," + - "blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5,h6," + - "header,hgroup,hr,ins,map,menu,nav,ol,pre,script,section,table,ul")); - -// Inline Elements - HTML5 -var inlineElements = angular.extend({}, optionalEndTagInlineElements, makeMap("a,abbr,acronym,b,bdi,bdo," + - "big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s,samp,small," + - "span,strike,strong,sub,sup,time,tt,u,var")); - - -// Special Elements (can contain anything) -var specialElements = makeMap("script,style"); - -var validElements = angular.extend({}, voidElements, blockElements, inlineElements, optionalEndTagElements); - -//Attributes that have href and hence need to be sanitized -var uriAttrs = makeMap("background,cite,href,longdesc,src,usemap"); -var validAttrs = angular.extend({}, uriAttrs, makeMap( - 'abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,'+ - 'color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,'+ - 'ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,'+ - 'scope,scrolling,shape,span,start,summary,target,title,type,'+ - 'valign,value,vspace,width')); - -function makeMap(str) { - var obj = {}, items = str.split(','), i; - for (i = 0; i < items.length; i++) obj[items[i]] = true; - return obj; -} - - -/** - * @example - * htmlParser(htmlString, { - * start: function(tag, attrs, unary) {}, - * end: function(tag) {}, - * chars: function(text) {}, - * comment: function(text) {} - * }); - * - * @param {string} html string - * @param {object} handler - */ -function htmlParser( html, handler ) { - var index, chars, match, stack = [], last = html; - stack.last = function() { return stack[ stack.length - 1 ]; }; - - while ( html ) { - chars = true; - - // Make sure we're not in a script or style element - if ( !stack.last() || !specialElements[ stack.last() ] ) { - - // Comment - if ( html.indexOf(""); - - if ( index >= 0 ) { - if (handler.comment) handler.comment( html.substring( 4, index ) ); - html = html.substring( index + 3 ); - chars = false; - } - - // end tag - } else if ( BEGING_END_TAGE_REGEXP.test(html) ) { - match = html.match( END_TAG_REGEXP ); - - if ( match ) { - html = html.substring( match[0].length ); - match[0].replace( END_TAG_REGEXP, parseEndTag ); - chars = false; - } - - // start tag - } else if ( BEGIN_TAG_REGEXP.test(html) ) { - match = html.match( START_TAG_REGEXP ); - - if ( match ) { - html = html.substring( match[0].length ); - match[0].replace( START_TAG_REGEXP, parseStartTag ); - chars = false; - } - } - - if ( chars ) { - index = html.indexOf("<"); - - var text = index < 0 ? html : html.substring( 0, index ); - html = index < 0 ? "" : html.substring( index ); - - if (handler.chars) handler.chars( decodeEntities(text) ); - } - - } else { - html = html.replace(new RegExp("(.*)<\\s*\\/\\s*" + stack.last() + "[^>]*>", 'i'), function(all, text){ - text = text. - replace(COMMENT_REGEXP, "$1"). - replace(CDATA_REGEXP, "$1"); - - if (handler.chars) handler.chars( decodeEntities(text) ); - - return ""; - }); - - parseEndTag( "", stack.last() ); - } - - if ( html == last ) { - throw "Parse Error: " + html; - } - last = html; - } - - // Clean up any remaining tags - parseEndTag(); - - function parseStartTag( tag, tagName, rest, unary ) { - tagName = angular.lowercase(tagName); - if ( blockElements[ tagName ] ) { - while ( stack.last() && inlineElements[ stack.last() ] ) { - parseEndTag( "", stack.last() ); - } - } - - if ( optionalEndTagElements[ tagName ] && stack.last() == tagName ) { - parseEndTag( "", tagName ); - } - - unary = voidElements[ tagName ] || !!unary; - - if ( !unary ) - stack.push( tagName ); - - var attrs = {}; - - rest.replace(ATTR_REGEXP, function(match, name, doubleQuotedValue, singleQoutedValue, unqoutedValue) { - var value = doubleQuotedValue - || singleQoutedValue - || unqoutedValue - || ''; - - attrs[name] = decodeEntities(value); - }); - if (handler.start) handler.start( tagName, attrs, unary ); - } - - function parseEndTag( tag, tagName ) { - var pos = 0, i; - tagName = angular.lowercase(tagName); - if ( tagName ) - // Find the closest opened tag of the same type - for ( pos = stack.length - 1; pos >= 0; pos-- ) - if ( stack[ pos ] == tagName ) - break; - - if ( pos >= 0 ) { - // Close all the open elements, up the stack - for ( i = stack.length - 1; i >= pos; i-- ) - if (handler.end) handler.end( stack[ i ] ); - - // Remove the open elements from the stack - stack.length = pos; - } - } -} - -/** - * decodes all entities into regular string - * @param value - * @returns {string} A string with decoded entities. - */ -var hiddenPre=document.createElement("pre"); -function decodeEntities(value) { - hiddenPre.innerHTML=value.replace(//g, '>'); -} - -/** - * create an HTML/XML writer which writes to buffer - * @param {Array} buf use buf.jain('') to get out sanitized html string - * @returns {object} in the form of { - * start: function(tag, attrs, unary) {}, - * end: function(tag) {}, - * chars: function(text) {}, - * comment: function(text) {} - * } - */ -function htmlSanitizeWriter(buf){ - var ignore = false; - var out = angular.bind(buf, buf.push); - return { - start: function(tag, attrs, unary){ - tag = angular.lowercase(tag); - if (!ignore && specialElements[tag]) { - ignore = tag; - } - if (!ignore && validElements[tag] == true) { - out('<'); - out(tag); - angular.forEach(attrs, function(value, key){ - var lkey=angular.lowercase(key); - if (validAttrs[lkey]==true && (uriAttrs[lkey]!==true || value.match(URI_REGEXP))) { - out(' '); - out(key); - out('="'); - out(encodeEntities(value)); - out('"'); - } - }); - out(unary ? '/>' : '>'); - } - }, - end: function(tag){ - tag = angular.lowercase(tag); - if (!ignore && validElements[tag] == true) { - out(''); - } - if (tag == ignore) { - ignore = false; - } - }, - chars: function(chars){ - if (!ignore) { - out(encodeEntities(chars)); - } - } - }; -} - - -// define ngSanitize module and register $sanitize service -angular.module('ngSanitize', []).value('$sanitize', $sanitize); - -/** - * @ngdoc directive - * @name ngSanitize.directive:ngBindHtml - * - * @description - * Creates a binding that will sanitize the result of evaluating the `expression` with the - * {@link ngSanitize.$sanitize $sanitize} service and innerHTML the result into the current element. - * - * See {@link ngSanitize.$sanitize $sanitize} docs for examples. - * - * @element ANY - * @param {expression} ngBindHtml {@link guide/expression Expression} to evaluate. - */ -angular.module('ngSanitize').directive('ngBindHtml', ['$sanitize', function($sanitize) { - return function(scope, element, attr) { - element.addClass('ng-binding').data('$binding', attr.ngBindHtml); - scope.$watch(attr.ngBindHtml, function ngBindHtmlWatchAction(value) { - value = $sanitize(value); - element.html(value || ''); - }); - }; -}]); - -/** - * @ngdoc filter - * @name ngSanitize.filter:linky - * @function - * - * @description - * Finds links in text input and turns them into html links. Supports http/https/ftp/mailto and - * plain email address links. - * - * @param {string} text Input text. - * @param {string} target Window (_blank|_self|_parent|_top) or named frame to open links in. - * @returns {string} Html-linkified text. - * - * @usage - - * - * @example - - - -
                - Snippet: - - - - - - - - - - - - - - - - - - - - - -
                FilterSourceRendered
                linky filter -
                <div ng-bind-html="snippet | linky">
                </div>
                -
                -
                -
                linky target -
                <div ng-bind-html="snippetWithTarget | linky:'_blank'">
                </div>
                -
                -
                -
                no filter
                <div ng-bind="snippet">
                </div>
                - - - it('should linkify the snippet with urls', function() { - expect(using('#linky-filter').binding('snippet | linky')). - toBe('Pretty text with some links: ' + - 'http://angularjs.org/, ' + - 'us@somewhere.org, ' + - 'another@somewhere.org, ' + - 'and one more: ftp://127.0.0.1/.'); - }); - - it ('should not linkify snippet without the linky filter', function() { - expect(using('#escaped-html').binding('snippet')). - toBe("Pretty text with some links:\n" + - "http://angularjs.org/,\n" + - "mailto:us@somewhere.org,\n" + - "another@somewhere.org,\n" + - "and one more: ftp://127.0.0.1/."); - }); - - it('should update', function() { - input('snippet').enter('new http://link.'); - expect(using('#linky-filter').binding('snippet | linky')). - toBe('new http://link.'); - expect(using('#escaped-html').binding('snippet')).toBe('new http://link.'); - }); - - it('should work with the target property', function() { - expect(using('#linky-target').binding("snippetWithTarget | linky:'_blank'")). - toBe('http://angularjs.org/'); - }); - - - */ -angular.module('ngSanitize').filter('linky', function() { - var LINKY_URL_REGEXP = /((ftp|https?):\/\/|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s\.\;\,\(\)\{\}\<\>]/, - MAILTO_REGEXP = /^mailto:/; - - return function(text, target) { - if (!text) return text; - var match; - var raw = text; - var html = []; - // TODO(vojta): use $sanitize instead - var writer = htmlSanitizeWriter(html); - var url; - var i; - var properties = {}; - if (angular.isDefined(target)) { - properties.target = target; - } - while ((match = raw.match(LINKY_URL_REGEXP))) { - // We can not end in these as they are sometimes found at the end of the sentence - url = match[0]; - // if we did not match ftp/http/mailto then assume mailto - if (match[2] == match[3]) url = 'mailto:' + url; - i = match.index; - writer.chars(raw.substr(0, i)); - properties.href = url; - writer.start('a', properties); - writer.chars(match[0].replace(MAILTO_REGEXP, '')); - writer.end('a'); - raw = raw.substring(i + match[0].length); - } - writer.chars(raw); - return html.join(''); - }; -}); - - -})(window, window.angular); diff --git a/src/Umbraco.Web.UI.Client/lib/angular/1.1.5/angular-sanitize.min.js b/src/Umbraco.Web.UI.Client/lib/angular/1.1.5/angular-sanitize.min.js deleted file mode 100644 index 011862bb66..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/angular/1.1.5/angular-sanitize.min.js +++ /dev/null @@ -1,13 +0,0 @@ -/* - AngularJS v1.1.5 - (c) 2010-2012 Google, Inc. http://angularjs.org - License: MIT -*/ -(function(I,h){'use strict';function i(a){var d={},a=a.split(","),c;for(c=0;c=0;c--)if(e[c]==b)break;if(c>=0){for(g=e.length-1;g>=c;g--)d.end&&d.end(e[g]);e.length= -c}}var b,f,e=[],j=a;for(e.last=function(){return e[e.length-1]};a;){f=!0;if(!e.last()||!q[e.last()]){if(a.indexOf("<\!--")===0)b=a.indexOf("--\>"),b>=0&&(d.comment&&d.comment(a.substring(4,b)),a=a.substring(b+3),f=!1);else if(B.test(a)){if(b=a.match(r))a=a.substring(b[0].length),b[0].replace(r,g),f=!1}else if(C.test(a)&&(b=a.match(s)))a=a.substring(b[0].length),b[0].replace(s,c),f=!1;f&&(b=a.indexOf("<"),f=b<0?a:a.substring(0,b),a=b<0?"":a.substring(b),d.chars&&d.chars(k(f)))}else a=a.replace(RegExp("(.*)<\\s*\\/\\s*"+ -e.last()+"[^>]*>","i"),function(a,b){b=b.replace(D,"$1").replace(E,"$1");d.chars&&d.chars(k(b));return""}),g("",e.last());if(a==j)throw"Parse Error: "+a;j=a}g()}function k(a){l.innerHTML=a.replace(//g,">")}function u(a){var d=!1,c=h.bind(a,a.push);return{start:function(a,b,f){a=h.lowercase(a);!d&&q[a]&&(d=a);!d&&v[a]== -!0&&(c("<"),c(a),h.forEach(b,function(a,b){var d=h.lowercase(b);if(G[d]==!0&&(w[d]!==!0||a.match(H)))c(" "),c(b),c('="'),c(t(a)),c('"')}),c(f?"/>":">"))},end:function(a){a=h.lowercase(a);!d&&v[a]==!0&&(c(""));a==d&&(d=!1)},chars:function(a){d||c(t(a))}}}var s=/^<\s*([\w:-]+)((?:\s+[\w:-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)\s*>/,r=/^<\s*\/\s*([\w:-]+)[^>]*>/,A=/([\w:-]+)(?:\s*=\s*(?:(?:"((?:[^"])*)")|(?:'((?:[^'])*)')|([^>\s]+)))?/g,C=/^/g, -E=//g,H=/^((ftp|https?):\/\/|mailto:|tel:|#)/,F=/([^\#-~| |!])/g,p=i("area,br,col,hr,img,wbr"),x=i("colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr"),y=i("rp,rt"),o=h.extend({},y,x),m=h.extend({},x,i("address,article,aside,blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5,h6,header,hgroup,hr,ins,map,menu,nav,ol,pre,script,section,table,ul")),n=h.extend({},y,i("a,abbr,acronym,b,bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s,samp,small,span,strike,strong,sub,sup,time,tt,u,var")), -q=i("script,style"),v=h.extend({},p,m,n,o),w=i("background,cite,href,longdesc,src,usemap"),G=h.extend({},w,i("abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,scope,scrolling,shape,span,start,summary,target,title,type,valign,value,vspace,width")),l=document.createElement("pre");h.module("ngSanitize",[]).value("$sanitize",function(a){var d=[]; -z(a,u(d));return d.join("")});h.module("ngSanitize").directive("ngBindHtml",["$sanitize",function(a){return function(d,c,g){c.addClass("ng-binding").data("$binding",g.ngBindHtml);d.$watch(g.ngBindHtml,function(b){b=a(b);c.html(b||"")})}}]);h.module("ngSanitize").filter("linky",function(){var a=/((ftp|https?):\/\/|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s\.\;\,\(\)\{\}\<\>]/,d=/^mailto:/;return function(c,g){if(!c)return c;var b,f=c,e=[],j=u(e),i,k,l={};if(h.isDefined(g))l.target=g;for(;b=f.match(a);)i= -b[0],b[2]==b[3]&&(i="mailto:"+i),k=b.index,j.chars(f.substr(0,k)),l.href=i,j.start("a",l),j.chars(b[0].replace(d,"")),j.end("a"),f=f.substring(k+b[0].length);j.chars(f);return e.join("")}})})(window,window.angular); diff --git a/src/Umbraco.Web.UI.Client/lib/angular/1.1.5/angular-scenario.js b/src/Umbraco.Web.UI.Client/lib/angular/1.1.5/angular-scenario.js deleted file mode 100644 index 8f3f78d2c3..0000000000 --- a/src/Umbraco.Web.UI.Client/lib/angular/1.1.5/angular-scenario.js +++ /dev/null @@ -1,28463 +0,0 @@ -/*! - * jQuery JavaScript Library v1.8.2 - * http://jquery.com/ - * - * Includes Sizzle.js - * http://sizzlejs.com/ - * - * Copyright 2012 jQuery Foundation and other contributors - * Released under the MIT license - * http://jquery.org/license - * - * Date: Thu Sep 20 2012 21:13:05 GMT-0400 (Eastern Daylight Time) - */ -(function( window, undefined ) { -'use strict'; -var - // A central reference to the root jQuery(document) - rootjQuery, - - // The deferred used on DOM ready - readyList, - - // Use the correct document accordingly with window argument (sandbox) - document = window.document, - location = window.location, - navigator = window.navigator, - - // Map over jQuery in case of overwrite - _jQuery = window.jQuery, - - // Map over the $ in case of overwrite - _$ = window.$, - - // Save a reference to some core methods - core_push = Array.prototype.push, - core_slice = Array.prototype.slice, - core_indexOf = Array.prototype.indexOf, - core_toString = Object.prototype.toString, - core_hasOwn = Object.prototype.hasOwnProperty, - core_trim = String.prototype.trim, - - // Define a local copy of jQuery - jQuery = function( selector, context ) { - // The jQuery object is actually just the init constructor 'enhanced' - return new jQuery.fn.init( selector, context, rootjQuery ); - }, - - // Used for matching numbers - core_pnum = /[\-+]?(?:\d*\.|)\d+(?:[eE][\-+]?\d+|)/.source, - - // Used for detecting and trimming whitespace - core_rnotwhite = /\S/, - core_rspace = /\s+/, - - // Make sure we trim BOM and NBSP (here's looking at you, Safari 5.0 and IE) - rtrim = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, - - // A simple way to check for HTML strings - // Prioritize #id over to avoid XSS via location.hash (#9521) - rquickExpr = /^(?:[^#<]*(<[\w\W]+>)[^>]*$|#([\w\-]*)$)/, - - // Match a standalone tag - rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>|)$/, - - // JSON RegExp - rvalidchars = /^[\],:{}\s]*$/, - rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g, - rvalidescape = /\\(?:["\\\/bfnrt]|u[\da-fA-F]{4})/g, - rvalidtokens = /"[^"\\\r\n]*"|true|false|null|-?(?:\d\d*\.|)\d+(?:[eE][\-+]?\d+|)/g, - - // Matches dashed string for camelizing - rmsPrefix = /^-ms-/, - rdashAlpha = /-([\da-z])/gi, - - // Used by jQuery.camelCase as callback to replace() - fcamelCase = function( all, letter ) { - return ( letter + "" ).toUpperCase(); - }, - - // The ready event handler and self cleanup method - DOMContentLoaded = function() { - if ( document.addEventListener ) { - document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false ); - jQuery.ready(); - } else if ( document.readyState === "complete" ) { - // we're here because readyState === "complete" in oldIE - // which is good enough for us to call the dom ready! - document.detachEvent( "onreadystatechange", DOMContentLoaded ); - jQuery.ready(); - } - }, - - // [[Class]] -> type pairs - class2type = {}; - -jQuery.fn = jQuery.prototype = { - constructor: jQuery, - init: function( selector, context, rootjQuery ) { - var match, elem, ret, doc; - - // Handle $(""), $(null), $(undefined), $(false) - if ( !selector ) { - return this; - } - - // Handle $(DOMElement) - if ( selector.nodeType ) { - this.context = this[0] = selector; - this.length = 1; - return this; - } - - // Handle HTML strings - if ( typeof selector === "string" ) { - if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) { - // Assume that strings that start and end with <> are HTML and skip the regex check - match = [ null, selector, null ]; - - } else { - match = rquickExpr.exec( selector ); - } - - // Match html or make sure no context is specified for #id - if ( match && (match[1] || !context) ) { - - // HANDLE: $(html) -> $(array) - if ( match[1] ) { - context = context instanceof jQuery ? context[0] : context; - doc = ( context && context.nodeType ? context.ownerDocument || context : document ); - - // scripts is true for back-compat - selector = jQuery.parseHTML( match[1], doc, true ); - if ( rsingleTag.test( match[1] ) && jQuery.isPlainObject( context ) ) { - this.attr.call( selector, context, true ); - } - - return jQuery.merge( this, selector ); - - // HANDLE: $(#id) - } else { - elem = document.getElementById( match[2] ); - - // Check parentNode to catch when Blackberry 4.6 returns - // nodes that are no longer in the document #6963 - if ( elem && elem.parentNode ) { - // Handle the case where IE and Opera return items - // by name instead of ID - if ( elem.id !== match[2] ) { - return rootjQuery.find( selector ); - } - - // Otherwise, we inject the element directly into the jQuery object - this.length = 1; - this[0] = elem; - } - - this.context = document; - this.selector = selector; - return this; - } - - // HANDLE: $(expr, $(...)) - } else if ( !context || context.jquery ) { - return ( context || rootjQuery ).find( selector ); - - // HANDLE: $(expr, context) - // (which is just equivalent to: $(context).find(expr) - } else { - return this.constructor( context ).find( selector ); - } - - // HANDLE: $(function) - // Shortcut for document ready - } else if ( jQuery.isFunction( selector ) ) { - return rootjQuery.ready( selector ); - } - - if ( selector.selector !== undefined ) { - this.selector = selector.selector; - this.context = selector.context; - } - - return jQuery.makeArray( selector, this ); - }, - - // Start with an empty selector - selector: "", - - // The current version of jQuery being used - jquery: "1.8.2", - - // The default length of a jQuery object is 0 - length: 0, - - // The number of elements contained in the matched element set - size: function() { - return this.length; - }, - - toArray: function() { - return core_slice.call( this ); - }, - - // Get the Nth element in the matched element set OR - // Get the whole matched element set as a clean array - get: function( num ) { - return num == null ? - - // Return a 'clean' array - this.toArray() : - - // Return just the object - ( num < 0 ? this[ this.length + num ] : this[ num ] ); - }, - - // Take an array of elements and push it onto the stack - // (returning the new matched element set) - pushStack: function( elems, name, selector ) { - - // Build a new jQuery matched element set - var ret = jQuery.merge( this.constructor(), elems ); - - // Add the old object onto the stack (as a reference) - ret.prevObject = this; - - ret.context = this.context; - - if ( name === "find" ) { - ret.selector = this.selector + ( this.selector ? " " : "" ) + selector; - } else if ( name ) { - ret.selector = this.selector + "." + name + "(" + selector + ")"; - } - - // Return the newly-formed element set - return ret; - }, - - // Execute a callback for every element in the matched set. - // (You can seed the arguments with an array of args, but this is - // only used internally.) - each: function( callback, args ) { - return jQuery.each( this, callback, args ); - }, - - ready: function( fn ) { - // Add the callback - jQuery.ready.promise().done( fn ); - - return this; - }, - - eq: function( i ) { - i = +i; - return i === -1 ? - this.slice( i ) : - this.slice( i, i + 1 ); - }, - - first: function() { - return this.eq( 0 ); - }, - - last: function() { - return this.eq( -1 ); - }, - - slice: function() { - return this.pushStack( core_slice.apply( this, arguments ), - "slice", core_slice.call(arguments).join(",") ); - }, - - map: function( callback ) { - return this.pushStack( jQuery.map(this, function( elem, i ) { - return callback.call( elem, i, elem ); - })); - }, - - end: function() { - return this.prevObject || this.constructor(null); - }, - - // For internal use only. - // Behaves like an Array's method, not like a jQuery method. - push: core_push, - sort: [].sort, - splice: [].splice -}; - -// Give the init function the jQuery prototype for later instantiation -jQuery.fn.init.prototype = jQuery.fn; - -jQuery.extend = jQuery.fn.extend = function() { - var options, name, src, copy, copyIsArray, clone, - target = arguments[0] || {}, - i = 1, - length = arguments.length, - deep = false; - - // Handle a deep copy situation - if ( typeof target === "boolean" ) { - deep = target; - target = arguments[1] || {}; - // skip the boolean and the target - i = 2; - } - - // Handle case when target is a string or something (possible in deep copy) - if ( typeof target !== "object" && !jQuery.isFunction(target) ) { - target = {}; - } - - // extend jQuery itself if only one argument is passed - if ( length === i ) { - target = this; - --i; - } - - for ( ; i < length; i++ ) { - // Only deal with non-null/undefined values - if ( (options = arguments[ i ]) != null ) { - // Extend the base object - for ( name in options ) { - src = target[ name ]; - copy = options[ name ]; - - // Prevent never-ending loop - if ( target === copy ) { - continue; - } - - // Recurse if we're merging plain objects or arrays - if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) { - if ( copyIsArray ) { - copyIsArray = false; - clone = src && jQuery.isArray(src) ? src : []; - - } else { - clone = src && jQuery.isPlainObject(src) ? src : {}; - } - - // Never move original objects, clone them - target[ name ] = jQuery.extend( deep, clone, copy ); - - // Don't bring in undefined values - } else if ( copy !== undefined ) { - target[ name ] = copy; - } - } - } - } - - // Return the modified object - return target; -}; - -jQuery.extend({ - noConflict: function( deep ) { - if ( window.$ === jQuery ) { - window.$ = _$; - } - - if ( deep && window.jQuery === jQuery ) { - window.jQuery = _jQuery; - } - - return jQuery; - }, - - // Is the DOM ready to be used? Set to true once it occurs. - isReady: false, - - // A counter to track how many items to wait for before - // the ready event fires. See #6781 - readyWait: 1, - - // Hold (or release) the ready event - holdReady: function( hold ) { - if ( hold ) { - jQuery.readyWait++; - } else { - jQuery.ready( true ); - } - }, - - // Handle when the DOM is ready - ready: function( wait ) { - - // Abort if there are pending holds or we're already ready - if ( wait === true ? --jQuery.readyWait : jQuery.isReady ) { - return; - } - - // Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443). - if ( !document.body ) { - return setTimeout( jQuery.ready, 1 ); - } - - // Remember that the DOM is ready - jQuery.isReady = true; - - // If a normal DOM Ready event fired, decrement, and wait if need be - if ( wait !== true && --jQuery.readyWait > 0 ) { - return; - } - - // If there are functions bound, to execute - readyList.resolveWith( document, [ jQuery ] ); - - // Trigger any bound ready events - if ( jQuery.fn.trigger ) { - jQuery( document ).trigger("ready").off("ready"); - } - }, - - // See test/unit/core.js for details concerning isFunction. - // Since version 1.3, DOM methods and functions like alert - // aren't supported. They return false on IE (#2968). - isFunction: function( obj ) { - return jQuery.type(obj) === "function"; - }, - - isArray: Array.isArray || function( obj ) { - return jQuery.type(obj) === "array"; - }, - - isWindow: function( obj ) { - return obj != null && obj == obj.window; - }, - - isNumeric: function( obj ) { - return !isNaN( parseFloat(obj) ) && isFinite( obj ); - }, - - type: function( obj ) { - return obj == null ? - String( obj ) : - class2type[ core_toString.call(obj) ] || "object"; - }, - - isPlainObject: function( obj ) { - // Must be an Object. - // Because of IE, we also have to check the presence of the constructor property. - // Make sure that DOM nodes and window objects don't pass through, as well - if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) { - return false; - } - - try { - // Not own constructor property must be Object - if ( obj.constructor && - !core_hasOwn.call(obj, "constructor") && - !core_hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) { - return false; - } - } catch ( e ) { - // IE8,9 Will throw exceptions on certain host objects #9897 - return false; - } - - // Own properties are enumerated firstly, so to speed up, - // if last one is own, then all properties are own. - - var key; - for ( key in obj ) {} - - return key === undefined || core_hasOwn.call( obj, key ); - }, - - isEmptyObject: function( obj ) { - var name; - for ( name in obj ) { - return false; - } - return true; - }, - - error: function( msg ) { - throw new Error( msg ); - }, - - // data: string of html - // context (optional): If specified, the fragment will be created in this context, defaults to document - // scripts (optional): If true, will include scripts passed in the html string - parseHTML: function( data, context, scripts ) { - var parsed; - if ( !data || typeof data !== "string" ) { - return null; - } - if ( typeof context === "boolean" ) { - scripts = context; - context = 0; - } - context = context || document; - - // Single tag - if ( (parsed = rsingleTag.exec( data )) ) { - return [ context.createElement( parsed[1] ) ]; - } - - parsed = jQuery.buildFragment( [ data ], context, scripts ? null : [] ); - return jQuery.merge( [], - (parsed.cacheable ? jQuery.clone( parsed.fragment ) : parsed.fragment).childNodes ); - }, - - parseJSON: function( data ) { - if ( !data || typeof data !== "string") { - return null; - } - - // Make sure leading/trailing whitespace is removed (IE can't handle it) - data = jQuery.trim( data ); - - // Attempt to parse using the native JSON parser first - if ( window.JSON && window.JSON.parse ) { - return window.JSON.parse( data ); - } - - // Make sure the incoming data is actual JSON - // Logic borrowed from http://json.org/json2.js - if ( rvalidchars.test( data.replace( rvalidescape, "@" ) - .replace( rvalidtokens, "]" ) - .replace( rvalidbraces, "")) ) { - - return ( new Function( "return " + data ) )(); - - } - jQuery.error( "Invalid JSON: " + data ); - }, - - // Cross-browser xml parsing - parseXML: function( data ) { - var xml, tmp; - if ( !data || typeof data !== "string" ) { - return null; - } - try { - if ( window.DOMParser ) { // Standard - tmp = new DOMParser(); - xml = tmp.parseFromString( data , "text/xml" ); - } else { // IE - xml = new ActiveXObject( "Microsoft.XMLDOM" ); - xml.async = "false"; - xml.loadXML( data ); - } - } catch( e ) { - xml = undefined; - } - if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) { - jQuery.error( "Invalid XML: " + data ); - } - return xml; - }, - - noop: function() {}, - - // Evaluates a script in a global context - // Workarounds based on findings by Jim Driscoll - // http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context - globalEval: function( data ) { - if ( data && core_rnotwhite.test( data ) ) { - // We use execScript on Internet Explorer - // We use an anonymous function so that context is window - // rather than jQuery in Firefox - ( window.execScript || function( data ) { - window[ "eval" ].call( window, data ); - } )( data ); - } - }, - - // Convert dashed to camelCase; used by the css and data modules - // Microsoft forgot to hump their vendor prefix (#9572) - camelCase: function( string ) { - return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase ); - }, - - nodeName: function( elem, name ) { - return elem.nodeName && elem.nodeName.toLowerCase() === name.toLowerCase(); - }, - - // args is for internal usage only - each: function( obj, callback, args ) { - var name, - i = 0, - length = obj.length, - isObj = length === undefined || jQuery.isFunction( obj ); - - if ( args ) { - if ( isObj ) { - for ( name in obj ) { - if ( callback.apply( obj[ name ], args ) === false ) { - break; - } - } - } else { - for ( ; i < length; ) { - if ( callback.apply( obj[ i++ ], args ) === false ) { - break; - } - } - } - - // A special, fast, case for the most common use of each - } else { - if ( isObj ) { - for ( name in obj ) { - if ( callback.call( obj[ name ], name, obj[ name ] ) === false ) { - break; - } - } - } else { - for ( ; i < length; ) { - if ( callback.call( obj[ i ], i, obj[ i++ ] ) === false ) { - break; - } - } - } - } - - return obj; - }, - - // Use native String.trim function wherever possible - trim: core_trim && !core_trim.call("\uFEFF\xA0") ? - function( text ) { - return text == null ? - "" : - core_trim.call( text ); - } : - - // Otherwise use our own trimming functionality - function( text ) { - return text == null ? - "" : - ( text + "" ).replace( rtrim, "" ); - }, - - // results is for internal usage only - makeArray: function( arr, results ) { - var type, - ret = results || []; - - if ( arr != null ) { - // The window, strings (and functions) also have 'length' - // Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930 - type = jQuery.type( arr ); - - if ( arr.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( arr ) ) { - core_push.call( ret, arr ); - } else { - jQuery.merge( ret, arr ); - } - } - - return ret; - }, - - inArray: function( elem, arr, i ) { - var len; - - if ( arr ) { - if ( core_indexOf ) { - return core_indexOf.call( arr, elem, i ); - } - - len = arr.length; - i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0; - - for ( ; i < len; i++ ) { - // Skip accessing in sparse arrays - if ( i in arr && arr[ i ] === elem ) { - return i; - } - } - } - - return -1; - }, - - merge: function( first, second ) { - var l = second.length, - i = first.length, - j = 0; - - if ( typeof l === "number" ) { - for ( ; j < l; j++ ) { - first[ i++ ] = second[ j ]; - } - - } else { - while ( second[j] !== undefined ) { - first[ i++ ] = second[ j++ ]; - } - } - - first.length = i; - - return first; - }, - - grep: function( elems, callback, inv ) { - var retVal, - ret = [], - i = 0, - length = elems.length; - inv = !!inv; - - // Go through the array, only saving the items - // that pass the validator function - for ( ; i < length; i++ ) { - retVal = !!callback( elems[ i ], i ); - if ( inv !== retVal ) { - ret.push( elems[ i ] ); - } - } - - return ret; - }, - - // arg is for internal usage only - map: function( elems, callback, arg ) { - var value, key, - ret = [], - i = 0, - length = elems.length, - // jquery objects are treated as arrays - isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ; - - // Go through the array, translating each of the items to their - if ( isArray ) { - for ( ; i < length; i++ ) { - value = callback( elems[ i ], i, arg ); - - if ( value != null ) { - ret[ ret.length ] = value; - } - } - - // Go through every key on the object, - } else { - for ( key in elems ) { - value = callback( elems[ key ], key, arg ); - - if ( value != null ) { - ret[ ret.length ] = value; - } - } - } - - // Flatten any nested arrays - return ret.concat.apply( [], ret ); - }, - - // A global GUID counter for objects - guid: 1, - - // Bind a function to a context, optionally partially applying any - // arguments. - proxy: function( fn, context ) { - var tmp, args, proxy; - - if ( typeof context === "string" ) { - tmp = fn[ context ]; - context = fn; - fn = tmp; - } - - // Quick check to determine if target is callable, in the spec - // this throws a TypeError, but we will just return undefined. - if ( !jQuery.isFunction( fn ) ) { - return undefined; - } - - // Simulated bind - args = core_slice.call( arguments, 2 ); - proxy = function() { - return fn.apply( context, args.concat( core_slice.call( arguments ) ) ); - }; - - // Set the guid of unique handler to the same of original handler, so it can be removed - proxy.guid = fn.guid = fn.guid || jQuery.guid++; - - return proxy; - }, - - // Multifunctional method to get and set values of a collection - // The value/s can optionally be executed if it's a function - access: function( elems, fn, key, value, chainable, emptyGet, pass ) { - var exec, - bulk = key == null, - i = 0, - length = elems.length; - - // Sets many values - if ( key && typeof key === "object" ) { - for ( i in key ) { - jQuery.access( elems, fn, i, key[i], 1, emptyGet, value ); - } - chainable = 1; - - // Sets one value - } else if ( value !== undefined ) { - // Optionally, function values get executed if exec is true - exec = pass === undefined && jQuery.isFunction( value ); - - if ( bulk ) { - // Bulk operations only iterate when executing function values - if ( exec ) { - exec = fn; - fn = function( elem, key, value ) { - return exec.call( jQuery( elem ), value ); - }; - - // Otherwise they run against the entire set - } else { - fn.call( elems, value ); - fn = null; - } - } - - if ( fn ) { - for (; i < length; i++ ) { - fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass ); - } - } - - chainable = 1; - } - - return chainable ? - elems : - - // Gets - bulk ? - fn.call( elems ) : - length ? fn( elems[0], key ) : emptyGet; - }, - - now: function() { - return ( new Date() ).getTime(); - } -}); - -jQuery.ready.promise = function( obj ) { - if ( !readyList ) { - - readyList = jQuery.Deferred(); - - // Catch cases where $(document).ready() is called after the browser event has already occurred. - // we once tried to use readyState "interactive" here, but it caused issues like the one - // discovered by ChrisS here: http://bugs.jquery.com/ticket/12282#comment:15 - if ( document.readyState === "complete" ) { - // Handle it asynchronously to allow scripts the opportunity to delay ready - setTimeout( jQuery.ready, 1 ); - - // Standards-based browsers support DOMContentLoaded - } else if ( document.addEventListener ) { - // Use the handy event callback - document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false ); - - // A fallback to window.onload, that will always work - window.addEventListener( "load", jQuery.ready, false ); - - // If IE event model is used - } else { - // Ensure firing before onload, maybe late but safe also for iframes - document.attachEvent( "onreadystatechange", DOMContentLoaded ); - - // A fallback to window.onload, that will always work - window.attachEvent( "onload", jQuery.ready ); - - // If IE and not a frame - // continually check to see if the document is ready - var top = false; - - try { - top = window.frameElement == null && document.documentElement; - } catch(e) {} - - if ( top && top.doScroll ) { - (function doScrollCheck() { - if ( !jQuery.isReady ) { - - try { - // Use the trick by Diego Perini - // http://javascript.nwbox.com/IEContentLoaded/ - top.doScroll("left"); - } catch(e) { - return setTimeout( doScrollCheck, 50 ); - } - - // and execute any waiting functions - jQuery.ready(); - } - })(); - } - } - } - return readyList.promise( obj ); -}; - -// Populate the class2type map -jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) { - class2type[ "[object " + name + "]" ] = name.toLowerCase(); -}); - -// All jQuery objects should point back to these -rootjQuery = jQuery(document); -// String to Object options format cache -var optionsCache = {}; - -// Convert String-formatted options into Object-formatted ones and store in cache -function createOptions( options ) { - var object = optionsCache[ options ] = {}; - jQuery.each( options.split( core_rspace ), function( _, flag ) { - object[ flag ] = true; - }); - return object; -} - -/* - * Create a callback list using the following parameters: - * - * options: an optional list of space-separated options that will change how - * the callback list behaves or a more traditional option object - * - * By default a callback list will act like an event callback list and can be - * "fired" multiple times. - * - * Possible options: - * - * once: will ensure the callback list can only be fired once (like a Deferred) - * - * memory: will keep track of previous values and will call any callback added - * after the list has been fired right away with the latest "memorized" - * values (like a Deferred) - * - * unique: will ensure a callback can only be added once (no duplicate in the list) - * - * stopOnFalse: interrupt callings when a callback returns false - * - */ -jQuery.Callbacks = function( options ) { - - // Convert options from String-formatted to Object-formatted if needed - // (we check in cache first) - options = typeof options === "string" ? - ( optionsCache[ options ] || createOptions( options ) ) : - jQuery.extend( {}, options ); - - var // Last fire value (for non-forgettable lists) - memory, - // Flag to know if list was already fired - fired, - // Flag to know if list is currently firing - firing, - // First callback to fire (used internally by add and fireWith) - firingStart, - // End of the loop when firing - firingLength, - // Index of currently firing callback (modified by remove if needed) - firingIndex, - // Actual callback list - list = [], - // Stack of fire calls for repeatable lists - stack = !options.once && [], - // Fire callbacks - fire = function( data ) { - memory = options.memory && data; - fired = true; - firingIndex = firingStart || 0; - firingStart = 0; - firingLength = list.length; - firing = true; - for ( ; list && firingIndex < firingLength; firingIndex++ ) { - if ( list[ firingIndex ].apply( data[ 0 ], data[ 1 ] ) === false && options.stopOnFalse ) { - memory = false; // To prevent further calls using add - break; - } - } - firing = false; - if ( list ) { - if ( stack ) { - if ( stack.length ) { - fire( stack.shift() ); - } - } else if ( memory ) { - list = []; - } else { - self.disable(); - } - } - }, - // Actual Callbacks object - self = { - // Add a callback or a collection of callbacks to the list - add: function() { - if ( list ) { - // First, we save the current length - var start = list.length; - (function add( args ) { - jQuery.each( args, function( _, arg ) { - var type = jQuery.type( arg ); - if ( type === "function" && ( !options.unique || !self.has( arg ) ) ) { - list.push( arg ); - } else if ( arg && arg.length && type !== "string" ) { - // Inspect recursively - add( arg ); - } - }); - })( arguments ); - // Do we need to add the callbacks to the - // current firing batch? - if ( firing ) { - firingLength = list.length; - // With memory, if we're not firing then - // we should call right away - } else if ( memory ) { - firingStart = start; - fire( memory ); - } - } - return this; - }, - // Remove a callback from the list - remove: function() { - if ( list ) { - jQuery.each( arguments, function( _, arg ) { - var index; - while( ( index = jQuery.inArray( arg, list, index ) ) > -1 ) { - list.splice( index, 1 ); - // Handle firing indexes - if ( firing ) { - if ( index <= firingLength ) { - firingLength--; - } - if ( index <= firingIndex ) { - firingIndex--; - } - } - } - }); - } - return this; - }, - // Control if a given callback is in the list - has: function( fn ) { - return jQuery.inArray( fn, list ) > -1; - }, - // Remove all callbacks from the list - empty: function() { - list = []; - return this; - }, - // Have the list do nothing anymore - disable: function() { - list = stack = memory = undefined; - return this; - }, - // Is it disabled? - disabled: function() { - return !list; - }, - // Lock the list in its current state - lock: function() { - stack = undefined; - if ( !memory ) { - self.disable(); - } - return this; - }, - // Is it locked? - locked: function() { - return !stack; - }, - // Call all callbacks with the given context and arguments - fireWith: function( context, args ) { - args = args || []; - args = [ context, args.slice ? args.slice() : args ]; - if ( list && ( !fired || stack ) ) { - if ( firing ) { - stack.push( args ); - } else { - fire( args ); - } - } - return this; - }, - // Call all the callbacks with the given arguments - fire: function() { - self.fireWith( this, arguments ); - return this; - }, - // To know if the callbacks have already been called at least once - fired: function() { - return !!fired; - } - }; - - return self; -}; -jQuery.extend({ - - Deferred: function( func ) { - var tuples = [ - // action, add listener, listener list, final state - [ "resolve", "done", jQuery.Callbacks("once memory"), "resolved" ], - [ "reject", "fail", jQuery.Callbacks("once memory"), "rejected" ], - [ "notify", "progress", jQuery.Callbacks("memory") ] - ], - state = "pending", - promise = { - state: function() { - return state; - }, - always: function() { - deferred.done( arguments ).fail( arguments ); - return this; - }, - then: function( /* fnDone, fnFail, fnProgress */ ) { - var fns = arguments; - return jQuery.Deferred(function( newDefer ) { - jQuery.each( tuples, function( i, tuple ) { - var action = tuple[ 0 ], - fn = fns[ i ]; - // deferred[ done | fail | progress ] for forwarding actions to newDefer - deferred[ tuple[1] ]( jQuery.isFunction( fn ) ? - function() { - var returned = fn.apply( this, arguments ); - if ( returned && jQuery.isFunction( returned.promise ) ) { - returned.promise() - .done( newDefer.resolve ) - .fail( newDefer.reject ) - .progress( newDefer.notify ); - } else { - newDefer[ action + "With" ]( this === deferred ? newDefer : this, [ returned ] ); - } - } : - newDefer[ action ] - ); - }); - fns = null; - }).promise(); - }, - // Get a promise for this deferred - // If obj is provided, the promise aspect is added to the object - promise: function( obj ) { - return obj != null ? jQuery.extend( obj, promise ) : promise; - } - }, - deferred = {}; - - // Keep pipe for back-compat - promise.pipe = promise.then; - - // Add list-specific methods - jQuery.each( tuples, function( i, tuple ) { - var list = tuple[ 2 ], - stateString = tuple[ 3 ]; - - // promise[ done | fail | progress ] = list.add - promise[ tuple[1] ] = list.add; - - // Handle state - if ( stateString ) { - list.add(function() { - // state = [ resolved | rejected ] - state = stateString; - - // [ reject_list | resolve_list ].disable; progress_list.lock - }, tuples[ i ^ 1 ][ 2 ].disable, tuples[ 2 ][ 2 ].lock ); - } - - // deferred[ resolve | reject | notify ] = list.fire - deferred[ tuple[0] ] = list.fire; - deferred[ tuple[0] + "With" ] = list.fireWith; - }); - - // Make the deferred a promise - promise.promise( deferred ); - - // Call given func if any - if ( func ) { - func.call( deferred, deferred ); - } - - // All done! - return deferred; - }, - - // Deferred helper - when: function( subordinate /* , ..., subordinateN */ ) { - var i = 0, - resolveValues = core_slice.call( arguments ), - length = resolveValues.length, - - // the count of uncompleted subordinates - remaining = length !== 1 || ( subordinate && jQuery.isFunction( subordinate.promise ) ) ? length : 0, - - // the master Deferred. If resolveValues consist of only a single Deferred, just use that. - deferred = remaining === 1 ? subordinate : jQuery.Deferred(), - - // Update function for both resolve and progress values - updateFunc = function( i, contexts, values ) { - return function( value ) { - contexts[ i ] = this; - values[ i ] = arguments.length > 1 ? core_slice.call( arguments ) : value; - if( values === progressValues ) { - deferred.notifyWith( contexts, values ); - } else if ( !( --remaining ) ) { - deferred.resolveWith( contexts, values ); - } - }; - }, - - progressValues, progressContexts, resolveContexts; - - // add listeners to Deferred subordinates; treat others as resolved - if ( length > 1 ) { - progressValues = new Array( length ); - progressContexts = new Array( length ); - resolveContexts = new Array( length ); - for ( ; i < length; i++ ) { - if ( resolveValues[ i ] && jQuery.isFunction( resolveValues[ i ].promise ) ) { - resolveValues[ i ].promise() - .done( updateFunc( i, resolveContexts, resolveValues ) ) - .fail( deferred.reject ) - .progress( updateFunc( i, progressContexts, progressValues ) ); - } else { - --remaining; - } - } - } - - // if we're not waiting on anything, resolve the master - if ( !remaining ) { - deferred.resolveWith( resolveContexts, resolveValues ); - } - - return deferred.promise(); - } -}); -jQuery.support = (function() { - - var support, - all, - a, - select, - opt, - input, - fragment, - eventName, - i, - isSupported, - clickFn, - div = document.createElement("div"); - - // Preliminary tests - div.setAttribute( "className", "t" ); - div.innerHTML = "
                a"; - - all = div.getElementsByTagName("*"); - a = div.getElementsByTagName("a")[ 0 ]; - a.style.cssText = "top:1px;float:left;opacity:.5"; - - // Can't get basic test support - if ( !all || !all.length ) { - return {}; - } - - // First batch of supports tests - select = document.createElement("select"); - opt = select.appendChild( document.createElement("option") ); - input = div.getElementsByTagName("input")[ 0 ]; - - support = { - // IE strips leading whitespace when .innerHTML is used - leadingWhitespace: ( div.firstChild.nodeType === 3 ), - - // Make sure that tbody elements aren't automatically inserted - // IE will insert them into empty tables - tbody: !div.getElementsByTagName("tbody").length, - - // Make sure that link elements get serialized correctly by innerHTML - // This requires a wrapper element in IE - htmlSerialize: !!div.getElementsByTagName("link").length, - - // Get the style information from getAttribute - // (IE uses .cssText instead) - style: /top/.test( a.getAttribute("style") ), - - // Make sure that URLs aren't manipulated - // (IE normalizes it by default) - hrefNormalized: ( a.getAttribute("href") === "/a" ), - - // Make sure that element opacity exists - // (IE uses filter instead) - // Use a regex to work around a WebKit issue. See #5145 - opacity: /^0.5/.test( a.style.opacity ), - - // Verify style float existence - // (IE uses styleFloat instead of cssFloat) - cssFloat: !!a.style.cssFloat, - - // Make sure that if no value is specified for a checkbox - // that it defaults to "on". - // (WebKit defaults to "" instead) - checkOn: ( input.value === "on" ), - - // Make sure that a selected-by-default option has a working selected property. - // (WebKit defaults to false instead of true, IE too, if it's in an optgroup) - optSelected: opt.selected, - - // Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7) - getSetAttribute: div.className !== "t", - - // Tests for enctype support on a form(#6743) - enctype: !!document.createElement("form").enctype, - - // Makes sure cloning an html5 element does not cause problems - // Where outerHTML is undefined, this still works - html5Clone: document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav>", - - // jQuery.support.boxModel DEPRECATED in 1.8 since we don't support Quirks Mode - boxModel: ( document.compatMode === "CSS1Compat" ), - - // Will be defined later - submitBubbles: true, - changeBubbles: true, - focusinBubbles: false, - deleteExpando: true, - noCloneEvent: true, - inlineBlockNeedsLayout: false, - shrinkWrapBlocks: false, - reliableMarginRight: true, - boxSizingReliable: true, - pixelPosition: false - }; - - // Make sure checked status is properly cloned - input.checked = true; - support.noCloneChecked = input.cloneNode( true ).checked; - - // Make sure that the options inside disabled selects aren't marked as disabled - // (WebKit marks them as disabled) - select.disabled = true; - support.optDisabled = !opt.disabled; - - // Test to see if it's possible to delete an expando from an element - // Fails in Internet Explorer - try { - delete div.test; - } catch( e ) { - support.deleteExpando = false; - } - - if ( !div.addEventListener && div.attachEvent && div.fireEvent ) { - div.attachEvent( "onclick", clickFn = function() { - // Cloning a node shouldn't copy over any - // bound event handlers (IE does this) - support.noCloneEvent = false; - }); - div.cloneNode( true ).fireEvent("onclick"); - div.detachEvent( "onclick", clickFn ); - } - - // Check if a radio maintains its value - // after being appended to the DOM - input = document.createElement("input"); - input.value = "t"; - input.setAttribute( "type", "radio" ); - support.radioValue = input.value === "t"; - - input.setAttribute( "checked", "checked" ); - - // #11217 - WebKit loses check when the name is after the checked attribute - input.setAttribute( "name", "t" ); - - div.appendChild( input ); - fragment = document.createDocumentFragment(); - fragment.appendChild( div.lastChild ); - - // WebKit doesn't clone checked state correctly in fragments - support.checkClone = fragment.cloneNode( true ).cloneNode( true ).lastChild.checked; - - // Check if a disconnected checkbox will retain its checked - // value of true after appended to the DOM (IE6/7) - support.appendChecked = input.checked; - - fragment.removeChild( input ); - fragment.appendChild( div ); - - // Technique from Juriy Zaytsev - // http://perfectionkills.com/detecting-event-support-without-browser-sniffing/ - // We only care about the case where non-standard event systems - // are used, namely in IE. Short-circuiting here helps us to - // avoid an eval call (in setAttribute) which can cause CSP - // to go haywire. See: https://developer.mozilla.org/en/Security/CSP - if ( div.attachEvent ) { - for ( i in { - submit: true, - change: true, - focusin: true - }) { - eventName = "on" + i; - isSupported = ( eventName in div ); - if ( !isSupported ) { - div.setAttribute( eventName, "return;" ); - isSupported = ( typeof div[ eventName ] === "function" ); - } - support[ i + "Bubbles" ] = isSupported; - } - } - - // Run tests that need a body at doc ready - jQuery(function() { - var container, div, tds, marginDiv, - divReset = "padding:0;margin:0;border:0;display:block;overflow:hidden;", - body = document.getElementsByTagName("body")[0]; - - if ( !body ) { - // Return for frameset docs that don't have a body - return; - } - - container = document.createElement("div"); - container.style.cssText = "visibility:hidden;border:0;width:0;height:0;position:static;top:0;margin-top:1px"; - body.insertBefore( container, body.firstChild ); - - // Construct the test element - div = document.createElement("div"); - container.appendChild( div ); - - // Check if table cells still have offsetWidth/Height when they are set - // to display:none and there are still other visible table cells in a - // table row; if so, offsetWidth/Height are not reliable for use when - // determining if an element has been hidden directly using - // display:none (it is still safe to use offsets if a parent element is - // hidden; don safety goggles and see bug #4512 for more information). - // (only IE 8 fails this test) - div.innerHTML = "
                t
                "; - tds = div.getElementsByTagName("td"); - tds[ 0 ].style.cssText = "padding:0;margin:0;border:0;display:none"; - isSupported = ( tds[ 0 ].offsetHeight === 0 ); - - tds[ 0 ].style.display = ""; - tds[ 1 ].style.display = "none"; - - // Check if empty table cells still have offsetWidth/Height - // (IE <= 8 fail this test) - support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 ); - - // Check box-sizing and margin behavior - div.innerHTML = ""; - div.style.cssText = "box-sizing:border-box;-moz-box-sizing:border-box;-webkit-box-sizing:border-box;padding:1px;border:1px;display:block;width:4px;margin-top:1%;position:absolute;top:1%;"; - support.boxSizing = ( div.offsetWidth === 4 ); - support.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== 1 ); - - // NOTE: To any future maintainer, we've window.getComputedStyle - // because jsdom on node.js will break without it. - if ( window.getComputedStyle ) { - support.pixelPosition = ( window.getComputedStyle( div, null ) || {} ).top !== "1%"; - support.boxSizingReliable = ( window.getComputedStyle( div, null ) || { width: "4px" } ).width === "4px"; - - // Check if div with explicit width and no margin-right incorrectly - // gets computed margin-right based on width of container. For more - // info see bug #3333 - // Fails in WebKit before Feb 2011 nightlies - // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right - marginDiv = document.createElement("div"); - marginDiv.style.cssText = div.style.cssText = divReset; - marginDiv.style.marginRight = marginDiv.style.width = "0"; - div.style.width = "1px"; - div.appendChild( marginDiv ); - support.reliableMarginRight = - !parseFloat( ( window.getComputedStyle( marginDiv, null ) || {} ).marginRight ); - } - - if ( typeof div.style.zoom !== "undefined" ) { - // Check if natively block-level elements act like inline-block - // elements when setting their display to 'inline' and giving - // them layout - // (IE < 8 does this) - div.innerHTML = ""; - div.style.cssText = divReset + "width:1px;padding:1px;display:inline;zoom:1"; - support.inlineBlockNeedsLayout = ( div.offsetWidth === 3 ); - - // Check if elements with layout shrink-wrap their children - // (IE 6 does this) - div.style.display = "block"; - div.style.overflow = "visible"; - div.innerHTML = "
                "; - div.firstChild.style.width = "5px"; - support.shrinkWrapBlocks = ( div.offsetWidth !== 3 ); - - container.style.zoom = 1; - } - - // Null elements to avoid leaks in IE - body.removeChild( container ); - container = div = tds = marginDiv = null; - }); - - // Null elements to avoid leaks in IE - fragment.removeChild( div ); - all = a = select = opt = input = fragment = div = null; - - return support; -})(); -var rbrace = /(?:\{[\s\S]*\}|\[[\s\S]*\])$/, - rmultiDash = /([A-Z])/g; - -jQuery.extend({ - cache: {}, - - deletedIds: [], - - // Remove at next major release (1.9/2.0) - uuid: 0, - - // Unique for each copy of jQuery on the page - // Non-digits removed to match rinlinejQuery - expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ), - - // The following elements throw uncatchable exceptions if you - // attempt to add expando properties to them. - noData: { - "embed": true, - // Ban all objects except for Flash (which handle expandos) - "object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000", - "applet": true - }, - - hasData: function( elem ) { - elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ]; - return !!elem && !isEmptyDataObject( elem ); - }, - - data: function( elem, name, data, pvt /* Internal Use Only */ ) { - if ( !jQuery.acceptData( elem ) ) { - return; - } - - var thisCache, ret, - internalKey = jQuery.expando, - getByName = typeof name === "string", - - // We have to handle DOM nodes and JS objects differently because IE6-7 - // can't GC object references properly across the DOM-JS boundary - isNode = elem.nodeType, - - // Only DOM nodes need the global jQuery cache; JS object data is - // attached directly to the object so GC can occur automatically - cache = isNode ? jQuery.cache : elem, - - // Only defining an ID for JS objects if its cache already exists allows - // the code to shortcut on the same path as a DOM node with no cache - id = isNode ? elem[ internalKey ] : elem[ internalKey ] && internalKey; - - // Avoid doing any more work than we need to when trying to get data on an - // object that has no data at all - if ( (!id || !cache[id] || (!pvt && !cache[id].data)) && getByName && data === undefined ) { - return; - } - - if ( !id ) { - // Only DOM nodes need a new unique ID for each element since their data - // ends up in the global cache - if ( isNode ) { - elem[ internalKey ] = id = jQuery.deletedIds.pop() || jQuery.guid++; - } else { - id = internalKey; - } - } - - if ( !cache[ id ] ) { - cache[ id ] = {}; - - // Avoids exposing jQuery metadata on plain JS objects when the object - // is serialized using JSON.stringify - if ( !isNode ) { - cache[ id ].toJSON = jQuery.noop; - } - } - - // An object can be passed to jQuery.data instead of a key/value pair; this gets - // shallow copied over onto the existing cache - if ( typeof name === "object" || typeof name === "function" ) { - if ( pvt ) { - cache[ id ] = jQuery.extend( cache[ id ], name ); - } else { - cache[ id ].data = jQuery.extend( cache[ id ].data, name ); - } - } - - thisCache = cache[ id ]; - - // jQuery data() is stored in a separate object inside the object's internal data - // cache in order to avoid key collisions between internal data and user-defined - // data. - if ( !pvt ) { - if ( !thisCache.data ) { - thisCache.data = {}; - } - - thisCache = thisCache.data; - } - - if ( data !== undefined ) { - thisCache[ jQuery.camelCase( name ) ] = data; - } - - // Check for both converted-to-camel and non-converted data property names - // If a data property was specified - if ( getByName ) { - - // First Try to find as-is property data - ret = thisCache[ name ]; - - // Test for null|undefined property data - if ( ret == null ) { - - // Try to find the camelCased property - ret = thisCache[ jQuery.camelCase( name ) ]; - } - } else { - ret = thisCache; - } - - return ret; - }, - - removeData: function( elem, name, pvt /* Internal Use Only */ ) { - if ( !jQuery.acceptData( elem ) ) { - return; - } - - var thisCache, i, l, - - isNode = elem.nodeType, - - // See jQuery.data for more information - cache = isNode ? jQuery.cache : elem, - id = isNode ? elem[ jQuery.expando ] : jQuery.expando; - - // If there is already no cache entry for this object, there is no - // purpose in continuing - if ( !cache[ id ] ) { - return; - } - - if ( name ) { - - thisCache = pvt ? cache[ id ] : cache[ id ].data; - - if ( thisCache ) { - - // Support array or space separated string names for data keys - if ( !jQuery.isArray( name ) ) { - - // try the string as a key before any manipulation - if ( name in thisCache ) { - name = [ name ]; - } else { - - // split the camel cased version by spaces unless a key with the spaces exists - name = jQuery.camelCase( name ); - if ( name in thisCache ) { - name = [ name ]; - } else { - name = name.split(" "); - } - } - } - - for ( i = 0, l = name.length; i < l; i++ ) { - delete thisCache[ name[i] ]; - } - - // If there is no data left in the cache, we want to continue - // and let the cache object itself get destroyed - if ( !( pvt ? isEmptyDataObject : jQuery.isEmptyObject )( thisCache ) ) { - return; - } - } - } - - // See jQuery.data for more information - if ( !pvt ) { - delete cache[ id ].data; - - // Don't destroy the parent cache unless the internal data object - // had been the only thing left in it - if ( !isEmptyDataObject( cache[ id ] ) ) { - return; - } - } - - // Destroy the cache - if ( isNode ) { - jQuery.cleanData( [ elem ], true ); - - // Use delete when supported for expandos or `cache` is not a window per isWindow (#10080) - } else if ( jQuery.support.deleteExpando || cache != cache.window ) { - delete cache[ id ]; - - // When all else fails, null - } else { - cache[ id ] = null; - } - }, - - // For internal use only. - _data: function( elem, name, data ) { - return jQuery.data( elem, name, data, true ); - }, - - // A method for determining if a DOM node can handle the data expando - acceptData: function( elem ) { - var noData = elem.nodeName && jQuery.noData[ elem.nodeName.toLowerCase() ]; - - // nodes accept data unless otherwise specified; rejection can be conditional - return !noData || noData !== true && elem.getAttribute("classid") === noData; - } -}); - -jQuery.fn.extend({ - data: function( key, value ) { - var parts, part, attr, name, l, - elem = this[0], - i = 0, - data = null; - - // Gets all values - if ( key === undefined ) { - if ( this.length ) { - data = jQuery.data( elem ); - - if ( elem.nodeType === 1 && !jQuery._data( elem, "parsedAttrs" ) ) { - attr = elem.attributes; - for ( l = attr.length; i < l; i++ ) { - name = attr[i].name; - - if ( !name.indexOf( "data-" ) ) { - name = jQuery.camelCase( name.substring(5) ); - - dataAttr( elem, name, data[ name ] ); - } - } - jQuery._data( elem, "parsedAttrs", true ); - } - } - - return data; - } - - // Sets multiple values - if ( typeof key === "object" ) { - return this.each(function() { - jQuery.data( this, key ); - }); - } - - parts = key.split( ".", 2 ); - parts[1] = parts[1] ? "." + parts[1] : ""; - part = parts[1] + "!"; - - return jQuery.access( this, function( value ) { - - if ( value === undefined ) { - data = this.triggerHandler( "getData" + part, [ parts[0] ] ); - - // Try to fetch any internally stored data first - if ( data === undefined && elem ) { - data = jQuery.data( elem, key ); - data = dataAttr( elem, key, data ); - } - - return data === undefined && parts[1] ? - this.data( parts[0] ) : - data; - } - - parts[1] = value; - this.each(function() { - var self = jQuery( this ); - - self.triggerHandler( "setData" + part, parts ); - jQuery.data( this, key, value ); - self.triggerHandler( "changeData" + part, parts ); - }); - }, null, value, arguments.length > 1, null, false ); - }, - - removeData: function( key ) { - return this.each(function() { - jQuery.removeData( this, key ); - }); - } -}); - -function dataAttr( elem, key, data ) { - // If nothing was found internally, try to fetch any - // data from the HTML5 data-* attribute - if ( data === undefined && elem.nodeType === 1 ) { - - var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase(); - - data = elem.getAttribute( name ); - - if ( typeof data === "string" ) { - try { - data = data === "true" ? true : - data === "false" ? false : - data === "null" ? null : - // Only convert to a number if it doesn't change the string - +data + "" === data ? +data : - rbrace.test( data ) ? jQuery.parseJSON( data ) : - data; - } catch( e ) {} - - // Make sure we set the data so it isn't changed later - jQuery.data( elem, key, data ); - - } else { - data = undefined; - } - } - - return data; -} - -// checks a cache object for emptiness -function isEmptyDataObject( obj ) { - var name; - for ( name in obj ) { - - // if the public data object is empty, the private is still empty - if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) { - continue; - } - if ( name !== "toJSON" ) { - return false; - } - } - - return true; -} -jQuery.extend({ - queue: function( elem, type, data ) { - var queue; - - if ( elem ) { - type = ( type || "fx" ) + "queue"; - queue = jQuery._data( elem, type ); - - // Speed up dequeue by getting out quickly if this is just a lookup - if ( data ) { - if ( !queue || jQuery.isArray(data) ) { - queue = jQuery._data( elem, type, jQuery.makeArray(data) ); - } else { - queue.push( data ); - } - } - return queue || []; - } - }, - - dequeue: function( elem, type ) { - type = type || "fx"; - - var queue = jQuery.queue( elem, type ), - startLength = queue.length, - fn = queue.shift(), - hooks = jQuery._queueHooks( elem, type ), - next = function() { - jQuery.dequeue( elem, type ); - }; - - // If the fx queue is dequeued, always remove the progress sentinel - if ( fn === "inprogress" ) { - fn = queue.shift(); - startLength--; - } - - if ( fn ) { - - // Add a progress sentinel to prevent the fx queue from being - // automatically dequeued - if ( type === "fx" ) { - queue.unshift( "inprogress" ); - } - - // clear up the last queue stop function - delete hooks.stop; - fn.call( elem, next, hooks ); - } - - if ( !startLength && hooks ) { - hooks.empty.fire(); - } - }, - - // not intended for public consumption - generates a queueHooks object, or returns the current one - _queueHooks: function( elem, type ) { - var key = type + "queueHooks"; - return jQuery._data( elem, key ) || jQuery._data( elem, key, { - empty: jQuery.Callbacks("once memory").add(function() { - jQuery.removeData( elem, type + "queue", true ); - jQuery.removeData( elem, key, true ); - }) - }); - } -}); - -jQuery.fn.extend({ - queue: function( type, data ) { - var setter = 2; - - if ( typeof type !== "string" ) { - data = type; - type = "fx"; - setter--; - } - - if ( arguments.length < setter ) { - return jQuery.queue( this[0], type ); - } - - return data === undefined ? - this : - this.each(function() { - var queue = jQuery.queue( this, type, data ); - - // ensure a hooks for this queue - jQuery._queueHooks( this, type ); - - if ( type === "fx" && queue[0] !== "inprogress" ) { - jQuery.dequeue( this, type ); - } - }); - }, - dequeue: function( type ) { - return this.each(function() { - jQuery.dequeue( this, type ); - }); - }, - // Based off of the plugin by Clint Helfers, with permission. - // http://blindsignals.com/index.php/2009/07/jquery-delay/ - delay: function( time, type ) { - time = jQuery.fx ? jQuery.fx.speeds[ time ] || time : time; - type = type || "fx"; - - return this.queue( type, function( next, hooks ) { - var timeout = setTimeout( next, time ); - hooks.stop = function() { - clearTimeout( timeout ); - }; - }); - }, - clearQueue: function( type ) { - return this.queue( type || "fx", [] ); - }, - // Get a promise resolved when queues of a certain type - // are emptied (fx is the type by default) - promise: function( type, obj ) { - var tmp, - count = 1, - defer = jQuery.Deferred(), - elements = this, - i = this.length, - resolve = function() { - if ( !( --count ) ) { - defer.resolveWith( elements, [ elements ] ); - } - }; - - if ( typeof type !== "string" ) { - obj = type; - type = undefined; - } - type = type || "fx"; - - while( i-- ) { - tmp = jQuery._data( elements[ i ], type + "queueHooks" ); - if ( tmp && tmp.empty ) { - count++; - tmp.empty.add( resolve ); - } - } - resolve(); - return defer.promise( obj ); - } -}); -var nodeHook, boolHook, fixSpecified, - rclass = /[\t\r\n]/g, - rreturn = /\r/g, - rtype = /^(?:button|input)$/i, - rfocusable = /^(?:button|input|object|select|textarea)$/i, - rclickable = /^a(?:rea|)$/i, - rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i, - getSetAttribute = jQuery.support.getSetAttribute; - -jQuery.fn.extend({ - attr: function( name, value ) { - return jQuery.access( this, jQuery.attr, name, value, arguments.length > 1 ); - }, - - removeAttr: function( name ) { - return this.each(function() { - jQuery.removeAttr( this, name ); - }); - }, - - prop: function( name, value ) { - return jQuery.access( this, jQuery.prop, name, value, arguments.length > 1 ); - }, - - removeProp: function( name ) { - name = jQuery.propFix[ name ] || name; - return this.each(function() { - // try/catch handles cases where IE balks (such as removing a property on window) - try { - this[ name ] = undefined; - delete this[ name ]; - } catch( e ) {} - }); - }, - - addClass: function( value ) { - var classNames, i, l, elem, - setClass, c, cl; - - if ( jQuery.isFunction( value ) ) { - return this.each(function( j ) { - jQuery( this ).addClass( value.call(this, j, this.className) ); - }); - } - - if ( value && typeof value === "string" ) { - classNames = value.split( core_rspace ); - - for ( i = 0, l = this.length; i < l; i++ ) { - elem = this[ i ]; - - if ( elem.nodeType === 1 ) { - if ( !elem.className && classNames.length === 1 ) { - elem.className = value; - - } else { - setClass = " " + elem.className + " "; - - for ( c = 0, cl = classNames.length; c < cl; c++ ) { - if ( setClass.indexOf( " " + classNames[ c ] + " " ) < 0 ) { - setClass += classNames[ c ] + " "; - } - } - elem.className = jQuery.trim( setClass ); - } - } - } - } - - return this; - }, - - removeClass: function( value ) { - var removes, className, elem, c, cl, i, l; - - if ( jQuery.isFunction( value ) ) { - return this.each(function( j ) { - jQuery( this ).removeClass( value.call(this, j, this.className) ); - }); - } - if ( (value && typeof value === "string") || value === undefined ) { - removes = ( value || "" ).split( core_rspace ); - - for ( i = 0, l = this.length; i < l; i++ ) { - elem = this[ i ]; - if ( elem.nodeType === 1 && elem.className ) { - - className = (" " + elem.className + " ").replace( rclass, " " ); - - // loop over each item in the removal list - for ( c = 0, cl = removes.length; c < cl; c++ ) { - // Remove until there is nothing to remove, - while ( className.indexOf(" " + removes[ c ] + " ") >= 0 ) { - className = className.replace( " " + removes[ c ] + " " , " " ); - } - } - elem.className = value ? jQuery.trim( className ) : ""; - } - } - } - - return this; - }, - - toggleClass: function( value, stateVal ) { - var type = typeof value, - isBool = typeof stateVal === "boolean"; - - if ( jQuery.isFunction( value ) ) { - return this.each(function( i ) { - jQuery( this ).toggleClass( value.call(this, i, this.className, stateVal), stateVal ); - }); - } - - return this.each(function() { - if ( type === "string" ) { - // toggle individual class names - var className, - i = 0, - self = jQuery( this ), - state = stateVal, - classNames = value.split( core_rspace ); - - while ( (className = classNames[ i++ ]) ) { - // check each className given, space separated list - state = isBool ? state : !self.hasClass( className ); - self[ state ? "addClass" : "removeClass" ]( className ); - } - - } else if ( type === "undefined" || type === "boolean" ) { - if ( this.className ) { - // store className if set - jQuery._data( this, "__className__", this.className ); - } - - // toggle whole className - this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || ""; - } - }); - }, - - hasClass: function( selector ) { - var className = " " + selector + " ", - i = 0, - l = this.length; - for ( ; i < l; i++ ) { - if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) >= 0 ) { - return true; - } - } - - return false; - }, - - val: function( value ) { - var hooks, ret, isFunction, - elem = this[0]; - - if ( !arguments.length ) { - if ( elem ) { - hooks = jQuery.valHooks[ elem.type ] || jQuery.valHooks[ elem.nodeName.toLowerCase() ]; - - if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) { - return ret; - } - - ret = elem.value; - - return typeof ret === "string" ? - // handle most common string cases - ret.replace(rreturn, "") : - // handle cases where value is null/undef or number - ret == null ? "" : ret; - } - - return; - } - - isFunction = jQuery.isFunction( value ); - - return this.each(function( i ) { - var val, - self = jQuery(this); - - if ( this.nodeType !== 1 ) { - return; - } - - if ( isFunction ) { - val = value.call( this, i, self.val() ); - } else { - val = value; - } - - // Treat null/undefined as ""; convert numbers to string - if ( val == null ) { - val = ""; - } else if ( typeof val === "number" ) { - val += ""; - } else if ( jQuery.isArray( val ) ) { - val = jQuery.map(val, function ( value ) { - return value == null ? "" : value + ""; - }); - } - - hooks = jQuery.valHooks[ this.type ] || jQuery.valHooks[ this.nodeName.toLowerCase() ]; - - // If set returns undefined, fall back to normal setting - if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) { - this.value = val; - } - }); - } -}); - -jQuery.extend({ - valHooks: { - option: { - get: function( elem ) { - // attributes.value is undefined in Blackberry 4.7 but - // uses .value. See #6932 - var val = elem.attributes.value; - return !val || val.specified ? elem.value : elem.text; - } - }, - select: { - get: function( elem ) { - var value, i, max, option, - index = elem.selectedIndex, - values = [], - options = elem.options, - one = elem.type === "select-one"; - - // Nothing was selected - if ( index < 0 ) { - return null; - } - - // Loop through all the selected options - i = one ? index : 0; - max = one ? index + 1 : options.length; - for ( ; i < max; i++ ) { - option = options[ i ]; - - // Don't return options that are disabled or in a disabled optgroup - if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) && - (!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) { - - // Get the specific value for the option - value = jQuery( option ).val(); - - // We don't need an array for one selects - if ( one ) { - return value; - } - - // Multi-Selects return an array - values.push( value ); - } - } - - // Fixes Bug #2551 -- select.val() broken in IE after form.reset() - if ( one && !values.length && options.length ) { - return jQuery( options[ index ] ).val(); - } - - return values; - }, - - set: function( elem, value ) { - var values = jQuery.makeArray( value ); - - jQuery(elem).find("option").each(function() { - this.selected = jQuery.inArray( jQuery(this).val(), values ) >= 0; - }); - - if ( !values.length ) { - elem.selectedIndex = -1; - } - return values; - } - } - }, - - // Unused in 1.8, left in so attrFn-stabbers won't die; remove in 1.9 - attrFn: {}, - - attr: function( elem, name, value, pass ) { - var ret, hooks, notxml, - nType = elem.nodeType; - - // don't get/set attributes on text, comment and attribute nodes - if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { - return; - } - - if ( pass && jQuery.isFunction( jQuery.fn[ name ] ) ) { - return jQuery( elem )[ name ]( value ); - } - - // Fallback to prop when attributes are not supported - if ( typeof elem.getAttribute === "undefined" ) { - return jQuery.prop( elem, name, value ); - } - - notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); - - // All attributes are lowercase - // Grab necessary hook if one is defined - if ( notxml ) { - name = name.toLowerCase(); - hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook ); - } - - if ( value !== undefined ) { - - if ( value === null ) { - jQuery.removeAttr( elem, name ); - return; - - } else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) { - return ret; - - } else { - elem.setAttribute( name, value + "" ); - return value; - } - - } else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) { - return ret; - - } else { - - ret = elem.getAttribute( name ); - - // Non-existent attributes return null, we normalize to undefined - return ret === null ? - undefined : - ret; - } - }, - - removeAttr: function( elem, value ) { - var propName, attrNames, name, isBool, - i = 0; - - if ( value && elem.nodeType === 1 ) { - - attrNames = value.split( core_rspace ); - - for ( ; i < attrNames.length; i++ ) { - name = attrNames[ i ]; - - if ( name ) { - propName = jQuery.propFix[ name ] || name; - isBool = rboolean.test( name ); - - // See #9699 for explanation of this approach (setting first, then removal) - // Do not do this for boolean attributes (see #10870) - if ( !isBool ) { - jQuery.attr( elem, name, "" ); - } - elem.removeAttribute( getSetAttribute ? name : propName ); - - // Set corresponding property to false for boolean attributes - if ( isBool && propName in elem ) { - elem[ propName ] = false; - } - } - } - } - }, - - attrHooks: { - type: { - set: function( elem, value ) { - // We can't allow the type property to be changed (since it causes problems in IE) - if ( rtype.test( elem.nodeName ) && elem.parentNode ) { - jQuery.error( "type property can't be changed" ); - } else if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) { - // Setting the type on a radio button after the value resets the value in IE6-9 - // Reset value to it's default in case type is set after value - // This is for element creation - var val = elem.value; - elem.setAttribute( "type", value ); - if ( val ) { - elem.value = val; - } - return value; - } - } - }, - // Use the value property for back compat - // Use the nodeHook for button elements in IE6/7 (#1954) - value: { - get: function( elem, name ) { - if ( nodeHook && jQuery.nodeName( elem, "button" ) ) { - return nodeHook.get( elem, name ); - } - return name in elem ? - elem.value : - null; - }, - set: function( elem, value, name ) { - if ( nodeHook && jQuery.nodeName( elem, "button" ) ) { - return nodeHook.set( elem, value, name ); - } - // Does not return so that setAttribute is also used - elem.value = value; - } - } - }, - - propFix: { - tabindex: "tabIndex", - readonly: "readOnly", - "for": "htmlFor", - "class": "className", - maxlength: "maxLength", - cellspacing: "cellSpacing", - cellpadding: "cellPadding", - rowspan: "rowSpan", - colspan: "colSpan", - usemap: "useMap", - frameborder: "frameBorder", - contenteditable: "contentEditable" - }, - - prop: function( elem, name, value ) { - var ret, hooks, notxml, - nType = elem.nodeType; - - // don't get/set properties on text, comment and attribute nodes - if ( !elem || nType === 3 || nType === 8 || nType === 2 ) { - return; - } - - notxml = nType !== 1 || !jQuery.isXMLDoc( elem ); - - if ( notxml ) { - // Fix name and attach hooks - name = jQuery.propFix[ name ] || name; - hooks = jQuery.propHooks[ name ]; - } - - if ( value !== undefined ) { - if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) { - return ret; - - } else { - return ( elem[ name ] = value ); - } - - } else { - if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) { - return ret; - - } else { - return elem[ name ]; - } - } - }, - - propHooks: { - tabIndex: { - get: function( elem ) { - // elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set - // http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/ - var attributeNode = elem.getAttributeNode("tabindex"); - - return attributeNode && attributeNode.specified ? - parseInt( attributeNode.value, 10 ) : - rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ? - 0 : - undefined; - } - } - } -}); - -// Hook for boolean attributes -boolHook = { - get: function( elem, name ) { - // Align boolean attributes with corresponding properties - // Fall back to attribute presence where some booleans are not supported - var attrNode, - property = jQuery.prop( elem, name ); - return property === true || typeof property !== "boolean" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ? - name.toLowerCase() : - undefined; - }, - set: function( elem, value, name ) { - var propName; - if ( value === false ) { - // Remove boolean attributes when set to false - jQuery.removeAttr( elem, name ); - } else { - // value is true since we know at this point it's type boolean and not false - // Set boolean attributes to the same name and set the DOM property - propName = jQuery.propFix[ name ] || name; - if ( propName in elem ) { - // Only set the IDL specifically if it already exists on the element - elem[ propName ] = true; - } - - elem.setAttribute( name, name.toLowerCase() ); - } - return name; - } -}; - -// IE6/7 do not support getting/setting some attributes with get/setAttribute -if ( !getSetAttribute ) { - - fixSpecified = { - name: true, - id: true, - coords: true - }; - - // Use this for any attribute in IE6/7 - // This fixes almost every IE6/7 issue - nodeHook = jQuery.valHooks.button = { - get: function( elem, name ) { - var ret; - ret = elem.getAttributeNode( name ); - return ret && ( fixSpecified[ name ] ? ret.value !== "" : ret.specified ) ? - ret.value : - undefined; - }, - set: function( elem, value, name ) { - // Set the existing or create a new attribute node - var ret = elem.getAttributeNode( name ); - if ( !ret ) { - ret = document.createAttribute( name ); - elem.setAttributeNode( ret ); - } - return ( ret.value = value + "" ); - } - }; - - // Set width and height to auto instead of 0 on empty string( Bug #8150 ) - // This is for removals - jQuery.each([ "width", "height" ], function( i, name ) { - jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { - set: function( elem, value ) { - if ( value === "" ) { - elem.setAttribute( name, "auto" ); - return value; - } - } - }); - }); - - // Set contenteditable to false on removals(#10429) - // Setting to empty string throws an error as an invalid value - jQuery.attrHooks.contenteditable = { - get: nodeHook.get, - set: function( elem, value, name ) { - if ( value === "" ) { - value = "false"; - } - nodeHook.set( elem, value, name ); - } - }; -} - - -// Some attributes require a special call on IE -if ( !jQuery.support.hrefNormalized ) { - jQuery.each([ "href", "src", "width", "height" ], function( i, name ) { - jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], { - get: function( elem ) { - var ret = elem.getAttribute( name, 2 ); - return ret === null ? undefined : ret; - } - }); - }); -} - -if ( !jQuery.support.style ) { - jQuery.attrHooks.style = { - get: function( elem ) { - // Return undefined in the case of empty string - // Normalize to lowercase since IE uppercases css property names - return elem.style.cssText.toLowerCase() || undefined; - }, - set: function( elem, value ) { - return ( elem.style.cssText = value + "" ); - } - }; -} - -// Safari mis-reports the default selected property of an option -// Accessing the parent's selectedIndex property fixes it -if ( !jQuery.support.optSelected ) { - jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, { - get: function( elem ) { - var parent = elem.parentNode; - - if ( parent ) { - parent.selectedIndex; - - // Make sure that it also works with optgroups, see #5701 - if ( parent.parentNode ) { - parent.parentNode.selectedIndex; - } - } - return null; - } - }); -} - -// IE6/7 call enctype encoding -if ( !jQuery.support.enctype ) { - jQuery.propFix.enctype = "encoding"; -} - -// Radios and checkboxes getter/setter -if ( !jQuery.support.checkOn ) { - jQuery.each([ "radio", "checkbox" ], function() { - jQuery.valHooks[ this ] = { - get: function( elem ) { - // Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified - return elem.getAttribute("value") === null ? "on" : elem.value; - } - }; - }); -} -jQuery.each([ "radio", "checkbox" ], function() { - jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], { - set: function( elem, value ) { - if ( jQuery.isArray( value ) ) { - return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 ); - } - } - }); -}); -var rformElems = /^(?:textarea|input|select)$/i, - rtypenamespace = /^([^\.]*|)(?:\.(.+)|)$/, - rhoverHack = /(?:^|\s)hover(\.\S+|)\b/, - rkeyEvent = /^key/, - rmouseEvent = /^(?:mouse|contextmenu)|click/, - rfocusMorph = /^(?:focusinfocus|focusoutblur)$/, - hoverHack = function( events ) { - return jQuery.event.special.hover ? events : events.replace( rhoverHack, "mouseenter$1 mouseleave$1" ); - }; - -/* - * Helper functions for managing events -- not part of the public interface. - * Props to Dean Edwards' addEvent library for many of the ideas. - */ -jQuery.event = { - - add: function( elem, types, handler, data, selector ) { - - var elemData, eventHandle, events, - t, tns, type, namespaces, handleObj, - handleObjIn, handlers, special; - - // Don't attach events to noData or text/comment nodes (allow plain objects tho) - if ( elem.nodeType === 3 || elem.nodeType === 8 || !types || !handler || !(elemData = jQuery._data( elem )) ) { - return; - } - - // Caller can pass in an object of custom data in lieu of the handler - if ( handler.handler ) { - handleObjIn = handler; - handler = handleObjIn.handler; - selector = handleObjIn.selector; - } - - // Make sure that the handler has a unique ID, used to find/remove it later - if ( !handler.guid ) { - handler.guid = jQuery.guid++; - } - - // Init the element's event structure and main handler, if this is the first - events = elemData.events; - if ( !events ) { - elemData.events = events = {}; - } - eventHandle = elemData.handle; - if ( !eventHandle ) { - elemData.handle = eventHandle = function( e ) { - // Discard the second event of a jQuery.event.trigger() and - // when an event is called after a page has unloaded - return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ? - jQuery.event.dispatch.apply( eventHandle.elem, arguments ) : - undefined; - }; - // Add elem as a property of the handle fn to prevent a memory leak with IE non-native events - eventHandle.elem = elem; - } - - // Handle multiple events separated by a space - // jQuery(...).bind("mouseover mouseout", fn); - types = jQuery.trim( hoverHack(types) ).split( " " ); - for ( t = 0; t < types.length; t++ ) { - - tns = rtypenamespace.exec( types[t] ) || []; - type = tns[1]; - namespaces = ( tns[2] || "" ).split( "." ).sort(); - - // If event changes its type, use the special event handlers for the changed type - special = jQuery.event.special[ type ] || {}; - - // If selector defined, determine special event api type, otherwise given type - type = ( selector ? special.delegateType : special.bindType ) || type; - - // Update special based on newly reset type - special = jQuery.event.special[ type ] || {}; - - // handleObj is passed to all event handlers - handleObj = jQuery.extend({ - type: type, - origType: tns[1], - data: data, - handler: handler, - guid: handler.guid, - selector: selector, - needsContext: selector && jQuery.expr.match.needsContext.test( selector ), - namespace: namespaces.join(".") - }, handleObjIn ); - - // Init the event handler queue if we're the first - handlers = events[ type ]; - if ( !handlers ) { - handlers = events[ type ] = []; - handlers.delegateCount = 0; - - // Only use addEventListener/attachEvent if the special events handler returns false - if ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) { - // Bind the global event handler to the element - if ( elem.addEventListener ) { - elem.addEventListener( type, eventHandle, false ); - - } else if ( elem.attachEvent ) { - elem.attachEvent( "on" + type, eventHandle ); - } - } - } - - if ( special.add ) { - special.add.call( elem, handleObj ); - - if ( !handleObj.handler.guid ) { - handleObj.handler.guid = handler.guid; - } - } - - // Add to the element's handler list, delegates in front - if ( selector ) { - handlers.splice( handlers.delegateCount++, 0, handleObj ); - } else { - handlers.push( handleObj ); - } - - // Keep track of which events have ever been used, for event optimization - jQuery.event.global[ type ] = true; - } - - // Nullify elem to prevent memory leaks in IE - elem = null; - }, - - global: {}, - - // Detach an event or set of events from an element - remove: function( elem, types, handler, selector, mappedTypes ) { - - var t, tns, type, origType, namespaces, origCount, - j, events, special, eventType, handleObj, - elemData = jQuery.hasData( elem ) && jQuery._data( elem ); - - if ( !elemData || !(events = elemData.events) ) { - return; - } - - // Once for each type.namespace in types; type may be omitted - types = jQuery.trim( hoverHack( types || "" ) ).split(" "); - for ( t = 0; t < types.length; t++ ) { - tns = rtypenamespace.exec( types[t] ) || []; - type = origType = tns[1]; - namespaces = tns[2]; - - // Unbind all events (on this namespace, if provided) for the element - if ( !type ) { - for ( type in events ) { - jQuery.event.remove( elem, type + types[ t ], handler, selector, true ); - } - continue; - } - - special = jQuery.event.special[ type ] || {}; - type = ( selector? special.delegateType : special.bindType ) || type; - eventType = events[ type ] || []; - origCount = eventType.length; - namespaces = namespaces ? new RegExp("(^|\\.)" + namespaces.split(".").sort().join("\\.(?:.*\\.|)") + "(\\.|$)") : null; - - // Remove matching events - for ( j = 0; j < eventType.length; j++ ) { - handleObj = eventType[ j ]; - - if ( ( mappedTypes || origType === handleObj.origType ) && - ( !handler || handler.guid === handleObj.guid ) && - ( !namespaces || namespaces.test( handleObj.namespace ) ) && - ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) { - eventType.splice( j--, 1 ); - - if ( handleObj.selector ) { - eventType.delegateCount--; - } - if ( special.remove ) { - special.remove.call( elem, handleObj ); - } - } - } - - // Remove generic event handler if we removed something and no more handlers exist - // (avoids potential for endless recursion during removal of special event handlers) - if ( eventType.length === 0 && origCount !== eventType.length ) { - if ( !special.teardown || special.teardown.call( elem, namespaces, elemData.handle ) === false ) { - jQuery.removeEvent( elem, type, elemData.handle ); - } - - delete events[ type ]; - } - } - - // Remove the expando if it's no longer used - if ( jQuery.isEmptyObject( events ) ) { - delete elemData.handle; - - // removeData also checks for emptiness and clears the expando if empty - // so use it instead of delete - jQuery.removeData( elem, "events", true ); - } - }, - - // Events that are safe to short-circuit if no handlers are attached. - // Native DOM events should not be added, they may have inline handlers. - customEvent: { - "getData": true, - "setData": true, - "changeData": true - }, - - trigger: function( event, data, elem, onlyHandlers ) { - // Don't do events on text and comment nodes - if ( elem && (elem.nodeType === 3 || elem.nodeType === 8) ) { - return; - } - - // Event object or event type - var cache, exclusive, i, cur, old, ontype, special, handle, eventPath, bubbleType, - type = event.type || event, - namespaces = []; - - // focus/blur morphs to focusin/out; ensure we're not firing them right now - if ( rfocusMorph.test( type + jQuery.event.triggered ) ) { - return; - } - - if ( type.indexOf( "!" ) >= 0 ) { - // Exclusive events trigger only for the exact event (no namespaces) - type = type.slice(0, -1); - exclusive = true; - } - - if ( type.indexOf( "." ) >= 0 ) { - // Namespaced trigger; create a regexp to match event type in handle() - namespaces = type.split("."); - type = namespaces.shift(); - namespaces.sort(); - } - - if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) { - // No jQuery handlers for this event type, and it can't have inline handlers - return; - } - - // Caller can pass in an Event, Object, or just an event type string - event = typeof event === "object" ? - // jQuery.Event object - event[ jQuery.expando ] ? event : - // Object literal - new jQuery.Event( type, event ) : - // Just the event type (string) - new jQuery.Event( type ); - - event.type = type; - event.isTrigger = true; - event.exclusive = exclusive; - event.namespace = namespaces.join( "." ); - event.namespace_re = event.namespace? new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.|)") + "(\\.|$)") : null; - ontype = type.indexOf( ":" ) < 0 ? "on" + type : ""; - - // Handle a global trigger - if ( !elem ) { - - // TODO: Stop taunting the data cache; remove global events and always attach to document - cache = jQuery.cache; - for ( i in cache ) { - if ( cache[ i ].events && cache[ i ].events[ type ] ) { - jQuery.event.trigger( event, data, cache[ i ].handle.elem, true ); - } - } - return; - } - - // Clean up the event in case it is being reused - event.result = undefined; - if ( !event.target ) { - event.target = elem; - } - - // Clone any incoming data and prepend the event, creating the handler arg list - data = data != null ? jQuery.makeArray( data ) : []; - data.unshift( event ); - - // Allow special events to draw outside the lines - special = jQuery.event.special[ type ] || {}; - if ( special.trigger && special.trigger.apply( elem, data ) === false ) { - return; - } - - // Determine event propagation path in advance, per W3C events spec (#9951) - // Bubble up to document, then to window; watch for a global ownerDocument var (#9724) - eventPath = [[ elem, special.bindType || type ]]; - if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) { - - bubbleType = special.delegateType || type; - cur = rfocusMorph.test( bubbleType + type ) ? elem : elem.parentNode; - for ( old = elem; cur; cur = cur.parentNode ) { - eventPath.push([ cur, bubbleType ]); - old = cur; - } - - // Only add window if we got to document (e.g., not plain obj or detached DOM) - if ( old === (elem.ownerDocument || document) ) { - eventPath.push([ old.defaultView || old.parentWindow || window, bubbleType ]); - } - } - - // Fire handlers on the event path - for ( i = 0; i < eventPath.length && !event.isPropagationStopped(); i++ ) { - - cur = eventPath[i][0]; - event.type = eventPath[i][1]; - - handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" ); - if ( handle ) { - handle.apply( cur, data ); - } - // Note that this is a bare JS function and not a jQuery handler - handle = ontype && cur[ ontype ]; - if ( handle && jQuery.acceptData( cur ) && handle.apply && handle.apply( cur, data ) === false ) { - event.preventDefault(); - } - } - event.type = type; - - // If nobody prevented the default action, do it now - if ( !onlyHandlers && !event.isDefaultPrevented() ) { - - if ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) && - !(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) { - - // Call a native DOM method on the target with the same name name as the event. - // Can't use an .isFunction() check here because IE6/7 fails that test. - // Don't do default actions on window, that's where global variables be (#6170) - // IE<9 dies on focus/blur to hidden element (#1486) - if ( ontype && elem[ type ] && ((type !== "focus" && type !== "blur") || event.target.offsetWidth !== 0) && !jQuery.isWindow( elem ) ) { - - // Don't re-trigger an onFOO event when we call its FOO() method - old = elem[ ontype ]; - - if ( old ) { - elem[ ontype ] = null; - } - - // Prevent re-triggering of the same event, since we already bubbled it above - jQuery.event.triggered = type; - elem[ type ](); - jQuery.event.triggered = undefined; - - if ( old ) { - elem[ ontype ] = old; - } - } - } - } - - return event.result; - }, - - dispatch: function( event ) { - - // Make a writable jQuery.Event from the native event object - event = jQuery.event.fix( event || window.event ); - - var i, j, cur, ret, selMatch, matched, matches, handleObj, sel, related, - handlers = ( (jQuery._data( this, "events" ) || {} )[ event.type ] || []), - delegateCount = handlers.delegateCount, - args = core_slice.call( arguments ), - run_all = !event.exclusive && !event.namespace, - special = jQuery.event.special[ event.type ] || {}, - handlerQueue = []; - - // Use the fix-ed jQuery.Event rather than the (read-only) native event - args[0] = event; - event.delegateTarget = this; - - // Call the preDispatch hook for the mapped type, and let it bail if desired - if ( special.preDispatch && special.preDispatch.call( this, event ) === false ) { - return; - } - - // Determine handlers that should run if there are delegated events - // Avoid non-left-click bubbling in Firefox (#3861) - if ( delegateCount && !(event.button && event.type === "click") ) { - - for ( cur = event.target; cur != this; cur = cur.parentNode || this ) { - - // Don't process clicks (ONLY) on disabled elements (#6911, #8165, #11382, #11764) - if ( cur.disabled !== true || event.type !== "click" ) { - selMatch = {}; - matches = []; - for ( i = 0; i < delegateCount; i++ ) { - handleObj = handlers[ i ]; - sel = handleObj.selector; - - if ( selMatch[ sel ] === undefined ) { - selMatch[ sel ] = handleObj.needsContext ? - jQuery( sel, this ).index( cur ) >= 0 : - jQuery.find( sel, this, null, [ cur ] ).length; - } - if ( selMatch[ sel ] ) { - matches.push( handleObj ); - } - } - if ( matches.length ) { - handlerQueue.push({ elem: cur, matches: matches }); - } - } - } - } - - // Add the remaining (directly-bound) handlers - if ( handlers.length > delegateCount ) { - handlerQueue.push({ elem: this, matches: handlers.slice( delegateCount ) }); - } - - // Run delegates first; they may want to stop propagation beneath us - for ( i = 0; i < handlerQueue.length && !event.isPropagationStopped(); i++ ) { - matched = handlerQueue[ i ]; - event.currentTarget = matched.elem; - - for ( j = 0; j < matched.matches.length && !event.isImmediatePropagationStopped(); j++ ) { - handleObj = matched.matches[ j ]; - - // Triggered event must either 1) be non-exclusive and have no namespace, or - // 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace). - if ( run_all || (!event.namespace && !handleObj.namespace) || event.namespace_re && event.namespace_re.test( handleObj.namespace ) ) { - - event.data = handleObj.data; - event.handleObj = handleObj; - - ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler ) - .apply( matched.elem, args ); - - if ( ret !== undefined ) { - event.result = ret; - if ( ret === false ) { - event.preventDefault(); - event.stopPropagation(); - } - } - } - } - } - - // Call the postDispatch hook for the mapped type - if ( special.postDispatch ) { - special.postDispatch.call( this, event ); - } - - return event.result; - }, - - // Includes some event props shared by KeyEvent and MouseEvent - // *** attrChange attrName relatedNode srcElement are not normalized, non-W3C, deprecated, will be removed in 1.8 *** - props: "attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "), - - fixHooks: {}, - - keyHooks: { - props: "char charCode key keyCode".split(" "), - filter: function( event, original ) { - - // Add which for key events - if ( event.which == null ) { - event.which = original.charCode != null ? original.charCode : original.keyCode; - } - - return event; - } - }, - - mouseHooks: { - props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "), - filter: function( event, original ) { - var eventDoc, doc, body, - button = original.button, - fromElement = original.fromElement; - - // Calculate pageX/Y if missing and clientX/Y available - if ( event.pageX == null && original.clientX != null ) { - eventDoc = event.target.ownerDocument || document; - doc = eventDoc.documentElement; - body = eventDoc.body; - - event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 ); - event.pageY = original.clientY + ( doc && doc.scrollTop || body && body.scrollTop || 0 ) - ( doc && doc.clientTop || body && body.clientTop || 0 ); - } - - // Add relatedTarget, if necessary - if ( !event.relatedTarget && fromElement ) { - event.relatedTarget = fromElement === event.target ? original.toElement : fromElement; - } - - // Add which for click: 1 === left; 2 === middle; 3 === right - // Note: button is not normalized, so don't use it - if ( !event.which && button !== undefined ) { - event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) ); - } - - return event; - } - }, - - fix: function( event ) { - if ( event[ jQuery.expando ] ) { - return event; - } - - // Create a writable copy of the event object and normalize some properties - var i, prop, - originalEvent = event, - fixHook = jQuery.event.fixHooks[ event.type ] || {}, - copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props; - - event = jQuery.Event( originalEvent ); - - for ( i = copy.length; i; ) { - prop = copy[ --i ]; - event[ prop ] = originalEvent[ prop ]; - } - - // Fix target property, if necessary (#1925, IE 6/7/8 & Safari2) - if ( !event.target ) { - event.target = originalEvent.srcElement || document; - } - - // Target should not be a text node (#504, Safari) - if ( event.target.nodeType === 3 ) { - event.target = event.target.parentNode; - } - - // For mouse/key events, metaKey==false if it's undefined (#3368, #11328; IE6/7/8) - event.metaKey = !!event.metaKey; - - return fixHook.filter? fixHook.filter( event, originalEvent ) : event; - }, - - special: { - load: { - // Prevent triggered image.load events from bubbling to window.load - noBubble: true - }, - - focus: { - delegateType: "focusin" - }, - blur: { - delegateType: "focusout" - }, - - beforeunload: { - setup: function( data, namespaces, eventHandle ) { - // We only want to do this special case on windows - if ( jQuery.isWindow( this ) ) { - this.onbeforeunload = eventHandle; - } - }, - - teardown: function( namespaces, eventHandle ) { - if ( this.onbeforeunload === eventHandle ) { - this.onbeforeunload = null; - } - } - } - }, - - simulate: function( type, elem, event, bubble ) { - // Piggyback on a donor event to simulate a different one. - // Fake originalEvent to avoid donor's stopPropagation, but if the - // simulated event prevents default then we do the same on the donor. - var e = jQuery.extend( - new jQuery.Event(), - event, - { type: type, - isSimulated: true, - originalEvent: {} - } - ); - if ( bubble ) { - jQuery.event.trigger( e, null, elem ); - } else { - jQuery.event.dispatch.call( elem, e ); - } - if ( e.isDefaultPrevented() ) { - event.preventDefault(); - } - } -}; - -// Some plugins are using, but it's undocumented/deprecated and will be removed. -// The 1.7 special event interface should provide all the hooks needed now. -jQuery.event.handle = jQuery.event.dispatch; - -jQuery.removeEvent = document.removeEventListener ? - function( elem, type, handle ) { - if ( elem.removeEventListener ) { - elem.removeEventListener( type, handle, false ); - } - } : - function( elem, type, handle ) { - var name = "on" + type; - - if ( elem.detachEvent ) { - - // #8545, #7054, preventing memory leaks for custom events in IE6-8 – - // detachEvent needed property on element, by name of that event, to properly expose it to GC - if ( typeof elem[ name ] === "undefined" ) { - elem[ name ] = null; - } - - elem.detachEvent( name, handle ); - } - }; - -jQuery.Event = function( src, props ) { - // Allow instantiation without the 'new' keyword - if ( !(this instanceof jQuery.Event) ) { - return new jQuery.Event( src, props ); - } - - // Event object - if ( src && src.type ) { - this.originalEvent = src; - this.type = src.type; - - // Events bubbling up the document may have been marked as prevented - // by a handler lower down the tree; reflect the correct value. - this.isDefaultPrevented = ( src.defaultPrevented || src.returnValue === false || - src.getPreventDefault && src.getPreventDefault() ) ? returnTrue : returnFalse; - - // Event type - } else { - this.type = src; - } - - // Put explicitly provided properties onto the event object - if ( props ) { - jQuery.extend( this, props ); - } - - // Create a timestamp if incoming event doesn't have one - this.timeStamp = src && src.timeStamp || jQuery.now(); - - // Mark it as fixed - this[ jQuery.expando ] = true; -}; - -function returnFalse() { - return false; -} -function returnTrue() { - return true; -} - -// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding -// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html -jQuery.Event.prototype = { - preventDefault: function() { - this.isDefaultPrevented = returnTrue; - - var e = this.originalEvent; - if ( !e ) { - return; - } - - // if preventDefault exists run it on the original event - if ( e.preventDefault ) { - e.preventDefault(); - - // otherwise set the returnValue property of the original event to false (IE) - } else { - e.returnValue = false; - } - }, - stopPropagation: function() { - this.isPropagationStopped = returnTrue; - - var e = this.originalEvent; - if ( !e ) { - return; - } - // if stopPropagation exists run it on the original event - if ( e.stopPropagation ) { - e.stopPropagation(); - } - // otherwise set the cancelBubble property of the original event to true (IE) - e.cancelBubble = true; - }, - stopImmediatePropagation: function() { - this.isImmediatePropagationStopped = returnTrue; - this.stopPropagation(); - }, - isDefaultPrevented: returnFalse, - isPropagationStopped: returnFalse, - isImmediatePropagationStopped: returnFalse -}; - -// Create mouseenter/leave events using mouseover/out and event-time checks -jQuery.each({ - mouseenter: "mouseover", - mouseleave: "mouseout" -}, function( orig, fix ) { - jQuery.event.special[ orig ] = { - delegateType: fix, - bindType: fix, - - handle: function( event ) { - var ret, - target = this, - related = event.relatedTarget, - handleObj = event.handleObj, - selector = handleObj.selector; - - // For mousenter/leave call the handler if related is outside the target. - // NB: No relatedTarget if the mouse left/entered the browser window - if ( !related || (related !== target && !jQuery.contains( target, related )) ) { - event.type = handleObj.origType; - ret = handleObj.handler.apply( this, arguments ); - event.type = fix; - } - return ret; - } - }; -}); - -// IE submit delegation -if ( !jQuery.support.submitBubbles ) { - - jQuery.event.special.submit = { - setup: function() { - // Only need this for delegated form submit events - if ( jQuery.nodeName( this, "form" ) ) { - return false; - } - - // Lazy-add a submit handler when a descendant form may potentially be submitted - jQuery.event.add( this, "click._submit keypress._submit", function( e ) { - // Node name check avoids a VML-related crash in IE (#9807) - var elem = e.target, - form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined; - if ( form && !jQuery._data( form, "_submit_attached" ) ) { - jQuery.event.add( form, "submit._submit", function( event ) { - event._submit_bubble = true; - }); - jQuery._data( form, "_submit_attached", true ); - } - }); - // return undefined since we don't need an event listener - }, - - postDispatch: function( event ) { - // If form was submitted by the user, bubble the event up the tree - if ( event._submit_bubble ) { - delete event._submit_bubble; - if ( this.parentNode && !event.isTrigger ) { - jQuery.event.simulate( "submit", this.parentNode, event, true ); - } - } - }, - - teardown: function() { - // Only need this for delegated form submit events - if ( jQuery.nodeName( this, "form" ) ) { - return false; - } - - // Remove delegated handlers; cleanData eventually reaps submit handlers attached above - jQuery.event.remove( this, "._submit" ); - } - }; -} - -// IE change delegation and checkbox/radio fix -if ( !jQuery.support.changeBubbles ) { - - jQuery.event.special.change = { - - setup: function() { - - if ( rformElems.test( this.nodeName ) ) { - // IE doesn't fire change on a check/radio until blur; trigger it on click - // after a propertychange. Eat the blur-change in special.change.handle. - // This still fires onchange a second time for check/radio after blur. - if ( this.type === "checkbox" || this.type === "radio" ) { - jQuery.event.add( this, "propertychange._change", function( event ) { - if ( event.originalEvent.propertyName === "checked" ) { - this._just_changed = true; - } - }); - jQuery.event.add( this, "click._change", function( event ) { - if ( this._just_changed && !event.isTrigger ) { - this._just_changed = false; - } - // Allow triggered, simulated change events (#11500) - jQuery.event.simulate( "change", this, event, true ); - }); - } - return false; - } - // Delegated event; lazy-add a change handler on descendant inputs - jQuery.event.add( this, "beforeactivate._change", function( e ) { - var elem = e.target; - - if ( rformElems.test( elem.nodeName ) && !jQuery._data( elem, "_change_attached" ) ) { - jQuery.event.add( elem, "change._change", function( event ) { - if ( this.parentNode && !event.isSimulated && !event.isTrigger ) { - jQuery.event.simulate( "change", this.parentNode, event, true ); - } - }); - jQuery._data( elem, "_change_attached", true ); - } - }); - }, - - handle: function( event ) { - var elem = event.target; - - // Swallow native change events from checkbox/radio, we already triggered them above - if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) { - return event.handleObj.handler.apply( this, arguments ); - } - }, - - teardown: function() { - jQuery.event.remove( this, "._change" ); - - return !rformElems.test( this.nodeName ); - } - }; -} - -// Create "bubbling" focus and blur events -if ( !jQuery.support.focusinBubbles ) { - jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) { - - // Attach a single capturing handler while someone wants focusin/focusout - var attaches = 0, - handler = function( event ) { - jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true ); - }; - - jQuery.event.special[ fix ] = { - setup: function() { - if ( attaches++ === 0 ) { - document.addEventListener( orig, handler, true ); - } - }, - teardown: function() { - if ( --attaches === 0 ) { - document.removeEventListener( orig, handler, true ); - } - } - }; - }); -} - -jQuery.fn.extend({ - - on: function( types, selector, data, fn, /*INTERNAL*/ one ) { - var origFn, type; - - // Types can be a map of types/handlers - if ( typeof types === "object" ) { - // ( types-Object, selector, data ) - if ( typeof selector !== "string" ) { // && selector != null - // ( types-Object, data ) - data = data || selector; - selector = undefined; - } - for ( type in types ) { - this.on( type, selector, data, types[ type ], one ); - } - return this; - } - - if ( data == null && fn == null ) { - // ( types, fn ) - fn = selector; - data = selector = undefined; - } else if ( fn == null ) { - if ( typeof selector === "string" ) { - // ( types, selector, fn ) - fn = data; - data = undefined; - } else { - // ( types, data, fn ) - fn = data; - data = selector; - selector = undefined; - } - } - if ( fn === false ) { - fn = returnFalse; - } else if ( !fn ) { - return this; - } - - if ( one === 1 ) { - origFn = fn; - fn = function( event ) { - // Can use an empty set, since event contains the info - jQuery().off( event ); - return origFn.apply( this, arguments ); - }; - // Use same guid so caller can remove using origFn - fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ ); - } - return this.each( function() { - jQuery.event.add( this, types, fn, data, selector ); - }); - }, - one: function( types, selector, data, fn ) { - return this.on( types, selector, data, fn, 1 ); - }, - off: function( types, selector, fn ) { - var handleObj, type; - if ( types && types.preventDefault && types.handleObj ) { - // ( event ) dispatched jQuery.Event - handleObj = types.handleObj; - jQuery( types.delegateTarget ).off( - handleObj.namespace ? handleObj.origType + "." + handleObj.namespace : handleObj.origType, - handleObj.selector, - handleObj.handler - ); - return this; - } - if ( typeof types === "object" ) { - // ( types-object [, selector] ) - for ( type in types ) { - this.off( type, selector, types[ type ] ); - } - return this; - } - if ( selector === false || typeof selector === "function" ) { - // ( types [, fn] ) - fn = selector; - selector = undefined; - } - if ( fn === false ) { - fn = returnFalse; - } - return this.each(function() { - jQuery.event.remove( this, types, fn, selector ); - }); - }, - - bind: function( types, data, fn ) { - return this.on( types, null, data, fn ); - }, - unbind: function( types, fn ) { - return this.off( types, null, fn ); - }, - - live: function( types, data, fn ) { - jQuery( this.context ).on( types, this.selector, data, fn ); - return this; - }, - die: function( types, fn ) { - jQuery( this.context ).off( types, this.selector || "**", fn ); - return this; - }, - - delegate: function( selector, types, data, fn ) { - return this.on( types, selector, data, fn ); - }, - undelegate: function( selector, types, fn ) { - // ( namespace ) or ( selector, types [, fn] ) - return arguments.length === 1 ? this.off( selector, "**" ) : this.off( types, selector || "**", fn ); - }, - - trigger: function( type, data ) { - return this.each(function() { - jQuery.event.trigger( type, data, this ); - }); - }, - triggerHandler: function( type, data ) { - if ( this[0] ) { - return jQuery.event.trigger( type, data, this[0], true ); - } - }, - - toggle: function( fn ) { - // Save reference to arguments for access in closure - var args = arguments, - guid = fn.guid || jQuery.guid++, - i = 0, - toggler = function( event ) { - // Figure out which function to execute - var lastToggle = ( jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i; - jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 ); - - // Make sure that clicks stop - event.preventDefault(); - - // and execute the function - return args[ lastToggle ].apply( this, arguments ) || false; - }; - - // link all the functions, so any of them can unbind this click handler - toggler.guid = guid; - while ( i < args.length ) { - args[ i++ ].guid = guid; - } - - return this.click( toggler ); - }, - - hover: function( fnOver, fnOut ) { - return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver ); - } -}); - -jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " + - "mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " + - "change select submit keydown keypress keyup error contextmenu").split(" "), function( i, name ) { - - // Handle event binding - jQuery.fn[ name ] = function( data, fn ) { - if ( fn == null ) { - fn = data; - data = null; - } - - return arguments.length > 0 ? - this.on( name, null, data, fn ) : - this.trigger( name ); - }; - - if ( rkeyEvent.test( name ) ) { - jQuery.event.fixHooks[ name ] = jQuery.event.keyHooks; - } - - if ( rmouseEvent.test( name ) ) { - jQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks; - } -}); -/*! - * Sizzle CSS Selector Engine - * Copyright 2012 jQuery Foundation and other contributors - * Released under the MIT license - * http://sizzlejs.com/ - */ -(function( window, undefined ) { - -var cachedruns, - assertGetIdNotName, - Expr, - getText, - isXML, - contains, - compile, - sortOrder, - hasDuplicate, - outermostContext, - - baseHasDuplicate = true, - strundefined = "undefined", - - expando = ( "sizcache" + Math.random() ).replace( ".", "" ), - - Token = String, - document = window.document, - docElem = document.documentElement, - dirruns = 0, - done = 0, - pop = [].pop, - push = [].push, - slice = [].slice, - // Use a stripped-down indexOf if a native one is unavailable - indexOf = [].indexOf || function( elem ) { - var i = 0, - len = this.length; - for ( ; i < len; i++ ) { - if ( this[i] === elem ) { - return i; - } - } - return -1; - }, - - // Augment a function for special use by Sizzle - markFunction = function( fn, value ) { - fn[ expando ] = value == null || value; - return fn; - }, - - createCache = function() { - var cache = {}, - keys = []; - - return markFunction(function( key, value ) { - // Only keep the most recent entries - if ( keys.push( key ) > Expr.cacheLength ) { - delete cache[ keys.shift() ]; - } - - return (cache[ key ] = value); - }, cache ); - }, - - classCache = createCache(), - tokenCache = createCache(), - compilerCache = createCache(), - - // Regex - - // Whitespace characters http://www.w3.org/TR/css3-selectors/#whitespace - whitespace = "[\\x20\\t\\r\\n\\f]", - // http://www.w3.org/TR/css3-syntax/#characters - characterEncoding = "(?:\\\\.|[-\\w]|[^\\x00-\\xa0])+", - - // Loosely modeled on CSS identifier characters - // An unquoted value should be a CSS identifier (http://www.w3.org/TR/css3-selectors/#attribute-selectors) - // Proper syntax: http://www.w3.org/TR/CSS21/syndata.html#value-def-identifier - identifier = characterEncoding.replace( "w", "w#" ), - - // Acceptable operators http://www.w3.org/TR/selectors/#attribute-selectors - operators = "([*^$|!~]?=)", - attributes = "\\[" + whitespace + "*(" + characterEncoding + ")" + whitespace + - "*(?:" + operators + whitespace + "*(?:(['\"])((?:\\\\.|[^\\\\])*?)\\3|(" + identifier + ")|)|)" + whitespace + "*\\]", - - // Prefer arguments not in parens/brackets, - // then attribute selectors and non-pseudos (denoted by :), - // then anything else - // These preferences are here to reduce the number of selectors - // needing tokenize in the PSEUDO preFilter - pseudos = ":(" + characterEncoding + ")(?:\\((?:(['\"])((?:\\\\.|[^\\\\])*?)\\2|([^()[\\]]*|(?:(?:" + attributes + ")|[^:]|\\\\.)*|.*))\\)|)", - - // For matchExpr.POS and matchExpr.needsContext - pos = ":(even|odd|eq|gt|lt|nth|first|last)(?:\\(" + whitespace + - "*((?:-\\d)?\\d*)" + whitespace + "*\\)|)(?=[^-]|$)", - - // Leading and non-escaped trailing whitespace, capturing some non-whitespace characters preceding the latter - rtrim = new RegExp( "^" + whitespace + "+|((?:^|[^\\\\])(?:\\\\.)*)" + whitespace + "+$", "g" ), - - rcomma = new RegExp( "^" + whitespace + "*," + whitespace + "*" ), - rcombinators = new RegExp( "^" + whitespace + "*([\\x20\\t\\r\\n\\f>+~])" + whitespace + "*" ), - rpseudo = new RegExp( pseudos ), - - // Easily-parseable/retrievable ID or TAG or CLASS selectors - rquickExpr = /^(?:#([\w\-]+)|(\w+)|\.([\w\-]+))$/, - - rnot = /^:not/, - rsibling = /[\x20\t\r\n\f]*[+~]/, - rendsWithNot = /:not\($/, - - rheader = /h\d/i, - rinputs = /input|select|textarea|button/i, - - rbackslash = /\\(?!\\)/g, - - matchExpr = { - "ID": new RegExp( "^#(" + characterEncoding + ")" ), - "CLASS": new RegExp( "^\\.(" + characterEncoding + ")" ), - "NAME": new RegExp( "^\\[name=['\"]?(" + characterEncoding + ")['\"]?\\]" ), - "TAG": new RegExp( "^(" + characterEncoding.replace( "w", "w*" ) + ")" ), - "ATTR": new RegExp( "^" + attributes ), - "PSEUDO": new RegExp( "^" + pseudos ), - "POS": new RegExp( pos, "i" ), - "CHILD": new RegExp( "^:(only|nth|first|last)-child(?:\\(" + whitespace + - "*(even|odd|(([+-]|)(\\d*)n|)" + whitespace + "*(?:([+-]|)" + whitespace + - "*(\\d+)|))" + whitespace + "*\\)|)", "i" ), - // For use in libraries implementing .is() - "needsContext": new RegExp( "^" + whitespace + "*[>+~]|" + pos, "i" ) - }, - - // Support - - // Used for testing something on an element - assert = function( fn ) { - var div = document.createElement("div"); - - try { - return fn( div ); - } catch (e) { - return false; - } finally { - // release memory in IE - div = null; - } - }, - - // Check if getElementsByTagName("*") returns only elements - assertTagNameNoComments = assert(function( div ) { - div.appendChild( document.createComment("") ); - return !div.getElementsByTagName("*").length; - }), - - // Check if getAttribute returns normalized href attributes - assertHrefNotNormalized = assert(function( div ) { - div.innerHTML = ""; - return div.firstChild && typeof div.firstChild.getAttribute !== strundefined && - div.firstChild.getAttribute("href") === "#"; - }), - - // Check if attributes should be retrieved by attribute nodes - assertAttributes = assert(function( div ) { - div.innerHTML = ""; - var type = typeof div.lastChild.getAttribute("multiple"); - // IE8 returns a string for some attributes even when not present - return type !== "boolean" && type !== "string"; - }), - - // Check if getElementsByClassName can be trusted - assertUsableClassName = assert(function( div ) { - // Opera can't find a second classname (in 9.6) - div.innerHTML = ""; - if ( !div.getElementsByClassName || !div.getElementsByClassName("e").length ) { - return false; - } - - // Safari 3.2 caches class attributes and doesn't catch changes - div.lastChild.className = "e"; - return div.getElementsByClassName("e").length === 2; - }), - - // Check if getElementById returns elements by name - // Check if getElementsByName privileges form controls or returns elements by ID - assertUsableName = assert(function( div ) { - // Inject content - div.id = expando + 0; - div.innerHTML = "
                "; - docElem.insertBefore( div, docElem.firstChild ); - - // Test - var pass = document.getElementsByName && - // buggy browsers will return fewer than the correct 2 - document.getElementsByName( expando ).length === 2 + - // buggy browsers will return more than the correct 0 - document.getElementsByName( expando + 0 ).length; - assertGetIdNotName = !document.getElementById( expando ); - - // Cleanup - docElem.removeChild( div ); - - return pass; - }); - -// If slice is not available, provide a backup -try { - slice.call( docElem.childNodes, 0 )[0].nodeType; -} catch ( e ) { - slice = function( i ) { - var elem, - results = []; - for ( ; (elem = this[i]); i++ ) { - results.push( elem ); - } - return results; - }; -} - -function Sizzle( selector, context, results, seed ) { - results = results || []; - context = context || document; - var match, elem, xml, m, - nodeType = context.nodeType; - - if ( !selector || typeof selector !== "string" ) { - return results; - } - - if ( nodeType !== 1 && nodeType !== 9 ) { - return []; - } - - xml = isXML( context ); - - if ( !xml && !seed ) { - if ( (match = rquickExpr.exec( selector )) ) { - // Speed-up: Sizzle("#ID") - if ( (m = match[1]) ) { - if ( nodeType === 9 ) { - elem = context.getElementById( m ); - // Check parentNode to catch when Blackberry 4.6 returns - // nodes that are no longer in the document #6963 - if ( elem && elem.parentNode ) { - // Handle the case where IE, Opera, and Webkit return items - // by name instead of ID - if ( elem.id === m ) { - results.push( elem ); - return results; - } - } else { - return results; - } - } else { - // Context is not a document - if ( context.ownerDocument && (elem = context.ownerDocument.getElementById( m )) && - contains( context, elem ) && elem.id === m ) { - results.push( elem ); - return results; - } - } - - // Speed-up: Sizzle("TAG") - } else if ( match[2] ) { - push.apply( results, slice.call(context.getElementsByTagName( selector ), 0) ); - return results; - - // Speed-up: Sizzle(".CLASS") - } else if ( (m = match[3]) && assertUsableClassName && context.getElementsByClassName ) { - push.apply( results, slice.call(context.getElementsByClassName( m ), 0) ); - return results; - } - } - } - - // All others - return select( selector.replace( rtrim, "$1" ), context, results, seed, xml ); -} - -Sizzle.matches = function( expr, elements ) { - return Sizzle( expr, null, null, elements ); -}; - -Sizzle.matchesSelector = function( elem, expr ) { - return Sizzle( expr, null, null, [ elem ] ).length > 0; -}; - -// Returns a function to use in pseudos for input types -function createInputPseudo( type ) { - return function( elem ) { - var name = elem.nodeName.toLowerCase(); - return name === "input" && elem.type === type; - }; -} - -// Returns a function to use in pseudos for buttons -function createButtonPseudo( type ) { - return function( elem ) { - var name = elem.nodeName.toLowerCase(); - return (name === "input" || name === "button") && elem.type === type; - }; -} - -// Returns a function to use in pseudos for positionals -function createPositionalPseudo( fn ) { - return markFunction(function( argument ) { - argument = +argument; - return markFunction(function( seed, matches ) { - var j, - matchIndexes = fn( [], seed.length, argument ), - i = matchIndexes.length; - - // Match elements found at the specified indexes - while ( i-- ) { - if ( seed[ (j = matchIndexes[i]) ] ) { - seed[j] = !(matches[j] = seed[j]); - } - } - }); - }); -} - -/** - * Utility function for retrieving the text value of an array of DOM nodes - * @param {Array|Element} elem - */ -getText = Sizzle.getText = function( elem ) { - var node, - ret = "", - i = 0, - nodeType = elem.nodeType; - - if ( nodeType ) { - if ( nodeType === 1 || nodeType === 9 || nodeType === 11 ) { - // Use textContent for elements - // innerText usage removed for consistency of new lines (see #11153) - if ( typeof elem.textContent === "string" ) { - return elem.textContent; - } else { - // Traverse its children - for ( elem = elem.firstChild; elem; elem = elem.nextSibling ) { - ret += getText( elem ); - } - } - } else if ( nodeType === 3 || nodeType === 4 ) { - return elem.nodeValue; - } - // Do not include comment or processing instruction nodes - } else { - - // If no nodeType, this is expected to be an array - for ( ; (node = elem[i]); i++ ) { - // Do not traverse comment nodes - ret += getText( node ); - } - } - return ret; -}; - -isXML = Sizzle.isXML = function( elem ) { - // documentElement is verified for cases where it doesn't yet exist - // (such as loading iframes in IE - #4833) - var documentElement = elem && (elem.ownerDocument || elem).documentElement; - return documentElement ? documentElement.nodeName !== "HTML" : false; -}; - -// Element contains another -contains = Sizzle.contains = docElem.contains ? - function( a, b ) { - var adown = a.nodeType === 9 ? a.documentElement : a, - bup = b && b.parentNode; - return a === bup || !!( bup && bup.nodeType === 1 && adown.contains && adown.contains(bup) ); - } : - docElem.compareDocumentPosition ? - function( a, b ) { - return b && !!( a.compareDocumentPosition( b ) & 16 ); - } : - function( a, b ) { - while ( (b = b.parentNode) ) { - if ( b === a ) { - return true; - } - } - return false; - }; - -Sizzle.attr = function( elem, name ) { - var val, - xml = isXML( elem ); - - if ( !xml ) { - name = name.toLowerCase(); - } - if ( (val = Expr.attrHandle[ name ]) ) { - return val( elem ); - } - if ( xml || assertAttributes ) { - return elem.getAttribute( name ); - } - val = elem.getAttributeNode( name ); - return val ? - typeof elem[ name ] === "boolean" ? - elem[ name ] ? name : null : - val.specified ? val.value : null : - null; -}; - -Expr = Sizzle.selectors = { - - // Can be adjusted by the user - cacheLength: 50, - - createPseudo: markFunction, - - match: matchExpr, - - // IE6/7 return a modified href - attrHandle: assertHrefNotNormalized ? - {} : - { - "href": function( elem ) { - return elem.getAttribute( "href", 2 ); - }, - "type": function( elem ) { - return elem.getAttribute("type"); - } - }, - - find: { - "ID": assertGetIdNotName ? - function( id, context, xml ) { - if ( typeof context.getElementById !== strundefined && !xml ) { - var m = context.getElementById( id ); - // Check parentNode to catch when Blackberry 4.6 returns - // nodes that are no longer in the document #6963 - return m && m.parentNode ? [m] : []; - } - } : - function( id, context, xml ) { - if ( typeof context.getElementById !== strundefined && !xml ) { - var m = context.getElementById( id ); - - return m ? - m.id === id || typeof m.getAttributeNode !== strundefined && m.getAttributeNode("id").value === id ? - [m] : - undefined : - []; - } - }, - - "TAG": assertTagNameNoComments ? - function( tag, context ) { - if ( typeof context.getElementsByTagName !== strundefined ) { - return context.getElementsByTagName( tag ); - } - } : - function( tag, context ) { - var results = context.getElementsByTagName( tag ); - - // Filter out possible comments - if ( tag === "*" ) { - var elem, - tmp = [], - i = 0; - - for ( ; (elem = results[i]); i++ ) { - if ( elem.nodeType === 1 ) { - tmp.push( elem ); - } - } - - return tmp; - } - return results; - }, - - "NAME": assertUsableName && function( tag, context ) { - if ( typeof context.getElementsByName !== strundefined ) { - return context.getElementsByName( name ); - } - }, - - "CLASS": assertUsableClassName && function( className, context, xml ) { - if ( typeof context.getElementsByClassName !== strundefined && !xml ) { - return context.getElementsByClassName( className ); - } - } - }, - - relative: { - ">": { dir: "parentNode", first: true }, - " ": { dir: "parentNode" }, - "+": { dir: "previousSibling", first: true }, - "~": { dir: "previousSibling" } - }, - - preFilter: { - "ATTR": function( match ) { - match[1] = match[1].replace( rbackslash, "" ); - - // Move the given value to match[3] whether quoted or unquoted - match[3] = ( match[4] || match[5] || "" ).replace( rbackslash, "" ); - - if ( match[2] === "~=" ) { - match[3] = " " + match[3] + " "; - } - - return match.slice( 0, 4 ); - }, - - "CHILD": function( match ) { - /* matches from matchExpr["CHILD"] - 1 type (only|nth|...) - 2 argument (even|odd|\d*|\d*n([+-]\d+)?|...) - 3 xn-component of xn+y argument ([+-]?\d*n|) - 4 sign of xn-component - 5 x of xn-component - 6 sign of y-component - 7 y of y-component - */ - match[1] = match[1].toLowerCase(); - - if ( match[1] === "nth" ) { - // nth-child requires argument - if ( !match[2] ) { - Sizzle.error( match[0] ); - } - - // numeric x and y parameters for Expr.filter.CHILD - // remember that false/true cast respectively to 0/1 - match[3] = +( match[3] ? match[4] + (match[5] || 1) : 2 * ( match[2] === "even" || match[2] === "odd" ) ); - match[4] = +( ( match[6] + match[7] ) || match[2] === "odd" ); - - // other types prohibit arguments - } else if ( match[2] ) { - Sizzle.error( match[0] ); - } - - return match; - }, - - "PSEUDO": function( match ) { - var unquoted, excess; - if ( matchExpr["CHILD"].test( match[0] ) ) { - return null; - } - - if ( match[3] ) { - match[2] = match[3]; - } else if ( (unquoted = match[4]) ) { - // Only check arguments that contain a pseudo - if ( rpseudo.test(unquoted) && - // Get excess from tokenize (recursively) - (excess = tokenize( unquoted, true )) && - // advance to the next closing parenthesis - (excess = unquoted.indexOf( ")", unquoted.length - excess ) - unquoted.length) ) { - - // excess is a negative index - unquoted = unquoted.slice( 0, excess ); - match[0] = match[0].slice( 0, excess ); - } - match[2] = unquoted; - } - - // Return only captures needed by the pseudo filter method (type and argument) - return match.slice( 0, 3 ); - } - }, - - filter: { - "ID": assertGetIdNotName ? - function( id ) { - id = id.replace( rbackslash, "" ); - return function( elem ) { - return elem.getAttribute("id") === id; - }; - } : - function( id ) { - id = id.replace( rbackslash, "" ); - return function( elem ) { - var node = typeof elem.getAttributeNode !== strundefined && elem.getAttributeNode("id"); - return node && node.value === id; - }; - }, - - "TAG": function( nodeName ) { - if ( nodeName === "*" ) { - return function() { return true; }; - } - nodeName = nodeName.replace( rbackslash, "" ).toLowerCase(); - - return function( elem ) { - return elem.nodeName && elem.nodeName.toLowerCase() === nodeName; - }; - }, - - "CLASS": function( className ) { - var pattern = classCache[ expando ][ className ]; - if ( !pattern ) { - pattern = classCache( className, new RegExp("(^|" + whitespace + ")" + className + "(" + whitespace + "|$)") ); - } - return function( elem ) { - return pattern.test( elem.className || (typeof elem.getAttribute !== strundefined && elem.getAttribute("class")) || "" ); - }; - }, - - "ATTR": function( name, operator, check ) { - return function( elem, context ) { - var result = Sizzle.attr( elem, name ); - - if ( result == null ) { - return operator === "!="; - } - if ( !operator ) { - return true; - } - - result += ""; - - return operator === "=" ? result === check : - operator === "!=" ? result !== check : - operator === "^=" ? check && result.indexOf( check ) === 0 : - operator === "*=" ? check && result.indexOf( check ) > -1 : - operator === "$=" ? check && result.substr( result.length - check.length ) === check : - operator === "~=" ? ( " " + result + " " ).indexOf( check ) > -1 : - operator === "|=" ? result === check || result.substr( 0, check.length + 1 ) === check + "-" : - false; - }; - }, - - "CHILD": function( type, argument, first, last ) { - - if ( type === "nth" ) { - return function( elem ) { - var node, diff, - parent = elem.parentNode; - - if ( first === 1 && last === 0 ) { - return true; - } - - if ( parent ) { - diff = 0; - for ( node = parent.firstChild; node; node = node.nextSibling ) { - if ( node.nodeType === 1 ) { - diff++; - if ( elem === node ) { - break; - } - } - } - } - - // Incorporate the offset (or cast to NaN), then check against cycle size - diff -= last; - return diff === first || ( diff % first === 0 && diff / first >= 0 ); - }; - } - - return function( elem ) { - var node = elem; - - switch ( type ) { - case "only": - case "first": - while ( (node = node.previousSibling) ) { - if ( node.nodeType === 1 ) { - return false; - } - } - - if ( type === "first" ) { - return true; - } - - node = elem; - - /* falls through */ - case "last": - while ( (node = node.nextSibling) ) { - if ( node.nodeType === 1 ) { - return false; - } - } - - return true; - } - }; - }, - - "PSEUDO": function( pseudo, argument ) { - // pseudo-class names are case-insensitive - // http://www.w3.org/TR/selectors/#pseudo-classes - // Prioritize by case sensitivity in case custom pseudos are added with uppercase letters - // Remember that setFilters inherits from pseudos - var args, - fn = Expr.pseudos[ pseudo ] || Expr.setFilters[ pseudo.toLowerCase() ] || - Sizzle.error( "unsupported pseudo: " + pseudo ); - - // The user may use createPseudo to indicate that - // arguments are needed to create the filter function - // just as Sizzle does - if ( fn[ expando ] ) { - return fn( argument ); - } - - // But maintain support for old signatures - if ( fn.length > 1 ) { - args = [ pseudo, pseudo, "", argument ]; - return Expr.setFilters.hasOwnProperty( pseudo.toLowerCase() ) ? - markFunction(function( seed, matches ) { - var idx, - matched = fn( seed, argument ), - i = matched.length; - while ( i-- ) { - idx = indexOf.call( seed, matched[i] ); - seed[ idx ] = !( matches[ idx ] = matched[i] ); - } - }) : - function( elem ) { - return fn( elem, 0, args ); - }; - } - - return fn; - } - }, - - pseudos: { - "not": markFunction(function( selector ) { - // Trim the selector passed to compile - // to avoid treating leading and trailing - // spaces as combinators - var input = [], - results = [], - matcher = compile( selector.replace( rtrim, "$1" ) ); - - return matcher[ expando ] ? - markFunction(function( seed, matches, context, xml ) { - var elem, - unmatched = matcher( seed, null, xml, [] ), - i = seed.length; - - // Match elements unmatched by `matcher` - while ( i-- ) { - if ( (elem = unmatched[i]) ) { - seed[i] = !(matches[i] = elem); - } - } - }) : - function( elem, context, xml ) { - input[0] = elem; - matcher( input, null, xml, results ); - return !results.pop(); - }; - }), - - "has": markFunction(function( selector ) { - return function( elem ) { - return Sizzle( selector, elem ).length > 0; - }; - }), - - "contains": markFunction(function( text ) { - return function( elem ) { - return ( elem.textContent || elem.innerText || getText( elem ) ).indexOf( text ) > -1; - }; - }), - - "enabled": function( elem ) { - return elem.disabled === false; - }, - - "disabled": function( elem ) { - return elem.disabled === true; - }, - - "checked": function( elem ) { - // In CSS3, :checked should return both checked and selected elements - // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked - var nodeName = elem.nodeName.toLowerCase(); - return (nodeName === "input" && !!elem.checked) || (nodeName === "option" && !!elem.selected); - }, - - "selected": function( elem ) { - // Accessing this property makes selected-by-default - // options in Safari work properly - if ( elem.parentNode ) { - elem.parentNode.selectedIndex; - } - - return elem.selected === true; - }, - - "parent": function( elem ) { - return !Expr.pseudos["empty"]( elem ); - }, - - "empty": function( elem ) { - // http://www.w3.org/TR/selectors/#empty-pseudo - // :empty is only affected by element nodes and content nodes(including text(3), cdata(4)), - // not comment, processing instructions, or others - // Thanks to Diego Perini for the nodeName shortcut - // Greater than "@" means alpha characters (specifically not starting with "#" or "?") - var nodeType; - elem = elem.firstChild; - while ( elem ) { - if ( elem.nodeName > "@" || (nodeType = elem.nodeType) === 3 || nodeType === 4 ) { - return false; - } - elem = elem.nextSibling; - } - return true; - }, - - "header": function( elem ) { - return rheader.test( elem.nodeName ); - }, - - "text": function( elem ) { - var type, attr; - // IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) - // use getAttribute instead to test this case - return elem.nodeName.toLowerCase() === "input" && - (type = elem.type) === "text" && - ( (attr = elem.getAttribute("type")) == null || attr.toLowerCase() === type ); - }, - - // Input types - "radio": createInputPseudo("radio"), - "checkbox": createInputPseudo("checkbox"), - "file": createInputPseudo("file"), - "password": createInputPseudo("password"), - "image": createInputPseudo("image"), - - "submit": createButtonPseudo("submit"), - "reset": createButtonPseudo("reset"), - - "button": function( elem ) { - var name = elem.nodeName.toLowerCase(); - return name === "input" && elem.type === "button" || name === "button"; - }, - - "input": function( elem ) { - return rinputs.test( elem.nodeName ); - }, - - "focus": function( elem ) { - var doc = elem.ownerDocument; - return elem === doc.activeElement && (!doc.hasFocus || doc.hasFocus()) && !!(elem.type || elem.href); - }, - - "active": function( elem ) { - return elem === elem.ownerDocument.activeElement; - }, - - // Positional types - "first": createPositionalPseudo(function( matchIndexes, length, argument ) { - return [ 0 ]; - }), - - "last": createPositionalPseudo(function( matchIndexes, length, argument ) { - return [ length - 1 ]; - }), - - "eq": createPositionalPseudo(function( matchIndexes, length, argument ) { - return [ argument < 0 ? argument + length : argument ]; - }), - - "even": createPositionalPseudo(function( matchIndexes, length, argument ) { - for ( var i = 0; i < length; i += 2 ) { - matchIndexes.push( i ); - } - return matchIndexes; - }), - - "odd": createPositionalPseudo(function( matchIndexes, length, argument ) { - for ( var i = 1; i < length; i += 2 ) { - matchIndexes.push( i ); - } - return matchIndexes; - }), - - "lt": createPositionalPseudo(function( matchIndexes, length, argument ) { - for ( var i = argument < 0 ? argument + length : argument; --i >= 0; ) { - matchIndexes.push( i ); - } - return matchIndexes; - }), - - "gt": createPositionalPseudo(function( matchIndexes, length, argument ) { - for ( var i = argument < 0 ? argument + length : argument; ++i < length; ) { - matchIndexes.push( i ); - } - return matchIndexes; - }) - } -}; - -function siblingCheck( a, b, ret ) { - if ( a === b ) { - return ret; - } - - var cur = a.nextSibling; - - while ( cur ) { - if ( cur === b ) { - return -1; - } - - cur = cur.nextSibling; - } - - return 1; -} - -sortOrder = docElem.compareDocumentPosition ? - function( a, b ) { - if ( a === b ) { - hasDuplicate = true; - return 0; - } - - return ( !a.compareDocumentPosition || !b.compareDocumentPosition ? - a.compareDocumentPosition : - a.compareDocumentPosition(b) & 4 - ) ? -1 : 1; - } : - function( a, b ) { - // The nodes are identical, we can exit early - if ( a === b ) { - hasDuplicate = true; - return 0; - - // Fallback to using sourceIndex (in IE) if it's available on both nodes - } else if ( a.sourceIndex && b.sourceIndex ) { - return a.sourceIndex - b.sourceIndex; - } - - var al, bl, - ap = [], - bp = [], - aup = a.parentNode, - bup = b.parentNode, - cur = aup; - - // If the nodes are siblings (or identical) we can do a quick check - if ( aup === bup ) { - return siblingCheck( a, b ); - - // If no parents were found then the nodes are disconnected - } else if ( !aup ) { - return -1; - - } else if ( !bup ) { - return 1; - } - - // Otherwise they're somewhere else in the tree so we need - // to build up a full list of the parentNodes for comparison - while ( cur ) { - ap.unshift( cur ); - cur = cur.parentNode; - } - - cur = bup; - - while ( cur ) { - bp.unshift( cur ); - cur = cur.parentNode; - } - - al = ap.length; - bl = bp.length; - - // Start walking down the tree looking for a discrepancy - for ( var i = 0; i < al && i < bl; i++ ) { - if ( ap[i] !== bp[i] ) { - return siblingCheck( ap[i], bp[i] ); - } - } - - // We ended someplace up the tree so do a sibling check - return i === al ? - siblingCheck( a, bp[i], -1 ) : - siblingCheck( ap[i], b, 1 ); - }; - -// Always assume the presence of duplicates if sort doesn't -// pass them to our comparison function (as in Google Chrome). -[0, 0].sort( sortOrder ); -baseHasDuplicate = !hasDuplicate; - -// Document sorting and removing duplicates -Sizzle.uniqueSort = function( results ) { - var elem, - i = 1; - - hasDuplicate = baseHasDuplicate; - results.sort( sortOrder ); - - if ( hasDuplicate ) { - for ( ; (elem = results[i]); i++ ) { - if ( elem === results[ i - 1 ] ) { - results.splice( i--, 1 ); - } - } - } - - return results; -}; - -Sizzle.error = function( msg ) { - throw new Error( "Syntax error, unrecognized expression: " + msg ); -}; - -function tokenize( selector, parseOnly ) { - var matched, match, tokens, type, soFar, groups, preFilters, - cached = tokenCache[ expando ][ selector ]; - - if ( cached ) { - return parseOnly ? 0 : cached.slice( 0 ); - } - - soFar = selector; - groups = []; - preFilters = Expr.preFilter; - - while ( soFar ) { - - // Comma and first run - if ( !matched || (match = rcomma.exec( soFar )) ) { - if ( match ) { - soFar = soFar.slice( match[0].length ); - } - groups.push( tokens = [] ); - } - - matched = false; - - // Combinators - if ( (match = rcombinators.exec( soFar )) ) { - tokens.push( matched = new Token( match.shift() ) ); - soFar = soFar.slice( matched.length ); - - // Cast descendant combinators to space - matched.type = match[0].replace( rtrim, " " ); - } - - // Filters - for ( type in Expr.filter ) { - if ( (match = matchExpr[ type ].exec( soFar )) && (!preFilters[ type ] || - // The last two arguments here are (context, xml) for backCompat - (match = preFilters[ type ]( match, document, true ))) ) { - - tokens.push( matched = new Token( match.shift() ) ); - soFar = soFar.slice( matched.length ); - matched.type = type; - matched.matches = match; - } - } - - if ( !matched ) { - break; - } - } - - // Return the length of the invalid excess - // if we're just parsing - // Otherwise, throw an error or return tokens - return parseOnly ? - soFar.length : - soFar ? - Sizzle.error( selector ) : - // Cache the tokens - tokenCache( selector, groups ).slice( 0 ); -} - -function addCombinator( matcher, combinator, base ) { - var dir = combinator.dir, - checkNonElements = base && combinator.dir === "parentNode", - doneName = done++; - - return combinator.first ? - // Check against closest ancestor/preceding element - function( elem, context, xml ) { - while ( (elem = elem[ dir ]) ) { - if ( checkNonElements || elem.nodeType === 1 ) { - return matcher( elem, context, xml ); - } - } - } : - - // Check against all ancestor/preceding elements - function( elem, context, xml ) { - // We can't set arbitrary data on XML nodes, so they don't benefit from dir caching - if ( !xml ) { - var cache, - dirkey = dirruns + " " + doneName + " ", - cachedkey = dirkey + cachedruns; - while ( (elem = elem[ dir ]) ) { - if ( checkNonElements || elem.nodeType === 1 ) { - if ( (cache = elem[ expando ]) === cachedkey ) { - return elem.sizset; - } else if ( typeof cache === "string" && cache.indexOf(dirkey) === 0 ) { - if ( elem.sizset ) { - return elem; - } - } else { - elem[ expando ] = cachedkey; - if ( matcher( elem, context, xml ) ) { - elem.sizset = true; - return elem; - } - elem.sizset = false; - } - } - } - } else { - while ( (elem = elem[ dir ]) ) { - if ( checkNonElements || elem.nodeType === 1 ) { - if ( matcher( elem, context, xml ) ) { - return elem; - } - } - } - } - }; -} - -function elementMatcher( matchers ) { - return matchers.length > 1 ? - function( elem, context, xml ) { - var i = matchers.length; - while ( i-- ) { - if ( !matchers[i]( elem, context, xml ) ) { - return false; - } - } - return true; - } : - matchers[0]; -} - -function condense( unmatched, map, filter, context, xml ) { - var elem, - newUnmatched = [], - i = 0, - len = unmatched.length, - mapped = map != null; - - for ( ; i < len; i++ ) { - if ( (elem = unmatched[i]) ) { - if ( !filter || filter( elem, context, xml ) ) { - newUnmatched.push( elem ); - if ( mapped ) { - map.push( i ); - } - } - } - } - - return newUnmatched; -} - -function setMatcher( preFilter, selector, matcher, postFilter, postFinder, postSelector ) { - if ( postFilter && !postFilter[ expando ] ) { - postFilter = setMatcher( postFilter ); - } - if ( postFinder && !postFinder[ expando ] ) { - postFinder = setMatcher( postFinder, postSelector ); - } - return markFunction(function( seed, results, context, xml ) { - // Positional selectors apply to seed elements, so it is invalid to follow them with relative ones - if ( seed && postFinder ) { - return; - } - - var i, elem, postFilterIn, - preMap = [], - postMap = [], - preexisting = results.length, - - // Get initial elements from seed or context - elems = seed || multipleContexts( selector || "*", context.nodeType ? [ context ] : context, [], seed ), - - // Prefilter to get matcher input, preserving a map for seed-results synchronization - matcherIn = preFilter && ( seed || !selector ) ? - condense( elems, preMap, preFilter, context, xml ) : - elems, - - matcherOut = matcher ? - // If we have a postFinder, or filtered seed, or non-seed postFilter or preexisting results, - postFinder || ( seed ? preFilter : preexisting || postFilter ) ? - - // ...intermediate processing is necessary - [] : - - // ...otherwise use results directly - results : - matcherIn; - - // Find primary matches - if ( matcher ) { - matcher( matcherIn, matcherOut, context, xml ); - } - - // Apply postFilter - if ( postFilter ) { - postFilterIn = condense( matcherOut, postMap ); - postFilter( postFilterIn, [], context, xml ); - - // Un-match failing elements by moving them back to matcherIn - i = postFilterIn.length; - while ( i-- ) { - if ( (elem = postFilterIn[i]) ) { - matcherOut[ postMap[i] ] = !(matcherIn[ postMap[i] ] = elem); - } - } - } - - // Keep seed and results synchronized - if ( seed ) { - // Ignore postFinder because it can't coexist with seed - i = preFilter && matcherOut.length; - while ( i-- ) { - if ( (elem = matcherOut[i]) ) { - seed[ preMap[i] ] = !(results[ preMap[i] ] = elem); - } - } - } else { - matcherOut = condense( - matcherOut === results ? - matcherOut.splice( preexisting, matcherOut.length ) : - matcherOut - ); - if ( postFinder ) { - postFinder( null, results, matcherOut, xml ); - } else { - push.apply( results, matcherOut ); - } - } - }); -} - -function matcherFromTokens( tokens ) { - var checkContext, matcher, j, - len = tokens.length, - leadingRelative = Expr.relative[ tokens[0].type ], - implicitRelative = leadingRelative || Expr.relative[" "], - i = leadingRelative ? 1 : 0, - - // The foundational matcher ensures that elements are reachable from top-level context(s) - matchContext = addCombinator( function( elem ) { - return elem === checkContext; - }, implicitRelative, true ), - matchAnyContext = addCombinator( function( elem ) { - return indexOf.call( checkContext, elem ) > -1; - }, implicitRelative, true ), - matchers = [ function( elem, context, xml ) { - return ( !leadingRelative && ( xml || context !== outermostContext ) ) || ( - (checkContext = context).nodeType ? - matchContext( elem, context, xml ) : - matchAnyContext( elem, context, xml ) ); - } ]; - - for ( ; i < len; i++ ) { - if ( (matcher = Expr.relative[ tokens[i].type ]) ) { - matchers = [ addCombinator( elementMatcher( matchers ), matcher ) ]; - } else { - // The concatenated values are (context, xml) for backCompat - matcher = Expr.filter[ tokens[i].type ].apply( null, tokens[i].matches ); - - // Return special upon seeing a positional matcher - if ( matcher[ expando ] ) { - // Find the next relative operator (if any) for proper handling - j = ++i; - for ( ; j < len; j++ ) { - if ( Expr.relative[ tokens[j].type ] ) { - break; - } - } - return setMatcher( - i > 1 && elementMatcher( matchers ), - i > 1 && tokens.slice( 0, i - 1 ).join("").replace( rtrim, "$1" ), - matcher, - i < j && matcherFromTokens( tokens.slice( i, j ) ), - j < len && matcherFromTokens( (tokens = tokens.slice( j )) ), - j < len && tokens.join("") - ); - } - matchers.push( matcher ); - } - } - - return elementMatcher( matchers ); -} - -function matcherFromGroupMatchers( elementMatchers, setMatchers ) { - var bySet = setMatchers.length > 0, - byElement = elementMatchers.length > 0, - superMatcher = function( seed, context, xml, results, expandContext ) { - var elem, j, matcher, - setMatched = [], - matchedCount = 0, - i = "0", - unmatched = seed && [], - outermost = expandContext != null, - contextBackup = outermostContext, - // We must always have either seed elements or context - elems = seed || byElement && Expr.find["TAG"]( "*", expandContext && context.parentNode || context ), - // Nested matchers should use non-integer dirruns - dirrunsUnique = (dirruns += contextBackup == null ? 1 : Math.E); - - if ( outermost ) { - outermostContext = context !== document && context; - cachedruns = superMatcher.el; - } - - // Add elements passing elementMatchers directly to results - for ( ; (elem = elems[i]) != null; i++ ) { - if ( byElement && elem ) { - for ( j = 0; (matcher = elementMatchers[j]); j++ ) { - if ( matcher( elem, context, xml ) ) { - results.push( elem ); - break; - } - } - if ( outermost ) { - dirruns = dirrunsUnique; - cachedruns = ++superMatcher.el; - } - } - - // Track unmatched elements for set filters - if ( bySet ) { - // They will have gone through all possible matchers - if ( (elem = !matcher && elem) ) { - matchedCount--; - } - - // Lengthen the array for every element, matched or not - if ( seed ) { - unmatched.push( elem ); - } - } - } - - // Apply set filters to unmatched elements - matchedCount += i; - if ( bySet && i !== matchedCount ) { - for ( j = 0; (matcher = setMatchers[j]); j++ ) { - matcher( unmatched, setMatched, context, xml ); - } - - if ( seed ) { - // Reintegrate element matches to eliminate the need for sorting - if ( matchedCount > 0 ) { - while ( i-- ) { - if ( !(unmatched[i] || setMatched[i]) ) { - setMatched[i] = pop.call( results ); - } - } - } - - // Discard index placeholder values to get only actual matches - setMatched = condense( setMatched ); - } - - // Add matches to results - push.apply( results, setMatched ); - - // Seedless set matches succeeding multiple successful matchers stipulate sorting - if ( outermost && !seed && setMatched.length > 0 && - ( matchedCount + setMatchers.length ) > 1 ) { - - Sizzle.uniqueSort( results ); - } - } - - // Override manipulation of globals by nested matchers - if ( outermost ) { - dirruns = dirrunsUnique; - outermostContext = contextBackup; - } - - return unmatched; - }; - - superMatcher.el = 0; - return bySet ? - markFunction( superMatcher ) : - superMatcher; -} - -compile = Sizzle.compile = function( selector, group /* Internal Use Only */ ) { - var i, - setMatchers = [], - elementMatchers = [], - cached = compilerCache[ expando ][ selector ]; - - if ( !cached ) { - // Generate a function of recursive functions that can be used to check each element - if ( !group ) { - group = tokenize( selector ); - } - i = group.length; - while ( i-- ) { - cached = matcherFromTokens( group[i] ); - if ( cached[ expando ] ) { - setMatchers.push( cached ); - } else { - elementMatchers.push( cached ); - } - } - - // Cache the compiled function - cached = compilerCache( selector, matcherFromGroupMatchers( elementMatchers, setMatchers ) ); - } - return cached; -}; - -function multipleContexts( selector, contexts, results, seed ) { - var i = 0, - len = contexts.length; - for ( ; i < len; i++ ) { - Sizzle( selector, contexts[i], results, seed ); - } - return results; -} - -function select( selector, context, results, seed, xml ) { - var i, tokens, token, type, find, - match = tokenize( selector ), - j = match.length; - - if ( !seed ) { - // Try to minimize operations if there is only one group - if ( match.length === 1 ) { - - // Take a shortcut and set the context if the root selector is an ID - tokens = match[0] = match[0].slice( 0 ); - if ( tokens.length > 2 && (token = tokens[0]).type === "ID" && - context.nodeType === 9 && !xml && - Expr.relative[ tokens[1].type ] ) { - - context = Expr.find["ID"]( token.matches[0].replace( rbackslash, "" ), context, xml )[0]; - if ( !context ) { - return results; - } - - selector = selector.slice( tokens.shift().length ); - } - - // Fetch a seed set for right-to-left matching - for ( i = matchExpr["POS"].test( selector ) ? -1 : tokens.length - 1; i >= 0; i-- ) { - token = tokens[i]; - - // Abort if we hit a combinator - if ( Expr.relative[ (type = token.type) ] ) { - break; - } - if ( (find = Expr.find[ type ]) ) { - // Search, expanding context for leading sibling combinators - if ( (seed = find( - token.matches[0].replace( rbackslash, "" ), - rsibling.test( tokens[0].type ) && context.parentNode || context, - xml - )) ) { - - // If seed is empty or no tokens remain, we can return early - tokens.splice( i, 1 ); - selector = seed.length && tokens.join(""); - if ( !selector ) { - push.apply( results, slice.call( seed, 0 ) ); - return results; - } - - break; - } - } - } - } - } - - // Compile and execute a filtering function - // Provide `match` to avoid retokenization if we modified the selector above - compile( selector, match )( - seed, - context, - xml, - results, - rsibling.test( selector ) - ); - return results; -} - -if ( document.querySelectorAll ) { - (function() { - var disconnectedMatch, - oldSelect = select, - rescape = /'|\\/g, - rattributeQuotes = /\=[\x20\t\r\n\f]*([^'"\]]*)[\x20\t\r\n\f]*\]/g, - - // qSa(:focus) reports false when true (Chrome 21), - // A support test would require too much code (would include document ready) - rbuggyQSA = [":focus"], - - // matchesSelector(:focus) reports false when true (Chrome 21), - // matchesSelector(:active) reports false when true (IE9/Opera 11.5) - // A support test would require too much code (would include document ready) - // just skip matchesSelector for :active - rbuggyMatches = [ ":active", ":focus" ], - matches = docElem.matchesSelector || - docElem.mozMatchesSelector || - docElem.webkitMatchesSelector || - docElem.oMatchesSelector || - docElem.msMatchesSelector; - - // Build QSA regex - // Regex strategy adopted from Diego Perini - assert(function( div ) { - // Select is set to empty string on purpose - // This is to test IE's treatment of not explictly - // setting a boolean content attribute, - // since its presence should be enough - // http://bugs.jquery.com/ticket/12359 - div.innerHTML = ""; - - // IE8 - Some boolean attributes are not treated correctly - if ( !div.querySelectorAll("[selected]").length ) { - rbuggyQSA.push( "\\[" + whitespace + "*(?:checked|disabled|ismap|multiple|readonly|selected|value)" ); - } - - // Webkit/Opera - :checked should return selected option elements - // http://www.w3.org/TR/2011/REC-css3-selectors-20110929/#checked - // IE8 throws error here (do not put tests after this one) - if ( !div.querySelectorAll(":checked").length ) { - rbuggyQSA.push(":checked"); - } - }); - - assert(function( div ) { - - // Opera 10-12/IE9 - ^= $= *= and empty values - // Should not select anything - div.innerHTML = "

                "; - if ( div.querySelectorAll("[test^='']").length ) { - rbuggyQSA.push( "[*^$]=" + whitespace + "*(?:\"\"|'')" ); - } - - // FF 3.5 - :enabled/:disabled and hidden elements (hidden elements are still enabled) - // IE8 throws error here (do not put tests after this one) - div.innerHTML = ""; - if ( !div.querySelectorAll(":enabled").length ) { - rbuggyQSA.push(":enabled", ":disabled"); - } - }); - - // rbuggyQSA always contains :focus, so no need for a length check - rbuggyQSA = /* rbuggyQSA.length && */ new RegExp( rbuggyQSA.join("|") ); - - select = function( selector, context, results, seed, xml ) { - // Only use querySelectorAll when not filtering, - // when this is not xml, - // and when no QSA bugs apply - if ( !seed && !xml && (!rbuggyQSA || !rbuggyQSA.test( selector )) ) { - var groups, i, - old = true, - nid = expando, - newContext = context, - newSelector = context.nodeType === 9 && selector; - - // qSA works strangely on Element-rooted queries - // We can work around this by specifying an extra ID on the root - // and working up from there (Thanks to Andrew Dupont for the technique) - // IE 8 doesn't work on object elements - if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) { - groups = tokenize( selector ); - - if ( (old = context.getAttribute("id")) ) { - nid = old.replace( rescape, "\\$&" ); - } else { - context.setAttribute( "id", nid ); - } - nid = "[id='" + nid + "'] "; - - i = groups.length; - while ( i-- ) { - groups[i] = nid + groups[i].join(""); - } - newContext = rsibling.test( selector ) && context.parentNode || context; - newSelector = groups.join(","); - } - - if ( newSelector ) { - try { - push.apply( results, slice.call( newContext.querySelectorAll( - newSelector - ), 0 ) ); - return results; - } catch(qsaError) { - } finally { - if ( !old ) { - context.removeAttribute("id"); - } - } - } - } - - return oldSelect( selector, context, results, seed, xml ); - }; - - if ( matches ) { - assert(function( div ) { - // Check to see if it's possible to do matchesSelector - // on a disconnected node (IE 9) - disconnectedMatch = matches.call( div, "div" ); - - // This should fail with an exception - // Gecko does not error, returns false instead - try { - matches.call( div, "[test!='']:sizzle" ); - rbuggyMatches.push( "!=", pseudos ); - } catch ( e ) {} - }); - - // rbuggyMatches always contains :active and :focus, so no need for a length check - rbuggyMatches = /* rbuggyMatches.length && */ new RegExp( rbuggyMatches.join("|") ); - - Sizzle.matchesSelector = function( elem, expr ) { - // Make sure that attribute selectors are quoted - expr = expr.replace( rattributeQuotes, "='$1']" ); - - // rbuggyMatches always contains :active, so no need for an existence check - if ( !isXML( elem ) && !rbuggyMatches.test( expr ) && (!rbuggyQSA || !rbuggyQSA.test( expr )) ) { - try { - var ret = matches.call( elem, expr ); - - // IE 9's matchesSelector returns false on disconnected nodes - if ( ret || disconnectedMatch || - // As well, disconnected nodes are said to be in a document - // fragment in IE 9 - elem.document && elem.document.nodeType !== 11 ) { - return ret; - } - } catch(e) {} - } - - return Sizzle( expr, null, null, [ elem ] ).length > 0; - }; - } - })(); -} - -// Deprecated -Expr.pseudos["nth"] = Expr.pseudos["eq"]; - -// Back-compat -function setFilters() {} -Expr.filters = setFilters.prototype = Expr.pseudos; -Expr.setFilters = new setFilters(); - -// Override sizzle attribute retrieval -Sizzle.attr = jQuery.attr; -jQuery.find = Sizzle; -jQuery.expr = Sizzle.selectors; -jQuery.expr[":"] = jQuery.expr.pseudos; -jQuery.unique = Sizzle.uniqueSort; -jQuery.text = Sizzle.getText; -jQuery.isXMLDoc = Sizzle.isXML; -jQuery.contains = Sizzle.contains; - - -})( window ); -var runtil = /Until$/, - rparentsprev = /^(?:parents|prev(?:Until|All))/, - isSimple = /^.[^:#\[\.,]*$/, - rneedsContext = jQuery.expr.match.needsContext, - // methods guaranteed to produce a unique set when starting from a unique set - guaranteedUnique = { - children: true, - contents: true, - next: true, - prev: true - }; - -jQuery.fn.extend({ - find: function( selector ) { - var i, l, length, n, r, ret, - self = this; - - if ( typeof selector !== "string" ) { - return jQuery( selector ).filter(function() { - for ( i = 0, l = self.length; i < l; i++ ) { - if ( jQuery.contains( self[ i ], this ) ) { - return true; - } - } - }); - } - - ret = this.pushStack( "", "find", selector ); - - for ( i = 0, l = this.length; i < l; i++ ) { - length = ret.length; - jQuery.find( selector, this[i], ret ); - - if ( i > 0 ) { - // Make sure that the results are unique - for ( n = length; n < ret.length; n++ ) { - for ( r = 0; r < length; r++ ) { - if ( ret[r] === ret[n] ) { - ret.splice(n--, 1); - break; - } - } - } - } - } - - return ret; - }, - - has: function( target ) { - var i, - targets = jQuery( target, this ), - len = targets.length; - - return this.filter(function() { - for ( i = 0; i < len; i++ ) { - if ( jQuery.contains( this, targets[i] ) ) { - return true; - } - } - }); - }, - - not: function( selector ) { - return this.pushStack( winnow(this, selector, false), "not", selector); - }, - - filter: function( selector ) { - return this.pushStack( winnow(this, selector, true), "filter", selector ); - }, - - is: function( selector ) { - return !!selector && ( - typeof selector === "string" ? - // If this is a positional/relative selector, check membership in the returned set - // so $("p:first").is("p:last") won't return true for a doc with two "p". - rneedsContext.test( selector ) ? - jQuery( selector, this.context ).index( this[0] ) >= 0 : - jQuery.filter( selector, this ).length > 0 : - this.filter( selector ).length > 0 ); - }, - - closest: function( selectors, context ) { - var cur, - i = 0, - l = this.length, - ret = [], - pos = rneedsContext.test( selectors ) || typeof selectors !== "string" ? - jQuery( selectors, context || this.context ) : - 0; - - for ( ; i < l; i++ ) { - cur = this[i]; - - while ( cur && cur.ownerDocument && cur !== context && cur.nodeType !== 11 ) { - if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) { - ret.push( cur ); - break; - } - cur = cur.parentNode; - } - } - - ret = ret.length > 1 ? jQuery.unique( ret ) : ret; - - return this.pushStack( ret, "closest", selectors ); - }, - - // Determine the position of an element within - // the matched set of elements - index: function( elem ) { - - // No argument, return index in parent - if ( !elem ) { - return ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1; - } - - // index in selector - if ( typeof elem === "string" ) { - return jQuery.inArray( this[0], jQuery( elem ) ); - } - - // Locate the position of the desired element - return jQuery.inArray( - // If it receives a jQuery object, the first element is used - elem.jquery ? elem[0] : elem, this ); - }, - - add: function( selector, context ) { - var set = typeof selector === "string" ? - jQuery( selector, context ) : - jQuery.makeArray( selector && selector.nodeType ? [ selector ] : selector ), - all = jQuery.merge( this.get(), set ); - - return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ? - all : - jQuery.unique( all ) ); - }, - - addBack: function( selector ) { - return this.add( selector == null ? - this.prevObject : this.prevObject.filter(selector) - ); - } -}); - -jQuery.fn.andSelf = jQuery.fn.addBack; - -// A painfully simple check to see if an element is disconnected -// from a document (should be improved, where feasible). -function isDisconnected( node ) { - return !node || !node.parentNode || node.parentNode.nodeType === 11; -} - -function sibling( cur, dir ) { - do { - cur = cur[ dir ]; - } while ( cur && cur.nodeType !== 1 ); - - return cur; -} - -jQuery.each({ - parent: function( elem ) { - var parent = elem.parentNode; - return parent && parent.nodeType !== 11 ? parent : null; - }, - parents: function( elem ) { - return jQuery.dir( elem, "parentNode" ); - }, - parentsUntil: function( elem, i, until ) { - return jQuery.dir( elem, "parentNode", until ); - }, - next: function( elem ) { - return sibling( elem, "nextSibling" ); - }, - prev: function( elem ) { - return sibling( elem, "previousSibling" ); - }, - nextAll: function( elem ) { - return jQuery.dir( elem, "nextSibling" ); - }, - prevAll: function( elem ) { - return jQuery.dir( elem, "previousSibling" ); - }, - nextUntil: function( elem, i, until ) { - return jQuery.dir( elem, "nextSibling", until ); - }, - prevUntil: function( elem, i, until ) { - return jQuery.dir( elem, "previousSibling", until ); - }, - siblings: function( elem ) { - return jQuery.sibling( ( elem.parentNode || {} ).firstChild, elem ); - }, - children: function( elem ) { - return jQuery.sibling( elem.firstChild ); - }, - contents: function( elem ) { - return jQuery.nodeName( elem, "iframe" ) ? - elem.contentDocument || elem.contentWindow.document : - jQuery.merge( [], elem.childNodes ); - } -}, function( name, fn ) { - jQuery.fn[ name ] = function( until, selector ) { - var ret = jQuery.map( this, fn, until ); - - if ( !runtil.test( name ) ) { - selector = until; - } - - if ( selector && typeof selector === "string" ) { - ret = jQuery.filter( selector, ret ); - } - - ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret; - - if ( this.length > 1 && rparentsprev.test( name ) ) { - ret = ret.reverse(); - } - - return this.pushStack( ret, name, core_slice.call( arguments ).join(",") ); - }; -}); - -jQuery.extend({ - filter: function( expr, elems, not ) { - if ( not ) { - expr = ":not(" + expr + ")"; - } - - return elems.length === 1 ? - jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] : - jQuery.find.matches(expr, elems); - }, - - dir: function( elem, dir, until ) { - var matched = [], - cur = elem[ dir ]; - - while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) { - if ( cur.nodeType === 1 ) { - matched.push( cur ); - } - cur = cur[dir]; - } - return matched; - }, - - sibling: function( n, elem ) { - var r = []; - - for ( ; n; n = n.nextSibling ) { - if ( n.nodeType === 1 && n !== elem ) { - r.push( n ); - } - } - - return r; - } -}); - -// Implement the identical functionality for filter and not -function winnow( elements, qualifier, keep ) { - - // Can't pass null or undefined to indexOf in Firefox 4 - // Set to 0 to skip string check - qualifier = qualifier || 0; - - if ( jQuery.isFunction( qualifier ) ) { - return jQuery.grep(elements, function( elem, i ) { - var retVal = !!qualifier.call( elem, i, elem ); - return retVal === keep; - }); - - } else if ( qualifier.nodeType ) { - return jQuery.grep(elements, function( elem, i ) { - return ( elem === qualifier ) === keep; - }); - - } else if ( typeof qualifier === "string" ) { - var filtered = jQuery.grep(elements, function( elem ) { - return elem.nodeType === 1; - }); - - if ( isSimple.test( qualifier ) ) { - return jQuery.filter(qualifier, filtered, !keep); - } else { - qualifier = jQuery.filter( qualifier, filtered ); - } - } - - return jQuery.grep(elements, function( elem, i ) { - return ( jQuery.inArray( elem, qualifier ) >= 0 ) === keep; - }); -} -function createSafeFragment( document ) { - var list = nodeNames.split( "|" ), - safeFrag = document.createDocumentFragment(); - - if ( safeFrag.createElement ) { - while ( list.length ) { - safeFrag.createElement( - list.pop() - ); - } - } - return safeFrag; -} - -var nodeNames = "abbr|article|aside|audio|bdi|canvas|data|datalist|details|figcaption|figure|footer|" + - "header|hgroup|mark|meter|nav|output|progress|section|summary|time|video", - rinlinejQuery = / jQuery\d+="(?:null|\d+)"/g, - rleadingWhitespace = /^\s+/, - rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/gi, - rtagName = /<([\w:]+)/, - rtbody = /]", "i"), - rcheckableType = /^(?:checkbox|radio)$/, - // checked="checked" or checked - rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i, - rscriptType = /\/(java|ecma)script/i, - rcleanScript = /^\s*\s*$/g, - wrapMap = { - option: [ 1, "" ], - legend: [ 1, "
                ", "
                " ], - thead: [ 1, "", "
                " ], - tr: [ 2, "", "
                " ], - td: [ 3, "", "
                " ], - col: [ 2, "", "
                " ], - area: [ 1, "", "" ], - _default: [ 0, "", "" ] - }, - safeFragment = createSafeFragment( document ), - fragmentDiv = safeFragment.appendChild( document.createElement("div") ); - -wrapMap.optgroup = wrapMap.option; -wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead; -wrapMap.th = wrapMap.td; - -// IE6-8 can't serialize link, script, style, or any html5 (NoScope) tags, -// unless wrapped in a div with non-breaking characters in front of it. -if ( !jQuery.support.htmlSerialize ) { - wrapMap._default = [ 1, "X
                ", "
                " ]; -} - -jQuery.fn.extend({ - text: function( value ) { - return jQuery.access( this, function( value ) { - return value === undefined ? - jQuery.text( this ) : - this.empty().append( ( this[0] && this[0].ownerDocument || document ).createTextNode( value ) ); - }, null, value, arguments.length ); - }, - - wrapAll: function( html ) { - if ( jQuery.isFunction( html ) ) { - return this.each(function(i) { - jQuery(this).wrapAll( html.call(this, i) ); - }); - } - - if ( this[0] ) { - // The elements to wrap the target around - var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true); - - if ( this[0].parentNode ) { - wrap.insertBefore( this[0] ); - } - - wrap.map(function() { - var elem = this; - - while ( elem.firstChild && elem.firstChild.nodeType === 1 ) { - elem = elem.firstChild; - } - - return elem; - }).append( this ); - } - - return this; - }, - - wrapInner: function( html ) { - if ( jQuery.isFunction( html ) ) { - return this.each(function(i) { - jQuery(this).wrapInner( html.call(this, i) ); - }); - } - - return this.each(function() { - var self = jQuery( this ), - contents = self.contents(); - - if ( contents.length ) { - contents.wrapAll( html ); - - } else { - self.append( html ); - } - }); - }, - - wrap: function( html ) { - var isFunction = jQuery.isFunction( html ); - - return this.each(function(i) { - jQuery( this ).wrapAll( isFunction ? html.call(this, i) : html ); - }); - }, - - unwrap: function() { - return this.parent().each(function() { - if ( !jQuery.nodeName( this, "body" ) ) { - jQuery( this ).replaceWith( this.childNodes ); - } - }).end(); - }, - - append: function() { - return this.domManip(arguments, true, function( elem ) { - if ( this.nodeType === 1 || this.nodeType === 11 ) { - this.appendChild( elem ); - } - }); - }, - - prepend: function() { - return this.domManip(arguments, true, function( elem ) { - if ( this.nodeType === 1 || this.nodeType === 11 ) { - this.insertBefore( elem, this.firstChild ); - } - }); - }, - - before: function() { - if ( !isDisconnected( this[0] ) ) { - return this.domManip(arguments, false, function( elem ) { - this.parentNode.insertBefore( elem, this ); - }); - } - - if ( arguments.length ) { - var set = jQuery.clean( arguments ); - return this.pushStack( jQuery.merge( set, this ), "before", this.selector ); - } - }, - - after: function() { - if ( !isDisconnected( this[0] ) ) { - return this.domManip(arguments, false, function( elem ) { - this.parentNode.insertBefore( elem, this.nextSibling ); - }); - } - - if ( arguments.length ) { - var set = jQuery.clean( arguments ); - return this.pushStack( jQuery.merge( this, set ), "after", this.selector ); - } - }, - - // keepData is for internal use only--do not document - remove: function( selector, keepData ) { - var elem, - i = 0; - - for ( ; (elem = this[i]) != null; i++ ) { - if ( !selector || jQuery.filter( selector, [ elem ] ).length ) { - if ( !keepData && elem.nodeType === 1 ) { - jQuery.cleanData( elem.getElementsByTagName("*") ); - jQuery.cleanData( [ elem ] ); - } - - if ( elem.parentNode ) { - elem.parentNode.removeChild( elem ); - } - } - } - - return this; - }, - - empty: function() { - var elem, - i = 0; - - for ( ; (elem = this[i]) != null; i++ ) { - // Remove element nodes and prevent memory leaks - if ( elem.nodeType === 1 ) { - jQuery.cleanData( elem.getElementsByTagName("*") ); - } - - // Remove any remaining nodes - while ( elem.firstChild ) { - elem.removeChild( elem.firstChild ); - } - } - - return this; - }, - - clone: function( dataAndEvents, deepDataAndEvents ) { - dataAndEvents = dataAndEvents == null ? false : dataAndEvents; - deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents; - - return this.map( function () { - return jQuery.clone( this, dataAndEvents, deepDataAndEvents ); - }); - }, - - html: function( value ) { - return jQuery.access( this, function( value ) { - var elem = this[0] || {}, - i = 0, - l = this.length; - - if ( value === undefined ) { - return elem.nodeType === 1 ? - elem.innerHTML.replace( rinlinejQuery, "" ) : - undefined; - } - - // See if we can take a shortcut and just use innerHTML - if ( typeof value === "string" && !rnoInnerhtml.test( value ) && - ( jQuery.support.htmlSerialize || !rnoshimcache.test( value ) ) && - ( jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value ) ) && - !wrapMap[ ( rtagName.exec( value ) || ["", ""] )[1].toLowerCase() ] ) { - - value = value.replace( rxhtmlTag, "<$1>" ); - - try { - for (; i < l; i++ ) { - // Remove element nodes and prevent memory leaks - elem = this[i] || {}; - if ( elem.nodeType === 1 ) { - jQuery.cleanData( elem.getElementsByTagName( "*" ) ); - elem.innerHTML = value; - } - } - - elem = 0; - - // If using innerHTML throws an exception, use the fallback method - } catch(e) {} - } - - if ( elem ) { - this.empty().append( value ); - } - }, null, value, arguments.length ); - }, - - replaceWith: function( value ) { - if ( !isDisconnected( this[0] ) ) { - // Make sure that the elements are removed from the DOM before they are inserted - // this can help fix replacing a parent with child elements - if ( jQuery.isFunction( value ) ) { - return this.each(function(i) { - var self = jQuery(this), old = self.html(); - self.replaceWith( value.call( this, i, old ) ); - }); - } - - if ( typeof value !== "string" ) { - value = jQuery( value ).detach(); - } - - return this.each(function() { - var next = this.nextSibling, - parent = this.parentNode; - - jQuery( this ).remove(); - - if ( next ) { - jQuery(next).before( value ); - } else { - jQuery(parent).append( value ); - } - }); - } - - return this.length ? - this.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), "replaceWith", value ) : - this; - }, - - detach: function( selector ) { - return this.remove( selector, true ); - }, - - domManip: function( args, table, callback ) { - - // Flatten any nested arrays - args = [].concat.apply( [], args ); - - var results, first, fragment, iNoClone, - i = 0, - value = args[0], - scripts = [], - l = this.length; - - // We can't cloneNode fragments that contain checked, in WebKit - if ( !jQuery.support.checkClone && l > 1 && typeof value === "string" && rchecked.test( value ) ) { - return this.each(function() { - jQuery(this).domManip( args, table, callback ); - }); - } - - if ( jQuery.isFunction(value) ) { - return this.each(function(i) { - var self = jQuery(this); - args[0] = value.call( this, i, table ? self.html() : undefined ); - self.domManip( args, table, callback ); - }); - } - - if ( this[0] ) { - results = jQuery.buildFragment( args, this, scripts ); - fragment = results.fragment; - first = fragment.firstChild; - - if ( fragment.childNodes.length === 1 ) { - fragment = first; - } - - if ( first ) { - table = table && jQuery.nodeName( first, "tr" ); - - // Use the original fragment for the last item instead of the first because it can end up - // being emptied incorrectly in certain situations (#8070). - // Fragments from the fragment cache must always be cloned and never used in place. - for ( iNoClone = results.cacheable || l - 1; i < l; i++ ) { - callback.call( - table && jQuery.nodeName( this[i], "table" ) ? - findOrAppend( this[i], "tbody" ) : - this[i], - i === iNoClone ? - fragment : - jQuery.clone( fragment, true, true ) - ); - } - } - - // Fix #11809: Avoid leaking memory - fragment = first = null; - - if ( scripts.length ) { - jQuery.each( scripts, function( i, elem ) { - if ( elem.src ) { - if ( jQuery.ajax ) { - jQuery.ajax({ - url: elem.src, - type: "GET", - dataType: "script", - async: false, - global: false, - "throws": true - }); - } else { - jQuery.error("no ajax"); - } - } else { - jQuery.globalEval( ( elem.text || elem.textContent || elem.innerHTML || "" ).replace( rcleanScript, "" ) ); - } - - if ( elem.parentNode ) { - elem.parentNode.removeChild( elem ); - } - }); - } - } - - return this; - } -}); - -function findOrAppend( elem, tag ) { - return elem.getElementsByTagName( tag )[0] || elem.appendChild( elem.ownerDocument.createElement( tag ) ); -} - -function cloneCopyEvent( src, dest ) { - - if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) { - return; - } - - var type, i, l, - oldData = jQuery._data( src ), - curData = jQuery._data( dest, oldData ), - events = oldData.events; - - if ( events ) { - delete curData.handle; - curData.events = {}; - - for ( type in events ) { - for ( i = 0, l = events[ type ].length; i < l; i++ ) { - jQuery.event.add( dest, type, events[ type ][ i ] ); - } - } - } - - // make the cloned public data object a copy from the original - if ( curData.data ) { - curData.data = jQuery.extend( {}, curData.data ); - } -} - -function cloneFixAttributes( src, dest ) { - var nodeName; - - // We do not need to do anything for non-Elements - if ( dest.nodeType !== 1 ) { - return; - } - - // clearAttributes removes the attributes, which we don't want, - // but also removes the attachEvent events, which we *do* want - if ( dest.clearAttributes ) { - dest.clearAttributes(); - } - - // mergeAttributes, in contrast, only merges back on the - // original attributes, not the events - if ( dest.mergeAttributes ) { - dest.mergeAttributes( src ); - } - - nodeName = dest.nodeName.toLowerCase(); - - if ( nodeName === "object" ) { - // IE6-10 improperly clones children of object elements using classid. - // IE10 throws NoModificationAllowedError if parent is null, #12132. - if ( dest.parentNode ) { - dest.outerHTML = src.outerHTML; - } - - // This path appears unavoidable for IE9. When cloning an object - // element in IE9, the outerHTML strategy above is not sufficient. - // If the src has innerHTML and the destination does not, - // copy the src.innerHTML into the dest.innerHTML. #10324 - if ( jQuery.support.html5Clone && (src.innerHTML && !jQuery.trim(dest.innerHTML)) ) { - dest.innerHTML = src.innerHTML; - } - - } else if ( nodeName === "input" && rcheckableType.test( src.type ) ) { - // IE6-8 fails to persist the checked state of a cloned checkbox - // or radio button. Worse, IE6-7 fail to give the cloned element - // a checked appearance if the defaultChecked value isn't also set - - dest.defaultChecked = dest.checked = src.checked; - - // IE6-7 get confused and end up setting the value of a cloned - // checkbox/radio button to an empty string instead of "on" - if ( dest.value !== src.value ) { - dest.value = src.value; - } - - // IE6-8 fails to return the selected option to the default selected - // state when cloning options - } else if ( nodeName === "option" ) { - dest.selected = src.defaultSelected; - - // IE6-8 fails to set the defaultValue to the correct value when - // cloning other types of input fields - } else if ( nodeName === "input" || nodeName === "textarea" ) { - dest.defaultValue = src.defaultValue; - - // IE blanks contents when cloning scripts - } else if ( nodeName === "script" && dest.text !== src.text ) { - dest.text = src.text; - } - - // Event data gets referenced instead of copied if the expando - // gets copied too - dest.removeAttribute( jQuery.expando ); -} - -jQuery.buildFragment = function( args, context, scripts ) { - var fragment, cacheable, cachehit, - first = args[ 0 ]; - - // Set context from what may come in as undefined or a jQuery collection or a node - // Updated to fix #12266 where accessing context[0] could throw an exception in IE9/10 & - // also doubles as fix for #8950 where plain objects caused createDocumentFragment exception - context = context || document; - context = !context.nodeType && context[0] || context; - context = context.ownerDocument || context; - - // Only cache "small" (1/2 KB) HTML strings that are associated with the main document - // Cloning options loses the selected state, so don't cache them - // IE 6 doesn't like it when you put or elements in a fragment - // Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache - // Lastly, IE6,7,8 will not correctly reuse cached fragments that were created from unknown elems #10501 - if ( args.length === 1 && typeof first === "string" && first.length < 512 && context === document && - first.charAt(0) === "<" && !rnocache.test( first ) && - (jQuery.support.checkClone || !rchecked.test( first )) && - (jQuery.support.html5Clone || !rnoshimcache.test( first )) ) { - - // Mark cacheable and look for a hit - cacheable = true; - fragment = jQuery.fragments[ first ]; - cachehit = fragment !== undefined; - } - - if ( !fragment ) { - fragment = context.createDocumentFragment(); - jQuery.clean( args, context, fragment, scripts ); - - // Update the cache, but only store false - // unless this is a second parsing of the same content - if ( cacheable ) { - jQuery.fragments[ first ] = cachehit && fragment; - } - } - - return { fragment: fragment, cacheable: cacheable }; -}; - -jQuery.fragments = {}; - -jQuery.each({ - appendTo: "append", - prependTo: "prepend", - insertBefore: "before", - insertAfter: "after", - replaceAll: "replaceWith" -}, function( name, original ) { - jQuery.fn[ name ] = function( selector ) { - var elems, - i = 0, - ret = [], - insert = jQuery( selector ), - l = insert.length, - parent = this.length === 1 && this[0].parentNode; - - if ( (parent == null || parent && parent.nodeType === 11 && parent.childNodes.length === 1) && l === 1 ) { - insert[ original ]( this[0] ); - return this; - } else { - for ( ; i < l; i++ ) { - elems = ( i > 0 ? this.clone(true) : this ).get(); - jQuery( insert[i] )[ original ]( elems ); - ret = ret.concat( elems ); - } - - return this.pushStack( ret, name, insert.selector ); - } - }; -}); - -function getAll( elem ) { - if ( typeof elem.getElementsByTagName !== "undefined" ) { - return elem.getElementsByTagName( "*" ); - - } else if ( typeof elem.querySelectorAll !== "undefined" ) { - return elem.querySelectorAll( "*" ); - - } else { - return []; - } -} - -// Used in clean, fixes the defaultChecked property -function fixDefaultChecked( elem ) { - if ( rcheckableType.test( elem.type ) ) { - elem.defaultChecked = elem.checked; - } -} - -jQuery.extend({ - clone: function( elem, dataAndEvents, deepDataAndEvents ) { - var srcElements, - destElements, - i, - clone; - - if ( jQuery.support.html5Clone || jQuery.isXMLDoc(elem) || !rnoshimcache.test( "<" + elem.nodeName + ">" ) ) { - clone = elem.cloneNode( true ); - - // IE<=8 does not properly clone detached, unknown element nodes - } else { - fragmentDiv.innerHTML = elem.outerHTML; - fragmentDiv.removeChild( clone = fragmentDiv.firstChild ); - } - - if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) && - (elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) { - // IE copies events bound via attachEvent when using cloneNode. - // Calling detachEvent on the clone will also remove the events - // from the original. In order to get around this, we use some - // proprietary methods to clear the events. Thanks to MooTools - // guys for this hotness. - - cloneFixAttributes( elem, clone ); - - // Using Sizzle here is crazy slow, so we use getElementsByTagName instead - srcElements = getAll( elem ); - destElements = getAll( clone ); - - // Weird iteration because IE will replace the length property - // with an element if you are cloning the body and one of the - // elements on the page has a name or id of "length" - for ( i = 0; srcElements[i]; ++i ) { - // Ensure that the destination node is not null; Fixes #9587 - if ( destElements[i] ) { - cloneFixAttributes( srcElements[i], destElements[i] ); - } - } - } - - // Copy the events from the original to the clone - if ( dataAndEvents ) { - cloneCopyEvent( elem, clone ); - - if ( deepDataAndEvents ) { - srcElements = getAll( elem ); - destElements = getAll( clone ); - - for ( i = 0; srcElements[i]; ++i ) { - cloneCopyEvent( srcElements[i], destElements[i] ); - } - } - } - - srcElements = destElements = null; - - // Return the cloned set - return clone; - }, - - clean: function( elems, context, fragment, scripts ) { - var i, j, elem, tag, wrap, depth, div, hasBody, tbody, len, handleScript, jsTags, - safe = context === document && safeFragment, - ret = []; - - // Ensure that context is a document - if ( !context || typeof context.createDocumentFragment === "undefined" ) { - context = document; - } - - // Use the already-created safe fragment if context permits - for ( i = 0; (elem = elems[i]) != null; i++ ) { - if ( typeof elem === "number" ) { - elem += ""; - } - - if ( !elem ) { - continue; - } - - // Convert html string into DOM nodes - if ( typeof elem === "string" ) { - if ( !rhtml.test( elem ) ) { - elem = context.createTextNode( elem ); - } else { - // Ensure a safe container in which to render the html - safe = safe || createSafeFragment( context ); - div = context.createElement("div"); - safe.appendChild( div ); - - // Fix "XHTML"-style tags in all browsers - elem = elem.replace(rxhtmlTag, "<$1>"); - - // Go to html and back, then peel off extra wrappers - tag = ( rtagName.exec( elem ) || ["", ""] )[1].toLowerCase(); - wrap = wrapMap[ tag ] || wrapMap._default; - depth = wrap[0]; - div.innerHTML = wrap[1] + elem + wrap[2]; - - // Move to the right depth - while ( depth-- ) { - div = div.lastChild; - } - - // Remove IE's autoinserted from table fragments - if ( !jQuery.support.tbody ) { - - // String was a , *may* have spurious - hasBody = rtbody.test(elem); - tbody = tag === "table" && !hasBody ? - div.firstChild && div.firstChild.childNodes : - - // String was a bare or - wrap[1] === "
                " && !hasBody ? - div.childNodes : - []; - - for ( j = tbody.length - 1; j >= 0 ; --j ) { - if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length ) { - tbody[ j ].parentNode.removeChild( tbody[ j ] ); - } - } - } - - // IE completely kills leading whitespace when innerHTML is used - if ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) { - div.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild ); - } - - elem = div.childNodes; - - // Take out of fragment container (we need a fresh div each time) - div.parentNode.removeChild( div ); - } - } - - if ( elem.nodeType ) { - ret.push( elem ); - } else { - jQuery.merge( ret, elem ); - } - } - - // Fix #11356: Clear elements from safeFragment - if ( div ) { - elem = div = safe = null; - } - - // Reset defaultChecked for any radios and checkboxes - // about to be appended to the DOM in IE 6/7 (#8060) - if ( !jQuery.support.appendChecked ) { - for ( i = 0; (elem = ret[i]) != null; i++ ) { - if ( jQuery.nodeName( elem, "input" ) ) { - fixDefaultChecked( elem ); - } else if ( typeof elem.getElementsByTagName !== "undefined" ) { - jQuery.grep( elem.getElementsByTagName("input"), fixDefaultChecked ); - } - } - } - - // Append elements to a provided document fragment - if ( fragment ) { - // Special handling of each script element - handleScript = function( elem ) { - // Check if we consider it executable - if ( !elem.type || rscriptType.test( elem.type ) ) { - // Detach the script and store it in the scripts array (if provided) or the fragment - // Return truthy to indicate that it has been handled - return scripts ? - scripts.push( elem.parentNode ? elem.parentNode.removeChild( elem ) : elem ) : - fragment.appendChild( elem ); - } - }; - - for ( i = 0; (elem = ret[i]) != null; i++ ) { - // Check if we're done after handling an executable script - if ( !( jQuery.nodeName( elem, "script" ) && handleScript( elem ) ) ) { - // Append to fragment and handle embedded scripts - fragment.appendChild( elem ); - if ( typeof elem.getElementsByTagName !== "undefined" ) { - // handleScript alters the DOM, so use jQuery.merge to ensure snapshot iteration - jsTags = jQuery.grep( jQuery.merge( [], elem.getElementsByTagName("script") ), handleScript ); - - // Splice the scripts into ret after their former ancestor and advance our index beyond them - ret.splice.apply( ret, [i + 1, 0].concat( jsTags ) ); - i += jsTags.length; - } - } - } - } - - return ret; - }, - - cleanData: function( elems, /* internal */ acceptData ) { - var data, id, elem, type, - i = 0, - internalKey = jQuery.expando, - cache = jQuery.cache, - deleteExpando = jQuery.support.deleteExpando, - special = jQuery.event.special; - - for ( ; (elem = elems[i]) != null; i++ ) { - - if ( acceptData || jQuery.acceptData( elem ) ) { - - id = elem[ internalKey ]; - data = id && cache[ id ]; - - if ( data ) { - if ( data.events ) { - for ( type in data.events ) { - if ( special[ type ] ) { - jQuery.event.remove( elem, type ); - - // This is a shortcut to avoid jQuery.event.remove's overhead - } else { - jQuery.removeEvent( elem, type, data.handle ); - } - } - } - - // Remove cache only if it was not already removed by jQuery.event.remove - if ( cache[ id ] ) { - - delete cache[ id ]; - - // IE does not allow us to delete expando properties from nodes, - // nor does it have a removeAttribute function on Document nodes; - // we must handle all of these cases - if ( deleteExpando ) { - delete elem[ internalKey ]; - - } else if ( elem.removeAttribute ) { - elem.removeAttribute( internalKey ); - - } else { - elem[ internalKey ] = null; - } - - jQuery.deletedIds.push( id ); - } - } - } - } - } -}); -// Limit scope pollution from any deprecated API -(function() { - -var matched, browser; - -// Use of jQuery.browser is frowned upon. -// More details: http://api.jquery.com/jQuery.browser -// jQuery.uaMatch maintained for back-compat -jQuery.uaMatch = function( ua ) { - ua = ua.toLowerCase(); - - var match = /(chrome)[ \/]([\w.]+)/.exec( ua ) || - /(webkit)[ \/]([\w.]+)/.exec( ua ) || - /(opera)(?:.*version|)[ \/]([\w.]+)/.exec( ua ) || - /(msie) ([\w.]+)/.exec( ua ) || - ua.indexOf("compatible") < 0 && /(mozilla)(?:.*? rv:([\w.]+)|)/.exec( ua ) || - []; - - return { - browser: match[ 1 ] || "", - version: match[ 2 ] || "0" - }; -}; - -matched = jQuery.uaMatch( navigator.userAgent ); -browser = {}; - -if ( matched.browser ) { - browser[ matched.browser ] = true; - browser.version = matched.version; -} - -// Chrome is Webkit, but Webkit is also Safari. -if ( browser.chrome ) { - browser.webkit = true; -} else if ( browser.webkit ) { - browser.safari = true; -} - -jQuery.browser = browser; - -jQuery.sub = function() { - function jQuerySub( selector, context ) { - return new jQuerySub.fn.init( selector, context ); - } - jQuery.extend( true, jQuerySub, this ); - jQuerySub.superclass = this; - jQuerySub.fn = jQuerySub.prototype = this(); - jQuerySub.fn.constructor = jQuerySub; - jQuerySub.sub = this.sub; - jQuerySub.fn.init = function init( selector, context ) { - if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) { - context = jQuerySub( context ); - } - - return jQuery.fn.init.call( this, selector, context, rootjQuerySub ); - }; - jQuerySub.fn.init.prototype = jQuerySub.fn; - var rootjQuerySub = jQuerySub(document); - return jQuerySub; -}; - -})(); -var curCSS, iframe, iframeDoc, - ralpha = /alpha\([^)]*\)/i, - ropacity = /opacity=([^)]*)/, - rposition = /^(top|right|bottom|left)$/, - // swappable if display is none or starts with table except "table", "table-cell", or "table-caption" - // see here for display values: https://developer.mozilla.org/en-US/docs/CSS/display - rdisplayswap = /^(none|table(?!-c[ea]).+)/, - rmargin = /^margin/, - rnumsplit = new RegExp( "^(" + core_pnum + ")(.*)$", "i" ), - rnumnonpx = new RegExp( "^(" + core_pnum + ")(?!px)[a-z%]+$", "i" ), - rrelNum = new RegExp( "^([-+])=(" + core_pnum + ")", "i" ), - elemdisplay = {}, - - cssShow = { position: "absolute", visibility: "hidden", display: "block" }, - cssNormalTransform = { - letterSpacing: 0, - fontWeight: 400 - }, - - cssExpand = [ "Top", "Right", "Bottom", "Left" ], - cssPrefixes = [ "Webkit", "O", "Moz", "ms" ], - - eventsToggle = jQuery.fn.toggle; - -// return a css property mapped to a potentially vendor prefixed property -function vendorPropName( style, name ) { - - // shortcut for names that are not vendor prefixed - if ( name in style ) { - return name; - } - - // check for vendor prefixed names - var capName = name.charAt(0).toUpperCase() + name.slice(1), - origName = name, - i = cssPrefixes.length; - - while ( i-- ) { - name = cssPrefixes[ i ] + capName; - if ( name in style ) { - return name; - } - } - - return origName; -} - -function isHidden( elem, el ) { - elem = el || elem; - return jQuery.css( elem, "display" ) === "none" || !jQuery.contains( elem.ownerDocument, elem ); -} - -function showHide( elements, show ) { - var elem, display, - values = [], - index = 0, - length = elements.length; - - for ( ; index < length; index++ ) { - elem = elements[ index ]; - if ( !elem.style ) { - continue; - } - values[ index ] = jQuery._data( elem, "olddisplay" ); - if ( show ) { - // Reset the inline display of this element to learn if it is - // being hidden by cascaded rules or not - if ( !values[ index ] && elem.style.display === "none" ) { - elem.style.display = ""; - } - - // Set elements which have been overridden with display: none - // in a stylesheet to whatever the default browser style is - // for such an element - if ( elem.style.display === "" && isHidden( elem ) ) { - values[ index ] = jQuery._data( elem, "olddisplay", css_defaultDisplay(elem.nodeName) ); - } - } else { - display = curCSS( elem, "display" ); - - if ( !values[ index ] && display !== "none" ) { - jQuery._data( elem, "olddisplay", display ); - } - } - } - - // Set the display of most of the elements in a second loop - // to avoid the constant reflow - for ( index = 0; index < length; index++ ) { - elem = elements[ index ]; - if ( !elem.style ) { - continue; - } - if ( !show || elem.style.display === "none" || elem.style.display === "" ) { - elem.style.display = show ? values[ index ] || "" : "none"; - } - } - - return elements; -} - -jQuery.fn.extend({ - css: function( name, value ) { - return jQuery.access( this, function( elem, name, value ) { - return value !== undefined ? - jQuery.style( elem, name, value ) : - jQuery.css( elem, name ); - }, name, value, arguments.length > 1 ); - }, - show: function() { - return showHide( this, true ); - }, - hide: function() { - return showHide( this ); - }, - toggle: function( state, fn2 ) { - var bool = typeof state === "boolean"; - - if ( jQuery.isFunction( state ) && jQuery.isFunction( fn2 ) ) { - return eventsToggle.apply( this, arguments ); - } - - return this.each(function() { - if ( bool ? state : isHidden( this ) ) { - jQuery( this ).show(); - } else { - jQuery( this ).hide(); - } - }); - } -}); - -jQuery.extend({ - // Add in style property hooks for overriding the default - // behavior of getting and setting a style property - cssHooks: { - opacity: { - get: function( elem, computed ) { - if ( computed ) { - // We should always get a number back from opacity - var ret = curCSS( elem, "opacity" ); - return ret === "" ? "1" : ret; - - } - } - } - }, - - // Exclude the following css properties to add px - cssNumber: { - "fillOpacity": true, - "fontWeight": true, - "lineHeight": true, - "opacity": true, - "orphans": true, - "widows": true, - "zIndex": true, - "zoom": true - }, - - // Add in properties whose names you wish to fix before - // setting or getting the value - cssProps: { - // normalize float css property - "float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat" - }, - - // Get and set the style property on a DOM Node - style: function( elem, name, value, extra ) { - // Don't set styles on text and comment nodes - if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) { - return; - } - - // Make sure that we're working with the right name - var ret, type, hooks, - origName = jQuery.camelCase( name ), - style = elem.style; - - name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( style, origName ) ); - - // gets hook for the prefixed version - // followed by the unprefixed version - hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; - - // Check if we're setting a value - if ( value !== undefined ) { - type = typeof value; - - // convert relative number strings (+= or -=) to relative numbers. #7345 - if ( type === "string" && (ret = rrelNum.exec( value )) ) { - value = ( ret[1] + 1 ) * ret[2] + parseFloat( jQuery.css( elem, name ) ); - // Fixes bug #9237 - type = "number"; - } - - // Make sure that NaN and null values aren't set. See: #7116 - if ( value == null || type === "number" && isNaN( value ) ) { - return; - } - - // If a number was passed in, add 'px' to the (except for certain CSS properties) - if ( type === "number" && !jQuery.cssNumber[ origName ] ) { - value += "px"; - } - - // If a hook was provided, use that value, otherwise just set the specified value - if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value, extra )) !== undefined ) { - // Wrapped to prevent IE from throwing errors when 'invalid' values are provided - // Fixes bug #5509 - try { - style[ name ] = value; - } catch(e) {} - } - - } else { - // If a hook was provided get the non-computed value from there - if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) { - return ret; - } - - // Otherwise just get the value from the style object - return style[ name ]; - } - }, - - css: function( elem, name, numeric, extra ) { - var val, num, hooks, - origName = jQuery.camelCase( name ); - - // Make sure that we're working with the right name - name = jQuery.cssProps[ origName ] || ( jQuery.cssProps[ origName ] = vendorPropName( elem.style, origName ) ); - - // gets hook for the prefixed version - // followed by the unprefixed version - hooks = jQuery.cssHooks[ name ] || jQuery.cssHooks[ origName ]; - - // If a hook was provided get the computed value from there - if ( hooks && "get" in hooks ) { - val = hooks.get( elem, true, extra ); - } - - // Otherwise, if a way to get the computed value exists, use that - if ( val === undefined ) { - val = curCSS( elem, name ); - } - - //convert "normal" to computed value - if ( val === "normal" && name in cssNormalTransform ) { - val = cssNormalTransform[ name ]; - } - - // Return, converting to number if forced or a qualifier was provided and val looks numeric - if ( numeric || extra !== undefined ) { - num = parseFloat( val ); - return numeric || jQuery.isNumeric( num ) ? num || 0 : val; - } - return val; - }, - - // A method for quickly swapping in/out CSS properties to get correct calculations - swap: function( elem, options, callback ) { - var ret, name, - old = {}; - - // Remember the old values, and insert the new ones - for ( name in options ) { - old[ name ] = elem.style[ name ]; - elem.style[ name ] = options[ name ]; - } - - ret = callback.call( elem ); - - // Revert the old values - for ( name in options ) { - elem.style[ name ] = old[ name ]; - } - - return ret; - } -}); - -// NOTE: To any future maintainer, we've window.getComputedStyle -// because jsdom on node.js will break without it. -if ( window.getComputedStyle ) { - curCSS = function( elem, name ) { - var ret, width, minWidth, maxWidth, - computed = window.getComputedStyle( elem, null ), - style = elem.style; - - if ( computed ) { - - ret = computed[ name ]; - if ( ret === "" && !jQuery.contains( elem.ownerDocument, elem ) ) { - ret = jQuery.style( elem, name ); - } - - // A tribute to the "awesome hack by Dean Edwards" - // Chrome < 17 and Safari 5.0 uses "computed value" instead of "used value" for margin-right - // Safari 5.1.7 (at least) returns percentage for a larger set of values, but width seems to be reliably pixels - // this is against the CSSOM draft spec: http://dev.w3.org/csswg/cssom/#resolved-values - if ( rnumnonpx.test( ret ) && rmargin.test( name ) ) { - width = style.width; - minWidth = style.minWidth; - maxWidth = style.maxWidth; - - style.minWidth = style.maxWidth = style.width = ret; - ret = computed.width; - - style.width = width; - style.minWidth = minWidth; - style.maxWidth = maxWidth; - } - } - - return ret; - }; -} else if ( document.documentElement.currentStyle ) { - curCSS = function( elem, name ) { - var left, rsLeft, - ret = elem.currentStyle && elem.currentStyle[ name ], - style = elem.style; - - // Avoid setting ret to empty string here - // so we don't default to auto - if ( ret == null && style && style[ name ] ) { - ret = style[ name ]; - } - - // From the awesome hack by Dean Edwards - // http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291 - - // If we're not dealing with a regular pixel number - // but a number that has a weird ending, we need to convert it to pixels - // but not position css attributes, as those are proportional to the parent element instead - // and we can't measure the parent instead because it might trigger a "stacking dolls" problem - if ( rnumnonpx.test( ret ) && !rposition.test( name ) ) { - - // Remember the original values - left = style.left; - rsLeft = elem.runtimeStyle && elem.runtimeStyle.left; - - // Put in the new values to get a computed value out - if ( rsLeft ) { - elem.runtimeStyle.left = elem.currentStyle.left; - } - style.left = name === "fontSize" ? "1em" : ret; - ret = style.pixelLeft + "px"; - - // Revert the changed values - style.left = left; - if ( rsLeft ) { - elem.runtimeStyle.left = rsLeft; - } - } - - return ret === "" ? "auto" : ret; - }; -} - -function setPositiveNumber( elem, value, subtract ) { - var matches = rnumsplit.exec( value ); - return matches ? - Math.max( 0, matches[ 1 ] - ( subtract || 0 ) ) + ( matches[ 2 ] || "px" ) : - value; -} - -function augmentWidthOrHeight( elem, name, extra, isBorderBox ) { - var i = extra === ( isBorderBox ? "border" : "content" ) ? - // If we already have the right measurement, avoid augmentation - 4 : - // Otherwise initialize for horizontal or vertical properties - name === "width" ? 1 : 0, - - val = 0; - - for ( ; i < 4; i += 2 ) { - // both box models exclude margin, so add it if we want it - if ( extra === "margin" ) { - // we use jQuery.css instead of curCSS here - // because of the reliableMarginRight CSS hook! - val += jQuery.css( elem, extra + cssExpand[ i ], true ); - } - - // From this point on we use curCSS for maximum performance (relevant in animations) - if ( isBorderBox ) { - // border-box includes padding, so remove it if we want content - if ( extra === "content" ) { - val -= parseFloat( curCSS( elem, "padding" + cssExpand[ i ] ) ) || 0; - } - - // at this point, extra isn't border nor margin, so remove border - if ( extra !== "margin" ) { - val -= parseFloat( curCSS( elem, "border" + cssExpand[ i ] + "Width" ) ) || 0; - } - } else { - // at this point, extra isn't content, so add padding - val += parseFloat( curCSS( elem, "padding" + cssExpand[ i ] ) ) || 0; - - // at this point, extra isn't content nor padding, so add border - if ( extra !== "padding" ) { - val += parseFloat( curCSS( elem, "border" + cssExpand[ i ] + "Width" ) ) || 0; - } - } - } - - return val; -} - -function getWidthOrHeight( elem, name, extra ) { - - // Start with offset property, which is equivalent to the border-box value - var val = name === "width" ? elem.offsetWidth : elem.offsetHeight, - valueIsBorderBox = true, - isBorderBox = jQuery.support.boxSizing && jQuery.css( elem, "boxSizing" ) === "border-box"; - - // some non-html elements return undefined for offsetWidth, so check for null/undefined - // svg - https://bugzilla.mozilla.org/show_bug.cgi?id=649285 - // MathML - https://bugzilla.mozilla.org/show_bug.cgi?id=491668 - if ( val <= 0 || val == null ) { - // Fall back to computed then uncomputed css if necessary - val = curCSS( elem, name ); - if ( val < 0 || val == null ) { - val = elem.style[ name ]; - } - - // Computed unit is not pixels. Stop here and return. - if ( rnumnonpx.test(val) ) { - return val; - } - - // we need the check for style in case a browser which returns unreliable values - // for getComputedStyle silently falls back to the reliable elem.style - valueIsBorderBox = isBorderBox && ( jQuery.support.boxSizingReliable || val === elem.style[ name ] ); - - // Normalize "", auto, and prepare for extra - val = parseFloat( val ) || 0; - } - - // use the active box-sizing model to add/subtract irrelevant styles - return ( val + - augmentWidthOrHeight( - elem, - name, - extra || ( isBorderBox ? "border" : "content" ), - valueIsBorderBox - ) - ) + "px"; -} - - -// Try to determine the default display value of an element -function css_defaultDisplay( nodeName ) { - if ( elemdisplay[ nodeName ] ) { - return elemdisplay[ nodeName ]; - } - - var elem = jQuery( "<" + nodeName + ">" ).appendTo( document.body ), - display = elem.css("display"); - elem.remove(); - - // If the simple way fails, - // get element's real default display by attaching it to a temp iframe - if ( display === "none" || display === "" ) { - // Use the already-created iframe if possible - iframe = document.body.appendChild( - iframe || jQuery.extend( document.createElement("iframe"), { - frameBorder: 0, - width: 0, - height: 0 - }) - ); - - // Create a cacheable copy of the iframe document on first call. - // IE and Opera will allow us to reuse the iframeDoc without re-writing the fake HTML - // document to it; WebKit & Firefox won't allow reusing the iframe document. - if ( !iframeDoc || !iframe.createElement ) { - iframeDoc = ( iframe.contentWindow || iframe.contentDocument ).document; - iframeDoc.write(""); - iframeDoc.close(); - } - - elem = iframeDoc.body.appendChild( iframeDoc.createElement(nodeName) ); - - display = curCSS( elem, "display" ); - document.body.removeChild( iframe ); - } - - // Store the correct default display - elemdisplay[ nodeName ] = display; - - return display; -} - -jQuery.each([ "height", "width" ], function( i, name ) { - jQuery.cssHooks[ name ] = { - get: function( elem, computed, extra ) { - if ( computed ) { - // certain elements can have dimension info if we invisibly show them - // however, it must have a current display style that would benefit from this - if ( elem.offsetWidth === 0 && rdisplayswap.test( curCSS( elem, "display" ) ) ) { - return jQuery.swap( elem, cssShow, function() { - return getWidthOrHeight( elem, name, extra ); - }); - } else { - return getWidthOrHeight( elem, name, extra ); - } - } - }, - - set: function( elem, value, extra ) { - return setPositiveNumber( elem, value, extra ? - augmentWidthOrHeight( - elem, - name, - extra, - jQuery.support.boxSizing && jQuery.css( elem, "boxSizing" ) === "border-box" - ) : 0 - ); - } - }; -}); - -if ( !jQuery.support.opacity ) { - jQuery.cssHooks.opacity = { - get: function( elem, computed ) { - // IE uses filters for opacity - return ropacity.test( (computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "" ) ? - ( 0.01 * parseFloat( RegExp.$1 ) ) + "" : - computed ? "1" : ""; - }, - - set: function( elem, value ) { - var style = elem.style, - currentStyle = elem.currentStyle, - opacity = jQuery.isNumeric( value ) ? "alpha(opacity=" + value * 100 + ")" : "", - filter = currentStyle && currentStyle.filter || style.filter || ""; - - // IE has trouble with opacity if it does not have layout - // Force it by setting the zoom level - style.zoom = 1; - - // if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652 - if ( value >= 1 && jQuery.trim( filter.replace( ralpha, "" ) ) === "" && - style.removeAttribute ) { - - // Setting style.filter to null, "" & " " still leave "filter:" in the cssText - // if "filter:" is present at all, clearType is disabled, we want to avoid this - // style.removeAttribute is IE Only, but so apparently is this code path... - style.removeAttribute( "filter" ); - - // if there there is no filter style applied in a css rule, we are done - if ( currentStyle && !currentStyle.filter ) { - return; - } - } - - // otherwise, set new filter values - style.filter = ralpha.test( filter ) ? - filter.replace( ralpha, opacity ) : - filter + " " + opacity; - } - }; -} - -// These hooks cannot be added until DOM ready because the support test -// for it is not run until after DOM ready -jQuery(function() { - if ( !jQuery.support.reliableMarginRight ) { - jQuery.cssHooks.marginRight = { - get: function( elem, computed ) { - // WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right - // Work around by temporarily setting element display to inline-block - return jQuery.swap( elem, { "display": "inline-block" }, function() { - if ( computed ) { - return curCSS( elem, "marginRight" ); - } - }); - } - }; - } - - // Webkit bug: https://bugs.webkit.org/show_bug.cgi?id=29084 - // getComputedStyle returns percent when specified for top/left/bottom/right - // rather than make the css module depend on the offset module, we just check for it here - if ( !jQuery.support.pixelPosition && jQuery.fn.position ) { - jQuery.each( [ "top", "left" ], function( i, prop ) { - jQuery.cssHooks[ prop ] = { - get: function( elem, computed ) { - if ( computed ) { - var ret = curCSS( elem, prop ); - // if curCSS returns percentage, fallback to offset - return rnumnonpx.test( ret ) ? jQuery( elem ).position()[ prop ] + "px" : ret; - } - } - }; - }); - } - -}); - -if ( jQuery.expr && jQuery.expr.filters ) { - jQuery.expr.filters.hidden = function( elem ) { - return ( elem.offsetWidth === 0 && elem.offsetHeight === 0 ) || (!jQuery.support.reliableHiddenOffsets && ((elem.style && elem.style.display) || curCSS( elem, "display" )) === "none"); - }; - - jQuery.expr.filters.visible = function( elem ) { - return !jQuery.expr.filters.hidden( elem ); - }; -} - -// These hooks are used by animate to expand properties -jQuery.each({ - margin: "", - padding: "", - border: "Width" -}, function( prefix, suffix ) { - jQuery.cssHooks[ prefix + suffix ] = { - expand: function( value ) { - var i, - - // assumes a single number if not a string - parts = typeof value === "string" ? value.split(" ") : [ value ], - expanded = {}; - - for ( i = 0; i < 4; i++ ) { - expanded[ prefix + cssExpand[ i ] + suffix ] = - parts[ i ] || parts[ i - 2 ] || parts[ 0 ]; - } - - return expanded; - } - }; - - if ( !rmargin.test( prefix ) ) { - jQuery.cssHooks[ prefix + suffix ].set = setPositiveNumber; - } -}); -var r20 = /%20/g, - rbracket = /\[\]$/, - rCRLF = /\r?\n/g, - rinput = /^(?:color|date|datetime|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i, - rselectTextarea = /^(?:select|textarea)/i; - -jQuery.fn.extend({ - serialize: function() { - return jQuery.param( this.serializeArray() ); - }, - serializeArray: function() { - return this.map(function(){ - return this.elements ? jQuery.makeArray( this.elements ) : this; - }) - .filter(function(){ - return this.name && !this.disabled && - ( this.checked || rselectTextarea.test( this.nodeName ) || - rinput.test( this.type ) ); - }) - .map(function( i, elem ){ - var val = jQuery( this ).val(); - - return val == null ? - null : - jQuery.isArray( val ) ? - jQuery.map( val, function( val, i ){ - return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; - }) : - { name: elem.name, value: val.replace( rCRLF, "\r\n" ) }; - }).get(); - } -}); - -//Serialize an array of form elements or a set of -//key/values into a query string -jQuery.param = function( a, traditional ) { - var prefix, - s = [], - add = function( key, value ) { - // If value is a function, invoke it and return its value - value = jQuery.isFunction( value ) ? value() : ( value == null ? "" : value ); - s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value ); - }; - - // Set traditional to true for jQuery <= 1.3.2 behavior. - if ( traditional === undefined ) { - traditional = jQuery.ajaxSettings && jQuery.ajaxSettings.traditional; - } - - // If an array was passed in, assume that it is an array of form elements. - if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) { - // Serialize the form elements - jQuery.each( a, function() { - add( this.name, this.value ); - }); - - } else { - // If traditional, encode the "old" way (the way 1.3.2 or older - // did it), otherwise encode params recursively. - for ( prefix in a ) { - buildParams( prefix, a[ prefix ], traditional, add ); - } - } - - // Return the resulting serialization - return s.join( "&" ).replace( r20, "+" ); -}; - -function buildParams( prefix, obj, traditional, add ) { - var name; - - if ( jQuery.isArray( obj ) ) { - // Serialize array item. - jQuery.each( obj, function( i, v ) { - if ( traditional || rbracket.test( prefix ) ) { - // Treat each array item as a scalar. - add( prefix, v ); - - } else { - // If array item is non-scalar (array or object), encode its - // numeric index to resolve deserialization ambiguity issues. - // Note that rack (as of 1.0.0) can't currently deserialize - // nested arrays properly, and attempting to do so may cause - // a server error. Possible fixes are to modify rack's - // deserialization algorithm or to provide an option or flag - // to force array serialization to be shallow. - buildParams( prefix + "[" + ( typeof v === "object" ? i : "" ) + "]", v, traditional, add ); - } - }); - - } else if ( !traditional && jQuery.type( obj ) === "object" ) { - // Serialize object item. - for ( name in obj ) { - buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add ); - } - - } else { - // Serialize scalar item. - add( prefix, obj ); - } -} -var - // Document location - ajaxLocParts, - ajaxLocation, - - rhash = /#.*$/, - rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL - // #7653, #8125, #8152: local protocol detection - rlocalProtocol = /^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/, - rnoContent = /^(?:GET|HEAD)$/, - rprotocol = /^\/\//, - rquery = /\?/, - rscript = /)<[^<]*)*<\/script>/gi, - rts = /([?&])_=[^&]*/, - rurl = /^([\w\+\.\-]+:)(?:\/\/([^\/?#:]*)(?::(\d+)|)|)/, - - // Keep a copy of the old load method - _load = jQuery.fn.load, - - /* Prefilters - * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example) - * 2) These are called: - * - BEFORE asking for a transport - * - AFTER param serialization (s.data is a string if s.processData is true) - * 3) key is the dataType - * 4) the catchall symbol "*" can be used - * 5) execution will start with transport dataType and THEN continue down to "*" if needed - */ - prefilters = {}, - - /* Transports bindings - * 1) key is the dataType - * 2) the catchall symbol "*" can be used - * 3) selection will start with transport dataType and THEN go to "*" if needed - */ - transports = {}, - - // Avoid comment-prolog char sequence (#10098); must appease lint and evade compression - allTypes = ["*/"] + ["*"]; - -// #8138, IE may throw an exception when accessing -// a field from window.location if document.domain has been set -try { - ajaxLocation = location.href; -} catch( e ) { - // Use the href attribute of an A element - // since IE will modify it given document.location - ajaxLocation = document.createElement( "a" ); - ajaxLocation.href = ""; - ajaxLocation = ajaxLocation.href; -} - -// Segment location into parts -ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() ) || []; - -// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport -function addToPrefiltersOrTransports( structure ) { - - // dataTypeExpression is optional and defaults to "*" - return function( dataTypeExpression, func ) { - - if ( typeof dataTypeExpression !== "string" ) { - func = dataTypeExpression; - dataTypeExpression = "*"; - } - - var dataType, list, placeBefore, - dataTypes = dataTypeExpression.toLowerCase().split( core_rspace ), - i = 0, - length = dataTypes.length; - - if ( jQuery.isFunction( func ) ) { - // For each dataType in the dataTypeExpression - for ( ; i < length; i++ ) { - dataType = dataTypes[ i ]; - // We control if we're asked to add before - // any existing element - placeBefore = /^\+/.test( dataType ); - if ( placeBefore ) { - dataType = dataType.substr( 1 ) || "*"; - } - list = structure[ dataType ] = structure[ dataType ] || []; - // then we add to the structure accordingly - list[ placeBefore ? "unshift" : "push" ]( func ); - } - } - }; -} - -// Base inspection function for prefilters and transports -function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR, - dataType /* internal */, inspected /* internal */ ) { - - dataType = dataType || options.dataTypes[ 0 ]; - inspected = inspected || {}; - - inspected[ dataType ] = true; - - var selection, - list = structure[ dataType ], - i = 0, - length = list ? list.length : 0, - executeOnly = ( structure === prefilters ); - - for ( ; i < length && ( executeOnly || !selection ); i++ ) { - selection = list[ i ]( options, originalOptions, jqXHR ); - // If we got redirected to another dataType - // we try there if executing only and not done already - if ( typeof selection === "string" ) { - if ( !executeOnly || inspected[ selection ] ) { - selection = undefined; - } else { - options.dataTypes.unshift( selection ); - selection = inspectPrefiltersOrTransports( - structure, options, originalOptions, jqXHR, selection, inspected ); - } - } - } - // If we're only executing or nothing was selected - // we try the catchall dataType if not done already - if ( ( executeOnly || !selection ) && !inspected[ "*" ] ) { - selection = inspectPrefiltersOrTransports( - structure, options, originalOptions, jqXHR, "*", inspected ); - } - // unnecessary when only executing (prefilters) - // but it'll be ignored by the caller in that case - return selection; -} - -// A special extend for ajax options -// that takes "flat" options (not to be deep extended) -// Fixes #9887 -function ajaxExtend( target, src ) { - var key, deep, - flatOptions = jQuery.ajaxSettings.flatOptions || {}; - for ( key in src ) { - if ( src[ key ] !== undefined ) { - ( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ]; - } - } - if ( deep ) { - jQuery.extend( true, target, deep ); - } -} - -jQuery.fn.load = function( url, params, callback ) { - if ( typeof url !== "string" && _load ) { - return _load.apply( this, arguments ); - } - - // Don't do a request if no elements are being requested - if ( !this.length ) { - return this; - } - - var selector, type, response, - self = this, - off = url.indexOf(" "); - - if ( off >= 0 ) { - selector = url.slice( off, url.length ); - url = url.slice( 0, off ); - } - - // If it's a function - if ( jQuery.isFunction( params ) ) { - - // We assume that it's the callback - callback = params; - params = undefined; - - // Otherwise, build a param string - } else if ( params && typeof params === "object" ) { - type = "POST"; - } - - // Request the remote document - jQuery.ajax({ - url: url, - - // if "type" variable is undefined, then "GET" method will be used - type: type, - dataType: "html", - data: params, - complete: function( jqXHR, status ) { - if ( callback ) { - self.each( callback, response || [ jqXHR.responseText, status, jqXHR ] ); - } - } - }).done(function( responseText ) { - - // Save response for use in complete callback - response = arguments; - - // See if a selector was specified - self.html( selector ? - - // Create a dummy div to hold the results - jQuery("
                ") - - // inject the contents of the document in, removing the scripts - // to avoid any 'Permission Denied' errors in IE - .append( responseText.replace( rscript, "" ) ) - - // Locate the specified elements - .find( selector ) : - - // If not, just inject the full result - responseText ); - - }); - - return this; -}; - -// Attach a bunch of functions for handling common AJAX events -jQuery.each( "ajaxStart ajaxStop ajaxComplete ajaxError ajaxSuccess ajaxSend".split( " " ), function( i, o ){ - jQuery.fn[ o ] = function( f ){ - return this.on( o, f ); - }; -}); - -jQuery.each( [ "get", "post" ], function( i, method ) { - jQuery[ method ] = function( url, data, callback, type ) { - // shift arguments if data argument was omitted - if ( jQuery.isFunction( data ) ) { - type = type || callback; - callback = data; - data = undefined; - } - - return jQuery.ajax({ - type: method, - url: url, - data: data, - success: callback, - dataType: type - }); - }; -}); - -jQuery.extend({ - - getScript: function( url, callback ) { - return jQuery.get( url, undefined, callback, "script" ); - }, - - getJSON: function( url, data, callback ) { - return jQuery.get( url, data, callback, "json" ); - }, - - // Creates a full fledged settings object into target - // with both ajaxSettings and settings fields. - // If target is omitted, writes into ajaxSettings. - ajaxSetup: function( target, settings ) { - if ( settings ) { - // Building a settings object - ajaxExtend( target, jQuery.ajaxSettings ); - } else { - // Extending ajaxSettings - settings = target; - target = jQuery.ajaxSettings; - } - ajaxExtend( target, settings ); - return target; - }, - - ajaxSettings: { - url: ajaxLocation, - isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ), - global: true, - type: "GET", - contentType: "application/x-www-form-urlencoded; charset=UTF-8", - processData: true, - async: true, - /* - timeout: 0, - data: null, - dataType: null, - username: null, - password: null, - cache: null, - throws: false, - traditional: false, - headers: {}, - */ - - accepts: { - xml: "application/xml, text/xml", - html: "text/html", - text: "text/plain", - json: "application/json, text/javascript", - "*": allTypes - }, - - contents: { - xml: /xml/, - html: /html/, - json: /json/ - }, - - responseFields: { - xml: "responseXML", - text: "responseText" - }, - - // List of data converters - // 1) key format is "source_type destination_type" (a single space in-between) - // 2) the catchall symbol "*" can be used for source_type - converters: { - - // Convert anything to text - "* text": window.String, - - // Text to html (true = no transformation) - "text html": true, - - // Evaluate text as a json expression - "text json": jQuery.parseJSON, - - // Parse text as xml - "text xml": jQuery.parseXML - }, - - // For options that shouldn't be deep extended: - // you can add your own custom options here if - // and when you create one that shouldn't be - // deep extended (see ajaxExtend) - flatOptions: { - context: true, - url: true - } - }, - - ajaxPrefilter: addToPrefiltersOrTransports( prefilters ), - ajaxTransport: addToPrefiltersOrTransports( transports ), - - // Main method - ajax: function( url, options ) { - - // If url is an object, simulate pre-1.5 signature - if ( typeof url === "object" ) { - options = url; - url = undefined; - } - - // Force options to be an object - options = options || {}; - - var // ifModified key - ifModifiedKey, - // Response headers - responseHeadersString, - responseHeaders, - // transport - transport, - // timeout handle - timeoutTimer, - // Cross-domain detection vars - parts, - // To know if global events are to be dispatched - fireGlobals, - // Loop variable - i, - // Create the final options object - s = jQuery.ajaxSetup( {}, options ), - // Callbacks context - callbackContext = s.context || s, - // Context for global events - // It's the callbackContext if one was provided in the options - // and if it's a DOM node or a jQuery collection - globalEventContext = callbackContext !== s && - ( callbackContext.nodeType || callbackContext instanceof jQuery ) ? - jQuery( callbackContext ) : jQuery.event, - // Deferreds - deferred = jQuery.Deferred(), - completeDeferred = jQuery.Callbacks( "once memory" ), - // Status-dependent callbacks - statusCode = s.statusCode || {}, - // Headers (they are sent all at once) - requestHeaders = {}, - requestHeadersNames = {}, - // The jqXHR state - state = 0, - // Default abort message - strAbort = "canceled", - // Fake xhr - jqXHR = { - - readyState: 0, - - // Caches the header - setRequestHeader: function( name, value ) { - if ( !state ) { - var lname = name.toLowerCase(); - name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name; - requestHeaders[ name ] = value; - } - return this; - }, - - // Raw string - getAllResponseHeaders: function() { - return state === 2 ? responseHeadersString : null; - }, - - // Builds headers hashtable if needed - getResponseHeader: function( key ) { - var match; - if ( state === 2 ) { - if ( !responseHeaders ) { - responseHeaders = {}; - while( ( match = rheaders.exec( responseHeadersString ) ) ) { - responseHeaders[ match[1].toLowerCase() ] = match[ 2 ]; - } - } - match = responseHeaders[ key.toLowerCase() ]; - } - return match === undefined ? null : match; - }, - - // Overrides response content-type header - overrideMimeType: function( type ) { - if ( !state ) { - s.mimeType = type; - } - return this; - }, - - // Cancel the request - abort: function( statusText ) { - statusText = statusText || strAbort; - if ( transport ) { - transport.abort( statusText ); - } - done( 0, statusText ); - return this; - } - }; - - // Callback for when everything is done - // It is defined here because jslint complains if it is declared - // at the end of the function (which would be more logical and readable) - function done( status, nativeStatusText, responses, headers ) { - var isSuccess, success, error, response, modified, - statusText = nativeStatusText; - - // Called once - if ( state === 2 ) { - return; - } - - // State is "done" now - state = 2; - - // Clear timeout if it exists - if ( timeoutTimer ) { - clearTimeout( timeoutTimer ); - } - - // Dereference transport for early garbage collection - // (no matter how long the jqXHR object will be used) - transport = undefined; - - // Cache response headers - responseHeadersString = headers || ""; - - // Set readyState - jqXHR.readyState = status > 0 ? 4 : 0; - - // Get response data - if ( responses ) { - response = ajaxHandleResponses( s, jqXHR, responses ); - } - - // If successful, handle type chaining - if ( status >= 200 && status < 300 || status === 304 ) { - - // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. - if ( s.ifModified ) { - - modified = jqXHR.getResponseHeader("Last-Modified"); - if ( modified ) { - jQuery.lastModified[ ifModifiedKey ] = modified; - } - modified = jqXHR.getResponseHeader("Etag"); - if ( modified ) { - jQuery.etag[ ifModifiedKey ] = modified; - } - } - - // If not modified - if ( status === 304 ) { - - statusText = "notmodified"; - isSuccess = true; - - // If we have data - } else { - - isSuccess = ajaxConvert( s, response ); - statusText = isSuccess.state; - success = isSuccess.data; - error = isSuccess.error; - isSuccess = !error; - } - } else { - // We extract error from statusText - // then normalize statusText and status for non-aborts - error = statusText; - if ( !statusText || status ) { - statusText = "error"; - if ( status < 0 ) { - status = 0; - } - } - } - - // Set data for the fake xhr object - jqXHR.status = status; - jqXHR.statusText = ( nativeStatusText || statusText ) + ""; - - // Success/Error - if ( isSuccess ) { - deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] ); - } else { - deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] ); - } - - // Status-dependent callbacks - jqXHR.statusCode( statusCode ); - statusCode = undefined; - - if ( fireGlobals ) { - globalEventContext.trigger( "ajax" + ( isSuccess ? "Success" : "Error" ), - [ jqXHR, s, isSuccess ? success : error ] ); - } - - // Complete - completeDeferred.fireWith( callbackContext, [ jqXHR, statusText ] ); - - if ( fireGlobals ) { - globalEventContext.trigger( "ajaxComplete", [ jqXHR, s ] ); - // Handle the global AJAX counter - if ( !( --jQuery.active ) ) { - jQuery.event.trigger( "ajaxStop" ); - } - } - } - - // Attach deferreds - deferred.promise( jqXHR ); - jqXHR.success = jqXHR.done; - jqXHR.error = jqXHR.fail; - jqXHR.complete = completeDeferred.add; - - // Status-dependent callbacks - jqXHR.statusCode = function( map ) { - if ( map ) { - var tmp; - if ( state < 2 ) { - for ( tmp in map ) { - statusCode[ tmp ] = [ statusCode[tmp], map[tmp] ]; - } - } else { - tmp = map[ jqXHR.status ]; - jqXHR.always( tmp ); - } - } - return this; - }; - - // Remove hash character (#7531: and string promotion) - // Add protocol if not provided (#5866: IE7 issue with protocol-less urls) - // We also use the url parameter if available - s.url = ( ( url || s.url ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" ); - - // Extract dataTypes list - s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().split( core_rspace ); - - // A cross-domain request is in order when we have a protocol:host:port mismatch - if ( s.crossDomain == null ) { - parts = rurl.exec( s.url.toLowerCase() ) || false; - s.crossDomain = parts && ( parts.join(":") + ( parts[ 3 ] ? "" : parts[ 1 ] === "http:" ? 80 : 443 ) ) !== - ( ajaxLocParts.join(":") + ( ajaxLocParts[ 3 ] ? "" : ajaxLocParts[ 1 ] === "http:" ? 80 : 443 ) ); - } - - // Convert data if not already a string - if ( s.data && s.processData && typeof s.data !== "string" ) { - s.data = jQuery.param( s.data, s.traditional ); - } - - // Apply prefilters - inspectPrefiltersOrTransports( prefilters, s, options, jqXHR ); - - // If request was aborted inside a prefilter, stop there - if ( state === 2 ) { - return jqXHR; - } - - // We can fire global events as of now if asked to - fireGlobals = s.global; - - // Uppercase the type - s.type = s.type.toUpperCase(); - - // Determine if request has content - s.hasContent = !rnoContent.test( s.type ); - - // Watch for a new set of requests - if ( fireGlobals && jQuery.active++ === 0 ) { - jQuery.event.trigger( "ajaxStart" ); - } - - // More options handling for requests with no content - if ( !s.hasContent ) { - - // If data is available, append data to url - if ( s.data ) { - s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.data; - // #9682: remove data so that it's not used in an eventual retry - delete s.data; - } - - // Get ifModifiedKey before adding the anti-cache parameter - ifModifiedKey = s.url; - - // Add anti-cache in url if needed - if ( s.cache === false ) { - - var ts = jQuery.now(), - // try replacing _= if it is there - ret = s.url.replace( rts, "$1_=" + ts ); - - // if nothing was replaced, add timestamp to the end - s.url = ret + ( ( ret === s.url ) ? ( rquery.test( s.url ) ? "&" : "?" ) + "_=" + ts : "" ); - } - } - - // Set the correct header, if data is being sent - if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) { - jqXHR.setRequestHeader( "Content-Type", s.contentType ); - } - - // Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode. - if ( s.ifModified ) { - ifModifiedKey = ifModifiedKey || s.url; - if ( jQuery.lastModified[ ifModifiedKey ] ) { - jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ ifModifiedKey ] ); - } - if ( jQuery.etag[ ifModifiedKey ] ) { - jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ ifModifiedKey ] ); - } - } - - // Set the Accepts header for the server, depending on the dataType - jqXHR.setRequestHeader( - "Accept", - s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ? - s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; q=0.01" : "" ) : - s.accepts[ "*" ] - ); - - // Check for headers option - for ( i in s.headers ) { - jqXHR.setRequestHeader( i, s.headers[ i ] ); - } - - // Allow custom headers/mimetypes and early abort - if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) { - // Abort if not done already and return - return jqXHR.abort(); - - } - - // aborting is no longer a cancellation - strAbort = "abort"; - - // Install callbacks on deferreds - for ( i in { success: 1, error: 1, complete: 1 } ) { - jqXHR[ i ]( s[ i ] ); - } - - // Get transport - transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR ); - - // If no transport, we auto-abort - if ( !transport ) { - done( -1, "No Transport" ); - } else { - jqXHR.readyState = 1; - // Send global event - if ( fireGlobals ) { - globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] ); - } - // Timeout - if ( s.async && s.timeout > 0 ) { - timeoutTimer = setTimeout( function(){ - jqXHR.abort( "timeout" ); - }, s.timeout ); - } - - try { - state = 1; - transport.send( requestHeaders, done ); - } catch (e) { - // Propagate exception as error if not done - if ( state < 2 ) { - done( -1, e ); - // Simply rethrow otherwise - } else { - throw e; - } - } - } - - return jqXHR; - }, - - // Counter for holding the number of active queries - active: 0, - - // Last-Modified header cache for next request - lastModified: {}, - etag: {} - -}); - -/* Handles responses to an ajax request: - * - sets all responseXXX fields accordingly - * - finds the right dataType (mediates between content-type and expected dataType) - * - returns the corresponding response - */ -function ajaxHandleResponses( s, jqXHR, responses ) { - - var ct, type, finalDataType, firstDataType, - contents = s.contents, - dataTypes = s.dataTypes, - responseFields = s.responseFields; - - // Fill responseXXX fields - for ( type in responseFields ) { - if ( type in responses ) { - jqXHR[ responseFields[type] ] = responses[ type ]; - } - } - - // Remove auto dataType and get content-type in the process - while( dataTypes[ 0 ] === "*" ) { - dataTypes.shift(); - if ( ct === undefined ) { - ct = s.mimeType || jqXHR.getResponseHeader( "content-type" ); - } - } - - // Check if we're dealing with a known content-type - if ( ct ) { - for ( type in contents ) { - if ( contents[ type ] && contents[ type ].test( ct ) ) { - dataTypes.unshift( type ); - break; - } - } - } - - // Check to see if we have a response for the expected dataType - if ( dataTypes[ 0 ] in responses ) { - finalDataType = dataTypes[ 0 ]; - } else { - // Try convertible dataTypes - for ( type in responses ) { - if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) { - finalDataType = type; - break; - } - if ( !firstDataType ) { - firstDataType = type; - } - } - // Or just use first one - finalDataType = finalDataType || firstDataType; - } - - // If we found a dataType - // We add the dataType to the list if needed - // and return the corresponding response - if ( finalDataType ) { - if ( finalDataType !== dataTypes[ 0 ] ) { - dataTypes.unshift( finalDataType ); - } - return responses[ finalDataType ]; - } -} - -// Chain conversions given the request and the original response -function ajaxConvert( s, response ) { - - var conv, conv2, current, tmp, - // Work with a copy of dataTypes in case we need to modify it for conversion - dataTypes = s.dataTypes.slice(), - prev = dataTypes[ 0 ], - converters = {}, - i = 0; - - // Apply the dataFilter if provided - if ( s.dataFilter ) { - response = s.dataFilter( response, s.dataType ); - } - - // Create converters map with lowercased keys - if ( dataTypes[ 1 ] ) { - for ( conv in s.converters ) { - converters[ conv.toLowerCase() ] = s.converters[ conv ]; - } - } - - // Convert to each sequential dataType, tolerating list modification - for ( ; (current = dataTypes[++i]); ) { - - // There's only work to do if current dataType is non-auto - if ( current !== "*" ) { - - // Convert response if prev dataType is non-auto and differs from current - if ( prev !== "*" && prev !== current ) { - - // Seek a direct converter - conv = converters[ prev + " " + current ] || converters[ "* " + current ]; - - // If none found, seek a pair - if ( !conv ) { - for ( conv2 in converters ) { - - // If conv2 outputs current - tmp = conv2.split(" "); - if ( tmp[ 1 ] === current ) { - - // If prev can be converted to accepted input - conv = converters[ prev + " " + tmp[ 0 ] ] || - converters[ "* " + tmp[ 0 ] ]; - if ( conv ) { - // Condense equivalence converters - if ( conv === true ) { - conv = converters[ conv2 ]; - - // Otherwise, insert the intermediate dataType - } else if ( converters[ conv2 ] !== true ) { - current = tmp[ 0 ]; - dataTypes.splice( i--, 0, current ); - } - - break; - } - } - } - } - - // Apply converter (if not an equivalence) - if ( conv !== true ) { - - // Unless errors are allowed to bubble, catch and return them - if ( conv && s["throws"] ) { - response = conv( response ); - } else { - try { - response = conv( response ); - } catch ( e ) { - return { state: "parsererror", error: conv ? e : "No conversion from " + prev + " to " + current }; - } - } - } - } - - // Update prev for next iteration - prev = current; - } - } - - return { state: "success", data: response }; -} -var oldCallbacks = [], - rquestion = /\?/, - rjsonp = /(=)\?(?=&|$)|\?\?/, - nonce = jQuery.now(); - -// Default jsonp settings -jQuery.ajaxSetup({ - jsonp: "callback", - jsonpCallback: function() { - var callback = oldCallbacks.pop() || ( jQuery.expando + "_" + ( nonce++ ) ); - this[ callback ] = true; - return callback; - } -}); - -// Detect, normalize options and install callbacks for jsonp requests -jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) { - - var callbackName, overwritten, responseContainer, - data = s.data, - url = s.url, - hasCallback = s.jsonp !== false, - replaceInUrl = hasCallback && rjsonp.test( url ), - replaceInData = hasCallback && !replaceInUrl && typeof data === "string" && - !( s.contentType || "" ).indexOf("application/x-www-form-urlencoded") && - rjsonp.test( data ); - - // Handle iff the expected data type is "jsonp" or we have a parameter to set - if ( s.dataTypes[ 0 ] === "jsonp" || replaceInUrl || replaceInData ) { - - // Get callback name, remembering preexisting value associated with it - callbackName = s.jsonpCallback = jQuery.isFunction( s.jsonpCallback ) ? - s.jsonpCallback() : - s.jsonpCallback; - overwritten = window[ callbackName ]; - - // Insert callback into url or form data - if ( replaceInUrl ) { - s.url = url.replace( rjsonp, "$1" + callbackName ); - } else if ( replaceInData ) { - s.data = data.replace( rjsonp, "$1" + callbackName ); - } else if ( hasCallback ) { - s.url += ( rquestion.test( url ) ? "&" : "?" ) + s.jsonp + "=" + callbackName; - } - - // Use data converter to retrieve json after script execution - s.converters["script json"] = function() { - if ( !responseContainer ) { - jQuery.error( callbackName + " was not called" ); - } - return responseContainer[ 0 ]; - }; - - // force json dataType - s.dataTypes[ 0 ] = "json"; - - // Install callback - window[ callbackName ] = function() { - responseContainer = arguments; - }; - - // Clean-up function (fires after converters) - jqXHR.always(function() { - // Restore preexisting value - window[ callbackName ] = overwritten; - - // Save back as free - if ( s[ callbackName ] ) { - // make sure that re-using the options doesn't screw things around - s.jsonpCallback = originalSettings.jsonpCallback; - - // save the callback name for future use - oldCallbacks.push( callbackName ); - } - - // Call if it was a function and we have a response - if ( responseContainer && jQuery.isFunction( overwritten ) ) { - overwritten( responseContainer[ 0 ] ); - } - - responseContainer = overwritten = undefined; - }); - - // Delegate to script - return "script"; - } -}); -// Install script dataType -jQuery.ajaxSetup({ - accepts: { - script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript" - }, - contents: { - script: /javascript|ecmascript/ - }, - converters: { - "text script": function( text ) { - jQuery.globalEval( text ); - return text; - } - } -}); - -// Handle cache's special case and global -jQuery.ajaxPrefilter( "script", function( s ) { - if ( s.cache === undefined ) { - s.cache = false; - } - if ( s.crossDomain ) { - s.type = "GET"; - s.global = false; - } -}); - -// Bind script tag hack transport -jQuery.ajaxTransport( "script", function(s) { - - // This transport only deals with cross domain requests - if ( s.crossDomain ) { - - var script, - head = document.head || document.getElementsByTagName( "head" )[0] || document.documentElement; - - return { - - send: function( _, callback ) { - - script = document.createElement( "script" ); - - script.async = "async"; - - if ( s.scriptCharset ) { - script.charset = s.scriptCharset; - } - - script.src = s.url; - - // Attach handlers for all browsers - script.onload = script.onreadystatechange = function( _, isAbort ) { - - if ( isAbort || !script.readyState || /loaded|complete/.test( script.readyState ) ) { - - // Handle memory leak in IE - script.onload = script.onreadystatechange = null; - - // Remove the script - if ( head && script.parentNode ) { - head.removeChild( script ); - } - - // Dereference the script - script = undefined; - - // Callback if not abort - if ( !isAbort ) { - callback( 200, "success" ); - } - } - }; - // Use insertBefore instead of appendChild to circumvent an IE6 bug. - // This arises when a base node is used (#2709 and #4378). - head.insertBefore( script, head.firstChild ); - }, - - abort: function() { - if ( script ) { - script.onload( 0, 1 ); - } - } - }; - } -}); -var xhrCallbacks, - // #5280: Internet Explorer will keep connections alive if we don't abort on unload - xhrOnUnloadAbort = window.ActiveXObject ? function() { - // Abort all pending requests - for ( var key in xhrCallbacks ) { - xhrCallbacks[ key ]( 0, 1 ); - } - } : false, - xhrId = 0; - -// Functions to create xhrs -function createStandardXHR() { - try { - return new window.XMLHttpRequest(); - } catch( e ) {} -} - -function createActiveXHR() { - try { - return new window.ActiveXObject( "Microsoft.XMLHTTP" ); - } catch( e ) {} -} - -// Create the request object -// (This is still attached to ajaxSettings for backward compatibility) -jQuery.ajaxSettings.xhr = window.ActiveXObject ? - /* Microsoft failed to properly - * implement the XMLHttpRequest in IE7 (can't request local files), - * so we use the ActiveXObject when it is available - * Additionally XMLHttpRequest can be disabled in IE7/IE8 so - * we need a fallback. - */ - function() { - return !this.isLocal && createStandardXHR() || createActiveXHR(); - } : - // For all other browsers, use the standard XMLHttpRequest object - createStandardXHR; - -// Determine support properties -(function( xhr ) { - jQuery.extend( jQuery.support, { - ajax: !!xhr, - cors: !!xhr && ( "withCredentials" in xhr ) - }); -})( jQuery.ajaxSettings.xhr() ); - -// Create transport if the browser can provide an xhr -if ( jQuery.support.ajax ) { - - jQuery.ajaxTransport(function( s ) { - // Cross domain only allowed if supported through XMLHttpRequest - if ( !s.crossDomain || jQuery.support.cors ) { - - var callback; - - return { - send: function( headers, complete ) { - - // Get a new xhr - var handle, i, - xhr = s.xhr(); - - // Open the socket - // Passing null username, generates a login popup on Opera (#2865) - if ( s.username ) { - xhr.open( s.type, s.url, s.async, s.username, s.password ); - } else { - xhr.open( s.type, s.url, s.async ); - } - - // Apply custom fields if provided - if ( s.xhrFields ) { - for ( i in s.xhrFields ) { - xhr[ i ] = s.xhrFields[ i ]; - } - } - - // Override mime type if needed - if ( s.mimeType && xhr.overrideMimeType ) { - xhr.overrideMimeType( s.mimeType ); - } - - // X-Requested-With header - // For cross-domain requests, seeing as conditions for a preflight are - // akin to a jigsaw puzzle, we simply never set it to be sure. - // (it can always be set on a per-request basis or even using ajaxSetup) - // For same-domain requests, won't change header if already provided. - if ( !s.crossDomain && !headers["X-Requested-With"] ) { - headers[ "X-Requested-With" ] = "XMLHttpRequest"; - } - - // Need an extra try/catch for cross domain requests in Firefox 3 - try { - for ( i in headers ) { - xhr.setRequestHeader( i, headers[ i ] ); - } - } catch( _ ) {} - - // Do send the request - // This may raise an exception which is actually - // handled in jQuery.ajax (so no try/catch here) - xhr.send( ( s.hasContent && s.data ) || null ); - - // Listener - callback = function( _, isAbort ) { - - var status, - statusText, - responseHeaders, - responses, - xml; - - // Firefox throws exceptions when accessing properties - // of an xhr when a network error occurred - // http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE) - try { - - // Was never called and is aborted or complete - if ( callback && ( isAbort || xhr.readyState === 4 ) ) { - - // Only called once - callback = undefined; - - // Do not keep as active anymore - if ( handle ) { - xhr.onreadystatechange = jQuery.noop; - if ( xhrOnUnloadAbort ) { - delete xhrCallbacks[ handle ]; - } - } - - // If it's an abort - if ( isAbort ) { - // Abort it manually if needed - if ( xhr.readyState !== 4 ) { - xhr.abort(); - } - } else { - status = xhr.status; - responseHeaders = xhr.getAllResponseHeaders(); - responses = {}; - xml = xhr.responseXML; - - // Construct response list - if ( xml && xml.documentElement /* #4958 */ ) { - responses.xml = xml; - } - - // When requesting binary data, IE6-9 will throw an exception - // on any attempt to access responseText (#11426) - try { - responses.text = xhr.responseText; - } catch( _ ) { - } - - // Firefox throws an exception when accessing - // statusText for faulty cross-domain requests - try { - statusText = xhr.statusText; - } catch( e ) { - // We normalize with Webkit giving an empty statusText - statusText = ""; - } - - // Filter status for non standard behaviors - - // If the request is local and we have data: assume a success - // (success with no data won't get notified, that's the best we - // can do given current implementations) - if ( !status && s.isLocal && !s.crossDomain ) { - status = responses.text ? 200 : 404; - // IE - #1450: sometimes returns 1223 when it should be 204 - } else if ( status === 1223 ) { - status = 204; - } - } - } - } catch( firefoxAccessException ) { - if ( !isAbort ) { - complete( -1, firefoxAccessException ); - } - } - - // Call complete if needed - if ( responses ) { - complete( status, statusText, responses, responseHeaders ); - } - }; - - if ( !s.async ) { - // if we're in sync mode we fire the callback - callback(); - } else if ( xhr.readyState === 4 ) { - // (IE6 & IE7) if it's in cache and has been - // retrieved directly we need to fire the callback - setTimeout( callback, 0 ); - } else { - handle = ++xhrId; - if ( xhrOnUnloadAbort ) { - // Create the active xhrs callbacks list if needed - // and attach the unload handler - if ( !xhrCallbacks ) { - xhrCallbacks = {}; - jQuery( window ).unload( xhrOnUnloadAbort ); - } - // Add to list of active xhrs callbacks - xhrCallbacks[ handle ] = callback; - } - xhr.onreadystatechange = callback; - } - }, - - abort: function() { - if ( callback ) { - callback(0,1); - } - } - }; - } - }); -} -var fxNow, timerId, - rfxtypes = /^(?:toggle|show|hide)$/, - rfxnum = new RegExp( "^(?:([-+])=|)(" + core_pnum + ")([a-z%]*)$", "i" ), - rrun = /queueHooks$/, - animationPrefilters = [ defaultPrefilter ], - tweeners = { - "*": [function( prop, value ) { - var end, unit, - tween = this.createTween( prop, value ), - parts = rfxnum.exec( value ), - target = tween.cur(), - start = +target || 0, - scale = 1, - maxIterations = 20; - - if ( parts ) { - end = +parts[2]; - unit = parts[3] || ( jQuery.cssNumber[ prop ] ? "" : "px" ); - - // We need to compute starting value - if ( unit !== "px" && start ) { - // Iteratively approximate from a nonzero starting point - // Prefer the current property, because this process will be trivial if it uses the same units - // Fallback to end or a simple constant - start = jQuery.css( tween.elem, prop, true ) || end || 1; - - do { - // If previous iteration zeroed out, double until we get *something* - // Use a string for doubling factor so we don't accidentally see scale as unchanged below - scale = scale || ".5"; - - // Adjust and apply - start = start / scale; - jQuery.style( tween.elem, prop, start + unit ); - - // Update scale, tolerating zero or NaN from tween.cur() - // And breaking the loop if scale is unchanged or perfect, or if we've just had enough - } while ( scale !== (scale = tween.cur() / target) && scale !== 1 && --maxIterations ); - } - - tween.unit = unit; - tween.start = start; - // If a +=/-= token was provided, we're doing a relative animation - tween.end = parts[1] ? start + ( parts[1] + 1 ) * end : end; - } - return tween; - }] - }; - -// Animations created synchronously will run synchronously -function createFxNow() { - setTimeout(function() { - fxNow = undefined; - }, 0 ); - return ( fxNow = jQuery.now() ); -} - -function createTweens( animation, props ) { - jQuery.each( props, function( prop, value ) { - var collection = ( tweeners[ prop ] || [] ).concat( tweeners[ "*" ] ), - index = 0, - length = collection.length; - for ( ; index < length; index++ ) { - if ( collection[ index ].call( animation, prop, value ) ) { - - // we're done with this property - return; - } - } - }); -} - -function Animation( elem, properties, options ) { - var result, - index = 0, - tweenerIndex = 0, - length = animationPrefilters.length, - deferred = jQuery.Deferred().always( function() { - // don't match elem in the :animated selector - delete tick.elem; - }), - tick = function() { - var currentTime = fxNow || createFxNow(), - remaining = Math.max( 0, animation.startTime + animation.duration - currentTime ), - percent = 1 - ( remaining / animation.duration || 0 ), - index = 0, - length = animation.tweens.length; - - for ( ; index < length ; index++ ) { - animation.tweens[ index ].run( percent ); - } - - deferred.notifyWith( elem, [ animation, percent, remaining ]); - - if ( percent < 1 && length ) { - return remaining; - } else { - deferred.resolveWith( elem, [ animation ] ); - return false; - } - }, - animation = deferred.promise({ - elem: elem, - props: jQuery.extend( {}, properties ), - opts: jQuery.extend( true, { specialEasing: {} }, options ), - originalProperties: properties, - originalOptions: options, - startTime: fxNow || createFxNow(), - duration: options.duration, - tweens: [], - createTween: function( prop, end, easing ) { - var tween = jQuery.Tween( elem, animation.opts, prop, end, - animation.opts.specialEasing[ prop ] || animation.opts.easing ); - animation.tweens.push( tween ); - return tween; - }, - stop: function( gotoEnd ) { - var index = 0, - // if we are going to the end, we want to run all the tweens - // otherwise we skip this part - length = gotoEnd ? animation.tweens.length : 0; - - for ( ; index < length ; index++ ) { - animation.tweens[ index ].run( 1 ); - } - - // resolve when we played the last frame - // otherwise, reject - if ( gotoEnd ) { - deferred.resolveWith( elem, [ animation, gotoEnd ] ); - } else { - deferred.rejectWith( elem, [ animation, gotoEnd ] ); - } - return this; - } - }), - props = animation.props; - - propFilter( props, animation.opts.specialEasing ); - - for ( ; index < length ; index++ ) { - result = animationPrefilters[ index ].call( animation, elem, props, animation.opts ); - if ( result ) { - return result; - } - } - - createTweens( animation, props ); - - if ( jQuery.isFunction( animation.opts.start ) ) { - animation.opts.start.call( elem, animation ); - } - - jQuery.fx.timer( - jQuery.extend( tick, { - anim: animation, - queue: animation.opts.queue, - elem: elem - }) - ); - - // attach callbacks from options - return animation.progress( animation.opts.progress ) - .done( animation.opts.done, animation.opts.complete ) - .fail( animation.opts.fail ) - .always( animation.opts.always ); -} - -function propFilter( props, specialEasing ) { - var index, name, easing, value, hooks; - - // camelCase, specialEasing and expand cssHook pass - for ( index in props ) { - name = jQuery.camelCase( index ); - easing = specialEasing[ name ]; - value = props[ index ]; - if ( jQuery.isArray( value ) ) { - easing = value[ 1 ]; - value = props[ index ] = value[ 0 ]; - } - - if ( index !== name ) { - props[ name ] = value; - delete props[ index ]; - } - - hooks = jQuery.cssHooks[ name ]; - if ( hooks && "expand" in hooks ) { - value = hooks.expand( value ); - delete props[ name ]; - - // not quite $.extend, this wont overwrite keys already present. - // also - reusing 'index' from above because we have the correct "name" - for ( index in value ) { - if ( !( index in props ) ) { - props[ index ] = value[ index ]; - specialEasing[ index ] = easing; - } - } - } else { - specialEasing[ name ] = easing; - } - } -} - -jQuery.Animation = jQuery.extend( Animation, { - - tweener: function( props, callback ) { - if ( jQuery.isFunction( props ) ) { - callback = props; - props = [ "*" ]; - } else { - props = props.split(" "); - } - - var prop, - index = 0, - length = props.length; - - for ( ; index < length ; index++ ) { - prop = props[ index ]; - tweeners[ prop ] = tweeners[ prop ] || []; - tweeners[ prop ].unshift( callback ); - } - }, - - prefilter: function( callback, prepend ) { - if ( prepend ) { - animationPrefilters.unshift( callback ); - } else { - animationPrefilters.push( callback ); - } - } -}); - -function defaultPrefilter( elem, props, opts ) { - var index, prop, value, length, dataShow, tween, hooks, oldfire, - anim = this, - style = elem.style, - orig = {}, - handled = [], - hidden = elem.nodeType && isHidden( elem ); - - // handle queue: false promises - if ( !opts.queue ) { - hooks = jQuery._queueHooks( elem, "fx" ); - if ( hooks.unqueued == null ) { - hooks.unqueued = 0; - oldfire = hooks.empty.fire; - hooks.empty.fire = function() { - if ( !hooks.unqueued ) { - oldfire(); - } - }; - } - hooks.unqueued++; - - anim.always(function() { - // doing this makes sure that the complete handler will be called - // before this completes - anim.always(function() { - hooks.unqueued--; - if ( !jQuery.queue( elem, "fx" ).length ) { - hooks.empty.fire(); - } - }); - }); - } - - // height/width overflow pass - if ( elem.nodeType === 1 && ( "height" in props || "width" in props ) ) { - // Make sure that nothing sneaks out - // Record all 3 overflow attributes because IE does not - // change the overflow attribute when overflowX and - // overflowY are set to the same value - opts.overflow = [ style.overflow, style.overflowX, style.overflowY ]; - - // Set display property to inline-block for height/width - // animations on inline elements that are having width/height animated - if ( jQuery.css( elem, "display" ) === "inline" && - jQuery.css( elem, "float" ) === "none" ) { - - // inline-level elements accept inline-block; - // block-level elements need to be inline with layout - if ( !jQuery.support.inlineBlockNeedsLayout || css_defaultDisplay( elem.nodeName ) === "inline" ) { - style.display = "inline-block"; - - } else { - style.zoom = 1; - } - } - } - - if ( opts.overflow ) { - style.overflow = "hidden"; - if ( !jQuery.support.shrinkWrapBlocks ) { - anim.done(function() { - style.overflow = opts.overflow[ 0 ]; - style.overflowX = opts.overflow[ 1 ]; - style.overflowY = opts.overflow[ 2 ]; - }); - } - } - - - // show/hide pass - for ( index in props ) { - value = props[ index ]; - if ( rfxtypes.exec( value ) ) { - delete props[ index ]; - if ( value === ( hidden ? "hide" : "show" ) ) { - continue; - } - handled.push( index ); - } - } - - length = handled.length; - if ( length ) { - dataShow = jQuery._data( elem, "fxshow" ) || jQuery._data( elem, "fxshow", {} ); - if ( hidden ) { - jQuery( elem ).show(); - } else { - anim.done(function() { - jQuery( elem ).hide(); - }); - } - anim.done(function() { - var prop; - jQuery.removeData( elem, "fxshow", true ); - for ( prop in orig ) { - jQuery.style( elem, prop, orig[ prop ] ); - } - }); - for ( index = 0 ; index < length ; index++ ) { - prop = handled[ index ]; - tween = anim.createTween( prop, hidden ? dataShow[ prop ] : 0 ); - orig[ prop ] = dataShow[ prop ] || jQuery.style( elem, prop ); - - if ( !( prop in dataShow ) ) { - dataShow[ prop ] = tween.start; - if ( hidden ) { - tween.end = tween.start; - tween.start = prop === "width" || prop === "height" ? 1 : 0; - } - } - } - } -} - -function Tween( elem, options, prop, end, easing ) { - return new Tween.prototype.init( elem, options, prop, end, easing ); -} -jQuery.Tween = Tween; - -Tween.prototype = { - constructor: Tween, - init: function( elem, options, prop, end, easing, unit ) { - this.elem = elem; - this.prop = prop; - this.easing = easing || "swing"; - this.options = options; - this.start = this.now = this.cur(); - this.end = end; - this.unit = unit || ( jQuery.cssNumber[ prop ] ? "" : "px" ); - }, - cur: function() { - var hooks = Tween.propHooks[ this.prop ]; - - return hooks && hooks.get ? - hooks.get( this ) : - Tween.propHooks._default.get( this ); - }, - run: function( percent ) { - var eased, - hooks = Tween.propHooks[ this.prop ]; - - if ( this.options.duration ) { - this.pos = eased = jQuery.easing[ this.easing ]( - percent, this.options.duration * percent, 0, 1, this.options.duration - ); - } else { - this.pos = eased = percent; - } - this.now = ( this.end - this.start ) * eased + this.start; - - if ( this.options.step ) { - this.options.step.call( this.elem, this.now, this ); - } - - if ( hooks && hooks.set ) { - hooks.set( this ); - } else { - Tween.propHooks._default.set( this ); - } - return this; - } -}; - -Tween.prototype.init.prototype = Tween.prototype; - -Tween.propHooks = { - _default: { - get: function( tween ) { - var result; - - if ( tween.elem[ tween.prop ] != null && - (!tween.elem.style || tween.elem.style[ tween.prop ] == null) ) { - return tween.elem[ tween.prop ]; - } - - // passing any value as a 4th parameter to .css will automatically - // attempt a parseFloat and fallback to a string if the parse fails - // so, simple values such as "10px" are parsed to Float. - // complex values such as "rotate(1rad)" are returned as is. - result = jQuery.css( tween.elem, tween.prop, false, "" ); - // Empty strings, null, undefined and "auto" are converted to 0. - return !result || result === "auto" ? 0 : result; - }, - set: function( tween ) { - // use step hook for back compat - use cssHook if its there - use .style if its - // available and use plain properties where available - if ( jQuery.fx.step[ tween.prop ] ) { - jQuery.fx.step[ tween.prop ]( tween ); - } else if ( tween.elem.style && ( tween.elem.style[ jQuery.cssProps[ tween.prop ] ] != null || jQuery.cssHooks[ tween.prop ] ) ) { - jQuery.style( tween.elem, tween.prop, tween.now + tween.unit ); - } else { - tween.elem[ tween.prop ] = tween.now; - } - } - } -}; - -// Remove in 2.0 - this supports IE8's panic based approach -// to setting things on disconnected nodes - -Tween.propHooks.scrollTop = Tween.propHooks.scrollLeft = { - set: function( tween ) { - if ( tween.elem.nodeType && tween.elem.parentNode ) { - tween.elem[ tween.prop ] = tween.now; - } - } -}; - -jQuery.each([ "toggle", "show", "hide" ], function( i, name ) { - var cssFn = jQuery.fn[ name ]; - jQuery.fn[ name ] = function( speed, easing, callback ) { - return speed == null || typeof speed === "boolean" || - // special check for .toggle( handler, handler, ... ) - ( !i && jQuery.isFunction( speed ) && jQuery.isFunction( easing ) ) ? - cssFn.apply( this, arguments ) : - this.animate( genFx( name, true ), speed, easing, callback ); - }; -}); - -jQuery.fn.extend({ - fadeTo: function( speed, to, easing, callback ) { - - // show any hidden elements after setting opacity to 0 - return this.filter( isHidden ).css( "opacity", 0 ).show() - - // animate to the value specified - .end().animate({ opacity: to }, speed, easing, callback ); - }, - animate: function( prop, speed, easing, callback ) { - var empty = jQuery.isEmptyObject( prop ), - optall = jQuery.speed( speed, easing, callback ), - doAnimation = function() { - // Operate on a copy of prop so per-property easing won't be lost - var anim = Animation( this, jQuery.extend( {}, prop ), optall ); - - // Empty animations resolve immediately - if ( empty ) { - anim.stop( true ); - } - }; - - return empty || optall.queue === false ? - this.each( doAnimation ) : - this.queue( optall.queue, doAnimation ); - }, - stop: function( type, clearQueue, gotoEnd ) { - var stopQueue = function( hooks ) { - var stop = hooks.stop; - delete hooks.stop; - stop( gotoEnd ); - }; - - if ( typeof type !== "string" ) { - gotoEnd = clearQueue; - clearQueue = type; - type = undefined; - } - if ( clearQueue && type !== false ) { - this.queue( type || "fx", [] ); - } - - return this.each(function() { - var dequeue = true, - index = type != null && type + "queueHooks", - timers = jQuery.timers, - data = jQuery._data( this ); - - if ( index ) { - if ( data[ index ] && data[ index ].stop ) { - stopQueue( data[ index ] ); - } - } else { - for ( index in data ) { - if ( data[ index ] && data[ index ].stop && rrun.test( index ) ) { - stopQueue( data[ index ] ); - } - } - } - - for ( index = timers.length; index--; ) { - if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) { - timers[ index ].anim.stop( gotoEnd ); - dequeue = false; - timers.splice( index, 1 ); - } - } - - // start the next in the queue if the last step wasn't forced - // timers currently will call their complete callbacks, which will dequeue - // but only if they were gotoEnd - if ( dequeue || !gotoEnd ) { - jQuery.dequeue( this, type ); - } - }); - } -}); - -// Generate parameters to create a standard animation -function genFx( type, includeWidth ) { - var which, - attrs = { height: type }, - i = 0; - - // if we include width, step value is 1 to do all cssExpand values, - // if we don't include width, step value is 2 to skip over Left and Right - includeWidth = includeWidth? 1 : 0; - for( ; i < 4 ; i += 2 - includeWidth ) { - which = cssExpand[ i ]; - attrs[ "margin" + which ] = attrs[ "padding" + which ] = type; - } - - if ( includeWidth ) { - attrs.opacity = attrs.width = type; - } - - return attrs; -} - -// Generate shortcuts for custom animations -jQuery.each({ - slideDown: genFx("show"), - slideUp: genFx("hide"), - slideToggle: genFx("toggle"), - fadeIn: { opacity: "show" }, - fadeOut: { opacity: "hide" }, - fadeToggle: { opacity: "toggle" } -}, function( name, props ) { - jQuery.fn[ name ] = function( speed, easing, callback ) { - return this.animate( props, speed, easing, callback ); - }; -}); - -jQuery.speed = function( speed, easing, fn ) { - var opt = speed && typeof speed === "object" ? jQuery.extend( {}, speed ) : { - complete: fn || !fn && easing || - jQuery.isFunction( speed ) && speed, - duration: speed, - easing: fn && easing || easing && !jQuery.isFunction( easing ) && easing - }; - - opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration : - opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[ opt.duration ] : jQuery.fx.speeds._default; - - // normalize opt.queue - true/undefined/null -> "fx" - if ( opt.queue == null || opt.queue === true ) { - opt.queue = "fx"; - } - - // Queueing - opt.old = opt.complete; - - opt.complete = function() { - if ( jQuery.isFunction( opt.old ) ) { - opt.old.call( this ); - } - - if ( opt.queue ) { - jQuery.dequeue( this, opt.queue ); - } - }; - - return opt; -}; - -jQuery.easing = { - linear: function( p ) { - return p; - }, - swing: function( p ) { - return 0.5 - Math.cos( p*Math.PI ) / 2; - } -}; - -jQuery.timers = []; -jQuery.fx = Tween.prototype.init; -jQuery.fx.tick = function() { - var timer, - timers = jQuery.timers, - i = 0; - - for ( ; i < timers.length; i++ ) { - timer = timers[ i ]; - // Checks the timer has not already been removed - if ( !timer() && timers[ i ] === timer ) { - timers.splice( i--, 1 ); - } - } - - if ( !timers.length ) { - jQuery.fx.stop(); - } -}; - -jQuery.fx.timer = function( timer ) { - if ( timer() && jQuery.timers.push( timer ) && !timerId ) { - timerId = setInterval( jQuery.fx.tick, jQuery.fx.interval ); - } -}; - -jQuery.fx.interval = 13; - -jQuery.fx.stop = function() { - clearInterval( timerId ); - timerId = null; -}; - -jQuery.fx.speeds = { - slow: 600, - fast: 200, - // Default speed - _default: 400 -}; - -// Back Compat <1.8 extension point -jQuery.fx.step = {}; - -if ( jQuery.expr && jQuery.expr.filters ) { - jQuery.expr.filters.animated = function( elem ) { - return jQuery.grep(jQuery.timers, function( fn ) { - return elem === fn.elem; - }).length; - }; -} -var rroot = /^(?:body|html)$/i; - -jQuery.fn.offset = function( options ) { - if ( arguments.length ) { - return options === undefined ? - this : - this.each(function( i ) { - jQuery.offset.setOffset( this, options, i ); - }); - } - - var docElem, body, win, clientTop, clientLeft, scrollTop, scrollLeft, - box = { top: 0, left: 0 }, - elem = this[ 0 ], - doc = elem && elem.ownerDocument; - - if ( !doc ) { - return; - } - - if ( (body = doc.body) === elem ) { - return jQuery.offset.bodyOffset( elem ); - } - - docElem = doc.documentElement; - - // Make sure it's not a disconnected DOM node - if ( !jQuery.contains( docElem, elem ) ) { - return box; - } - - // If we don't have gBCR, just use 0,0 rather than error - // BlackBerry 5, iOS 3 (original iPhone) - if ( typeof elem.getBoundingClientRect !== "undefined" ) { - box = elem.getBoundingClientRect(); - } - win = getWindow( doc ); - clientTop = docElem.clientTop || body.clientTop || 0; - clientLeft = docElem.clientLeft || body.clientLeft || 0; - scrollTop = win.pageYOffset || docElem.scrollTop; - scrollLeft = win.pageXOffset || docElem.scrollLeft; - return { - top: box.top + scrollTop - clientTop, - left: box.left + scrollLeft - clientLeft - }; -}; - -jQuery.offset = { - - bodyOffset: function( body ) { - var top = body.offsetTop, - left = body.offsetLeft; - - if ( jQuery.support.doesNotIncludeMarginInBodyOffset ) { - top += parseFloat( jQuery.css(body, "marginTop") ) || 0; - left += parseFloat( jQuery.css(body, "marginLeft") ) || 0; - } - - return { top: top, left: left }; - }, - - setOffset: function( elem, options, i ) { - var position = jQuery.css( elem, "position" ); - - // set position first, in-case top/left are set even on static elem - if ( position === "static" ) { - elem.style.position = "relative"; - } - - var curElem = jQuery( elem ), - curOffset = curElem.offset(), - curCSSTop = jQuery.css( elem, "top" ), - curCSSLeft = jQuery.css( elem, "left" ), - calculatePosition = ( position === "absolute" || position === "fixed" ) && jQuery.inArray("auto", [curCSSTop, curCSSLeft]) > -1, - props = {}, curPosition = {}, curTop, curLeft; - - // need to be able to calculate position if either top or left is auto and position is either absolute or fixed - if ( calculatePosition ) { - curPosition = curElem.position(); - curTop = curPosition.top; - curLeft = curPosition.left; - } else { - curTop = parseFloat( curCSSTop ) || 0; - curLeft = parseFloat( curCSSLeft ) || 0; - } - - if ( jQuery.isFunction( options ) ) { - options = options.call( elem, i, curOffset ); - } - - if ( options.top != null ) { - props.top = ( options.top - curOffset.top ) + curTop; - } - if ( options.left != null ) { - props.left = ( options.left - curOffset.left ) + curLeft; - } - - if ( "using" in options ) { - options.using.call( elem, props ); - } else { - curElem.css( props ); - } - } -}; - - -jQuery.fn.extend({ - - position: function() { - if ( !this[0] ) { - return; - } - - var elem = this[0], - - // Get *real* offsetParent - offsetParent = this.offsetParent(), - - // Get correct offsets - offset = this.offset(), - parentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset(); - - // Subtract element margins - // note: when an element has margin: auto the offsetLeft and marginLeft - // are the same in Safari causing offset.left to incorrectly be 0 - offset.top -= parseFloat( jQuery.css(elem, "marginTop") ) || 0; - offset.left -= parseFloat( jQuery.css(elem, "marginLeft") ) || 0; - - // Add offsetParent borders - parentOffset.top += parseFloat( jQuery.css(offsetParent[0], "borderTopWidth") ) || 0; - parentOffset.left += parseFloat( jQuery.css(offsetParent[0], "borderLeftWidth") ) || 0; - - // Subtract the two offsets - return { - top: offset.top - parentOffset.top, - left: offset.left - parentOffset.left - }; - }, - - offsetParent: function() { - return this.map(function() { - var offsetParent = this.offsetParent || document.body; - while ( offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, "position") === "static") ) { - offsetParent = offsetParent.offsetParent; - } - return offsetParent || document.body; - }); - } -}); - - -// Create scrollLeft and scrollTop methods -jQuery.each( {scrollLeft: "pageXOffset", scrollTop: "pageYOffset"}, function( method, prop ) { - var top = /Y/.test( prop ); - - jQuery.fn[ method ] = function( val ) { - return jQuery.access( this, function( elem, method, val ) { - var win = getWindow( elem ); - - if ( val === undefined ) { - return win ? (prop in win) ? win[ prop ] : - win.document.documentElement[ method ] : - elem[ method ]; - } - - if ( win ) { - win.scrollTo( - !top ? val : jQuery( win ).scrollLeft(), - top ? val : jQuery( win ).scrollTop() - ); - - } else { - elem[ method ] = val; - } - }, method, val, arguments.length, null ); - }; -}); - -function getWindow( elem ) { - return jQuery.isWindow( elem ) ? - elem : - elem.nodeType === 9 ? - elem.defaultView || elem.parentWindow : - false; -} -// Create innerHeight, innerWidth, height, width, outerHeight and outerWidth methods -jQuery.each( { Height: "height", Width: "width" }, function( name, type ) { - jQuery.each( { padding: "inner" + name, content: type, "": "outer" + name }, function( defaultExtra, funcName ) { - // margin is only for outerHeight, outerWidth - jQuery.fn[ funcName ] = function( margin, value ) { - var chainable = arguments.length && ( defaultExtra || typeof margin !== "boolean" ), - extra = defaultExtra || ( margin === true || value === true ? "margin" : "border" ); - - return jQuery.access( this, function( elem, type, value ) { - var doc; - - if ( jQuery.isWindow( elem ) ) { - // As of 5/8/2012 this will yield incorrect results for Mobile Safari, but there - // isn't a whole lot we can do. See pull request at this URL for discussion: - // https://github.com/jquery/jquery/pull/764 - return elem.document.documentElement[ "client" + name ]; - } - - // Get document width or height - if ( elem.nodeType === 9 ) { - doc = elem.documentElement; - - // Either scroll[Width/Height] or offset[Width/Height] or client[Width/Height], whichever is greatest - // unfortunately, this causes bug #3838 in IE6/8 only, but there is currently no good, small way to fix it. - return Math.max( - elem.body[ "scroll" + name ], doc[ "scroll" + name ], - elem.body[ "offset" + name ], doc[ "offset" + name ], - doc[ "client" + name ] - ); - } - - return value === undefined ? - // Get width or height on the element, requesting but not forcing parseFloat - jQuery.css( elem, type, value, extra ) : - - // Set width or height on the element - jQuery.style( elem, type, value, extra ); - }, type, chainable ? margin : undefined, chainable, null ); - }; - }); -}); -// Expose jQuery to the global object -window.jQuery = window.$ = jQuery; - -// Expose jQuery as an AMD module, but only for AMD loaders that -// understand the issues with loading multiple versions of jQuery -// in a page that all might call define(). The loader will indicate -// they have special allowances for multiple jQuery versions by -// specifying define.amd.jQuery = true. Register as a named module, -// since jQuery can be concatenated with other files that may use define, -// but not use a proper concatenation script that understands anonymous -// AMD modules. A named AMD is safest and most robust way to register. -// Lowercase jquery is used because AMD module names are derived from -// file names, and jQuery is normally delivered in a lowercase file name. -// Do this after creating the global so that if an AMD module wants to call -// noConflict to hide this version of jQuery, it will work. -if ( typeof define === "function" && define.amd && define.amd.jQuery ) { - define( "jquery", [], function () { return jQuery; } ); -} - -})( window ); - -/** - * @license AngularJS v1.1.5 - * (c) 2010-2012 Google, Inc. http://angularjs.org - * License: MIT - */ -(function(window, document){ - var _jQuery = window.jQuery.noConflict(true); - -//////////////////////////////////// - -/** - * @ngdoc function - * @name angular.lowercase - * @function - * - * @description Converts the specified string to lowercase. - * @param {string} string String to be converted to lowercase. - * @returns {string} Lowercased string. - */ -var lowercase = function(string){return isString(string) ? string.toLowerCase() : string;}; - - -/** - * @ngdoc function - * @name angular.uppercase - * @function - * - * @description Converts the specified string to uppercase. - * @param {string} string String to be converted to uppercase. - * @returns {string} Uppercased string. - */ -var uppercase = function(string){return isString(string) ? string.toUpperCase() : string;}; - - -var manualLowercase = function(s) { - return isString(s) - ? s.replace(/[A-Z]/g, function(ch) {return String.fromCharCode(ch.charCodeAt(0) | 32);}) - : s; -}; -var manualUppercase = function(s) { - return isString(s) - ? s.replace(/[a-z]/g, function(ch) {return String.fromCharCode(ch.charCodeAt(0) & ~32);}) - : s; -}; - - -// String#toLowerCase and String#toUpperCase don't produce correct results in browsers with Turkish -// locale, for this reason we need to detect this case and redefine lowercase/uppercase methods -// with correct but slower alternatives. -if ('i' !== 'I'.toLowerCase()) { - lowercase = manualLowercase; - uppercase = manualUppercase; -} - - -var /** holds major version number for IE or NaN for real browsers */ - msie = int((/msie (\d+)/.exec(lowercase(navigator.userAgent)) || [])[1]), - jqLite, // delay binding since jQuery could be loaded after us. - jQuery, // delay binding - slice = [].slice, - push = [].push, - toString = Object.prototype.toString, - - - _angular = window.angular, - /** @name angular */ - angular = window.angular || (window.angular = {}), - angularModule, - nodeName_, - uid = ['0', '0', '0']; - -/** - * @ngdoc function - * @name angular.noConflict - * @function - * - * @description - * Restores the previous global value of angular and returns the current instance. Other libraries may already use the - * angular namespace. Or a previous version of angular is already loaded on the page. In these cases you may want to - * restore the previous namespace and keep a reference to angular. - * - * @return {Object} The current angular namespace - */ -function noConflict() { - var a = window.angular; - window.angular = _angular; - return a; -} - -/** - * @private - * @param {*} obj - * @return {boolean} Returns true if `obj` is an array or array-like object (NodeList, Arguments, ...) - */ -function isArrayLike(obj) { - if (!obj || (typeof obj.length !== 'number')) return false; - - // We have on object which has length property. Should we treat it as array? - if (typeof obj.hasOwnProperty != 'function' && - typeof obj.constructor != 'function') { - // This is here for IE8: it is a bogus object treat it as array; - return true; - } else { - return obj instanceof JQLite || // JQLite - (jQuery && obj instanceof jQuery) || // jQuery - toString.call(obj) !== '[object Object]' || // some browser native object - typeof obj.callee === 'function'; // arguments (on IE8 looks like regular obj) - } -} - -/** - * @ngdoc function - * @name angular.forEach - * @function - * - * @description - * Invokes the `iterator` function once for each item in `obj` collection, which can be either an - * object or an array. The `iterator` function is invoked with `iterator(value, key)`, where `value` - * is the value of an object property or an array element and `key` is the object property key or - * array element index. Specifying a `context` for the function is optional. - * - * Note: this function was previously known as `angular.foreach`. - * -
                -     var values = {name: 'misko', gender: 'male'};
                -     var log = [];
                -     angular.forEach(values, function(value, key){
                -       this.push(key + ': ' + value);
                -     }, log);
                -     expect(log).toEqual(['name: misko', 'gender:male']);
                -   
                - * - * @param {Object|Array} obj Object to iterate over. - * @param {Function} iterator Iterator function. - * @param {Object=} context Object to become context (`this`) for the iterator function. - * @returns {Object|Array} Reference to `obj`. - */ -function forEach(obj, iterator, context) { - var key; - if (obj) { - if (isFunction(obj)){ - for (key in obj) { - if (key != 'prototype' && key != 'length' && key != 'name' && obj.hasOwnProperty(key)) { - iterator.call(context, obj[key], key); - } - } - } else if (obj.forEach && obj.forEach !== forEach) { - obj.forEach(iterator, context); - } else if (isArrayLike(obj)) { - for (key = 0; key < obj.length; key++) - iterator.call(context, obj[key], key); - } else { - for (key in obj) { - if (obj.hasOwnProperty(key)) { - iterator.call(context, obj[key], key); - } - } - } - } - return obj; -} - -function sortedKeys(obj) { - var keys = []; - for (var key in obj) { - if (obj.hasOwnProperty(key)) { - keys.push(key); - } - } - return keys.sort(); -} - -function forEachSorted(obj, iterator, context) { - var keys = sortedKeys(obj); - for ( var i = 0; i < keys.length; i++) { - iterator.call(context, obj[keys[i]], keys[i]); - } - return keys; -} - - -/** - * when using forEach the params are value, key, but it is often useful to have key, value. - * @param {function(string, *)} iteratorFn - * @returns {function(*, string)} - */ -function reverseParams(iteratorFn) { - return function(value, key) { iteratorFn(key, value) }; -} - -/** - * A consistent way of creating unique IDs in angular. The ID is a sequence of alpha numeric - * characters such as '012ABC'. The reason why we are not using simply a number counter is that - * the number string gets longer over time, and it can also overflow, where as the nextId - * will grow much slower, it is a string, and it will never overflow. - * - * @returns an unique alpha-numeric string - */ -function nextUid() { - var index = uid.length; - var digit; - - while(index) { - index--; - digit = uid[index].charCodeAt(0); - if (digit == 57 /*'9'*/) { - uid[index] = 'A'; - return uid.join(''); - } - if (digit == 90 /*'Z'*/) { - uid[index] = '0'; - } else { - uid[index] = String.fromCharCode(digit + 1); - return uid.join(''); - } - } - uid.unshift('0'); - return uid.join(''); -} - - -/** - * Set or clear the hashkey for an object. - * @param obj object - * @param h the hashkey (!truthy to delete the hashkey) - */ -function setHashKey(obj, h) { - if (h) { - obj.$$hashKey = h; - } - else { - delete obj.$$hashKey; - } -} - -/** - * @ngdoc function - * @name angular.extend - * @function - * - * @description - * Extends the destination object `dst` by copying all of the properties from the `src` object(s) - * to `dst`. You can specify multiple `src` objects. - * - * @param {Object} dst Destination object. - * @param {...Object} src Source object(s). - * @returns {Object} Reference to `dst`. - */ -function extend(dst) { - var h = dst.$$hashKey; - forEach(arguments, function(obj){ - if (obj !== dst) { - forEach(obj, function(value, key){ - dst[key] = value; - }); - } - }); - - setHashKey(dst,h); - return dst; -} - -function int(str) { - return parseInt(str, 10); -} - - -function inherit(parent, extra) { - return extend(new (extend(function() {}, {prototype:parent}))(), extra); -} - -var START_SPACE = /^\s*/; -var END_SPACE = /\s*$/; -function stripWhitespace(str) { - return isString(str) ? str.replace(START_SPACE, '').replace(END_SPACE, '') : str; -} - -/** - * @ngdoc function - * @name angular.noop - * @function - * - * @description - * A function that performs no operations. This function can be useful when writing code in the - * functional style. -
                -     function foo(callback) {
                -       var result = calculateResult();
                -       (callback || angular.noop)(result);
                -     }
                -   
                - */ -function noop() {} -noop.$inject = []; - - -/** - * @ngdoc function - * @name angular.identity - * @function - * - * @description - * A function that returns its first argument. This function is useful when writing code in the - * functional style. - * -
                -     function transformer(transformationFn, value) {
                -       return (transformationFn || identity)(value);
                -     };
                -   
                - */ -function identity($) {return $;} -identity.$inject = []; - - -function valueFn(value) {return function() {return value;};} - -/** - * @ngdoc function - * @name angular.isUndefined - * @function - * - * @description - * Determines if a reference is undefined. - * - * @param {*} value Reference to check. - * @returns {boolean} True if `value` is undefined. - */ -function isUndefined(value){return typeof value == 'undefined';} - - -/** - * @ngdoc function - * @name angular.isDefined - * @function - * - * @description - * Determines if a reference is defined. - * - * @param {*} value Reference to check. - * @returns {boolean} True if `value` is defined. - */ -function isDefined(value){return typeof value != 'undefined';} - - -/** - * @ngdoc function - * @name angular.isObject - * @function - * - * @description - * Determines if a reference is an `Object`. Unlike `typeof` in JavaScript, `null`s are not - * considered to be objects. - * - * @param {*} value Reference to check. - * @returns {boolean} True if `value` is an `Object` but not `null`. - */ -function isObject(value){return value != null && typeof value == 'object';} - - -/** - * @ngdoc function - * @name angular.isString - * @function - * - * @description - * Determines if a reference is a `String`. - * - * @param {*} value Reference to check. - * @returns {boolean} True if `value` is a `String`. - */ -function isString(value){return typeof value == 'string';} - - -/** - * @ngdoc function - * @name angular.isNumber - * @function - * - * @description - * Determines if a reference is a `Number`. - * - * @param {*} value Reference to check. - * @returns {boolean} True if `value` is a `Number`. - */ -function isNumber(value){return typeof value == 'number';} - - -/** - * @ngdoc function - * @name angular.isDate - * @function - * - * @description - * Determines if a value is a date. - * - * @param {*} value Reference to check. - * @returns {boolean} True if `value` is a `Date`. - */ -function isDate(value){ - return toString.apply(value) == '[object Date]'; -} - - -/** - * @ngdoc function - * @name angular.isArray - * @function - * - * @description - * Determines if a reference is an `Array`. - * - * @param {*} value Reference to check. - * @returns {boolean} True if `value` is an `Array`. - */ -function isArray(value) { - return toString.apply(value) == '[object Array]'; -} - - -/** - * @ngdoc function - * @name angular.isFunction - * @function - * - * @description - * Determines if a reference is a `Function`. - * - * @param {*} value Reference to check. - * @returns {boolean} True if `value` is a `Function`. - */ -function isFunction(value){return typeof value == 'function';} - - -/** - * Checks if `obj` is a window object. - * - * @private - * @param {*} obj Object to check - * @returns {boolean} True if `obj` is a window obj. - */ -function isWindow(obj) { - return obj && obj.document && obj.location && obj.alert && obj.setInterval; -} - - -function isScope(obj) { - return obj && obj.$evalAsync && obj.$watch; -} - - -function isFile(obj) { - return toString.apply(obj) === '[object File]'; -} - - -function isBoolean(value) { - return typeof value == 'boolean'; -} - - -function trim(value) { - return isString(value) ? value.replace(/^\s*/, '').replace(/\s*$/, '') : value; -} - -/** - * @ngdoc function - * @name angular.isElement - * @function - * - * @description - * Determines if a reference is a DOM element (or wrapped jQuery element). - * - * @param {*} value Reference to check. - * @returns {boolean} True if `value` is a DOM element (or wrapped jQuery element). - */ -function isElement(node) { - return node && - (node.nodeName // we are a direct element - || (node.bind && node.find)); // we have a bind and find method part of jQuery API -} - -/** - * @param str 'key1,key2,...' - * @returns {object} in the form of {key1:true, key2:true, ...} - */ -function makeMap(str){ - var obj = {}, items = str.split(","), i; - for ( i = 0; i < items.length; i++ ) - obj[ items[i] ] = true; - return obj; -} - - -if (msie < 9) { - nodeName_ = function(element) { - element = element.nodeName ? element : element[0]; - return (element.scopeName && element.scopeName != 'HTML') - ? uppercase(element.scopeName + ':' + element.nodeName) : element.nodeName; - }; -} else { - nodeName_ = function(element) { - return element.nodeName ? element.nodeName : element[0].nodeName; - }; -} - - -function map(obj, iterator, context) { - var results = []; - forEach(obj, function(value, index, list) { - results.push(iterator.call(context, value, index, list)); - }); - return results; -} - - -/** - * @description - * Determines the number of elements in an array, the number of properties an object has, or - * the length of a string. - * - * Note: This function is used to augment the Object type in Angular expressions. See - * {@link angular.Object} for more information about Angular arrays. - * - * @param {Object|Array|string} obj Object, array, or string to inspect. - * @param {boolean} [ownPropsOnly=false] Count only "own" properties in an object - * @returns {number} The size of `obj` or `0` if `obj` is neither an object nor an array. - */ -function size(obj, ownPropsOnly) { - var size = 0, key; - - if (isArray(obj) || isString(obj)) { - return obj.length; - } else if (isObject(obj)){ - for (key in obj) - if (!ownPropsOnly || obj.hasOwnProperty(key)) - size++; - } - - return size; -} - - -function includes(array, obj) { - return indexOf(array, obj) != -1; -} - -function indexOf(array, obj) { - if (array.indexOf) return array.indexOf(obj); - - for ( var i = 0; i < array.length; i++) { - if (obj === array[i]) return i; - } - return -1; -} - -function arrayRemove(array, value) { - var index = indexOf(array, value); - if (index >=0) - array.splice(index, 1); - return value; -} - -function isLeafNode (node) { - if (node) { - switch (node.nodeName) { - case "OPTION": - case "PRE": - case "TITLE": - return true; - } - } - return false; -} - -/** - * @ngdoc function - * @name angular.copy - * @function - * - * @description - * Creates a deep copy of `source`, which should be an object or an array. - * - * * If no destination is supplied, a copy of the object or array is created. - * * If a destination is provided, all of its elements (for array) or properties (for objects) - * are deleted and then all elements/properties from the source are copied to it. - * * If `source` is not an object or array, `source` is returned. - * - * Note: this function is used to augment the Object type in Angular expressions. See - * {@link ng.$filter} for more information about Angular arrays. - * - * @param {*} source The source that will be used to make a copy. - * Can be any type, including primitives, `null`, and `undefined`. - * @param {(Object|Array)=} destination Destination into which the source is copied. If - * provided, must be of the same type as `source`. - * @returns {*} The copy or updated `destination`, if `destination` was specified. - */ -function copy(source, destination){ - if (isWindow(source) || isScope(source)) throw Error("Can't copy Window or Scope"); - if (!destination) { - destination = source; - if (source) { - if (isArray(source)) { - destination = copy(source, []); - } else if (isDate(source)) { - destination = new Date(source.getTime()); - } else if (isObject(source)) { - destination = copy(source, {}); - } - } - } else { - if (source === destination) throw Error("Can't copy equivalent objects or arrays"); - if (isArray(source)) { - destination.length = 0; - for ( var i = 0; i < source.length; i++) { - destination.push(copy(source[i])); - } - } else { - var h = destination.$$hashKey; - forEach(destination, function(value, key){ - delete destination[key]; - }); - for ( var key in source) { - destination[key] = copy(source[key]); - } - setHashKey(destination,h); - } - } - return destination; -} - -/** - * Create a shallow copy of an object - */ -function shallowCopy(src, dst) { - dst = dst || {}; - - for(var key in src) { - if (src.hasOwnProperty(key) && key.substr(0, 2) !== '$$') { - dst[key] = src[key]; - } - } - - return dst; -} - - -/** - * @ngdoc function - * @name angular.equals - * @function - * - * @description - * Determines if two objects or two values are equivalent. Supports value types, arrays and - * objects. - * - * Two objects or values are considered equivalent if at least one of the following is true: - * - * * Both objects or values pass `===` comparison. - * * Both objects or values are of the same type and all of their properties pass `===` comparison. - * * Both values are NaN. (In JavasScript, NaN == NaN => false. But we consider two NaN as equal) - * - * During a property comparison, properties of `function` type and properties with names - * that begin with `$` are ignored. - * - * Scope and DOMWindow objects are being compared only by identify (`===`). - * - * @param {*} o1 Object or value to compare. - * @param {*} o2 Object or value to compare. - * @returns {boolean} True if arguments are equal. - */ -function equals(o1, o2) { - if (o1 === o2) return true; - if (o1 === null || o2 === null) return false; - if (o1 !== o1 && o2 !== o2) return true; // NaN === NaN - var t1 = typeof o1, t2 = typeof o2, length, key, keySet; - if (t1 == t2) { - if (t1 == 'object') { - if (isArray(o1)) { - if ((length = o1.length) == o2.length) { - for(key=0; key 2 ? sliceArgs(arguments, 2) : []; - if (isFunction(fn) && !(fn instanceof RegExp)) { - return curryArgs.length - ? function() { - return arguments.length - ? fn.apply(self, curryArgs.concat(slice.call(arguments, 0))) - : fn.apply(self, curryArgs); - } - : function() { - return arguments.length - ? fn.apply(self, arguments) - : fn.call(self); - }; - } else { - // in IE, native methods are not functions so they cannot be bound (note: they don't need to be) - return fn; - } -} - - -function toJsonReplacer(key, value) { - var val = value; - - if (/^\$+/.test(key)) { - val = undefined; - } else if (isWindow(value)) { - val = '$WINDOW'; - } else if (value && document === value) { - val = '$DOCUMENT'; - } else if (isScope(value)) { - val = '$SCOPE'; - } - - return val; -} - - -/** - * @ngdoc function - * @name angular.toJson - * @function - * - * @description - * Serializes input into a JSON-formatted string. - * - * @param {Object|Array|Date|string|number} obj Input to be serialized into JSON. - * @param {boolean=} pretty If set to true, the JSON output will contain newlines and whitespace. - * @returns {string} Jsonified string representing `obj`. - */ -function toJson(obj, pretty) { - return JSON.stringify(obj, toJsonReplacer, pretty ? ' ' : null); -} - - -/** - * @ngdoc function - * @name angular.fromJson - * @function - * - * @description - * Deserializes a JSON string. - * - * @param {string} json JSON string to deserialize. - * @returns {Object|Array|Date|string|number} Deserialized thingy. - */ -function fromJson(json) { - return isString(json) - ? JSON.parse(json) - : json; -} - - -function toBoolean(value) { - if (value && value.length !== 0) { - var v = lowercase("" + value); - value = !(v == 'f' || v == '0' || v == 'false' || v == 'no' || v == 'n' || v == '[]'); - } else { - value = false; - } - return value; -} - -/** - * @returns {string} Returns the string representation of the element. - */ -function startingTag(element) { - element = jqLite(element).clone(); - try { - // turns out IE does not let you set .html() on elements which - // are not allowed to have children. So we just ignore it. - element.html(''); - } catch(e) {} - // As Per DOM Standards - var TEXT_NODE = 3; - var elemHtml = jqLite('
                ').append(element).html(); - try { - return element[0].nodeType === TEXT_NODE ? lowercase(elemHtml) : - elemHtml. - match(/^(<[^>]+>)/)[1]. - replace(/^<([\w\-]+)/, function(match, nodeName) { return '<' + lowercase(nodeName); }); - } catch(e) { - return lowercase(elemHtml); - } - -} - - -///////////////////////////////////////////////// - -/** - * Parses an escaped url query string into key-value pairs. - * @returns Object.<(string|boolean)> - */ -function parseKeyValue(/**string*/keyValue) { - var obj = {}, key_value, key; - forEach((keyValue || "").split('&'), function(keyValue){ - if (keyValue) { - key_value = keyValue.split('='); - key = decodeURIComponent(key_value[0]); - obj[key] = isDefined(key_value[1]) ? decodeURIComponent(key_value[1]) : true; - } - }); - return obj; -} - -function toKeyValue(obj) { - var parts = []; - forEach(obj, function(value, key) { - parts.push(encodeUriQuery(key, true) + (value === true ? '' : '=' + encodeUriQuery(value, true))); - }); - return parts.length ? parts.join('&') : ''; -} - - -/** - * We need our custom method because encodeURIComponent is too aggressive and doesn't follow - * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path - * segments: - * segment = *pchar - * pchar = unreserved / pct-encoded / sub-delims / ":" / "@" - * pct-encoded = "%" HEXDIG HEXDIG - * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" - * sub-delims = "!" / "$" / "&" / "'" / "(" / ")" - * / "*" / "+" / "," / ";" / "=" - */ -function encodeUriSegment(val) { - return encodeUriQuery(val, true). - replace(/%26/gi, '&'). - replace(/%3D/gi, '='). - replace(/%2B/gi, '+'); -} - - -/** - * This method is intended for encoding *key* or *value* parts of query component. We need a custom - * method because encodeURIComponent is too aggressive and encodes stuff that doesn't have to be - * encoded per http://tools.ietf.org/html/rfc3986: - * query = *( pchar / "/" / "?" ) - * pchar = unreserved / pct-encoded / sub-delims / ":" / "@" - * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" - * pct-encoded = "%" HEXDIG HEXDIG - * sub-delims = "!" / "$" / "&" / "'" / "(" / ")" - * / "*" / "+" / "," / ";" / "=" - */ -function encodeUriQuery(val, pctEncodeSpaces) { - return encodeURIComponent(val). - replace(/%40/gi, '@'). - replace(/%3A/gi, ':'). - replace(/%24/g, '$'). - replace(/%2C/gi, ','). - replace(/%20/g, (pctEncodeSpaces ? '%20' : '+')); -} - - -/** - * @ngdoc directive - * @name ng.directive:ngApp - * - * @element ANY - * @param {angular.Module} ngApp an optional application - * {@link angular.module module} name to load. - * - * @description - * - * Use this directive to auto-bootstrap an application. Only - * one directive can be used per HTML document. The directive - * designates the root of the application and is typically placed - * at the root of the page. - * - * In the example below if the `ngApp` directive would not be placed - * on the `html` element then the document would not be compiled - * and the `{{ 1+2 }}` would not be resolved to `3`. - * - * `ngApp` is the easiest way to bootstrap an application. - * - - - I can add: 1 + 2 = {{ 1+2 }} - - - * - */ -function angularInit(element, bootstrap) { - var elements = [element], - appElement, - module, - names = ['ng:app', 'ng-app', 'x-ng-app', 'data-ng-app'], - NG_APP_CLASS_REGEXP = /\sng[:\-]app(:\s*([\w\d_]+);?)?\s/; - - function append(element) { - element && elements.push(element); - } - - forEach(names, function(name) { - names[name] = true; - append(document.getElementById(name)); - name = name.replace(':', '\\:'); - if (element.querySelectorAll) { - forEach(element.querySelectorAll('.' + name), append); - forEach(element.querySelectorAll('.' + name + '\\:'), append); - forEach(element.querySelectorAll('[' + name + ']'), append); - } - }); - - forEach(elements, function(element) { - if (!appElement) { - var className = ' ' + element.className + ' '; - var match = NG_APP_CLASS_REGEXP.exec(className); - if (match) { - appElement = element; - module = (match[2] || '').replace(/\s+/g, ','); - } else { - forEach(element.attributes, function(attr) { - if (!appElement && names[attr.name]) { - appElement = element; - module = attr.value; - } - }); - } - } - }); - if (appElement) { - bootstrap(appElement, module ? [module] : []); - } -} - -/** - * @ngdoc function - * @name angular.bootstrap - * @description - * Use this function to manually start up angular application. - * - * See: {@link guide/bootstrap Bootstrap} - * - * @param {Element} element DOM element which is the root of angular application. - * @param {Array=} modules an array of module declarations. See: {@link angular.module modules} - * @returns {AUTO.$injector} Returns the newly created injector for this app. - */ -function bootstrap(element, modules) { - var resumeBootstrapInternal = function() { - element = jqLite(element); - modules = modules || []; - modules.unshift(['$provide', function($provide) { - $provide.value('$rootElement', element); - }]); - modules.unshift('ng'); - var injector = createInjector(modules); - injector.invoke(['$rootScope', '$rootElement', '$compile', '$injector', '$animator', - function(scope, element, compile, injector, animator) { - scope.$apply(function() { - element.data('$injector', injector); - compile(element)(scope); - }); - animator.enabled(true); - }] - ); - return injector; - }; - - var NG_DEFER_BOOTSTRAP = /^NG_DEFER_BOOTSTRAP!/; - - if (window && !NG_DEFER_BOOTSTRAP.test(window.name)) { - return resumeBootstrapInternal(); - } - - window.name = window.name.replace(NG_DEFER_BOOTSTRAP, ''); - angular.resumeBootstrap = function(extraModules) { - forEach(extraModules, function(module) { - modules.push(module); - }); - resumeBootstrapInternal(); - }; -} - -var SNAKE_CASE_REGEXP = /[A-Z]/g; -function snake_case(name, separator){ - separator = separator || '_'; - return name.replace(SNAKE_CASE_REGEXP, function(letter, pos) { - return (pos ? separator : '') + letter.toLowerCase(); - }); -} - -function bindJQuery() { - // bind to jQuery if present; - jQuery = window.jQuery; - // reset to jQuery or default to us. - if (jQuery) { - jqLite = jQuery; - extend(jQuery.fn, { - scope: JQLitePrototype.scope, - controller: JQLitePrototype.controller, - injector: JQLitePrototype.injector, - inheritedData: JQLitePrototype.inheritedData - }); - JQLitePatchJQueryRemove('remove', true); - JQLitePatchJQueryRemove('empty'); - JQLitePatchJQueryRemove('html'); - } else { - jqLite = JQLite; - } - angular.element = jqLite; -} - -/** - * throw error if the argument is falsy. - */ -function assertArg(arg, name, reason) { - if (!arg) { - throw new Error("Argument '" + (name || '?') + "' is " + (reason || "required")); - } - return arg; -} - -function assertArgFn(arg, name, acceptArrayAnnotation) { - if (acceptArrayAnnotation && isArray(arg)) { - arg = arg[arg.length - 1]; - } - - assertArg(isFunction(arg), name, 'not a function, got ' + - (arg && typeof arg == 'object' ? arg.constructor.name || 'Object' : typeof arg)); - return arg; -} - -/** - * @ngdoc interface - * @name angular.Module - * @description - * - * Interface for configuring angular {@link angular.module modules}. - */ - -function setupModuleLoader(window) { - - function ensure(obj, name, factory) { - return obj[name] || (obj[name] = factory()); - } - - return ensure(ensure(window, 'angular', Object), 'module', function() { - /** @type {Object.} */ - var modules = {}; - - /** - * @ngdoc function - * @name angular.module - * @description - * - * The `angular.module` is a global place for creating and registering Angular modules. All - * modules (angular core or 3rd party) that should be available to an application must be - * registered using this mechanism. - * - * - * # Module - * - * A module is a collocation of services, directives, filters, and configuration information. Module - * is used to configure the {@link AUTO.$injector $injector}. - * - *
                -     * // Create a new module
                -     * var myModule = angular.module('myModule', []);
                -     *
                -     * // register a new service
                -     * myModule.value('appName', 'MyCoolApp');
                -     *
                -     * // configure existing services inside initialization blocks.
                -     * myModule.config(function($locationProvider) {
                -     *   // Configure existing providers
                -     *   $locationProvider.hashPrefix('!');
                -     * });
                -     * 
                - * - * Then you can create an injector and load your modules like this: - * - *
                -     * var injector = angular.injector(['ng', 'MyModule'])
                -     * 
                - * - * However it's more likely that you'll just use - * {@link ng.directive:ngApp ngApp} or - * {@link angular.bootstrap} to simplify this process for you. - * - * @param {!string} name The name of the module to create or retrieve. - * @param {Array.=} requires If specified then new module is being created. If unspecified then the - * the module is being retrieved for further configuration. - * @param {Function} configFn Optional configuration function for the module. Same as - * {@link angular.Module#config Module#config()}. - * @returns {module} new module with the {@link angular.Module} api. - */ - return function module(name, requires, configFn) { - if (requires && modules.hasOwnProperty(name)) { - modules[name] = null; - } - return ensure(modules, name, function() { - if (!requires) { - throw Error('No module: ' + name); - } - - /** @type {!Array.>} */ - var invokeQueue = []; - - /** @type {!Array.} */ - var runBlocks = []; - - var config = invokeLater('$injector', 'invoke'); - - /** @type {angular.Module} */ - var moduleInstance = { - // Private state - _invokeQueue: invokeQueue, - _runBlocks: runBlocks, - - /** - * @ngdoc property - * @name angular.Module#requires - * @propertyOf angular.Module - * @returns {Array.} List of module names which must be loaded before this module. - * @description - * Holds the list of modules which the injector will load before the current module is loaded. - */ - requires: requires, - - /** - * @ngdoc property - * @name angular.Module#name - * @propertyOf angular.Module - * @returns {string} Name of the module. - * @description - */ - name: name, - - - /** - * @ngdoc method - * @name angular.Module#provider - * @methodOf angular.Module - * @param {string} name service name - * @param {Function} providerType Construction function for creating new instance of the service. - * @description - * See {@link AUTO.$provide#provider $provide.provider()}. - */ - provider: invokeLater('$provide', 'provider'), - - /** - * @ngdoc method - * @name angular.Module#factory - * @methodOf angular.Module - * @param {string} name service name - * @param {Function} providerFunction Function for creating new instance of the service. - * @description - * See {@link AUTO.$provide#factory $provide.factory()}. - */ - factory: invokeLater('$provide', 'factory'), - - /** - * @ngdoc method - * @name angular.Module#service - * @methodOf angular.Module - * @param {string} name service name - * @param {Function} constructor A constructor function that will be instantiated. - * @description - * See {@link AUTO.$provide#service $provide.service()}. - */ - service: invokeLater('$provide', 'service'), - - /** - * @ngdoc method - * @name angular.Module#value - * @methodOf angular.Module - * @param {string} name service name - * @param {*} object Service instance object. - * @description - * See {@link AUTO.$provide#value $provide.value()}. - */ - value: invokeLater('$provide', 'value'), - - /** - * @ngdoc method - * @name angular.Module#constant - * @methodOf angular.Module - * @param {string} name constant name - * @param {*} object Constant value. - * @description - * Because the constant are fixed, they get applied before other provide methods. - * See {@link AUTO.$provide#constant $provide.constant()}. - */ - constant: invokeLater('$provide', 'constant', 'unshift'), - - /** - * @ngdoc method - * @name angular.Module#animation - * @methodOf angular.Module - * @param {string} name animation name - * @param {Function} animationFactory Factory function for creating new instance of an animation. - * @description - * - * Defines an animation hook that can be later used with {@link ng.directive:ngAnimate ngAnimate} - * alongside {@link ng.directive:ngAnimate#Description common ng directives} as well as custom directives. - *
                -           * module.animation('animation-name', function($inject1, $inject2) {
                -           *   return {
                -           *     //this gets called in preparation to setup an animation
                -           *     setup : function(element) { ... },
                -           *
                -           *     //this gets called once the animation is run
                -           *     start : function(element, done, memo) { ... }
                -           *   }
                -           * })
                -           * 
                - * - * See {@link ng.$animationProvider#register $animationProvider.register()} and - * {@link ng.directive:ngAnimate ngAnimate} for more information. - */ - animation: invokeLater('$animationProvider', 'register'), - - /** - * @ngdoc method - * @name angular.Module#filter - * @methodOf angular.Module - * @param {string} name Filter name. - * @param {Function} filterFactory Factory function for creating new instance of filter. - * @description - * See {@link ng.$filterProvider#register $filterProvider.register()}. - */ - filter: invokeLater('$filterProvider', 'register'), - - /** - * @ngdoc method - * @name angular.Module#controller - * @methodOf angular.Module - * @param {string} name Controller name. - * @param {Function} constructor Controller constructor function. - * @description - * See {@link ng.$controllerProvider#register $controllerProvider.register()}. - */ - controller: invokeLater('$controllerProvider', 'register'), - - /** - * @ngdoc method - * @name angular.Module#directive - * @methodOf angular.Module - * @param {string} name directive name - * @param {Function} directiveFactory Factory function for creating new instance of - * directives. - * @description - * See {@link ng.$compileProvider#directive $compileProvider.directive()}. - */ - directive: invokeLater('$compileProvider', 'directive'), - - /** - * @ngdoc method - * @name angular.Module#config - * @methodOf angular.Module - * @param {Function} configFn Execute this function on module load. Useful for service - * configuration. - * @description - * Use this method to register work which needs to be performed on module loading. - */ - config: config, - - /** - * @ngdoc method - * @name angular.Module#run - * @methodOf angular.Module - * @param {Function} initializationFn Execute this function after injector creation. - * Useful for application initialization. - * @description - * Use this method to register work which should be performed when the injector is done - * loading all modules. - */ - run: function(block) { - runBlocks.push(block); - return this; - } - }; - - if (configFn) { - config(configFn); - } - - return moduleInstance; - - /** - * @param {string} provider - * @param {string} method - * @param {String=} insertMethod - * @returns {angular.Module} - */ - function invokeLater(provider, method, insertMethod) { - return function() { - invokeQueue[insertMethod || 'push']([provider, method, arguments]); - return moduleInstance; - } - } - }); - }; - }); - -} - -/** - * @ngdoc property - * @name angular.version - * @description - * An object that contains information about the current AngularJS version. This object has the - * following properties: - * - * - `full` – `{string}` – Full version string, such as "0.9.18". - * - `major` – `{number}` – Major version number, such as "0". - * - `minor` – `{number}` – Minor version number, such as "9". - * - `dot` – `{number}` – Dot version number, such as "18". - * - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat". - */ -var version = { - full: '1.1.5', // all of these placeholder strings will be replaced by grunt's - major: 1, // package task - minor: 1, - dot: 5, - codeName: 'triangle-squarification' -}; - - -function publishExternalAPI(angular){ - extend(angular, { - 'bootstrap': bootstrap, - 'copy': copy, - 'extend': extend, - 'equals': equals, - 'element': jqLite, - 'forEach': forEach, - 'injector': createInjector, - 'noop':noop, - 'bind':bind, - 'toJson': toJson, - 'fromJson': fromJson, - 'identity':identity, - 'isUndefined': isUndefined, - 'isDefined': isDefined, - 'isString': isString, - 'isFunction': isFunction, - 'isObject': isObject, - 'isNumber': isNumber, - 'isElement': isElement, - 'isArray': isArray, - 'version': version, - 'isDate': isDate, - 'lowercase': lowercase, - 'uppercase': uppercase, - 'callbacks': {counter: 0}, - 'noConflict': noConflict - }); - - angularModule = setupModuleLoader(window); - try { - angularModule('ngLocale'); - } catch (e) { - angularModule('ngLocale', []).provider('$locale', $LocaleProvider); - } - - angularModule('ng', ['ngLocale'], ['$provide', - function ngModule($provide) { - $provide.provider('$compile', $CompileProvider). - directive({ - a: htmlAnchorDirective, - input: inputDirective, - textarea: inputDirective, - form: formDirective, - script: scriptDirective, - select: selectDirective, - style: styleDirective, - option: optionDirective, - ngBind: ngBindDirective, - ngBindHtmlUnsafe: ngBindHtmlUnsafeDirective, - ngBindTemplate: ngBindTemplateDirective, - ngClass: ngClassDirective, - ngClassEven: ngClassEvenDirective, - ngClassOdd: ngClassOddDirective, - ngCsp: ngCspDirective, - ngCloak: ngCloakDirective, - ngController: ngControllerDirective, - ngForm: ngFormDirective, - ngHide: ngHideDirective, - ngIf: ngIfDirective, - ngInclude: ngIncludeDirective, - ngInit: ngInitDirective, - ngNonBindable: ngNonBindableDirective, - ngPluralize: ngPluralizeDirective, - ngRepeat: ngRepeatDirective, - ngShow: ngShowDirective, - ngSubmit: ngSubmitDirective, - ngStyle: ngStyleDirective, - ngSwitch: ngSwitchDirective, - ngSwitchWhen: ngSwitchWhenDirective, - ngSwitchDefault: ngSwitchDefaultDirective, - ngOptions: ngOptionsDirective, - ngView: ngViewDirective, - ngTransclude: ngTranscludeDirective, - ngModel: ngModelDirective, - ngList: ngListDirective, - ngChange: ngChangeDirective, - required: requiredDirective, - ngRequired: requiredDirective, - ngValue: ngValueDirective - }). - directive(ngAttributeAliasDirectives). - directive(ngEventDirectives); - $provide.provider({ - $anchorScroll: $AnchorScrollProvider, - $animation: $AnimationProvider, - $animator: $AnimatorProvider, - $browser: $BrowserProvider, - $cacheFactory: $CacheFactoryProvider, - $controller: $ControllerProvider, - $document: $DocumentProvider, - $exceptionHandler: $ExceptionHandlerProvider, - $filter: $FilterProvider, - $interpolate: $InterpolateProvider, - $http: $HttpProvider, - $httpBackend: $HttpBackendProvider, - $location: $LocationProvider, - $log: $LogProvider, - $parse: $ParseProvider, - $route: $RouteProvider, - $routeParams: $RouteParamsProvider, - $rootScope: $RootScopeProvider, - $q: $QProvider, - $sniffer: $SnifferProvider, - $templateCache: $TemplateCacheProvider, - $timeout: $TimeoutProvider, - $window: $WindowProvider - }); - } - ]); -} - -////////////////////////////////// -//JQLite -////////////////////////////////// - -/** - * @ngdoc function - * @name angular.element - * @function - * - * @description - * Wraps a raw DOM element or HTML string as a [jQuery](http://jquery.com) element. - * `angular.element` can be either an alias for [jQuery](http://api.jquery.com/jQuery/) function, if - * jQuery is available, or a function that wraps the element or string in Angular's jQuery lite - * implementation (commonly referred to as jqLite). - * - * Real jQuery always takes precedence over jqLite, provided it was loaded before `DOMContentLoaded` - * event fired. - * - * jqLite is a tiny, API-compatible subset of jQuery that allows - * Angular to manipulate the DOM. jqLite implements only the most commonly needed functionality - * within a very small footprint, so only a subset of the jQuery API - methods, arguments and - * invocation styles - are supported. - * - * Note: All element references in Angular are always wrapped with jQuery or jqLite; they are never - * raw DOM references. - * - * ## Angular's jQuery lite provides the following methods: - * - * - [addClass()](http://api.jquery.com/addClass/) - * - [after()](http://api.jquery.com/after/) - * - [append()](http://api.jquery.com/append/) - * - [attr()](http://api.jquery.com/attr/) - * - [bind()](http://api.jquery.com/bind/) - Does not support namespaces - * - [children()](http://api.jquery.com/children/) - Does not support selectors - * - [clone()](http://api.jquery.com/clone/) - * - [contents()](http://api.jquery.com/contents/) - * - [css()](http://api.jquery.com/css/) - * - [data()](http://api.jquery.com/data/) - * - [eq()](http://api.jquery.com/eq/) - * - [find()](http://api.jquery.com/find/) - Limited to lookups by tag name - * - [hasClass()](http://api.jquery.com/hasClass/) - * - [html()](http://api.jquery.com/html/) - * - [next()](http://api.jquery.com/next/) - Does not support selectors - * - [parent()](http://api.jquery.com/parent/) - Does not support selectors - * - [prepend()](http://api.jquery.com/prepend/) - * - [prop()](http://api.jquery.com/prop/) - * - [ready()](http://api.jquery.com/ready/) - * - [remove()](http://api.jquery.com/remove/) - * - [removeAttr()](http://api.jquery.com/removeAttr/) - * - [removeClass()](http://api.jquery.com/removeClass/) - * - [removeData()](http://api.jquery.com/removeData/) - * - [replaceWith()](http://api.jquery.com/replaceWith/) - * - [text()](http://api.jquery.com/text/) - * - [toggleClass()](http://api.jquery.com/toggleClass/) - * - [triggerHandler()](http://api.jquery.com/triggerHandler/) - Passes a dummy event object to handlers. - * - [unbind()](http://api.jquery.com/unbind/) - Does not support namespaces - * - [val()](http://api.jquery.com/val/) - * - [wrap()](http://api.jquery.com/wrap/) - * - * ## In addition to the above, Angular provides additional methods to both jQuery and jQuery lite: - * - * - `controller(name)` - retrieves the controller of the current element or its parent. By default - * retrieves controller associated with the `ngController` directive. If `name` is provided as - * camelCase directive name, then the controller for this directive will be retrieved (e.g. - * `'ngModel'`). - * - `injector()` - retrieves the injector of the current element or its parent. - * - `scope()` - retrieves the {@link api/ng.$rootScope.Scope scope} of the current - * element or its parent. - * - `inheritedData()` - same as `data()`, but walks up the DOM until a value is found or the top - * parent element is reached. - * - * @param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery. - * @returns {Object} jQuery object. - */ - -var jqCache = JQLite.cache = {}, - jqName = JQLite.expando = 'ng-' + new Date().getTime(), - jqId = 1, - addEventListenerFn = (window.document.addEventListener - ? function(element, type, fn) {element.addEventListener(type, fn, false);} - : function(element, type, fn) {element.attachEvent('on' + type, fn);}), - removeEventListenerFn = (window.document.removeEventListener - ? function(element, type, fn) {element.removeEventListener(type, fn, false); } - : function(element, type, fn) {element.detachEvent('on' + type, fn); }); - -function jqNextId() { return ++jqId; } - - -var SPECIAL_CHARS_REGEXP = /([\:\-\_]+(.))/g; -var MOZ_HACK_REGEXP = /^moz([A-Z])/; - -/** - * Converts snake_case to camelCase. - * Also there is special case for Moz prefix starting with upper case letter. - * @param name Name to normalize - */ -function camelCase(name) { - return name. - replace(SPECIAL_CHARS_REGEXP, function(_, separator, letter, offset) { - return offset ? letter.toUpperCase() : letter; - }). - replace(MOZ_HACK_REGEXP, 'Moz$1'); -} - -///////////////////////////////////////////// -// jQuery mutation patch -// -// In conjunction with bindJQuery intercepts all jQuery's DOM destruction apis and fires a -// $destroy event on all DOM nodes being removed. -// -///////////////////////////////////////////// - -function JQLitePatchJQueryRemove(name, dispatchThis) { - var originalJqFn = jQuery.fn[name]; - originalJqFn = originalJqFn.$original || originalJqFn; - removePatch.$original = originalJqFn; - jQuery.fn[name] = removePatch; - - function removePatch() { - var list = [this], - fireEvent = dispatchThis, - set, setIndex, setLength, - element, childIndex, childLength, children, - fns, events; - - while(list.length) { - set = list.shift(); - for(setIndex = 0, setLength = set.length; setIndex < setLength; setIndex++) { - element = jqLite(set[setIndex]); - if (fireEvent) { - element.triggerHandler('$destroy'); - } else { - fireEvent = !fireEvent; - } - for(childIndex = 0, childLength = (children = element.children()).length; - childIndex < childLength; - childIndex++) { - list.push(jQuery(children[childIndex])); - } - } - } - return originalJqFn.apply(this, arguments); - } -} - -///////////////////////////////////////////// -function JQLite(element) { - if (element instanceof JQLite) { - return element; - } - if (!(this instanceof JQLite)) { - if (isString(element) && element.charAt(0) != '<') { - throw Error('selectors not implemented'); - } - return new JQLite(element); - } - - if (isString(element)) { - var div = document.createElement('div'); - // Read about the NoScope elements here: - // http://msdn.microsoft.com/en-us/library/ms533897(VS.85).aspx - div.innerHTML = '
                 
                ' + element; // IE insanity to make NoScope elements work! - div.removeChild(div.firstChild); // remove the superfluous div - JQLiteAddNodes(this, div.childNodes); - this.remove(); // detach the elements from the temporary DOM div. - } else { - JQLiteAddNodes(this, element); - } -} - -function JQLiteClone(element) { - return element.cloneNode(true); -} - -function JQLiteDealoc(element){ - JQLiteRemoveData(element); - for ( var i = 0, children = element.childNodes || []; i < children.length; i++) { - JQLiteDealoc(children[i]); - } -} - -function JQLiteUnbind(element, type, fn) { - var events = JQLiteExpandoStore(element, 'events'), - handle = JQLiteExpandoStore(element, 'handle'); - - if (!handle) return; //no listeners registered - - if (isUndefined(type)) { - forEach(events, function(eventHandler, type) { - removeEventListenerFn(element, type, eventHandler); - delete events[type]; - }); - } else { - if (isUndefined(fn)) { - removeEventListenerFn(element, type, events[type]); - delete events[type]; - } else { - arrayRemove(events[type], fn); - } - } -} - -function JQLiteRemoveData(element) { - var expandoId = element[jqName], - expandoStore = jqCache[expandoId]; - - if (expandoStore) { - if (expandoStore.handle) { - expandoStore.events.$destroy && expandoStore.handle({}, '$destroy'); - JQLiteUnbind(element); - } - delete jqCache[expandoId]; - element[jqName] = undefined; // ie does not allow deletion of attributes on elements. - } -} - -function JQLiteExpandoStore(element, key, value) { - var expandoId = element[jqName], - expandoStore = jqCache[expandoId || -1]; - - if (isDefined(value)) { - if (!expandoStore) { - element[jqName] = expandoId = jqNextId(); - expandoStore = jqCache[expandoId] = {}; - } - expandoStore[key] = value; - } else { - return expandoStore && expandoStore[key]; - } -} - -function JQLiteData(element, key, value) { - var data = JQLiteExpandoStore(element, 'data'), - isSetter = isDefined(value), - keyDefined = !isSetter && isDefined(key), - isSimpleGetter = keyDefined && !isObject(key); - - if (!data && !isSimpleGetter) { - JQLiteExpandoStore(element, 'data', data = {}); - } - - if (isSetter) { - data[key] = value; - } else { - if (keyDefined) { - if (isSimpleGetter) { - // don't create data in this case. - return data && data[key]; - } else { - extend(data, key); - } - } else { - return data; - } - } -} - -function JQLiteHasClass(element, selector) { - return ((" " + element.className + " ").replace(/[\n\t]/g, " "). - indexOf( " " + selector + " " ) > -1); -} - -function JQLiteRemoveClass(element, cssClasses) { - if (cssClasses) { - forEach(cssClasses.split(' '), function(cssClass) { - element.className = trim( - (" " + element.className + " ") - .replace(/[\n\t]/g, " ") - .replace(" " + trim(cssClass) + " ", " ") - ); - }); - } -} - -function JQLiteAddClass(element, cssClasses) { - if (cssClasses) { - forEach(cssClasses.split(' '), function(cssClass) { - if (!JQLiteHasClass(element, cssClass)) { - element.className = trim(element.className + ' ' + trim(cssClass)); - } - }); - } -} - -function JQLiteAddNodes(root, elements) { - if (elements) { - elements = (!elements.nodeName && isDefined(elements.length) && !isWindow(elements)) - ? elements - : [ elements ]; - for(var i=0; i < elements.length; i++) { - root.push(elements[i]); - } - } -} - -function JQLiteController(element, name) { - return JQLiteInheritedData(element, '$' + (name || 'ngController' ) + 'Controller'); -} - -function JQLiteInheritedData(element, name, value) { - element = jqLite(element); - - // if element is the document object work with the html element instead - // this makes $(document).scope() possible - if(element[0].nodeType == 9) { - element = element.find('html'); - } - - while (element.length) { - if (value = element.data(name)) return value; - element = element.parent(); - } -} - -////////////////////////////////////////// -// Functions which are declared directly. -////////////////////////////////////////// -var JQLitePrototype = JQLite.prototype = { - ready: function(fn) { - var fired = false; - - function trigger() { - if (fired) return; - fired = true; - fn(); - } - - // check if document already is loaded - if (document.readyState === 'complete'){ - setTimeout(trigger); - } else { - this.bind('DOMContentLoaded', trigger); // works for modern browsers and IE9 - // we can not use jqLite since we are not done loading and jQuery could be loaded later. - JQLite(window).bind('load', trigger); // fallback to window.onload for others - } - }, - toString: function() { - var value = []; - forEach(this, function(e){ value.push('' + e);}); - return '[' + value.join(', ') + ']'; - }, - - eq: function(index) { - return (index >= 0) ? jqLite(this[index]) : jqLite(this[this.length + index]); - }, - - length: 0, - push: push, - sort: [].sort, - splice: [].splice -}; - -////////////////////////////////////////// -// Functions iterating getter/setters. -// these functions return self on setter and -// value on get. -////////////////////////////////////////// -var BOOLEAN_ATTR = {}; -forEach('multiple,selected,checked,disabled,readOnly,required,open'.split(','), function(value) { - BOOLEAN_ATTR[lowercase(value)] = value; -}); -var BOOLEAN_ELEMENTS = {}; -forEach('input,select,option,textarea,button,form,details'.split(','), function(value) { - BOOLEAN_ELEMENTS[uppercase(value)] = true; -}); - -function getBooleanAttrName(element, name) { - // check dom last since we will most likely fail on name - var booleanAttr = BOOLEAN_ATTR[name.toLowerCase()]; - - // booleanAttr is here twice to minimize DOM access - return booleanAttr && BOOLEAN_ELEMENTS[element.nodeName] && booleanAttr; -} - -forEach({ - data: JQLiteData, - inheritedData: JQLiteInheritedData, - - scope: function(element) { - return JQLiteInheritedData(element, '$scope'); - }, - - controller: JQLiteController , - - injector: function(element) { - return JQLiteInheritedData(element, '$injector'); - }, - - removeAttr: function(element,name) { - element.removeAttribute(name); - }, - - hasClass: JQLiteHasClass, - - css: function(element, name, value) { - name = camelCase(name); - - if (isDefined(value)) { - element.style[name] = value; - } else { - var val; - - if (msie <= 8) { - // this is some IE specific weirdness that jQuery 1.6.4 does not sure why - val = element.currentStyle && element.currentStyle[name]; - if (val === '') val = 'auto'; - } - - val = val || element.style[name]; - - if (msie <= 8) { - // jquery weirdness :-/ - val = (val === '') ? undefined : val; - } - - return val; - } - }, - - attr: function(element, name, value){ - var lowercasedName = lowercase(name); - if (BOOLEAN_ATTR[lowercasedName]) { - if (isDefined(value)) { - if (!!value) { - element[name] = true; - element.setAttribute(name, lowercasedName); - } else { - element[name] = false; - element.removeAttribute(lowercasedName); - } - } else { - return (element[name] || - (element.attributes.getNamedItem(name)|| noop).specified) - ? lowercasedName - : undefined; - } - } else if (isDefined(value)) { - element.setAttribute(name, value); - } else if (element.getAttribute) { - // the extra argument "2" is to get the right thing for a.href in IE, see jQuery code - // some elements (e.g. Document) don't have get attribute, so return undefined - var ret = element.getAttribute(name, 2); - // normalize non-existing attributes to undefined (as jQuery) - return ret === null ? undefined : ret; - } - }, - - prop: function(element, name, value) { - if (isDefined(value)) { - element[name] = value; - } else { - return element[name]; - } - }, - - text: extend((msie < 9) - ? function(element, value) { - if (element.nodeType == 1 /** Element */) { - if (isUndefined(value)) - return element.innerText; - element.innerText = value; - } else { - if (isUndefined(value)) - return element.nodeValue; - element.nodeValue = value; - } - } - : function(element, value) { - if (isUndefined(value)) { - return element.textContent; - } - element.textContent = value; - }, {$dv:''}), - - val: function(element, value) { - if (isUndefined(value)) { - return element.value; - } - element.value = value; - }, - - html: function(element, value) { - if (isUndefined(value)) { - return element.innerHTML; - } - for (var i = 0, childNodes = element.childNodes; i < childNodes.length; i++) { - JQLiteDealoc(childNodes[i]); - } - element.innerHTML = value; - } -}, function(fn, name){ - /** - * Properties: writes return selection, reads return first value - */ - JQLite.prototype[name] = function(arg1, arg2) { - var i, key; - - // JQLiteHasClass has only two arguments, but is a getter-only fn, so we need to special-case it - // in a way that survives minification. - if (((fn.length == 2 && (fn !== JQLiteHasClass && fn !== JQLiteController)) ? arg1 : arg2) === undefined) { - if (isObject(arg1)) { - - // we are a write, but the object properties are the key/values - for(i=0; i < this.length; i++) { - if (fn === JQLiteData) { - // data() takes the whole object in jQuery - fn(this[i], arg1); - } else { - for (key in arg1) { - fn(this[i], key, arg1[key]); - } - } - } - // return self for chaining - return this; - } else { - // we are a read, so read the first child. - if (this.length) - return fn(this[0], arg1, arg2); - } - } else { - // we are a write, so apply to all children - for(i=0; i < this.length; i++) { - fn(this[i], arg1, arg2); - } - // return self for chaining - return this; - } - return fn.$dv; - }; -}); - -function createEventHandler(element, events) { - var eventHandler = function (event, type) { - if (!event.preventDefault) { - event.preventDefault = function() { - event.returnValue = false; //ie - }; - } - - if (!event.stopPropagation) { - event.stopPropagation = function() { - event.cancelBubble = true; //ie - }; - } - - if (!event.target) { - event.target = event.srcElement || document; - } - - if (isUndefined(event.defaultPrevented)) { - var prevent = event.preventDefault; - event.preventDefault = function() { - event.defaultPrevented = true; - prevent.call(event); - }; - event.defaultPrevented = false; - } - - event.isDefaultPrevented = function() { - return event.defaultPrevented || event.returnValue == false; - }; - - forEach(events[type || event.type], function(fn) { - fn.call(element, event); - }); - - // Remove monkey-patched methods (IE), - // as they would cause memory leaks in IE8. - if (msie <= 8) { - // IE7/8 does not allow to delete property on native object - event.preventDefault = null; - event.stopPropagation = null; - event.isDefaultPrevented = null; - } else { - // It shouldn't affect normal browsers (native methods are defined on prototype). - delete event.preventDefault; - delete event.stopPropagation; - delete event.isDefaultPrevented; - } - }; - eventHandler.elem = element; - return eventHandler; -} - -////////////////////////////////////////// -// Functions iterating traversal. -// These functions chain results into a single -// selector. -////////////////////////////////////////// -forEach({ - removeData: JQLiteRemoveData, - - dealoc: JQLiteDealoc, - - bind: function bindFn(element, type, fn){ - var events = JQLiteExpandoStore(element, 'events'), - handle = JQLiteExpandoStore(element, 'handle'); - - if (!events) JQLiteExpandoStore(element, 'events', events = {}); - if (!handle) JQLiteExpandoStore(element, 'handle', handle = createEventHandler(element, events)); - - forEach(type.split(' '), function(type){ - var eventFns = events[type]; - - if (!eventFns) { - if (type == 'mouseenter' || type == 'mouseleave') { - var contains = document.body.contains || document.body.compareDocumentPosition ? - function( a, b ) { - var adown = a.nodeType === 9 ? a.documentElement : a, - bup = b && b.parentNode; - return a === bup || !!( bup && bup.nodeType === 1 && ( - adown.contains ? - adown.contains( bup ) : - a.compareDocumentPosition && a.compareDocumentPosition( bup ) & 16 - )); - } : - function( a, b ) { - if ( b ) { - while ( (b = b.parentNode) ) { - if ( b === a ) { - return true; - } - } - } - return false; - }; - - events[type] = []; - - // Refer to jQuery's implementation of mouseenter & mouseleave - // Read about mouseenter and mouseleave: - // http://www.quirksmode.org/js/events_mouse.html#link8 - var eventmap = { mouseleave : "mouseout", mouseenter : "mouseover"} - bindFn(element, eventmap[type], function(event) { - var ret, target = this, related = event.relatedTarget; - // For mousenter/leave call the handler if related is outside the target. - // NB: No relatedTarget if the mouse left/entered the browser window - if ( !related || (related !== target && !contains(target, related)) ){ - handle(event, type); - } - - }); - - } else { - addEventListenerFn(element, type, handle); - events[type] = []; - } - eventFns = events[type] - } - eventFns.push(fn); - }); - }, - - unbind: JQLiteUnbind, - - replaceWith: function(element, replaceNode) { - var index, parent = element.parentNode; - JQLiteDealoc(element); - forEach(new JQLite(replaceNode), function(node){ - if (index) { - parent.insertBefore(node, index.nextSibling); - } else { - parent.replaceChild(node, element); - } - index = node; - }); - }, - - children: function(element) { - var children = []; - forEach(element.childNodes, function(element){ - if (element.nodeType === 1) - children.push(element); - }); - return children; - }, - - contents: function(element) { - return element.childNodes || []; - }, - - append: function(element, node) { - forEach(new JQLite(node), function(child){ - if (element.nodeType === 1 || element.nodeType === 11) { - element.appendChild(child); - } - }); - }, - - prepend: function(element, node) { - if (element.nodeType === 1) { - var index = element.firstChild; - forEach(new JQLite(node), function(child){ - if (index) { - element.insertBefore(child, index); - } else { - element.appendChild(child); - index = child; - } - }); - } - }, - - wrap: function(element, wrapNode) { - wrapNode = jqLite(wrapNode)[0]; - var parent = element.parentNode; - if (parent) { - parent.replaceChild(wrapNode, element); - } - wrapNode.appendChild(element); - }, - - remove: function(element) { - JQLiteDealoc(element); - var parent = element.parentNode; - if (parent) parent.removeChild(element); - }, - - after: function(element, newElement) { - var index = element, parent = element.parentNode; - forEach(new JQLite(newElement), function(node){ - parent.insertBefore(node, index.nextSibling); - index = node; - }); - }, - - addClass: JQLiteAddClass, - removeClass: JQLiteRemoveClass, - - toggleClass: function(element, selector, condition) { - if (isUndefined(condition)) { - condition = !JQLiteHasClass(element, selector); - } - (condition ? JQLiteAddClass : JQLiteRemoveClass)(element, selector); - }, - - parent: function(element) { - var parent = element.parentNode; - return parent && parent.nodeType !== 11 ? parent : null; - }, - - next: function(element) { - if (element.nextElementSibling) { - return element.nextElementSibling; - } - - // IE8 doesn't have nextElementSibling - var elm = element.nextSibling; - while (elm != null && elm.nodeType !== 1) { - elm = elm.nextSibling; - } - return elm; - }, - - find: function(element, selector) { - return element.getElementsByTagName(selector); - }, - - clone: JQLiteClone, - - triggerHandler: function(element, eventName) { - var eventFns = (JQLiteExpandoStore(element, 'events') || {})[eventName]; - var event; - - forEach(eventFns, function(fn) { - fn.call(element, {preventDefault: noop}); - }); - } -}, function(fn, name){ - /** - * chaining functions - */ - JQLite.prototype[name] = function(arg1, arg2) { - var value; - for(var i=0; i < this.length; i++) { - if (value == undefined) { - value = fn(this[i], arg1, arg2); - if (value !== undefined) { - // any function which returns a value needs to be wrapped - value = jqLite(value); - } - } else { - JQLiteAddNodes(value, fn(this[i], arg1, arg2)); - } - } - return value == undefined ? this : value; - }; -}); - -/** - * Computes a hash of an 'obj'. - * Hash of a: - * string is string - * number is number as string - * object is either result of calling $$hashKey function on the object or uniquely generated id, - * that is also assigned to the $$hashKey property of the object. - * - * @param obj - * @returns {string} hash string such that the same input will have the same hash string. - * The resulting string key is in 'type:hashKey' format. - */ -function hashKey(obj) { - var objType = typeof obj, - key; - - if (objType == 'object' && obj !== null) { - if (typeof (key = obj.$$hashKey) == 'function') { - // must invoke on object to keep the right this - key = obj.$$hashKey(); - } else if (key === undefined) { - key = obj.$$hashKey = nextUid(); - } - } else { - key = obj; - } - - return objType + ':' + key; -} - -/** - * HashMap which can use objects as keys - */ -function HashMap(array){ - forEach(array, this.put, this); -} -HashMap.prototype = { - /** - * Store key value pair - * @param key key to store can be any type - * @param value value to store can be any type - */ - put: function(key, value) { - this[hashKey(key)] = value; - }, - - /** - * @param key - * @returns the value for the key - */ - get: function(key) { - return this[hashKey(key)]; - }, - - /** - * Remove the key/value pair - * @param key - */ - remove: function(key) { - var value = this[key = hashKey(key)]; - delete this[key]; - return value; - } -}; - -/** - * @ngdoc function - * @name angular.injector - * @function - * - * @description - * Creates an injector function that can be used for retrieving services as well as for - * dependency injection (see {@link guide/di dependency injection}). - * - - * @param {Array.} modules A list of module functions or their aliases. See - * {@link angular.module}. The `ng` module must be explicitly added. - * @returns {function()} Injector function. See {@link AUTO.$injector $injector}. - * - * @example - * Typical usage - *
                - *   // create an injector
                - *   var $injector = angular.injector(['ng']);
                - *
                - *   // use the injector to kick off your application
                - *   // use the type inference to auto inject arguments, or use implicit injection
                - *   $injector.invoke(function($rootScope, $compile, $document){
                - *     $compile($document)($rootScope);
                - *     $rootScope.$digest();
                - *   });
                - * 
                - */ - - -/** - * @ngdoc overview - * @name AUTO - * @description - * - * Implicit module which gets automatically added to each {@link AUTO.$injector $injector}. - */ - -var FN_ARGS = /^function\s*[^\(]*\(\s*([^\)]*)\)/m; -var FN_ARG_SPLIT = /,/; -var FN_ARG = /^\s*(_?)(\S+?)\1\s*$/; -var STRIP_COMMENTS = /((\/\/.*$)|(\/\*[\s\S]*?\*\/))/mg; -function annotate(fn) { - var $inject, - fnText, - argDecl, - last; - - if (typeof fn == 'function') { - if (!($inject = fn.$inject)) { - $inject = []; - fnText = fn.toString().replace(STRIP_COMMENTS, ''); - argDecl = fnText.match(FN_ARGS); - forEach(argDecl[1].split(FN_ARG_SPLIT), function(arg){ - arg.replace(FN_ARG, function(all, underscore, name){ - $inject.push(name); - }); - }); - fn.$inject = $inject; - } - } else if (isArray(fn)) { - last = fn.length - 1; - assertArgFn(fn[last], 'fn'); - $inject = fn.slice(0, last); - } else { - assertArgFn(fn, 'fn', true); - } - return $inject; -} - -/////////////////////////////////////// - -/** - * @ngdoc object - * @name AUTO.$injector - * @function - * - * @description - * - * `$injector` is used to retrieve object instances as defined by - * {@link AUTO.$provide provider}, instantiate types, invoke methods, - * and load modules. - * - * The following always holds true: - * - *
                - *   var $injector = angular.injector();
                - *   expect($injector.get('$injector')).toBe($injector);
                - *   expect($injector.invoke(function($injector){
                - *     return $injector;
                - *   }).toBe($injector);
                - * 
                - * - * # Injection Function Annotation - * - * JavaScript does not have annotations, and annotations are needed for dependency injection. The - * following are all valid ways of annotating function with injection arguments and are equivalent. - * - *
                - *   // inferred (only works if code not minified/obfuscated)
                - *   $injector.invoke(function(serviceA){});
                - *
                - *   // annotated
                - *   function explicit(serviceA) {};
                - *   explicit.$inject = ['serviceA'];
                - *   $injector.invoke(explicit);
                - *
                - *   // inline
                - *   $injector.invoke(['serviceA', function(serviceA){}]);
                - * 
                - * - * ## Inference - * - * In JavaScript calling `toString()` on a function returns the function definition. The definition can then be - * parsed and the function arguments can be extracted. *NOTE:* This does not work with minification, and obfuscation - * tools since these tools change the argument names. - * - * ## `$inject` Annotation - * By adding a `$inject` property onto a function the injection parameters can be specified. - * - * ## Inline - * As an array of injection names, where the last item in the array is the function to call. - */ - -/** - * @ngdoc method - * @name AUTO.$injector#get - * @methodOf AUTO.$injector - * - * @description - * Return an instance of the service. - * - * @param {string} name The name of the instance to retrieve. - * @return {*} The instance. - */ - -/** - * @ngdoc method - * @name AUTO.$injector#invoke - * @methodOf AUTO.$injector - * - * @description - * Invoke the method and supply the method arguments from the `$injector`. - * - * @param {!function} fn The function to invoke. The function arguments come form the function annotation. - * @param {Object=} self The `this` for the invoked method. - * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before - * the `$injector` is consulted. - * @returns {*} the value returned by the invoked `fn` function. - */ - -/** - * @ngdoc method - * @name AUTO.$injector#has - * @methodOf AUTO.$injector - * - * @description - * Allows the user to query if the particular service exist. - * - * @param {string} Name of the service to query. - * @returns {boolean} returns true if injector has given service. - */ - -/** - * @ngdoc method - * @name AUTO.$injector#instantiate - * @methodOf AUTO.$injector - * @description - * Create a new instance of JS type. The method takes a constructor function invokes the new operator and supplies - * all of the arguments to the constructor function as specified by the constructor annotation. - * - * @param {function} Type Annotated constructor function. - * @param {Object=} locals Optional object. If preset then any argument names are read from this object first, before - * the `$injector` is consulted. - * @returns {Object} new instance of `Type`. - */ - -/** - * @ngdoc method - * @name AUTO.$injector#annotate - * @methodOf AUTO.$injector - * - * @description - * Returns an array of service names which the function is requesting for injection. This API is used by the injector - * to determine which services need to be injected into the function when the function is invoked. There are three - * ways in which the function can be annotated with the needed dependencies. - * - * # Argument names - * - * The simplest form is to extract the dependencies from the arguments of the function. This is done by converting - * the function into a string using `toString()` method and extracting the argument names. - *
                - *   // Given
                - *   function MyController($scope, $route) {
                - *     // ...
                - *   }
                - *
                - *   // Then
                - *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);
                - * 
                - * - * This method does not work with code minfication / obfuscation. For this reason the following annotation strategies - * are supported. - * - * # The `$inject` property - * - * If a function has an `$inject` property and its value is an array of strings, then the strings represent names of - * services to be injected into the function. - *
                - *   // Given
                - *   var MyController = function(obfuscatedScope, obfuscatedRoute) {
                - *     // ...
                - *   }
                - *   // Define function dependencies
                - *   MyController.$inject = ['$scope', '$route'];
                - *
                - *   // Then
                - *   expect(injector.annotate(MyController)).toEqual(['$scope', '$route']);
                - * 
                - * - * # The array notation - * - * It is often desirable to inline Injected functions and that's when setting the `$inject` property is very - * inconvenient. In these situations using the array notation to specify the dependencies in a way that survives - * minification is a better choice: - * - *
                - *   // We wish to write this (not minification / obfuscation safe)
                - *   injector.invoke(function($compile, $rootScope) {
                - *     // ...
                - *   });
                - *
                - *   // We are forced to write break inlining
                - *   var tmpFn = function(obfuscatedCompile, obfuscatedRootScope) {
                - *     // ...
                - *   };
                - *   tmpFn.$inject = ['$compile', '$rootScope'];
                - *   injector.invoke(tmpFn);
                - *
                - *   // To better support inline function the inline annotation is supported
                - *   injector.invoke(['$compile', '$rootScope', function(obfCompile, obfRootScope) {
                - *     // ...
                - *   }]);
                - *
                - *   // Therefore
                - *   expect(injector.annotate(
                - *      ['$compile', '$rootScope', function(obfus_$compile, obfus_$rootScope) {}])
                - *    ).toEqual(['$compile', '$rootScope']);
                - * 
                - * - * @param {function|Array.} fn Function for which dependent service names need to be retrieved as described - * above. - * - * @returns {Array.} The names of the services which the function requires. - */ - - - - -/** - * @ngdoc object - * @name AUTO.$provide - * - * @description - * - * Use `$provide` to register new providers with the `$injector`. The providers are the factories for the instance. - * The providers share the same name as the instance they create with `Provider` suffixed to them. - * - * A provider is an object with a `$get()` method. The injector calls the `$get` method to create a new instance of - * a service. The Provider can have additional methods which would allow for configuration of the provider. - * - *
                - *   function GreetProvider() {
                - *     var salutation = 'Hello';
                - *
                - *     this.salutation = function(text) {
                - *       salutation = text;
                - *     };
                - *
                - *     this.$get = function() {
                - *       return function (name) {
                - *         return salutation + ' ' + name + '!';
                - *       };
                - *     };
                - *   }
                - *
                - *   describe('Greeter', function(){
                - *
                - *     beforeEach(module(function($provide) {
                - *       $provide.provider('greet', GreetProvider);
                - *     }));
                - *
                - *     it('should greet', inject(function(greet) {
                - *       expect(greet('angular')).toEqual('Hello angular!');
                - *     }));
                - *
                - *     it('should allow configuration of salutation', function() {
                - *       module(function(greetProvider) {
                - *         greetProvider.salutation('Ahoj');
                - *       });
                - *       inject(function(greet) {
                - *         expect(greet('angular')).toEqual('Ahoj angular!');
                - *       });
                - *     });
                - * 
                - */ - -/** - * @ngdoc method - * @name AUTO.$provide#provider - * @methodOf AUTO.$provide - * @description - * - * Register a provider for a service. The providers can be retrieved and can have additional configuration methods. - * - * @param {string} name The name of the instance. NOTE: the provider will be available under `name + 'Provider'` key. - * @param {(Object|function())} provider If the provider is: - * - * - `Object`: then it should have a `$get` method. The `$get` method will be invoked using - * {@link AUTO.$injector#invoke $injector.invoke()} when an instance needs to be created. - * - `Constructor`: a new instance of the provider will be created using - * {@link AUTO.$injector#instantiate $injector.instantiate()}, then treated as `object`. - * - * @returns {Object} registered provider instance - */ - -/** - * @ngdoc method - * @name AUTO.$provide#factory - * @methodOf AUTO.$provide - * @description - * - * A short hand for configuring services if only `$get` method is required. - * - * @param {string} name The name of the instance. - * @param {function()} $getFn The $getFn for the instance creation. Internally this is a short hand for - * `$provide.provider(name, {$get: $getFn})`. - * @returns {Object} registered provider instance - */ - - -/** - * @ngdoc method - * @name AUTO.$provide#service - * @methodOf AUTO.$provide - * @description - * - * A short hand for registering service of given class. - * - * @param {string} name The name of the instance. - * @param {Function} constructor A class (constructor function) that will be instantiated. - * @returns {Object} registered provider instance - */ - - -/** - * @ngdoc method - * @name AUTO.$provide#value - * @methodOf AUTO.$provide - * @description - * - * A short hand for configuring services if the `$get` method is a constant. - * - * @param {string} name The name of the instance. - * @param {*} value The value. - * @returns {Object} registered provider instance - */ - - -/** - * @ngdoc method - * @name AUTO.$provide#constant - * @methodOf AUTO.$provide - * @description - * - * A constant value, but unlike {@link AUTO.$provide#value value} it can be injected - * into configuration function (other modules) and it is not interceptable by - * {@link AUTO.$provide#decorator decorator}. - * - * @param {string} name The name of the constant. - * @param {*} value The constant value. - * @returns {Object} registered instance - */ - - -/** - * @ngdoc method - * @name AUTO.$provide#decorator - * @methodOf AUTO.$provide - * @description - * - * Decoration of service, allows the decorator to intercept the service instance creation. The - * returned instance may be the original instance, or a new instance which delegates to the - * original instance. - * - * @param {string} name The name of the service to decorate. - * @param {function()} decorator This function will be invoked when the service needs to be - * instantiated. The function is called using the {@link AUTO.$injector#invoke - * injector.invoke} method and is therefore fully injectable. Local injection arguments: - * - * * `$delegate` - The original service instance, which can be monkey patched, configured, - * decorated or delegated to. - */ - - -function createInjector(modulesToLoad) { - var INSTANTIATING = {}, - providerSuffix = 'Provider', - path = [], - loadedModules = new HashMap(), - providerCache = { - $provide: { - provider: supportObject(provider), - factory: supportObject(factory), - service: supportObject(service), - value: supportObject(value), - constant: supportObject(constant), - decorator: decorator - } - }, - providerInjector = (providerCache.$injector = - createInternalInjector(providerCache, function() { - throw Error("Unknown provider: " + path.join(' <- ')); - })), - instanceCache = {}, - instanceInjector = (instanceCache.$injector = - createInternalInjector(instanceCache, function(servicename) { - var provider = providerInjector.get(servicename + providerSuffix); - return instanceInjector.invoke(provider.$get, provider); - })); - - - forEach(loadModules(modulesToLoad), function(fn) { instanceInjector.invoke(fn || noop); }); - - return instanceInjector; - - //////////////////////////////////// - // $provider - //////////////////////////////////// - - function supportObject(delegate) { - return function(key, value) { - if (isObject(key)) { - forEach(key, reverseParams(delegate)); - } else { - return delegate(key, value); - } - } - } - - function provider(name, provider_) { - if (isFunction(provider_) || isArray(provider_)) { - provider_ = providerInjector.instantiate(provider_); - } - if (!provider_.$get) { - throw Error('Provider ' + name + ' must define $get factory method.'); - } - return providerCache[name + providerSuffix] = provider_; - } - - function factory(name, factoryFn) { return provider(name, { $get: factoryFn }); } - - function service(name, constructor) { - return factory(name, ['$injector', function($injector) { - return $injector.instantiate(constructor); - }]); - } - - function value(name, value) { return factory(name, valueFn(value)); } - - function constant(name, value) { - providerCache[name] = value; - instanceCache[name] = value; - } - - function decorator(serviceName, decorFn) { - var origProvider = providerInjector.get(serviceName + providerSuffix), - orig$get = origProvider.$get; - - origProvider.$get = function() { - var origInstance = instanceInjector.invoke(orig$get, origProvider); - return instanceInjector.invoke(decorFn, null, {$delegate: origInstance}); - }; - } - - //////////////////////////////////// - // Module Loading - //////////////////////////////////// - function loadModules(modulesToLoad){ - var runBlocks = []; - forEach(modulesToLoad, function(module) { - if (loadedModules.get(module)) return; - loadedModules.put(module, true); - if (isString(module)) { - var moduleFn = angularModule(module); - runBlocks = runBlocks.concat(loadModules(moduleFn.requires)).concat(moduleFn._runBlocks); - - try { - for(var invokeQueue = moduleFn._invokeQueue, i = 0, ii = invokeQueue.length; i < ii; i++) { - var invokeArgs = invokeQueue[i], - provider = providerInjector.get(invokeArgs[0]); - - provider[invokeArgs[1]].apply(provider, invokeArgs[2]); - } - } catch (e) { - if (e.message) e.message += ' from ' + module; - throw e; - } - } else if (isFunction(module)) { - try { - runBlocks.push(providerInjector.invoke(module)); - } catch (e) { - if (e.message) e.message += ' from ' + module; - throw e; - } - } else if (isArray(module)) { - try { - runBlocks.push(providerInjector.invoke(module)); - } catch (e) { - if (e.message) e.message += ' from ' + String(module[module.length - 1]); - throw e; - } - } else { - assertArgFn(module, 'module'); - } - }); - return runBlocks; - } - - //////////////////////////////////// - // internal Injector - //////////////////////////////////// - - function createInternalInjector(cache, factory) { - - function getService(serviceName) { - if (typeof serviceName !== 'string') { - throw Error('Service name expected'); - } - if (cache.hasOwnProperty(serviceName)) { - if (cache[serviceName] === INSTANTIATING) { - throw Error('Circular dependency: ' + path.join(' <- ')); - } - return cache[serviceName]; - } else { - try { - path.unshift(serviceName); - cache[serviceName] = INSTANTIATING; - return cache[serviceName] = factory(serviceName); - } finally { - path.shift(); - } - } - } - - function invoke(fn, self, locals){ - var args = [], - $inject = annotate(fn), - length, i, - key; - - for(i = 0, length = $inject.length; i < length; i++) { - key = $inject[i]; - args.push( - locals && locals.hasOwnProperty(key) - ? locals[key] - : getService(key) - ); - } - if (!fn.$inject) { - // this means that we must be an array. - fn = fn[length]; - } - - - // Performance optimization: http://jsperf.com/apply-vs-call-vs-invoke - switch (self ? -1 : args.length) { - case 0: return fn(); - case 1: return fn(args[0]); - case 2: return fn(args[0], args[1]); - case 3: return fn(args[0], args[1], args[2]); - case 4: return fn(args[0], args[1], args[2], args[3]); - case 5: return fn(args[0], args[1], args[2], args[3], args[4]); - case 6: return fn(args[0], args[1], args[2], args[3], args[4], args[5]); - case 7: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6]); - case 8: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7]); - case 9: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8]); - case 10: return fn(args[0], args[1], args[2], args[3], args[4], args[5], args[6], args[7], args[8], args[9]); - default: return fn.apply(self, args); - } - } - - function instantiate(Type, locals) { - var Constructor = function() {}, - instance, returnedValue; - - // Check if Type is annotated and use just the given function at n-1 as parameter - // e.g. someModule.factory('greeter', ['$window', function(renamed$window) {}]); - Constructor.prototype = (isArray(Type) ? Type[Type.length - 1] : Type).prototype; - instance = new Constructor(); - returnedValue = invoke(Type, instance, locals); - - return isObject(returnedValue) ? returnedValue : instance; - } - - return { - invoke: invoke, - instantiate: instantiate, - get: getService, - annotate: annotate, - has: function(name) { - return providerCache.hasOwnProperty(name + providerSuffix) || cache.hasOwnProperty(name); - } - }; - } -} - -/** - * @ngdoc function - * @name ng.$anchorScroll - * @requires $window - * @requires $location - * @requires $rootScope - * - * @description - * When called, it checks current value of `$location.hash()` and scroll to related element, - * according to rules specified in - * {@link http://dev.w3.org/html5/spec/Overview.html#the-indicated-part-of-the-document Html5 spec}. - * - * It also watches the `$location.hash()` and scroll whenever it changes to match any anchor. - * This can be disabled by calling `$anchorScrollProvider.disableAutoScrolling()`. - */ -function $AnchorScrollProvider() { - - var autoScrollingEnabled = true; - - this.disableAutoScrolling = function() { - autoScrollingEnabled = false; - }; - - this.$get = ['$window', '$location', '$rootScope', function($window, $location, $rootScope) { - var document = $window.document; - - // helper function to get first anchor from a NodeList - // can't use filter.filter, as it accepts only instances of Array - // and IE can't convert NodeList to an array using [].slice - // TODO(vojta): use filter if we change it to accept lists as well - function getFirstAnchor(list) { - var result = null; - forEach(list, function(element) { - if (!result && lowercase(element.nodeName) === 'a') result = element; - }); - return result; - } - - function scroll() { - var hash = $location.hash(), elm; - - // empty hash, scroll to the top of the page - if (!hash) $window.scrollTo(0, 0); - - // element with given id - else if ((elm = document.getElementById(hash))) elm.scrollIntoView(); - - // first anchor with given name :-D - else if ((elm = getFirstAnchor(document.getElementsByName(hash)))) elm.scrollIntoView(); - - // no element and hash == 'top', scroll to the top of the page - else if (hash === 'top') $window.scrollTo(0, 0); - } - - // does not scroll when user clicks on anchor link that is currently on - // (no url change, no $location.hash() change), browser native does scroll - if (autoScrollingEnabled) { - $rootScope.$watch(function autoScrollWatch() {return $location.hash();}, - function autoScrollWatchAction() { - $rootScope.$evalAsync(scroll); - }); - } - - return scroll; - }]; -} - - -/** - * @ngdoc object - * @name ng.$animationProvider - * @description - * - * The $AnimationProvider provider allows developers to register and access custom JavaScript animations directly inside - * of a module. - * - */ -$AnimationProvider.$inject = ['$provide']; -function $AnimationProvider($provide) { - var suffix = 'Animation'; - - /** - * @ngdoc function - * @name ng.$animation#register - * @methodOf ng.$animationProvider - * - * @description - * Registers a new injectable animation factory function. The factory function produces the animation object which - * has these two properties: - * - * * `setup`: `function(Element):*` A function which receives the starting state of the element. The purpose - * of this function is to get the element ready for animation. Optionally the function returns an memento which - * is passed to the `start` function. - * * `start`: `function(Element, doneFunction, *)` The element to animate, the `doneFunction` to be called on - * element animation completion, and an optional memento from the `setup` function. - * - * @param {string} name The name of the animation. - * @param {function} factory The factory function that will be executed to return the animation object. - * - */ - this.register = function(name, factory) { - $provide.factory(camelCase(name) + suffix, factory); - }; - - this.$get = ['$injector', function($injector) { - /** - * @ngdoc function - * @name ng.$animation - * @function - * - * @description - * The $animation service is used to retrieve any defined animation functions. When executed, the $animation service - * will return a object that contains the setup and start functions that were defined for the animation. - * - * @param {String} name Name of the animation function to retrieve. Animation functions are registered and stored - * inside of the AngularJS DI so a call to $animate('custom') is the same as injecting `customAnimation` - * via dependency injection. - * @return {Object} the animation object which contains the `setup` and `start` functions that perform the animation. - */ - return function $animation(name) { - if (name) { - var animationName = camelCase(name) + suffix; - if ($injector.has(animationName)) { - return $injector.get(animationName); - } - } - }; - }]; -} - -// NOTE: this is a pseudo directive. - -/** - * @ngdoc directive - * @name ng.directive:ngAnimate - * - * @description - * The `ngAnimate` directive works as an attribute that is attached alongside pre-existing directives. - * It effects how the directive will perform DOM manipulation. This allows for complex animations to take place - * without burdening the directive which uses the animation with animation details. The built in directives - * `ngRepeat`, `ngInclude`, `ngSwitch`, `ngShow`, `ngHide` and `ngView` already accept `ngAnimate` directive. - * Custom directives can take advantage of animation through {@link ng.$animator $animator service}. - * - * Below is a more detailed breakdown of the supported callback events provided by pre-exisitng ng directives: - * - * | Directive | Supported Animations | - * |========================================================== |====================================================| - * | {@link ng.directive:ngRepeat#animations ngRepeat} | enter, leave and move | - * | {@link ng.directive:ngView#animations ngView} | enter and leave | - * | {@link ng.directive:ngInclude#animations ngInclude} | enter and leave | - * | {@link ng.directive:ngSwitch#animations ngSwitch} | enter and leave | - * | {@link ng.directive:ngIf#animations ngIf} | enter and leave | - * | {@link ng.directive:ngShow#animations ngShow & ngHide} | show and hide | - * - * You can find out more information about animations upon visiting each directive page. - * - * Below is an example of a directive that makes use of the ngAnimate attribute: - * - *
                - * 
                - * 
                - *
                - * 
                - * 
                - * 
                - * 
                - *
                - * 
                - * 
                - * 
                - * - * The `event1` and `event2` attributes refer to the animation events specific to the directive that has been assigned. - * - * Keep in mind that if an animation is running, no child element of such animation can also be animated. - * - *

                CSS-defined Animations

                - * By default, ngAnimate attaches two CSS classes per animation event to the DOM element to achieve the animation. - * It is up to you, the developer, to ensure that the animations take place using cross-browser CSS3 transitions as - * well as CSS animations. - * - * The following code below demonstrates how to perform animations using **CSS transitions** with ngAnimate: - * - *
                - * 
                - *
                - * 
                - *
                - * - * The following code below demonstrates how to perform animations using **CSS animations** with ngAnimate: - * - *
                - * 
                - *
                - * 
                - *
                - * - * ngAnimate will first examine any CSS animation code and then fallback to using CSS transitions. - * - * Upon DOM mutation, the event class is added first, then the browser is allowed to reflow the content and then, - * the active class is added to trigger the animation. The ngAnimate directive will automatically extract the duration - * of the animation to determine when the animation ends. Once the animation is over then both CSS classes will be - * removed from the DOM. If a browser does not support CSS transitions or CSS animations then the animation will start and end - * immediately resulting in a DOM element that is at it's final state. This final state is when the DOM element - * has no CSS transition/animation classes surrounding it. - * - *

                JavaScript-defined Animations

                - * In the event that you do not want to use CSS3 transitions or CSS3 animations or if you wish to offer animations to browsers that do not - * yet support them, then you can make use of JavaScript animations defined inside of your AngularJS module. - * - *
                - * var ngModule = angular.module('YourApp', []);
                - * ngModule.animation('animate-enter', function() {
                - *   return {
                - *     setup : function(element) {
                - *       //prepare the element for animation
                - *       element.css({ 'opacity': 0 });
                - *       var memo = "..."; //this value is passed to the start function
                - *       return memo;
                - *     },
                - *     start : function(element, done, memo) {
                - *       //start the animation
                - *       element.animate({
                - *         'opacity' : 1
                - *       }, function() {
                - *         //call when the animation is complete
                - *         done()
                - *       });
                - *     }
                - *   }
                - * });
                - * 
                - * - * As you can see, the JavaScript code follows a similar template to the CSS3 animations. Once defined, the animation - * can be used in the same way with the ngAnimate attribute. Keep in mind that, when using JavaScript-enabled - * animations, ngAnimate will also add in the same CSS classes that CSS-enabled animations do (even if you're not using - * CSS animations) to animated the element, but it will not attempt to find any CSS3 transition or animation duration/delay values. - * It will instead close off the animation once the provided done function is executed. So it's important that you - * make sure your animations remember to fire off the done function once the animations are complete. - * - * @param {expression} ngAnimate Used to configure the DOM manipulation animations. - * - */ - -var $AnimatorProvider = function() { - var NG_ANIMATE_CONTROLLER = '$ngAnimateController'; - var rootAnimateController = {running:true}; - - this.$get = ['$animation', '$window', '$sniffer', '$rootElement', '$rootScope', - function($animation, $window, $sniffer, $rootElement, $rootScope) { - $rootElement.data(NG_ANIMATE_CONTROLLER, rootAnimateController); - - /** - * @ngdoc function - * @name ng.$animator - * @function - * - * @description - * The $animator.create service provides the DOM manipulation API which is decorated with animations. - * - * @param {Scope} scope the scope for the ng-animate. - * @param {Attributes} attr the attributes object which contains the ngAnimate key / value pair. (The attributes are - * passed into the linking function of the directive using the `$animator`.) - * @return {object} the animator object which contains the enter, leave, move, show, hide and animate methods. - */ - var AnimatorService = function(scope, attrs) { - var animator = {}; - - /** - * @ngdoc function - * @name ng.animator#enter - * @methodOf ng.$animator - * @function - * - * @description - * Injects the element object into the DOM (inside of the parent element) and then runs the enter animation. - * - * @param {jQuery/jqLite element} element the element that will be the focus of the enter animation - * @param {jQuery/jqLite element} parent the parent element of the element that will be the focus of the enter animation - * @param {jQuery/jqLite element} after the sibling element (which is the previous element) of the element that will be the focus of the enter animation - */ - animator.enter = animateActionFactory('enter', insert, noop); - - /** - * @ngdoc function - * @name ng.animator#leave - * @methodOf ng.$animator - * @function - * - * @description - * Runs the leave animation operation and, upon completion, removes the element from the DOM. - * - * @param {jQuery/jqLite element} element the element that will be the focus of the leave animation - * @param {jQuery/jqLite element} parent the parent element of the element that will be the focus of the leave animation - */ - animator.leave = animateActionFactory('leave', noop, remove); - - /** - * @ngdoc function - * @name ng.animator#move - * @methodOf ng.$animator - * @function - * - * @description - * Fires the move DOM operation. Just before the animation starts, the animator will either append it into the parent container or - * add the element directly after the after element if present. Then the move animation will be run. - * - * @param {jQuery/jqLite element} element the element that will be the focus of the move animation - * @param {jQuery/jqLite element} parent the parent element of the element that will be the focus of the move animation - * @param {jQuery/jqLite element} after the sibling element (which is the previous element) of the element that will be the focus of the move animation - */ - animator.move = animateActionFactory('move', move, noop); - - /** - * @ngdoc function - * @name ng.animator#show - * @methodOf ng.$animator - * @function - * - * @description - * Reveals the element by setting the CSS property `display` to `block` and then starts the show animation directly after. - * - * @param {jQuery/jqLite element} element the element that will be rendered visible or hidden - */ - animator.show = animateActionFactory('show', show, noop); - - /** - * @ngdoc function - * @name ng.animator#hide - * @methodOf ng.$animator - * - * @description - * Starts the hide animation first and sets the CSS `display` property to `none` upon completion. - * - * @param {jQuery/jqLite element} element the element that will be rendered visible or hidden - */ - animator.hide = animateActionFactory('hide', noop, hide); - - /** - * @ngdoc function - * @name ng.animator#animate - * @methodOf ng.$animator - * - * @description - * Triggers a custom animation event to be executed on the given element - * - * @param {jQuery/jqLite element} element that will be animated - */ - animator.animate = function(event, element) { - animateActionFactory(event, noop, noop)(element); - } - return animator; - - function animateActionFactory(type, beforeFn, afterFn) { - return function(element, parent, after) { - var ngAnimateValue = scope.$eval(attrs.ngAnimate); - var className = ngAnimateValue - ? isObject(ngAnimateValue) ? ngAnimateValue[type] : ngAnimateValue + '-' + type - : ''; - var animationPolyfill = $animation(className); - var polyfillSetup = animationPolyfill && animationPolyfill.setup; - var polyfillStart = animationPolyfill && animationPolyfill.start; - var polyfillCancel = animationPolyfill && animationPolyfill.cancel; - - if (!className) { - beforeFn(element, parent, after); - afterFn(element, parent, after); - } else { - var activeClassName = className + '-active'; - - if (!parent) { - parent = after ? after.parent() : element.parent(); - } - if ((!$sniffer.transitions && !polyfillSetup && !polyfillStart) || - (parent.inheritedData(NG_ANIMATE_CONTROLLER) || noop).running) { - beforeFn(element, parent, after); - afterFn(element, parent, after); - return; - } - - var animationData = element.data(NG_ANIMATE_CONTROLLER) || {}; - if(animationData.running) { - (polyfillCancel || noop)(element); - animationData.done(); - } - - element.data(NG_ANIMATE_CONTROLLER, {running:true, done:done}); - element.addClass(className); - beforeFn(element, parent, after); - if (element.length == 0) return done(); - - var memento = (polyfillSetup || noop)(element); - - // $window.setTimeout(beginAnimation, 0); this was causing the element not to animate - // keep at 1 for animation dom rerender - $window.setTimeout(beginAnimation, 1); - } - - function parseMaxTime(str) { - var total = 0, values = isString(str) ? str.split(/\s*,\s*/) : []; - forEach(values, function(value) { - total = Math.max(parseFloat(value) || 0, total); - }); - return total; - } - - function beginAnimation() { - element.addClass(activeClassName); - if (polyfillStart) { - polyfillStart(element, done, memento); - } else if (isFunction($window.getComputedStyle)) { - //one day all browsers will have these properties - var w3cAnimationProp = 'animation'; - var w3cTransitionProp = 'transition'; - - //but some still use vendor-prefixed styles - var vendorAnimationProp = $sniffer.vendorPrefix + 'Animation'; - var vendorTransitionProp = $sniffer.vendorPrefix + 'Transition'; - - var durationKey = 'Duration', - delayKey = 'Delay', - animationIterationCountKey = 'IterationCount', - duration = 0; - - //we want all the styles defined before and after - var ELEMENT_NODE = 1; - forEach(element, function(element) { - if (element.nodeType == ELEMENT_NODE) { - var w3cProp = w3cTransitionProp, - vendorProp = vendorTransitionProp, - iterations = 1, - elementStyles = $window.getComputedStyle(element) || {}; - - //use CSS Animations over CSS Transitions - if(parseFloat(elementStyles[w3cAnimationProp + durationKey]) > 0 || - parseFloat(elementStyles[vendorAnimationProp + durationKey]) > 0) { - w3cProp = w3cAnimationProp; - vendorProp = vendorAnimationProp; - iterations = Math.max(parseInt(elementStyles[w3cProp + animationIterationCountKey]) || 0, - parseInt(elementStyles[vendorProp + animationIterationCountKey]) || 0, - iterations); - } - - var parsedDelay = Math.max(parseMaxTime(elementStyles[w3cProp + delayKey]), - parseMaxTime(elementStyles[vendorProp + delayKey])); - - var parsedDuration = Math.max(parseMaxTime(elementStyles[w3cProp + durationKey]), - parseMaxTime(elementStyles[vendorProp + durationKey])); - - duration = Math.max(parsedDelay + (iterations * parsedDuration), duration); - } - }); - $window.setTimeout(done, duration * 1000); - } else { - done(); - } - } - - function done() { - if(!done.run) { - done.run = true; - afterFn(element, parent, after); - element.removeClass(className); - element.removeClass(activeClassName); - element.removeData(NG_ANIMATE_CONTROLLER); - } - } - }; - } - - function show(element) { - element.css('display', ''); - } - - function hide(element) { - element.css('display', 'none'); - } - - function insert(element, parent, after) { - if (after) { - after.after(element); - } else { - parent.append(element); - } - } - - function remove(element) { - element.remove(); - } - - function move(element, parent, after) { - // Do not remove element before insert. Removing will cause data associated with the - // element to be dropped. Insert will implicitly do the remove. - insert(element, parent, after); - } - }; - - /** - * @ngdoc function - * @name ng.animator#enabled - * @methodOf ng.$animator - * @function - * - * @param {Boolean=} If provided then set the animation on or off. - * @return {Boolean} Current animation state. - * - * @description - * Globally enables/disables animations. - * - */ - AnimatorService.enabled = function(value) { - if (arguments.length) { - rootAnimateController.running = !value; - } - return !rootAnimateController.running; - }; - - return AnimatorService; - }]; -}; - -/** - * ! This is a private undocumented service ! - * - * @name ng.$browser - * @requires $log - * @description - * This object has two goals: - * - * - hide all the global state in the browser caused by the window object - * - abstract away all the browser specific features and inconsistencies - * - * For tests we provide {@link ngMock.$browser mock implementation} of the `$browser` - * service, which can be used for convenient testing of the application without the interaction with - * the real browser apis. - */ -/** - * @param {object} window The global window object. - * @param {object} document jQuery wrapped document. - * @param {function()} XHR XMLHttpRequest constructor. - * @param {object} $log console.log or an object with the same interface. - * @param {object} $sniffer $sniffer service - */ -function Browser(window, document, $log, $sniffer) { - var self = this, - rawDocument = document[0], - location = window.location, - history = window.history, - setTimeout = window.setTimeout, - clearTimeout = window.clearTimeout, - pendingDeferIds = {}; - - self.isMock = false; - - var outstandingRequestCount = 0; - var outstandingRequestCallbacks = []; - - // TODO(vojta): remove this temporary api - self.$$completeOutstandingRequest = completeOutstandingRequest; - self.$$incOutstandingRequestCount = function() { outstandingRequestCount++; }; - - /** - * Executes the `fn` function(supports currying) and decrements the `outstandingRequestCallbacks` - * counter. If the counter reaches 0, all the `outstandingRequestCallbacks` are executed. - */ - function completeOutstandingRequest(fn) { - try { - fn.apply(null, sliceArgs(arguments, 1)); - } finally { - outstandingRequestCount--; - if (outstandingRequestCount === 0) { - while(outstandingRequestCallbacks.length) { - try { - outstandingRequestCallbacks.pop()(); - } catch (e) { - $log.error(e); - } - } - } - } - } - - /** - * @private - * Note: this method is used only by scenario runner - * TODO(vojta): prefix this method with $$ ? - * @param {function()} callback Function that will be called when no outstanding request - */ - self.notifyWhenNoOutstandingRequests = function(callback) { - // force browser to execute all pollFns - this is needed so that cookies and other pollers fire - // at some deterministic time in respect to the test runner's actions. Leaving things up to the - // regular poller would result in flaky tests. - forEach(pollFns, function(pollFn){ pollFn(); }); - - if (outstandingRequestCount === 0) { - callback(); - } else { - outstandingRequestCallbacks.push(callback); - } - }; - - ////////////////////////////////////////////////////////////// - // Poll Watcher API - ////////////////////////////////////////////////////////////// - var pollFns = [], - pollTimeout; - - /** - * @name ng.$browser#addPollFn - * @methodOf ng.$browser - * - * @param {function()} fn Poll function to add - * - * @description - * Adds a function to the list of functions that poller periodically executes, - * and starts polling if not started yet. - * - * @returns {function()} the added function - */ - self.addPollFn = function(fn) { - if (isUndefined(pollTimeout)) startPoller(100, setTimeout); - pollFns.push(fn); - return fn; - }; - - /** - * @param {number} interval How often should browser call poll functions (ms) - * @param {function()} setTimeout Reference to a real or fake `setTimeout` function. - * - * @description - * Configures the poller to run in the specified intervals, using the specified - * setTimeout fn and kicks it off. - */ - function startPoller(interval, setTimeout) { - (function check() { - forEach(pollFns, function(pollFn){ pollFn(); }); - pollTimeout = setTimeout(check, interval); - })(); - } - - ////////////////////////////////////////////////////////////// - // URL API - ////////////////////////////////////////////////////////////// - - var lastBrowserUrl = location.href, - baseElement = document.find('base'); - - /** - * @name ng.$browser#url - * @methodOf ng.$browser - * - * @description - * GETTER: - * Without any argument, this method just returns current value of location.href. - * - * SETTER: - * With at least one argument, this method sets url to new value. - * If html5 history api supported, pushState/replaceState is used, otherwise - * location.href/location.replace is used. - * Returns its own instance to allow chaining - * - * NOTE: this api is intended for use only by the $location service. Please use the - * {@link ng.$location $location service} to change url. - * - * @param {string} url New url (when used as setter) - * @param {boolean=} replace Should new url replace current history record ? - */ - self.url = function(url, replace) { - // setter - if (url) { - if (lastBrowserUrl == url) return; - lastBrowserUrl = url; - if ($sniffer.history) { - if (replace) history.replaceState(null, '', url); - else { - history.pushState(null, '', url); - // Crazy Opera Bug: http://my.opera.com/community/forums/topic.dml?id=1185462 - baseElement.attr('href', baseElement.attr('href')); - } - } else { - if (replace) location.replace(url); - else location.href = url; - } - return self; - // getter - } else { - // the replacement is a workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=407172 - return location.href.replace(/%27/g,"'"); - } - }; - - var urlChangeListeners = [], - urlChangeInit = false; - - function fireUrlChange() { - if (lastBrowserUrl == self.url()) return; - - lastBrowserUrl = self.url(); - forEach(urlChangeListeners, function(listener) { - listener(self.url()); - }); - } - - /** - * @name ng.$browser#onUrlChange - * @methodOf ng.$browser - * @TODO(vojta): refactor to use node's syntax for events - * - * @description - * Register callback function that will be called, when url changes. - * - * It's only called when the url is changed by outside of angular: - * - user types different url into address bar - * - user clicks on history (forward/back) button - * - user clicks on a link - * - * It's not called when url is changed by $browser.url() method - * - * The listener gets called with new url as parameter. - * - * NOTE: this api is intended for use only by the $location service. Please use the - * {@link ng.$location $location service} to monitor url changes in angular apps. - * - * @param {function(string)} listener Listener function to be called when url changes. - * @return {function(string)} Returns the registered listener fn - handy if the fn is anonymous. - */ - self.onUrlChange = function(callback) { - if (!urlChangeInit) { - // We listen on both (hashchange/popstate) when available, as some browsers (e.g. Opera) - // don't fire popstate when user change the address bar and don't fire hashchange when url - // changed by push/replaceState - - // html5 history api - popstate event - if ($sniffer.history) jqLite(window).bind('popstate', fireUrlChange); - // hashchange event - if ($sniffer.hashchange) jqLite(window).bind('hashchange', fireUrlChange); - // polling - else self.addPollFn(fireUrlChange); - - urlChangeInit = true; - } - - urlChangeListeners.push(callback); - return callback; - }; - - ////////////////////////////////////////////////////////////// - // Misc API - ////////////////////////////////////////////////////////////// - - /** - * Returns current - * (always relative - without domain) - * - * @returns {string=} - */ - self.baseHref = function() { - var href = baseElement.attr('href'); - return href ? href.replace(/^https?\:\/\/[^\/]*/, '') : ''; - }; - - ////////////////////////////////////////////////////////////// - // Cookies API - ////////////////////////////////////////////////////////////// - var lastCookies = {}; - var lastCookieString = ''; - var cookiePath = self.baseHref(); - - /** - * @name ng.$browser#cookies - * @methodOf ng.$browser - * - * @param {string=} name Cookie name - * @param {string=} value Cookie value - * - * @description - * The cookies method provides a 'private' low level access to browser cookies. - * It is not meant to be used directly, use the $cookie service instead. - * - * The return values vary depending on the arguments that the method was called with as follows: - *
                  - *
                • cookies() -> hash of all cookies, this is NOT a copy of the internal state, so do not modify it
                • - *
                • cookies(name, value) -> set name to value, if value is undefined delete the cookie
                • - *
                • cookies(name) -> the same as (name, undefined) == DELETES (no one calls it right now that way)
                • - *
                - * - * @returns {Object} Hash of all cookies (if called without any parameter) - */ - self.cookies = function(name, value) { - var cookieLength, cookieArray, cookie, i, index; - - if (name) { - if (value === undefined) { - rawDocument.cookie = escape(name) + "=;path=" + cookiePath + ";expires=Thu, 01 Jan 1970 00:00:00 GMT"; - } else { - if (isString(value)) { - cookieLength = (rawDocument.cookie = escape(name) + '=' + escape(value) + ';path=' + cookiePath).length + 1; - - // per http://www.ietf.org/rfc/rfc2109.txt browser must allow at minimum: - // - 300 cookies - // - 20 cookies per unique domain - // - 4096 bytes per cookie - if (cookieLength > 4096) { - $log.warn("Cookie '"+ name +"' possibly not set or overflowed because it was too large ("+ - cookieLength + " > 4096 bytes)!"); - } - } - } - } else { - if (rawDocument.cookie !== lastCookieString) { - lastCookieString = rawDocument.cookie; - cookieArray = lastCookieString.split("; "); - lastCookies = {}; - - for (i = 0; i < cookieArray.length; i++) { - cookie = cookieArray[i]; - index = cookie.indexOf('='); - if (index > 0) { //ignore nameless cookies - var name = unescape(cookie.substring(0, index)); - // the first value that is seen for a cookie is the most - // specific one. values for the same cookie name that - // follow are for less specific paths. - if (lastCookies[name] === undefined) { - lastCookies[name] = unescape(cookie.substring(index + 1)); - } - } - } - } - return lastCookies; - } - }; - - - /** - * @name ng.$browser#defer - * @methodOf ng.$browser - * @param {function()} fn A function, who's execution should be defered. - * @param {number=} [delay=0] of milliseconds to defer the function execution. - * @returns {*} DeferId that can be used to cancel the task via `$browser.defer.cancel()`. - * - * @description - * Executes a fn asynchronously via `setTimeout(fn, delay)`. - * - * Unlike when calling `setTimeout` directly, in test this function is mocked and instead of using - * `setTimeout` in tests, the fns are queued in an array, which can be programmatically flushed - * via `$browser.defer.flush()`. - * - */ - self.defer = function(fn, delay) { - var timeoutId; - outstandingRequestCount++; - timeoutId = setTimeout(function() { - delete pendingDeferIds[timeoutId]; - completeOutstandingRequest(fn); - }, delay || 0); - pendingDeferIds[timeoutId] = true; - return timeoutId; - }; - - - /** - * @name ng.$browser#defer.cancel - * @methodOf ng.$browser.defer - * - * @description - * Cancels a defered task identified with `deferId`. - * - * @param {*} deferId Token returned by the `$browser.defer` function. - * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully canceled. - */ - self.defer.cancel = function(deferId) { - if (pendingDeferIds[deferId]) { - delete pendingDeferIds[deferId]; - clearTimeout(deferId); - completeOutstandingRequest(noop); - return true; - } - return false; - }; - -} - -function $BrowserProvider(){ - this.$get = ['$window', '$log', '$sniffer', '$document', - function( $window, $log, $sniffer, $document){ - return new Browser($window, $document, $log, $sniffer); - }]; -} - -/** - * @ngdoc object - * @name ng.$cacheFactory - * - * @description - * Factory that constructs cache objects. - * - * - * @param {string} cacheId Name or id of the newly created cache. - * @param {object=} options Options object that specifies the cache behavior. Properties: - * - * - `{number=}` `capacity` — turns the cache into LRU cache. - * - * @returns {object} Newly created cache object with the following set of methods: - * - * - `{object}` `info()` — Returns id, size, and options of cache. - * - `{{*}}` `put({string} key, {*} value)` — Puts a new key-value pair into the cache and returns it. - * - `{{*}}` `get({string} key)` — Returns cached value for `key` or undefined for cache miss. - * - `{void}` `remove({string} key)` — Removes a key-value pair from the cache. - * - `{void}` `removeAll()` — Removes all cached values. - * - `{void}` `destroy()` — Removes references to this cache from $cacheFactory. - * - */ -function $CacheFactoryProvider() { - - this.$get = function() { - var caches = {}; - - function cacheFactory(cacheId, options) { - if (cacheId in caches) { - throw Error('cacheId ' + cacheId + ' taken'); - } - - var size = 0, - stats = extend({}, options, {id: cacheId}), - data = {}, - capacity = (options && options.capacity) || Number.MAX_VALUE, - lruHash = {}, - freshEnd = null, - staleEnd = null; - - return caches[cacheId] = { - - put: function(key, value) { - var lruEntry = lruHash[key] || (lruHash[key] = {key: key}); - - refresh(lruEntry); - - if (isUndefined(value)) return; - if (!(key in data)) size++; - data[key] = value; - - if (size > capacity) { - this.remove(staleEnd.key); - } - - return value; - }, - - - get: function(key) { - var lruEntry = lruHash[key]; - - if (!lruEntry) return; - - refresh(lruEntry); - - return data[key]; - }, - - - remove: function(key) { - var lruEntry = lruHash[key]; - - if (!lruEntry) return; - - if (lruEntry == freshEnd) freshEnd = lruEntry.p; - if (lruEntry == staleEnd) staleEnd = lruEntry.n; - link(lruEntry.n,lruEntry.p); - - delete lruHash[key]; - delete data[key]; - size--; - }, - - - removeAll: function() { - data = {}; - size = 0; - lruHash = {}; - freshEnd = staleEnd = null; - }, - - - destroy: function() { - data = null; - stats = null; - lruHash = null; - delete caches[cacheId]; - }, - - - info: function() { - return extend({}, stats, {size: size}); - } - }; - - - /** - * makes the `entry` the freshEnd of the LRU linked list - */ - function refresh(entry) { - if (entry != freshEnd) { - if (!staleEnd) { - staleEnd = entry; - } else if (staleEnd == entry) { - staleEnd = entry.n; - } - - link(entry.n, entry.p); - link(entry, freshEnd); - freshEnd = entry; - freshEnd.n = null; - } - } - - - /** - * bidirectionally links two entries of the LRU linked list - */ - function link(nextEntry, prevEntry) { - if (nextEntry != prevEntry) { - if (nextEntry) nextEntry.p = prevEntry; //p stands for previous, 'prev' didn't minify - if (prevEntry) prevEntry.n = nextEntry; //n stands for next, 'next' didn't minify - } - } - } - - - cacheFactory.info = function() { - var info = {}; - forEach(caches, function(cache, cacheId) { - info[cacheId] = cache.info(); - }); - return info; - }; - - - cacheFactory.get = function(cacheId) { - return caches[cacheId]; - }; - - - return cacheFactory; - }; -} - -/** - * @ngdoc object - * @name ng.$templateCache - * - * @description - * Cache used for storing html templates. - * - * See {@link ng.$cacheFactory $cacheFactory}. - * - */ -function $TemplateCacheProvider() { - this.$get = ['$cacheFactory', function($cacheFactory) { - return $cacheFactory('templates'); - }]; -} - -/* ! VARIABLE/FUNCTION NAMING CONVENTIONS THAT APPLY TO THIS FILE! - * - * DOM-related variables: - * - * - "node" - DOM Node - * - "element" - DOM Element or Node - * - "$node" or "$element" - jqLite-wrapped node or element - * - * - * Compiler related stuff: - * - * - "linkFn" - linking fn of a single directive - * - "nodeLinkFn" - function that aggregates all linking fns for a particular node - * - "childLinkFn" - function that aggregates all linking fns for child nodes of a particular node - * - "compositeLinkFn" - function that aggregates all linking fns for a compilation root (nodeList) - */ - - -var NON_ASSIGNABLE_MODEL_EXPRESSION = 'Non-assignable model expression: '; - - -/** - * @ngdoc function - * @name ng.$compile - * @function - * - * @description - * Compiles a piece of HTML string or DOM into a template and produces a template function, which - * can then be used to link {@link ng.$rootScope.Scope scope} and the template together. - * - * The compilation is a process of walking the DOM tree and trying to match DOM elements to - * {@link ng.$compileProvider#directive directives}. For each match it - * executes corresponding template function and collects the - * instance functions into a single template function which is then returned. - * - * The template function can then be used once to produce the view or as it is the case with - * {@link ng.directive:ngRepeat repeater} many-times, in which - * case each call results in a view that is a DOM clone of the original template. - * - - - -
                -
                -
                -
                -
                -
                - - it('should auto compile', function() { - expect(element('div[compile]').text()).toBe('Hello Angular'); - input('html').enter('{{name}}!'); - expect(element('div[compile]').text()).toBe('Angular!'); - }); - -
                - - * - * - * @param {string|DOMElement} element Element or HTML string to compile into a template function. - * @param {function(angular.Scope[, cloneAttachFn]} transclude function available to directives. - * @param {number} maxPriority only apply directives lower then given priority (Only effects the - * root element(s), not their children) - * @returns {function(scope[, cloneAttachFn])} a link function which is used to bind template - * (a DOM element/tree) to a scope. Where: - * - * * `scope` - A {@link ng.$rootScope.Scope Scope} to bind to. - * * `cloneAttachFn` - If `cloneAttachFn` is provided, then the link function will clone the - * `template` and call the `cloneAttachFn` function allowing the caller to attach the - * cloned elements to the DOM document at the appropriate place. The `cloneAttachFn` is - * called as:
                `cloneAttachFn(clonedElement, scope)` where: - * - * * `clonedElement` - is a clone of the original `element` passed into the compiler. - * * `scope` - is the current scope with which the linking function is working with. - * - * Calling the linking function returns the element of the template. It is either the original element - * passed in, or the clone of the element if the `cloneAttachFn` is provided. - * - * After linking the view is not updated until after a call to $digest which typically is done by - * Angular automatically. - * - * If you need access to the bound view, there are two ways to do it: - * - * - If you are not asking the linking function to clone the template, create the DOM element(s) - * before you send them to the compiler and keep this reference around. - *
                - *     var element = $compile('

                {{total}}

                ')(scope); - *
                - * - * - if on the other hand, you need the element to be cloned, the view reference from the original - * example would not point to the clone, but rather to the original template that was cloned. In - * this case, you can access the clone via the cloneAttachFn: - *
                - *     var templateHTML = angular.element('

                {{total}}

                '), - * scope = ....; - * - * var clonedElement = $compile(templateHTML)(scope, function(clonedElement, scope) { - * //attach the clone to DOM document at the right place - * }); - * - * //now we have reference to the cloned DOM via `clone` - *
                - * - * - * For information on how the compiler works, see the - * {@link guide/compiler Angular HTML Compiler} section of the Developer Guide. - */ - - -/** - * @ngdoc service - * @name ng.$compileProvider - * @function - * - * @description - */ -$CompileProvider.$inject = ['$provide']; -function $CompileProvider($provide) { - var hasDirectives = {}, - Suffix = 'Directive', - COMMENT_DIRECTIVE_REGEXP = /^\s*directive\:\s*([\d\w\-_]+)\s+(.*)$/, - CLASS_DIRECTIVE_REGEXP = /(([\d\w\-_]+)(?:\:([^;]+))?;?)/, - MULTI_ROOT_TEMPLATE_ERROR = 'Template must have exactly one root element. was: ', - urlSanitizationWhitelist = /^\s*(https?|ftp|mailto|file):/; - - - /** - * @ngdoc function - * @name ng.$compileProvider#directive - * @methodOf ng.$compileProvider - * @function - * - * @description - * Register a new directives with the compiler. - * - * @param {string} name Name of the directive in camel-case. (ie ngBind which will match as - * ng-bind). - * @param {function} directiveFactory An injectable directive factory function. See {@link guide/directive} for more - * info. - * @returns {ng.$compileProvider} Self for chaining. - */ - this.directive = function registerDirective(name, directiveFactory) { - if (isString(name)) { - assertArg(directiveFactory, 'directive'); - if (!hasDirectives.hasOwnProperty(name)) { - hasDirectives[name] = []; - $provide.factory(name + Suffix, ['$injector', '$exceptionHandler', - function($injector, $exceptionHandler) { - var directives = []; - forEach(hasDirectives[name], function(directiveFactory) { - try { - var directive = $injector.invoke(directiveFactory); - if (isFunction(directive)) { - directive = { compile: valueFn(directive) }; - } else if (!directive.compile && directive.link) { - directive.compile = valueFn(directive.link); - } - directive.priority = directive.priority || 0; - directive.name = directive.name || name; - directive.require = directive.require || (directive.controller && directive.name); - directive.restrict = directive.restrict || 'A'; - directives.push(directive); - } catch (e) { - $exceptionHandler(e); - } - }); - return directives; - }]); - } - hasDirectives[name].push(directiveFactory); - } else { - forEach(name, reverseParams(registerDirective)); - } - return this; - }; - - - /** - * @ngdoc function - * @name ng.$compileProvider#urlSanitizationWhitelist - * @methodOf ng.$compileProvider - * @function - * - * @description - * Retrieves or overrides the default regular expression that is used for whitelisting of safe - * urls during a[href] sanitization. - * - * The sanitization is a security measure aimed at prevent XSS attacks via html links. - * - * Any url about to be assigned to a[href] via data-binding is first normalized and turned into an - * absolute url. Afterwards the url is matched against the `urlSanitizationWhitelist` regular - * expression. If a match is found the original url is written into the dom. Otherwise the - * absolute url is prefixed with `'unsafe:'` string and only then it is written into the DOM. - * - * @param {RegExp=} regexp New regexp to whitelist urls with. - * @returns {RegExp|ng.$compileProvider} Current RegExp if called without value or self for - * chaining otherwise. - */ - this.urlSanitizationWhitelist = function(regexp) { - if (isDefined(regexp)) { - urlSanitizationWhitelist = regexp; - return this; - } - return urlSanitizationWhitelist; - }; - - - this.$get = [ - '$injector', '$interpolate', '$exceptionHandler', '$http', '$templateCache', '$parse', - '$controller', '$rootScope', '$document', - function($injector, $interpolate, $exceptionHandler, $http, $templateCache, $parse, - $controller, $rootScope, $document) { - - var Attributes = function(element, attr) { - this.$$element = element; - this.$attr = attr || {}; - }; - - Attributes.prototype = { - $normalize: directiveNormalize, - - - /** - * Set a normalized attribute on the element in a way such that all directives - * can share the attribute. This function properly handles boolean attributes. - * @param {string} key Normalized key. (ie ngAttribute) - * @param {string|boolean} value The value to set. If `null` attribute will be deleted. - * @param {boolean=} writeAttr If false, does not write the value to DOM element attribute. - * Defaults to true. - * @param {string=} attrName Optional none normalized name. Defaults to key. - */ - $set: function(key, value, writeAttr, attrName) { - var booleanKey = getBooleanAttrName(this.$$element[0], key), - $$observers = this.$$observers, - normalizedVal; - - if (booleanKey) { - this.$$element.prop(key, value); - attrName = booleanKey; - } - - this[key] = value; - - // translate normalized key to actual key - if (attrName) { - this.$attr[key] = attrName; - } else { - attrName = this.$attr[key]; - if (!attrName) { - this.$attr[key] = attrName = snake_case(key, '-'); - } - } - - - // sanitize a[href] values - if (nodeName_(this.$$element[0]) === 'A' && key === 'href') { - urlSanitizationNode.setAttribute('href', value); - - // href property always returns normalized absolute url, so we can match against that - normalizedVal = urlSanitizationNode.href; - if (!normalizedVal.match(urlSanitizationWhitelist)) { - this[key] = value = 'unsafe:' + normalizedVal; - } - } - - - if (writeAttr !== false) { - if (value === null || value === undefined) { - this.$$element.removeAttr(attrName); - } else { - this.$$element.attr(attrName, value); - } - } - - // fire observers - $$observers && forEach($$observers[key], function(fn) { - try { - fn(value); - } catch (e) { - $exceptionHandler(e); - } - }); - }, - - - /** - * Observe an interpolated attribute. - * The observer will never be called, if given attribute is not interpolated. - * - * @param {string} key Normalized key. (ie ngAttribute) . - * @param {function(*)} fn Function that will be called whenever the attribute value changes. - * @returns {function(*)} the `fn` Function passed in. - */ - $observe: function(key, fn) { - var attrs = this, - $$observers = (attrs.$$observers || (attrs.$$observers = {})), - listeners = ($$observers[key] || ($$observers[key] = [])); - - listeners.push(fn); - $rootScope.$evalAsync(function() { - if (!listeners.$$inter) { - // no one registered attribute interpolation function, so lets call it manually - fn(attrs[key]); - } - }); - return fn; - } - }; - - var urlSanitizationNode = $document[0].createElement('a'), - startSymbol = $interpolate.startSymbol(), - endSymbol = $interpolate.endSymbol(), - denormalizeTemplate = (startSymbol == '{{' || endSymbol == '}}') - ? identity - : function denormalizeTemplate(template) { - return template.replace(/\{\{/g, startSymbol).replace(/}}/g, endSymbol); - }, - NG_ATTR_BINDING = /^ngAttr[A-Z]/; - - - return compile; - - //================================ - - function compile($compileNodes, transcludeFn, maxPriority) { - if (!($compileNodes instanceof jqLite)) { - // jquery always rewraps, whereas we need to preserve the original selector so that we can modify it. - $compileNodes = jqLite($compileNodes); - } - // We can not compile top level text elements since text nodes can be merged and we will - // not be able to attach scope data to them, so we will wrap them in - forEach($compileNodes, function(node, index){ - if (node.nodeType == 3 /* text node */ && node.nodeValue.match(/\S+/) /* non-empty */ ) { - $compileNodes[index] = jqLite(node).wrap('').parent()[0]; - } - }); - var compositeLinkFn = compileNodes($compileNodes, transcludeFn, $compileNodes, maxPriority); - return function publicLinkFn(scope, cloneConnectFn){ - assertArg(scope, 'scope'); - // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart - // and sometimes changes the structure of the DOM. - var $linkNode = cloneConnectFn - ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!! - : $compileNodes; - - // Attach scope only to non-text nodes. - for(var i = 0, ii = $linkNode.length; i - addDirective(directives, - directiveNormalize(nodeName_(node).toLowerCase()), 'E', maxPriority); - - // iterate over the attributes - for (var attr, name, nName, ngAttrName, value, nAttrs = node.attributes, - j = 0, jj = nAttrs && nAttrs.length; j < jj; j++) { - attr = nAttrs[j]; - if (attr.specified) { - name = attr.name; - // support ngAttr attribute binding - ngAttrName = directiveNormalize(name); - if (NG_ATTR_BINDING.test(ngAttrName)) { - name = ngAttrName.substr(6).toLowerCase(); - } - nName = directiveNormalize(name.toLowerCase()); - attrsMap[nName] = name; - attrs[nName] = value = trim((msie && name == 'href') - ? decodeURIComponent(node.getAttribute(name, 2)) - : attr.value); - if (getBooleanAttrName(node, nName)) { - attrs[nName] = true; // presence means true - } - addAttrInterpolateDirective(node, directives, value, nName); - addDirective(directives, nName, 'A', maxPriority); - } - } - - // use class as directive - className = node.className; - if (isString(className) && className !== '') { - while (match = CLASS_DIRECTIVE_REGEXP.exec(className)) { - nName = directiveNormalize(match[2]); - if (addDirective(directives, nName, 'C', maxPriority)) { - attrs[nName] = trim(match[3]); - } - className = className.substr(match.index + match[0].length); - } - } - break; - case 3: /* Text Node */ - addTextInterpolateDirective(directives, node.nodeValue); - break; - case 8: /* Comment */ - try { - match = COMMENT_DIRECTIVE_REGEXP.exec(node.nodeValue); - if (match) { - nName = directiveNormalize(match[1]); - if (addDirective(directives, nName, 'M', maxPriority)) { - attrs[nName] = trim(match[2]); - } - } - } catch (e) { - // turns out that under some circumstances IE9 throws errors when one attempts to read comment's node value. - // Just ignore it and continue. (Can't seem to reproduce in test case.) - } - break; - } - - directives.sort(byPriority); - return directives; - } - - - /** - * Once the directives have been collected, their compile functions are executed. This method - * is responsible for inlining directive templates as well as terminating the application - * of the directives if the terminal directive has been reached. - * - * @param {Array} directives Array of collected directives to execute their compile function. - * this needs to be pre-sorted by priority order. - * @param {Node} compileNode The raw DOM node to apply the compile functions to - * @param {Object} templateAttrs The shared attribute function - * @param {function(angular.Scope[, cloneAttachFn]} transcludeFn A linking function, where the - * scope argument is auto-generated to the new child of the transcluded parent scope. - * @param {JQLite} jqCollection If we are working on the root of the compile tree then this - * argument has the root jqLite array so that we can replace nodes on it. - * @returns linkFn - */ - function applyDirectivesToNode(directives, compileNode, templateAttrs, transcludeFn, jqCollection) { - var terminalPriority = -Number.MAX_VALUE, - preLinkFns = [], - postLinkFns = [], - newScopeDirective = null, - newIsolateScopeDirective = null, - templateDirective = null, - $compileNode = templateAttrs.$$element = jqLite(compileNode), - directive, - directiveName, - $template, - transcludeDirective, - childTranscludeFn = transcludeFn, - controllerDirectives, - linkFn, - directiveValue; - - // executes all directives on the current element - for(var i = 0, ii = directives.length; i < ii; i++) { - directive = directives[i]; - $template = undefined; - - if (terminalPriority > directive.priority) { - break; // prevent further processing of directives - } - - if (directiveValue = directive.scope) { - assertNoDuplicate('isolated scope', newIsolateScopeDirective, directive, $compileNode); - if (isObject(directiveValue)) { - safeAddClass($compileNode, 'ng-isolate-scope'); - newIsolateScopeDirective = directive; - } - safeAddClass($compileNode, 'ng-scope'); - newScopeDirective = newScopeDirective || directive; - } - - directiveName = directive.name; - - if (directiveValue = directive.controller) { - controllerDirectives = controllerDirectives || {}; - assertNoDuplicate("'" + directiveName + "' controller", - controllerDirectives[directiveName], directive, $compileNode); - controllerDirectives[directiveName] = directive; - } - - if (directiveValue = directive.transclude) { - assertNoDuplicate('transclusion', transcludeDirective, directive, $compileNode); - transcludeDirective = directive; - terminalPriority = directive.priority; - if (directiveValue == 'element') { - $template = jqLite(compileNode); - $compileNode = templateAttrs.$$element = - jqLite(document.createComment(' ' + directiveName + ': ' + templateAttrs[directiveName] + ' ')); - compileNode = $compileNode[0]; - replaceWith(jqCollection, jqLite($template[0]), compileNode); - childTranscludeFn = compile($template, transcludeFn, terminalPriority); - } else { - $template = jqLite(JQLiteClone(compileNode)).contents(); - $compileNode.html(''); // clear contents - childTranscludeFn = compile($template, transcludeFn); - } - } - - if (directive.template) { - assertNoDuplicate('template', templateDirective, directive, $compileNode); - templateDirective = directive; - - directiveValue = (isFunction(directive.template)) - ? directive.template($compileNode, templateAttrs) - : directive.template; - - directiveValue = denormalizeTemplate(directiveValue); - - if (directive.replace) { - $template = jqLite('
                ' + - trim(directiveValue) + - '
                ').contents(); - compileNode = $template[0]; - - if ($template.length != 1 || compileNode.nodeType !== 1) { - throw new Error(MULTI_ROOT_TEMPLATE_ERROR + directiveValue); - } - - replaceWith(jqCollection, $compileNode, compileNode); - - var newTemplateAttrs = {$attr: {}}; - - // combine directives from the original node and from the template: - // - take the array of directives for this element - // - split it into two parts, those that were already applied and those that weren't - // - collect directives from the template, add them to the second group and sort them - // - append the second group with new directives to the first group - directives = directives.concat( - collectDirectives( - compileNode, - directives.splice(i + 1, directives.length - (i + 1)), - newTemplateAttrs - ) - ); - mergeTemplateAttributes(templateAttrs, newTemplateAttrs); - - ii = directives.length; - } else { - $compileNode.html(directiveValue); - } - } - - if (directive.templateUrl) { - assertNoDuplicate('template', templateDirective, directive, $compileNode); - templateDirective = directive; - nodeLinkFn = compileTemplateUrl(directives.splice(i, directives.length - i), - nodeLinkFn, $compileNode, templateAttrs, jqCollection, directive.replace, - childTranscludeFn); - ii = directives.length; - } else if (directive.compile) { - try { - linkFn = directive.compile($compileNode, templateAttrs, childTranscludeFn); - if (isFunction(linkFn)) { - addLinkFns(null, linkFn); - } else if (linkFn) { - addLinkFns(linkFn.pre, linkFn.post); - } - } catch (e) { - $exceptionHandler(e, startingTag($compileNode)); - } - } - - if (directive.terminal) { - nodeLinkFn.terminal = true; - terminalPriority = Math.max(terminalPriority, directive.priority); - } - - } - - nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope; - nodeLinkFn.transclude = transcludeDirective && childTranscludeFn; - - // might be normal or delayed nodeLinkFn depending on if templateUrl is present - return nodeLinkFn; - - //////////////////// - - function addLinkFns(pre, post) { - if (pre) { - pre.require = directive.require; - preLinkFns.push(pre); - } - if (post) { - post.require = directive.require; - postLinkFns.push(post); - } - } - - - function getControllers(require, $element) { - var value, retrievalMethod = 'data', optional = false; - if (isString(require)) { - while((value = require.charAt(0)) == '^' || value == '?') { - require = require.substr(1); - if (value == '^') { - retrievalMethod = 'inheritedData'; - } - optional = optional || value == '?'; - } - value = $element[retrievalMethod]('$' + require + 'Controller'); - if (!value && !optional) { - throw Error("No controller: " + require); - } - return value; - } else if (isArray(require)) { - value = []; - forEach(require, function(require) { - value.push(getControllers(require, $element)); - }); - } - return value; - } - - - function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) { - var attrs, $element, i, ii, linkFn, controller; - - if (compileNode === linkNode) { - attrs = templateAttrs; - } else { - attrs = shallowCopy(templateAttrs, new Attributes(jqLite(linkNode), templateAttrs.$attr)); - } - $element = attrs.$$element; - - if (newIsolateScopeDirective) { - var LOCAL_REGEXP = /^\s*([@=&])(\??)\s*(\w*)\s*$/; - - var parentScope = scope.$parent || scope; - - forEach(newIsolateScopeDirective.scope, function(definiton, scopeName) { - var match = definiton.match(LOCAL_REGEXP) || [], - attrName = match[3] || scopeName, - optional = (match[2] == '?'), - mode = match[1], // @, =, or & - lastValue, - parentGet, parentSet; - - scope.$$isolateBindings[scopeName] = mode + attrName; - - switch (mode) { - - case '@': { - attrs.$observe(attrName, function(value) { - scope[scopeName] = value; - }); - attrs.$$observers[attrName].$$scope = parentScope; - if( attrs[attrName] ) { - // If the attribute has been provided then we trigger an interpolation to ensure the value is there for use in the link fn - scope[scopeName] = $interpolate(attrs[attrName])(parentScope); - } - break; - } - - case '=': { - if (optional && !attrs[attrName]) { - return; - } - parentGet = $parse(attrs[attrName]); - parentSet = parentGet.assign || function() { - // reset the change, or we will throw this exception on every $digest - lastValue = scope[scopeName] = parentGet(parentScope); - throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + attrs[attrName] + - ' (directive: ' + newIsolateScopeDirective.name + ')'); - }; - lastValue = scope[scopeName] = parentGet(parentScope); - scope.$watch(function parentValueWatch() { - var parentValue = parentGet(parentScope); - - if (parentValue !== scope[scopeName]) { - // we are out of sync and need to copy - if (parentValue !== lastValue) { - // parent changed and it has precedence - lastValue = scope[scopeName] = parentValue; - } else { - // if the parent can be assigned then do so - parentSet(parentScope, parentValue = lastValue = scope[scopeName]); - } - } - return parentValue; - }); - break; - } - - case '&': { - parentGet = $parse(attrs[attrName]); - scope[scopeName] = function(locals) { - return parentGet(parentScope, locals); - }; - break; - } - - default: { - throw Error('Invalid isolate scope definition for directive ' + - newIsolateScopeDirective.name + ': ' + definiton); - } - } - }); - } - - if (controllerDirectives) { - forEach(controllerDirectives, function(directive) { - var locals = { - $scope: scope, - $element: $element, - $attrs: attrs, - $transclude: boundTranscludeFn - }; - - controller = directive.controller; - if (controller == '@') { - controller = attrs[directive.name]; - } - - $element.data( - '$' + directive.name + 'Controller', - $controller(controller, locals)); - }); - } - - // PRELINKING - for(i = 0, ii = preLinkFns.length; i < ii; i++) { - try { - linkFn = preLinkFns[i]; - linkFn(scope, $element, attrs, - linkFn.require && getControllers(linkFn.require, $element)); - } catch (e) { - $exceptionHandler(e, startingTag($element)); - } - } - - // RECURSION - childLinkFn && childLinkFn(scope, linkNode.childNodes, undefined, boundTranscludeFn); - - // POSTLINKING - for(i = 0, ii = postLinkFns.length; i < ii; i++) { - try { - linkFn = postLinkFns[i]; - linkFn(scope, $element, attrs, - linkFn.require && getControllers(linkFn.require, $element)); - } catch (e) { - $exceptionHandler(e, startingTag($element)); - } - } - } - } - - - /** - * looks up the directive and decorates it with exception handling and proper parameters. We - * call this the boundDirective. - * - * @param {string} name name of the directive to look up. - * @param {string} location The directive must be found in specific format. - * String containing any of theses characters: - * - * * `E`: element name - * * `A': attribute - * * `C`: class - * * `M`: comment - * @returns true if directive was added. - */ - function addDirective(tDirectives, name, location, maxPriority) { - var match = false; - if (hasDirectives.hasOwnProperty(name)) { - for(var directive, directives = $injector.get(name + Suffix), - i = 0, ii = directives.length; i directive.priority) && - directive.restrict.indexOf(location) != -1) { - tDirectives.push(directive); - match = true; - } - } catch(e) { $exceptionHandler(e); } - } - } - return match; - } - - - /** - * When the element is replaced with HTML template then the new attributes - * on the template need to be merged with the existing attributes in the DOM. - * The desired effect is to have both of the attributes present. - * - * @param {object} dst destination attributes (original DOM) - * @param {object} src source attributes (from the directive template) - */ - function mergeTemplateAttributes(dst, src) { - var srcAttr = src.$attr, - dstAttr = dst.$attr, - $element = dst.$$element; - - // reapply the old attributes to the new element - forEach(dst, function(value, key) { - if (key.charAt(0) != '$') { - if (src[key]) { - value += (key === 'style' ? ';' : ' ') + src[key]; - } - dst.$set(key, value, true, srcAttr[key]); - } - }); - - // copy the new attributes on the old attrs object - forEach(src, function(value, key) { - if (key == 'class') { - safeAddClass($element, value); - dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value; - } else if (key == 'style') { - $element.attr('style', $element.attr('style') + ';' + value); - } else if (key.charAt(0) != '$' && !dst.hasOwnProperty(key)) { - dst[key] = value; - dstAttr[key] = srcAttr[key]; - } - }); - } - - - function compileTemplateUrl(directives, beforeTemplateNodeLinkFn, $compileNode, tAttrs, - $rootElement, replace, childTranscludeFn) { - var linkQueue = [], - afterTemplateNodeLinkFn, - afterTemplateChildLinkFn, - beforeTemplateCompileNode = $compileNode[0], - origAsyncDirective = directives.shift(), - // The fact that we have to copy and patch the directive seems wrong! - derivedSyncDirective = extend({}, origAsyncDirective, { - controller: null, templateUrl: null, transclude: null, scope: null - }), - templateUrl = (isFunction(origAsyncDirective.templateUrl)) - ? origAsyncDirective.templateUrl($compileNode, tAttrs) - : origAsyncDirective.templateUrl; - - $compileNode.html(''); - - $http.get(templateUrl, {cache: $templateCache}). - success(function(content) { - var compileNode, tempTemplateAttrs, $template; - - content = denormalizeTemplate(content); - - if (replace) { - $template = jqLite('
                ' + trim(content) + '
                ').contents(); - compileNode = $template[0]; - - if ($template.length != 1 || compileNode.nodeType !== 1) { - throw new Error(MULTI_ROOT_TEMPLATE_ERROR + content); - } - - tempTemplateAttrs = {$attr: {}}; - replaceWith($rootElement, $compileNode, compileNode); - collectDirectives(compileNode, directives, tempTemplateAttrs); - mergeTemplateAttributes(tAttrs, tempTemplateAttrs); - } else { - compileNode = beforeTemplateCompileNode; - $compileNode.html(content); - } - - directives.unshift(derivedSyncDirective); - afterTemplateNodeLinkFn = applyDirectivesToNode(directives, compileNode, tAttrs, childTranscludeFn); - afterTemplateChildLinkFn = compileNodes($compileNode[0].childNodes, childTranscludeFn); - - - while(linkQueue.length) { - var scope = linkQueue.shift(), - beforeTemplateLinkNode = linkQueue.shift(), - linkRootElement = linkQueue.shift(), - controller = linkQueue.shift(), - linkNode = compileNode; - - if (beforeTemplateLinkNode !== beforeTemplateCompileNode) { - // it was cloned therefore we have to clone as well. - linkNode = JQLiteClone(compileNode); - replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode); - } - - afterTemplateNodeLinkFn(function() { - beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, controller); - }, scope, linkNode, $rootElement, controller); - } - linkQueue = null; - }). - error(function(response, code, headers, config) { - throw Error('Failed to load template: ' + config.url); - }); - - return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, controller) { - if (linkQueue) { - linkQueue.push(scope); - linkQueue.push(node); - linkQueue.push(rootElement); - linkQueue.push(controller); - } else { - afterTemplateNodeLinkFn(function() { - beforeTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, controller); - }, scope, node, rootElement, controller); - } - }; - } - - - /** - * Sorting function for bound directives. - */ - function byPriority(a, b) { - return b.priority - a.priority; - } - - - function assertNoDuplicate(what, previousDirective, directive, element) { - if (previousDirective) { - throw Error('Multiple directives [' + previousDirective.name + ', ' + - directive.name + '] asking for ' + what + ' on: ' + startingTag(element)); - } - } - - - function addTextInterpolateDirective(directives, text) { - var interpolateFn = $interpolate(text, true); - if (interpolateFn) { - directives.push({ - priority: 0, - compile: valueFn(function textInterpolateLinkFn(scope, node) { - var parent = node.parent(), - bindings = parent.data('$binding') || []; - bindings.push(interpolateFn); - safeAddClass(parent.data('$binding', bindings), 'ng-binding'); - scope.$watch(interpolateFn, function interpolateFnWatchAction(value) { - node[0].nodeValue = value; - }); - }) - }); - } - } - - - function addAttrInterpolateDirective(node, directives, value, name) { - var interpolateFn = $interpolate(value, true); - - // no interpolation found -> ignore - if (!interpolateFn) return; - - - directives.push({ - priority: 100, - compile: valueFn(function attrInterpolateLinkFn(scope, element, attr) { - var $$observers = (attr.$$observers || (attr.$$observers = {})); - - // we need to interpolate again, in case the attribute value has been updated - // (e.g. by another directive's compile function) - interpolateFn = $interpolate(attr[name], true); - - // if attribute was updated so that there is no interpolation going on we don't want to - // register any observers - if (!interpolateFn) return; - - attr[name] = interpolateFn(scope); - ($$observers[name] || ($$observers[name] = [])).$$inter = true; - (attr.$$observers && attr.$$observers[name].$$scope || scope). - $watch(interpolateFn, function interpolateFnWatchAction(value) { - attr.$set(name, value); - }); - }) - }); - } - - - /** - * This is a special jqLite.replaceWith, which can replace items which - * have no parents, provided that the containing jqLite collection is provided. - * - * @param {JqLite=} $rootElement The root of the compile tree. Used so that we can replace nodes - * in the root of the tree. - * @param {JqLite} $element The jqLite element which we are going to replace. We keep the shell, - * but replace its DOM node reference. - * @param {Node} newNode The new DOM node. - */ - function replaceWith($rootElement, $element, newNode) { - var oldNode = $element[0], - parent = oldNode.parentNode, - i, ii; - - if ($rootElement) { - for(i = 0, ii = $rootElement.length; i < ii; i++) { - if ($rootElement[i] == oldNode) { - $rootElement[i] = newNode; - break; - } - } - } - - if (parent) { - parent.replaceChild(newNode, oldNode); - } - - newNode[jqLite.expando] = oldNode[jqLite.expando]; - $element[0] = newNode; - } - }]; -} - -var PREFIX_REGEXP = /^(x[\:\-_]|data[\:\-_])/i; -/** - * Converts all accepted directives format into proper directive name. - * All of these will become 'myDirective': - * my:DiRective - * my-directive - * x-my-directive - * data-my:directive - * - * Also there is special case for Moz prefix starting with upper case letter. - * @param name Name to normalize - */ -function directiveNormalize(name) { - return camelCase(name.replace(PREFIX_REGEXP, '')); -} - -/** - * @ngdoc object - * @name ng.$compile.directive.Attributes - * @description - * - * A shared object between directive compile / linking functions which contains normalized DOM element - * attributes. The the values reflect current binding state `{{ }}`. The normalization is needed - * since all of these are treated as equivalent in Angular: - * - * - */ - -/** - * @ngdoc property - * @name ng.$compile.directive.Attributes#$attr - * @propertyOf ng.$compile.directive.Attributes - * @returns {object} A map of DOM element attribute names to the normalized name. This is - * needed to do reverse lookup from normalized name back to actual name. - */ - - -/** - * @ngdoc function - * @name ng.$compile.directive.Attributes#$set - * @methodOf ng.$compile.directive.Attributes - * @function - * - * @description - * Set DOM element attribute value. - * - * - * @param {string} name Normalized element attribute name of the property to modify. The name is - * revers translated using the {@link ng.$compile.directive.Attributes#$attr $attr} - * property to the original name. - * @param {string} value Value to set the attribute to. The value can be an interpolated string. - */ - - - -/** - * Closure compiler type information - */ - -function nodesetLinkingFn( - /* angular.Scope */ scope, - /* NodeList */ nodeList, - /* Element */ rootElement, - /* function(Function) */ boundTranscludeFn -){} - -function directiveLinkingFn( - /* nodesetLinkingFn */ nodesetLinkingFn, - /* angular.Scope */ scope, - /* Node */ node, - /* Element */ rootElement, - /* function(Function) */ boundTranscludeFn -){} - -/** - * @ngdoc object - * @name ng.$controllerProvider - * @description - * The {@link ng.$controller $controller service} is used by Angular to create new - * controllers. - * - * This provider allows controller registration via the - * {@link ng.$controllerProvider#register register} method. - */ -function $ControllerProvider() { - var controllers = {}, - CNTRL_REG = /^(\S+)(\s+as\s+(\w+))?$/; - - - /** - * @ngdoc function - * @name ng.$controllerProvider#register - * @methodOf ng.$controllerProvider - * @param {string} name Controller name - * @param {Function|Array} constructor Controller constructor fn (optionally decorated with DI - * annotations in the array notation). - */ - this.register = function(name, constructor) { - if (isObject(name)) { - extend(controllers, name) - } else { - controllers[name] = constructor; - } - }; - - - this.$get = ['$injector', '$window', function($injector, $window) { - - /** - * @ngdoc function - * @name ng.$controller - * @requires $injector - * - * @param {Function|string} constructor If called with a function then it's considered to be the - * controller constructor function. Otherwise it's considered to be a string which is used - * to retrieve the controller constructor using the following steps: - * - * * check if a controller with given name is registered via `$controllerProvider` - * * check if evaluating the string on the current scope returns a constructor - * * check `window[constructor]` on the global `window` object - * - * @param {Object} locals Injection locals for Controller. - * @return {Object} Instance of given controller. - * - * @description - * `$controller` service is responsible for instantiating controllers. - * - * It's just a simple call to {@link AUTO.$injector $injector}, but extracted into - * a service, so that one can override this service with {@link https://gist.github.com/1649788 - * BC version}. - */ - return function(expression, locals) { - var instance, match, constructor, identifier; - - if(isString(expression)) { - match = expression.match(CNTRL_REG), - constructor = match[1], - identifier = match[3]; - expression = controllers.hasOwnProperty(constructor) - ? controllers[constructor] - : getter(locals.$scope, constructor, true) || getter($window, constructor, true); - - assertArgFn(expression, constructor, true); - } - - instance = $injector.instantiate(expression, locals); - - if (identifier) { - if (typeof locals.$scope !== 'object') { - throw new Error('Can not export controller as "' + identifier + '". ' + - 'No scope object provided!'); - } - - locals.$scope[identifier] = instance; - } - - return instance; - }; - }]; -} - -/** - * @ngdoc object - * @name ng.$document - * @requires $window - * - * @description - * A {@link angular.element jQuery (lite)}-wrapped reference to the browser's `window.document` - * element. - */ -function $DocumentProvider(){ - this.$get = ['$window', function(window){ - return jqLite(window.document); - }]; -} - -/** - * @ngdoc function - * @name ng.$exceptionHandler - * @requires $log - * - * @description - * Any uncaught exception in angular expressions is delegated to this service. - * The default implementation simply delegates to `$log.error` which logs it into - * the browser console. - * - * In unit tests, if `angular-mocks.js` is loaded, this service is overridden by - * {@link ngMock.$exceptionHandler mock $exceptionHandler} which aids in testing. - * - * @param {Error} exception Exception associated with the error. - * @param {string=} cause optional information about the context in which - * the error was thrown. - * - */ -function $ExceptionHandlerProvider() { - this.$get = ['$log', function($log) { - return function(exception, cause) { - $log.error.apply($log, arguments); - }; - }]; -} - -/** - * @ngdoc object - * @name ng.$interpolateProvider - * @function - * - * @description - * - * Used for configuring the interpolation markup. Defaults to `{{` and `}}`. - */ -function $InterpolateProvider() { - var startSymbol = '{{'; - var endSymbol = '}}'; - - /** - * @ngdoc method - * @name ng.$interpolateProvider#startSymbol - * @methodOf ng.$interpolateProvider - * @description - * Symbol to denote start of expression in the interpolated string. Defaults to `{{`. - * - * @param {string=} value new value to set the starting symbol to. - * @returns {string|self} Returns the symbol when used as getter and self if used as setter. - */ - this.startSymbol = function(value){ - if (value) { - startSymbol = value; - return this; - } else { - return startSymbol; - } - }; - - /** - * @ngdoc method - * @name ng.$interpolateProvider#endSymbol - * @methodOf ng.$interpolateProvider - * @description - * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`. - * - * @param {string=} value new value to set the ending symbol to. - * @returns {string|self} Returns the symbol when used as getter and self if used as setter. - */ - this.endSymbol = function(value){ - if (value) { - endSymbol = value; - return this; - } else { - return endSymbol; - } - }; - - - this.$get = ['$parse', '$exceptionHandler', function($parse, $exceptionHandler) { - var startSymbolLength = startSymbol.length, - endSymbolLength = endSymbol.length; - - /** - * @ngdoc function - * @name ng.$interpolate - * @function - * - * @requires $parse - * - * @description - * - * Compiles a string with markup into an interpolation function. This service is used by the - * HTML {@link ng.$compile $compile} service for data binding. See - * {@link ng.$interpolateProvider $interpolateProvider} for configuring the - * interpolation markup. - * - * -
                -         var $interpolate = ...; // injected
                -         var exp = $interpolate('Hello {{name}}!');
                -         expect(exp({name:'Angular'}).toEqual('Hello Angular!');
                -       
                - * - * - * @param {string} text The text with markup to interpolate. - * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have - * embedded expression in order to return an interpolation function. Strings with no - * embedded expression will return null for the interpolation function. - * @returns {function(context)} an interpolation function which is used to compute the interpolated - * string. The function has these parameters: - * - * * `context`: an object against which any expressions embedded in the strings are evaluated - * against. - * - */ - function $interpolate(text, mustHaveExpression) { - var startIndex, - endIndex, - index = 0, - parts = [], - length = text.length, - hasInterpolation = false, - fn, - exp, - concat = []; - - while(index < length) { - if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) && - ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) { - (index != startIndex) && parts.push(text.substring(index, startIndex)); - parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex))); - fn.exp = exp; - index = endIndex + endSymbolLength; - hasInterpolation = true; - } else { - // we did not find anything, so we have to add the remainder to the parts array - (index != length) && parts.push(text.substring(index)); - index = length; - } - } - - if (!(length = parts.length)) { - // we added, nothing, must have been an empty string. - parts.push(''); - length = 1; - } - - if (!mustHaveExpression || hasInterpolation) { - concat.length = length; - fn = function(context) { - try { - for(var i = 0, ii = length, part; i=} search New search params - string or hash object - * @param {string=} paramValue If `search` is a string, then `paramValue` will override only a - * single search parameter. If the value is `null`, the parameter will be deleted. - * - * @return {string} search - */ - search: function(search, paramValue) { - if (isUndefined(search)) - return this.$$search; - - if (isDefined(paramValue)) { - if (paramValue === null) { - delete this.$$search[search]; - } else { - this.$$search[search] = paramValue; - } - } else { - this.$$search = isString(search) ? parseKeyValue(search) : search; - } - - this.$$compose(); - return this; - }, - - /** - * @ngdoc method - * @name ng.$location#hash - * @methodOf ng.$location - * - * @description - * This method is getter / setter. - * - * Return hash fragment when called without any parameter. - * - * Change hash fragment when called with parameter and return `$location`. - * - * @param {string=} hash New hash fragment - * @return {string} hash - */ - hash: locationGetterSetter('$$hash', identity), - - /** - * @ngdoc method - * @name ng.$location#replace - * @methodOf ng.$location - * - * @description - * If called, all changes to $location during current `$digest` will be replacing current history - * record, instead of adding new one. - */ - replace: function() { - this.$$replace = true; - return this; - } -}; - -function locationGetter(property) { - return function() { - return this[property]; - }; -} - - -function locationGetterSetter(property, preprocess) { - return function(value) { - if (isUndefined(value)) - return this[property]; - - this[property] = preprocess(value); - this.$$compose(); - - return this; - }; -} - - -/** - * @ngdoc object - * @name ng.$location - * - * @requires $browser - * @requires $sniffer - * @requires $rootElement - * - * @description - * The $location service parses the URL in the browser address bar (based on the - * {@link https://developer.mozilla.org/en/window.location window.location}) and makes the URL - * available to your application. Changes to the URL in the address bar are reflected into - * $location service and changes to $location are reflected into the browser address bar. - * - * **The $location service:** - * - * - Exposes the current URL in the browser address bar, so you can - * - Watch and observe the URL. - * - Change the URL. - * - Synchronizes the URL with the browser when the user - * - Changes the address bar. - * - Clicks the back or forward button (or clicks a History link). - * - Clicks on a link. - * - Represents the URL object as a set of methods (protocol, host, port, path, search, hash). - * - * For more information see {@link guide/dev_guide.services.$location Developer Guide: Angular - * Services: Using $location} - */ - -/** - * @ngdoc object - * @name ng.$locationProvider - * @description - * Use the `$locationProvider` to configure how the application deep linking paths are stored. - */ -function $LocationProvider(){ - var hashPrefix = '', - html5Mode = false; - - /** - * @ngdoc property - * @name ng.$locationProvider#hashPrefix - * @methodOf ng.$locationProvider - * @description - * @param {string=} prefix Prefix for hash part (containing path and search) - * @returns {*} current value if used as getter or itself (chaining) if used as setter - */ - this.hashPrefix = function(prefix) { - if (isDefined(prefix)) { - hashPrefix = prefix; - return this; - } else { - return hashPrefix; - } - }; - - /** - * @ngdoc property - * @name ng.$locationProvider#html5Mode - * @methodOf ng.$locationProvider - * @description - * @param {string=} mode Use HTML5 strategy if available. - * @returns {*} current value if used as getter or itself (chaining) if used as setter - */ - this.html5Mode = function(mode) { - if (isDefined(mode)) { - html5Mode = mode; - return this; - } else { - return html5Mode; - } - }; - - this.$get = ['$rootScope', '$browser', '$sniffer', '$rootElement', - function( $rootScope, $browser, $sniffer, $rootElement) { - var $location, - LocationMode, - baseHref = $browser.baseHref(), - initialUrl = $browser.url(), - appBase; - - if (html5Mode) { - appBase = baseHref ? serverBase(initialUrl) + baseHref : initialUrl; - LocationMode = $sniffer.history ? LocationHtml5Url : LocationHashbangInHtml5Url; - } else { - appBase = stripHash(initialUrl); - LocationMode = LocationHashbangUrl; - } - $location = new LocationMode(appBase, '#' + hashPrefix); - $location.$$parse($location.$$rewrite(initialUrl)); - - $rootElement.bind('click', function(event) { - // TODO(vojta): rewrite link when opening in new tab/window (in legacy browser) - // currently we open nice url link and redirect then - - if (event.ctrlKey || event.metaKey || event.which == 2) return; - - var elm = jqLite(event.target); - - // traverse the DOM up to find first A tag - while (lowercase(elm[0].nodeName) !== 'a') { - // ignore rewriting if no A tag (reached root element, or no parent - removed from document) - if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return; - } - - var absHref = elm.prop('href'); - var rewrittenUrl = $location.$$rewrite(absHref); - - if (absHref && !elm.attr('target') && rewrittenUrl && !event.isDefaultPrevented()) { - event.preventDefault(); - if (rewrittenUrl != $browser.url()) { - // update location manually - $location.$$parse(rewrittenUrl); - $rootScope.$apply(); - // hack to work around FF6 bug 684208 when scenario runner clicks on links - window.angular['ff-684208-preventDefault'] = true; - } - } - }); - - - // rewrite hashbang url <> html5 url - if ($location.absUrl() != initialUrl) { - $browser.url($location.absUrl(), true); - } - - // update $location when $browser url changes - $browser.onUrlChange(function(newUrl) { - if ($location.absUrl() != newUrl) { - if ($rootScope.$broadcast('$locationChangeStart', newUrl, $location.absUrl()).defaultPrevented) { - $browser.url($location.absUrl()); - return; - } - $rootScope.$evalAsync(function() { - var oldUrl = $location.absUrl(); - - $location.$$parse(newUrl); - afterLocationChange(oldUrl); - }); - if (!$rootScope.$$phase) $rootScope.$digest(); - } - }); - - // update browser - var changeCounter = 0; - $rootScope.$watch(function $locationWatch() { - var oldUrl = $browser.url(); - var currentReplace = $location.$$replace; - - if (!changeCounter || oldUrl != $location.absUrl()) { - changeCounter++; - $rootScope.$evalAsync(function() { - if ($rootScope.$broadcast('$locationChangeStart', $location.absUrl(), oldUrl). - defaultPrevented) { - $location.$$parse(oldUrl); - } else { - $browser.url($location.absUrl(), currentReplace); - afterLocationChange(oldUrl); - } - }); - } - $location.$$replace = false; - - return changeCounter; - }); - - return $location; - - function afterLocationChange(oldUrl) { - $rootScope.$broadcast('$locationChangeSuccess', $location.absUrl(), oldUrl); - } -}]; -} - -/** - * @ngdoc object - * @name ng.$log - * @requires $window - * - * @description - * Simple service for logging. Default implementation writes the message - * into the browser's console (if present). - * - * The main purpose of this service is to simplify debugging and troubleshooting. - * - * @example - - - function LogCtrl($scope, $log) { - $scope.$log = $log; - $scope.message = 'Hello World!'; - } - - -
                -

                Reload this page with open console, enter text and hit the log button...

                - Message: - - - - - -
                -
                -
                - */ - -/** - * @ngdoc object - * @name ng.$logProvider - * @description - * Use the `$logProvider` to configure how the application logs messages - */ -function $LogProvider(){ - var debug = true, - self = this; - - /** - * @ngdoc property - * @name ng.$logProvider#debugEnabled - * @methodOf ng.$logProvider - * @description - * @param {string=} flag enable or disable debug level messages - * @returns {*} current value if used as getter or itself (chaining) if used as setter - */ - this.debugEnabled = function(flag) { - if (isDefined(flag)) { - debug = flag; - return this; - } else { - return debug; - } - }; - - this.$get = ['$window', function($window){ - return { - /** - * @ngdoc method - * @name ng.$log#log - * @methodOf ng.$log - * - * @description - * Write a log message - */ - log: consoleLog('log'), - - /** - * @ngdoc method - * @name ng.$log#warn - * @methodOf ng.$log - * - * @description - * Write a warning message - */ - warn: consoleLog('warn'), - - /** - * @ngdoc method - * @name ng.$log#info - * @methodOf ng.$log - * - * @description - * Write an information message - */ - info: consoleLog('info'), - - /** - * @ngdoc method - * @name ng.$log#error - * @methodOf ng.$log - * - * @description - * Write an error message - */ - error: consoleLog('error'), - - /** - * @ngdoc method - * @name ng.$log#debug - * @methodOf ng.$log - * - * @description - * Write a debug message - */ - debug: (function () { - var fn = consoleLog('debug'); - - return function() { - if (debug) { - fn.apply(self, arguments); - } - } - }()) - }; - - function formatError(arg) { - if (arg instanceof Error) { - if (arg.stack) { - arg = (arg.message && arg.stack.indexOf(arg.message) === -1) - ? 'Error: ' + arg.message + '\n' + arg.stack - : arg.stack; - } else if (arg.sourceURL) { - arg = arg.message + '\n' + arg.sourceURL + ':' + arg.line; - } - } - return arg; - } - - function consoleLog(type) { - var console = $window.console || {}, - logFn = console[type] || console.log || noop; - - if (logFn.apply) { - return function() { - var args = []; - forEach(arguments, function(arg) { - args.push(formatError(arg)); - }); - return logFn.apply(console, args); - }; - } - - // we are IE which either doesn't have window.console => this is noop and we do nothing, - // or we are IE where console.log doesn't have apply so we log at least first 2 args - return function(arg1, arg2) { - logFn(arg1, arg2); - } - } - }]; -} - -var OPERATORS = { - 'null':function(){return null;}, - 'true':function(){return true;}, - 'false':function(){return false;}, - undefined:noop, - '+':function(self, locals, a,b){ - a=a(self, locals); b=b(self, locals); - if (isDefined(a)) { - if (isDefined(b)) { - return a + b; - } - return a; - } - return isDefined(b)?b:undefined;}, - '-':function(self, locals, a,b){a=a(self, locals); b=b(self, locals); return (isDefined(a)?a:0)-(isDefined(b)?b:0);}, - '*':function(self, locals, a,b){return a(self, locals)*b(self, locals);}, - '/':function(self, locals, a,b){return a(self, locals)/b(self, locals);}, - '%':function(self, locals, a,b){return a(self, locals)%b(self, locals);}, - '^':function(self, locals, a,b){return a(self, locals)^b(self, locals);}, - '=':noop, - '===':function(self, locals, a, b){return a(self, locals)===b(self, locals);}, - '!==':function(self, locals, a, b){return a(self, locals)!==b(self, locals);}, - '==':function(self, locals, a,b){return a(self, locals)==b(self, locals);}, - '!=':function(self, locals, a,b){return a(self, locals)!=b(self, locals);}, - '<':function(self, locals, a,b){return a(self, locals)':function(self, locals, a,b){return a(self, locals)>b(self, locals);}, - '<=':function(self, locals, a,b){return a(self, locals)<=b(self, locals);}, - '>=':function(self, locals, a,b){return a(self, locals)>=b(self, locals);}, - '&&':function(self, locals, a,b){return a(self, locals)&&b(self, locals);}, - '||':function(self, locals, a,b){return a(self, locals)||b(self, locals);}, - '&':function(self, locals, a,b){return a(self, locals)&b(self, locals);}, -// '|':function(self, locals, a,b){return a|b;}, - '|':function(self, locals, a,b){return b(self, locals)(self, locals, a(self, locals));}, - '!':function(self, locals, a){return !a(self, locals);} -}; -var ESCAPE = {"n":"\n", "f":"\f", "r":"\r", "t":"\t", "v":"\v", "'":"'", '"':'"'}; - -function lex(text, csp){ - var tokens = [], - token, - index = 0, - json = [], - ch, - lastCh = ':'; // can start regexp - - while (index < text.length) { - ch = text.charAt(index); - if (is('"\'')) { - readString(ch); - } else if (isNumber(ch) || is('.') && isNumber(peek())) { - readNumber(); - } else if (isIdent(ch)) { - readIdent(); - // identifiers can only be if the preceding char was a { or , - if (was('{,') && json[0]=='{' && - (token=tokens[tokens.length-1])) { - token.json = token.text.indexOf('.') == -1; - } - } else if (is('(){}[].,;:?')) { - tokens.push({ - index:index, - text:ch, - json:(was(':[,') && is('{[')) || is('}]:,') - }); - if (is('{[')) json.unshift(ch); - if (is('}]')) json.shift(); - index++; - } else if (isWhitespace(ch)) { - index++; - continue; - } else { - var ch2 = ch + peek(), - ch3 = ch2 + peek(2), - fn = OPERATORS[ch], - fn2 = OPERATORS[ch2], - fn3 = OPERATORS[ch3]; - if (fn3) { - tokens.push({index:index, text:ch3, fn:fn3}); - index += 3; - } else if (fn2) { - tokens.push({index:index, text:ch2, fn:fn2}); - index += 2; - } else if (fn) { - tokens.push({index:index, text:ch, fn:fn, json: was('[,:') && is('+-')}); - index += 1; - } else { - throwError("Unexpected next character ", index, index+1); - } - } - lastCh = ch; - } - return tokens; - - function is(chars) { - return chars.indexOf(ch) != -1; - } - - function was(chars) { - return chars.indexOf(lastCh) != -1; - } - - function peek(i) { - var num = i || 1; - return index + num < text.length ? text.charAt(index + num) : false; - } - function isNumber(ch) { - return '0' <= ch && ch <= '9'; - } - function isWhitespace(ch) { - return ch == ' ' || ch == '\r' || ch == '\t' || - ch == '\n' || ch == '\v' || ch == '\u00A0'; // IE treats non-breaking space as \u00A0 - } - function isIdent(ch) { - return 'a' <= ch && ch <= 'z' || - 'A' <= ch && ch <= 'Z' || - '_' == ch || ch == '$'; - } - function isExpOperator(ch) { - return ch == '-' || ch == '+' || isNumber(ch); - } - - function throwError(error, start, end) { - end = end || index; - throw Error("Lexer Error: " + error + " at column" + - (isDefined(start) - ? "s " + start + "-" + index + " [" + text.substring(start, end) + "]" - : " " + end) + - " in expression [" + text + "]."); - } - - function readNumber() { - var number = ""; - var start = index; - while (index < text.length) { - var ch = lowercase(text.charAt(index)); - if (ch == '.' || isNumber(ch)) { - number += ch; - } else { - var peekCh = peek(); - if (ch == 'e' && isExpOperator(peekCh)) { - number += ch; - } else if (isExpOperator(ch) && - peekCh && isNumber(peekCh) && - number.charAt(number.length - 1) == 'e') { - number += ch; - } else if (isExpOperator(ch) && - (!peekCh || !isNumber(peekCh)) && - number.charAt(number.length - 1) == 'e') { - throwError('Invalid exponent'); - } else { - break; - } - } - index++; - } - number = 1 * number; - tokens.push({index:start, text:number, json:true, - fn:function() {return number;}}); - } - function readIdent() { - var ident = "", - start = index, - lastDot, peekIndex, methodName, ch; - - while (index < text.length) { - ch = text.charAt(index); - if (ch == '.' || isIdent(ch) || isNumber(ch)) { - if (ch == '.') lastDot = index; - ident += ch; - } else { - break; - } - index++; - } - - //check if this is not a method invocation and if it is back out to last dot - if (lastDot) { - peekIndex = index; - while(peekIndex < text.length) { - ch = text.charAt(peekIndex); - if (ch == '(') { - methodName = ident.substr(lastDot - start + 1); - ident = ident.substr(0, lastDot - start); - index = peekIndex; - break; - } - if(isWhitespace(ch)) { - peekIndex++; - } else { - break; - } - } - } - - - var token = { - index:start, - text:ident - }; - - if (OPERATORS.hasOwnProperty(ident)) { - token.fn = token.json = OPERATORS[ident]; - } else { - var getter = getterFn(ident, csp); - token.fn = extend(function(self, locals) { - return (getter(self, locals)); - }, { - assign: function(self, value) { - return setter(self, ident, value); - } - }); - } - - tokens.push(token); - - if (methodName) { - tokens.push({ - index:lastDot, - text: '.', - json: false - }); - tokens.push({ - index: lastDot + 1, - text: methodName, - json: false - }); - } - } - - function readString(quote) { - var start = index; - index++; - var string = ""; - var rawString = quote; - var escape = false; - while (index < text.length) { - var ch = text.charAt(index); - rawString += ch; - if (escape) { - if (ch == 'u') { - var hex = text.substring(index + 1, index + 5); - if (!hex.match(/[\da-f]{4}/i)) - throwError( "Invalid unicode escape [\\u" + hex + "]"); - index += 4; - string += String.fromCharCode(parseInt(hex, 16)); - } else { - var rep = ESCAPE[ch]; - if (rep) { - string += rep; - } else { - string += ch; - } - } - escape = false; - } else if (ch == '\\') { - escape = true; - } else if (ch == quote) { - index++; - tokens.push({ - index:start, - text:rawString, - string:string, - json:true, - fn:function() { return string; } - }); - return; - } else { - string += ch; - } - index++; - } - throwError("Unterminated quote", start); - } -} - -///////////////////////////////////////// - -function parser(text, json, $filter, csp){ - var ZERO = valueFn(0), - value, - tokens = lex(text, csp), - assignment = _assignment, - functionCall = _functionCall, - fieldAccess = _fieldAccess, - objectIndex = _objectIndex, - filterChain = _filterChain; - - if(json){ - // The extra level of aliasing is here, just in case the lexer misses something, so that - // we prevent any accidental execution in JSON. - assignment = logicalOR; - functionCall = - fieldAccess = - objectIndex = - filterChain = - function() { throwError("is not valid json", {text:text, index:0}); }; - value = primary(); - } else { - value = statements(); - } - if (tokens.length !== 0) { - throwError("is an unexpected token", tokens[0]); - } - value.literal = !!value.literal; - value.constant = !!value.constant; - return value; - - /////////////////////////////////// - function throwError(msg, token) { - throw Error("Syntax Error: Token '" + token.text + - "' " + msg + " at column " + - (token.index + 1) + " of the expression [" + - text + "] starting at [" + text.substring(token.index) + "]."); - } - - function peekToken() { - if (tokens.length === 0) - throw Error("Unexpected end of expression: " + text); - return tokens[0]; - } - - function peek(e1, e2, e3, e4) { - if (tokens.length > 0) { - var token = tokens[0]; - var t = token.text; - if (t==e1 || t==e2 || t==e3 || t==e4 || - (!e1 && !e2 && !e3 && !e4)) { - return token; - } - } - return false; - } - - function expect(e1, e2, e3, e4){ - var token = peek(e1, e2, e3, e4); - if (token) { - if (json && !token.json) { - throwError("is not valid json", token); - } - tokens.shift(); - return token; - } - return false; - } - - function consume(e1){ - if (!expect(e1)) { - throwError("is unexpected, expecting [" + e1 + "]", peek()); - } - } - - function unaryFn(fn, right) { - return extend(function(self, locals) { - return fn(self, locals, right); - }, { - constant:right.constant - }); - } - - function ternaryFn(left, middle, right){ - return extend(function(self, locals){ - return left(self, locals) ? middle(self, locals) : right(self, locals); - }, { - constant: left.constant && middle.constant && right.constant - }); - } - - function binaryFn(left, fn, right) { - return extend(function(self, locals) { - return fn(self, locals, left, right); - }, { - constant:left.constant && right.constant - }); - } - - function statements() { - var statements = []; - while(true) { - if (tokens.length > 0 && !peek('}', ')', ';', ']')) - statements.push(filterChain()); - if (!expect(';')) { - // optimize for the common case where there is only one statement. - // TODO(size): maybe we should not support multiple statements? - return statements.length == 1 - ? statements[0] - : function(self, locals){ - var value; - for ( var i = 0; i < statements.length; i++) { - var statement = statements[i]; - if (statement) - value = statement(self, locals); - } - return value; - }; - } - } - } - - function _filterChain() { - var left = expression(); - var token; - while(true) { - if ((token = expect('|'))) { - left = binaryFn(left, token.fn, filter()); - } else { - return left; - } - } - } - - function filter() { - var token = expect(); - var fn = $filter(token.text); - var argsFn = []; - while(true) { - if ((token = expect(':'))) { - argsFn.push(expression()); - } else { - var fnInvoke = function(self, locals, input){ - var args = [input]; - for ( var i = 0; i < argsFn.length; i++) { - args.push(argsFn[i](self, locals)); - } - return fn.apply(self, args); - }; - return function() { - return fnInvoke; - }; - } - } - } - - function expression() { - return assignment(); - } - - function _assignment() { - var left = ternary(); - var right; - var token; - if ((token = expect('='))) { - if (!left.assign) { - throwError("implies assignment but [" + - text.substring(0, token.index) + "] can not be assigned to", token); - } - right = ternary(); - return function(scope, locals){ - return left.assign(scope, right(scope, locals), locals); - }; - } else { - return left; - } - } - - function ternary() { - var left = logicalOR(); - var middle; - var token; - if((token = expect('?'))){ - middle = ternary(); - if((token = expect(':'))){ - return ternaryFn(left, middle, ternary()); - } - else { - throwError('expected :', token); - } - } - else { - return left; - } - } - - function logicalOR() { - var left = logicalAND(); - var token; - while(true) { - if ((token = expect('||'))) { - left = binaryFn(left, token.fn, logicalAND()); - } else { - return left; - } - } - } - - function logicalAND() { - var left = equality(); - var token; - if ((token = expect('&&'))) { - left = binaryFn(left, token.fn, logicalAND()); - } - return left; - } - - function equality() { - var left = relational(); - var token; - if ((token = expect('==','!=','===','!=='))) { - left = binaryFn(left, token.fn, equality()); - } - return left; - } - - function relational() { - var left = additive(); - var token; - if ((token = expect('<', '>', '<=', '>='))) { - left = binaryFn(left, token.fn, relational()); - } - return left; - } - - function additive() { - var left = multiplicative(); - var token; - while ((token = expect('+','-'))) { - left = binaryFn(left, token.fn, multiplicative()); - } - return left; - } - - function multiplicative() { - var left = unary(); - var token; - while ((token = expect('*','/','%'))) { - left = binaryFn(left, token.fn, unary()); - } - return left; - } - - function unary() { - var token; - if (expect('+')) { - return primary(); - } else if ((token = expect('-'))) { - return binaryFn(ZERO, token.fn, unary()); - } else if ((token = expect('!'))) { - return unaryFn(token.fn, unary()); - } else { - return primary(); - } - } - - - function primary() { - var primary; - if (expect('(')) { - primary = filterChain(); - consume(')'); - } else if (expect('[')) { - primary = arrayDeclaration(); - } else if (expect('{')) { - primary = object(); - } else { - var token = expect(); - primary = token.fn; - if (!primary) { - throwError("not a primary expression", token); - } - if (token.json) { - primary.constant = primary.literal = true; - } - } - - var next, context; - while ((next = expect('(', '[', '.'))) { - if (next.text === '(') { - primary = functionCall(primary, context); - context = null; - } else if (next.text === '[') { - context = primary; - primary = objectIndex(primary); - } else if (next.text === '.') { - context = primary; - primary = fieldAccess(primary); - } else { - throwError("IMPOSSIBLE"); - } - } - return primary; - } - - function _fieldAccess(object) { - var field = expect().text; - var getter = getterFn(field, csp); - return extend( - function(scope, locals, self) { - return getter(self || object(scope, locals), locals); - }, - { - assign:function(scope, value, locals) { - return setter(object(scope, locals), field, value); - } - } - ); - } - - function _objectIndex(obj) { - var indexFn = expression(); - consume(']'); - return extend( - function(self, locals){ - var o = obj(self, locals), - i = indexFn(self, locals), - v, p; - - if (!o) return undefined; - v = o[i]; - if (v && v.then) { - p = v; - if (!('$$v' in v)) { - p.$$v = undefined; - p.then(function(val) { p.$$v = val; }); - } - v = v.$$v; - } - return v; - }, { - assign:function(self, value, locals){ - return obj(self, locals)[indexFn(self, locals)] = value; - } - }); - } - - function _functionCall(fn, contextGetter) { - var argsFn = []; - if (peekToken().text != ')') { - do { - argsFn.push(expression()); - } while (expect(',')); - } - consume(')'); - return function(scope, locals){ - var args = [], - context = contextGetter ? contextGetter(scope, locals) : scope; - - for ( var i = 0; i < argsFn.length; i++) { - args.push(argsFn[i](scope, locals)); - } - var fnPtr = fn(scope, locals, context) || noop; - // IE stupidity! - return fnPtr.apply - ? fnPtr.apply(context, args) - : fnPtr(args[0], args[1], args[2], args[3], args[4]); - }; - } - - // This is used with json array declaration - function arrayDeclaration () { - var elementFns = []; - var allConstant = true; - if (peekToken().text != ']') { - do { - var elementFn = expression(); - elementFns.push(elementFn); - if (!elementFn.constant) { - allConstant = false; - } - } while (expect(',')); - } - consume(']'); - return extend(function(self, locals){ - var array = []; - for ( var i = 0; i < elementFns.length; i++) { - array.push(elementFns[i](self, locals)); - } - return array; - }, { - literal:true, - constant:allConstant - }); - } - - function object () { - var keyValues = []; - var allConstant = true; - if (peekToken().text != '}') { - do { - var token = expect(), - key = token.string || token.text; - consume(":"); - var value = expression(); - keyValues.push({key:key, value:value}); - if (!value.constant) { - allConstant = false; - } - } while (expect(',')); - } - consume('}'); - return extend(function(self, locals){ - var object = {}; - for ( var i = 0; i < keyValues.length; i++) { - var keyValue = keyValues[i]; - object[keyValue.key] = keyValue.value(self, locals); - } - return object; - }, { - literal:true, - constant:allConstant - }); - } -} - -////////////////////////////////////////////////// -// Parser helper functions -////////////////////////////////////////////////// - -function setter(obj, path, setValue) { - var element = path.split('.'); - for (var i = 0; element.length > 1; i++) { - var key = element.shift(); - var propertyObj = obj[key]; - if (!propertyObj) { - propertyObj = {}; - obj[key] = propertyObj; - } - obj = propertyObj; - } - obj[element.shift()] = setValue; - return setValue; -} - -/** - * Return the value accessible from the object by path. Any undefined traversals are ignored - * @param {Object} obj starting object - * @param {string} path path to traverse - * @param {boolean=true} bindFnToScope - * @returns value as accessible by path - */ -//TODO(misko): this function needs to be removed -function getter(obj, path, bindFnToScope) { - if (!path) return obj; - var keys = path.split('.'); - var key; - var lastInstance = obj; - var len = keys.length; - - for (var i = 0; i < len; i++) { - key = keys[i]; - if (obj) { - obj = (lastInstance = obj)[key]; - } - } - if (!bindFnToScope && isFunction(obj)) { - return bind(lastInstance, obj); - } - return obj; -} - -var getterFnCache = {}; - -/** - * Implementation of the "Black Hole" variant from: - * - http://jsperf.com/angularjs-parse-getter/4 - * - http://jsperf.com/path-evaluation-simplified/7 - */ -function cspSafeGetterFn(key0, key1, key2, key3, key4) { - return function(scope, locals) { - var pathVal = (locals && locals.hasOwnProperty(key0)) ? locals : scope, - promise; - - if (pathVal === null || pathVal === undefined) return pathVal; - - pathVal = pathVal[key0]; - if (pathVal && pathVal.then) { - if (!("$$v" in pathVal)) { - promise = pathVal; - promise.$$v = undefined; - promise.then(function(val) { promise.$$v = val; }); - } - pathVal = pathVal.$$v; - } - if (!key1 || pathVal === null || pathVal === undefined) return pathVal; - - pathVal = pathVal[key1]; - if (pathVal && pathVal.then) { - if (!("$$v" in pathVal)) { - promise = pathVal; - promise.$$v = undefined; - promise.then(function(val) { promise.$$v = val; }); - } - pathVal = pathVal.$$v; - } - if (!key2 || pathVal === null || pathVal === undefined) return pathVal; - - pathVal = pathVal[key2]; - if (pathVal && pathVal.then) { - if (!("$$v" in pathVal)) { - promise = pathVal; - promise.$$v = undefined; - promise.then(function(val) { promise.$$v = val; }); - } - pathVal = pathVal.$$v; - } - if (!key3 || pathVal === null || pathVal === undefined) return pathVal; - - pathVal = pathVal[key3]; - if (pathVal && pathVal.then) { - if (!("$$v" in pathVal)) { - promise = pathVal; - promise.$$v = undefined; - promise.then(function(val) { promise.$$v = val; }); - } - pathVal = pathVal.$$v; - } - if (!key4 || pathVal === null || pathVal === undefined) return pathVal; - - pathVal = pathVal[key4]; - if (pathVal && pathVal.then) { - if (!("$$v" in pathVal)) { - promise = pathVal; - promise.$$v = undefined; - promise.then(function(val) { promise.$$v = val; }); - } - pathVal = pathVal.$$v; - } - return pathVal; - }; -} - -function getterFn(path, csp) { - if (getterFnCache.hasOwnProperty(path)) { - return getterFnCache[path]; - } - - var pathKeys = path.split('.'), - pathKeysLength = pathKeys.length, - fn; - - if (csp) { - fn = (pathKeysLength < 6) - ? cspSafeGetterFn(pathKeys[0], pathKeys[1], pathKeys[2], pathKeys[3], pathKeys[4]) - : function(scope, locals) { - var i = 0, val; - do { - val = cspSafeGetterFn( - pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++], pathKeys[i++] - )(scope, locals); - - locals = undefined; // clear after first iteration - scope = val; - } while (i < pathKeysLength); - return val; - } - } else { - var code = 'var l, fn, p;\n'; - forEach(pathKeys, function(key, index) { - code += 'if(s === null || s === undefined) return s;\n' + - 'l=s;\n' + - 's='+ (index - // we simply dereference 's' on any .dot notation - ? 's' - // but if we are first then we check locals first, and if so read it first - : '((k&&k.hasOwnProperty("' + key + '"))?k:s)') + '["' + key + '"]' + ';\n' + - 'if (s && s.then) {\n' + - ' if (!("$$v" in s)) {\n' + - ' p=s;\n' + - ' p.$$v = undefined;\n' + - ' p.then(function(v) {p.$$v=v;});\n' + - '}\n' + - ' s=s.$$v\n' + - '}\n'; - }); - code += 'return s;'; - fn = Function('s', 'k', code); // s=scope, k=locals - fn.toString = function() { return code; }; - } - - return getterFnCache[path] = fn; -} - -/////////////////////////////////// - -/** - * @ngdoc function - * @name ng.$parse - * @function - * - * @description - * - * Converts Angular {@link guide/expression expression} into a function. - * - *
                - *   var getter = $parse('user.name');
                - *   var setter = getter.assign;
                - *   var context = {user:{name:'angular'}};
                - *   var locals = {user:{name:'local'}};
                - *
                - *   expect(getter(context)).toEqual('angular');
                - *   setter(context, 'newValue');
                - *   expect(context.user.name).toEqual('newValue');
                - *   expect(getter(context, locals)).toEqual('local');
                - * 
                - * - * - * @param {string} expression String expression to compile. - * @returns {function(context, locals)} a function which represents the compiled expression: - * - * * `context` – `{object}` – an object against which any expressions embedded in the strings - * are evaluated against (typically a scope object). - * * `locals` – `{object=}` – local variables context object, useful for overriding values in - * `context`. - * - * The returned function also has the following properties: - * * `literal` – `{boolean}` – whether the expression's top-level node is a JavaScript - * literal. - * * `constant` – `{boolean}` – whether the expression is made entirely of JavaScript - * constant literals. - * * `assign` – `{?function(context, value)}` – if the expression is assignable, this will be - * set to a function to change its value on the given context. - * - */ -function $ParseProvider() { - var cache = {}; - this.$get = ['$filter', '$sniffer', function($filter, $sniffer) { - return function(exp) { - switch(typeof exp) { - case 'string': - return cache.hasOwnProperty(exp) - ? cache[exp] - : cache[exp] = parser(exp, false, $filter, $sniffer.csp); - case 'function': - return exp; - default: - return noop; - } - }; - }]; -} - -/** - * @ngdoc service - * @name ng.$q - * @requires $rootScope - * - * @description - * A promise/deferred implementation inspired by [Kris Kowal's Q](https://github.com/kriskowal/q). - * - * [The CommonJS Promise proposal](http://wiki.commonjs.org/wiki/Promises) describes a promise as an - * interface for interacting with an object that represents the result of an action that is - * performed asynchronously, and may or may not be finished at any given point in time. - * - * From the perspective of dealing with error handling, deferred and promise APIs are to - * asynchronous programming what `try`, `catch` and `throw` keywords are to synchronous programming. - * - *
                - *   // for the purpose of this example let's assume that variables `$q` and `scope` are
                - *   // available in the current lexical scope (they could have been injected or passed in).
                - *
                - *   function asyncGreet(name) {
                - *     var deferred = $q.defer();
                - *
                - *     setTimeout(function() {
                - *       // since this fn executes async in a future turn of the event loop, we need to wrap
                - *       // our code into an $apply call so that the model changes are properly observed.
                - *       scope.$apply(function() {
                - *         if (okToGreet(name)) {
                - *           deferred.resolve('Hello, ' + name + '!');
                - *         } else {
                - *           deferred.reject('Greeting ' + name + ' is not allowed.');
                - *         }
                - *       });
                - *     }, 1000);
                - *
                - *     return deferred.promise;
                - *   }
                - *
                - *   var promise = asyncGreet('Robin Hood');
                - *   promise.then(function(greeting) {
                - *     alert('Success: ' + greeting);
                - *   }, function(reason) {
                - *     alert('Failed: ' + reason);
                - *   });
                - * 
                - * - * At first it might not be obvious why this extra complexity is worth the trouble. The payoff - * comes in the way of - * [guarantees that promise and deferred APIs make](https://github.com/kriskowal/uncommonjs/blob/master/promises/specification.md). - * - * Additionally the promise api allows for composition that is very hard to do with the - * traditional callback ([CPS](http://en.wikipedia.org/wiki/Continuation-passing_style)) approach. - * For more on this please see the [Q documentation](https://github.com/kriskowal/q) especially the - * section on serial or parallel joining of promises. - * - * - * # The Deferred API - * - * A new instance of deferred is constructed by calling `$q.defer()`. - * - * The purpose of the deferred object is to expose the associated Promise instance as well as APIs - * that can be used for signaling the successful or unsuccessful completion of the task. - * - * **Methods** - * - * - `resolve(value)` – resolves the derived promise with the `value`. If the value is a rejection - * constructed via `$q.reject`, the promise will be rejected instead. - * - `reject(reason)` – rejects the derived promise with the `reason`. This is equivalent to - * resolving it with a rejection constructed via `$q.reject`. - * - * **Properties** - * - * - promise – `{Promise}` – promise object associated with this deferred. - * - * - * # The Promise API - * - * A new promise instance is created when a deferred instance is created and can be retrieved by - * calling `deferred.promise`. - * - * The purpose of the promise object is to allow for interested parties to get access to the result - * of the deferred task when it completes. - * - * **Methods** - * - * - `then(successCallback, errorCallback)` – regardless of when the promise was or will be resolved - * or rejected calls one of the success or error callbacks asynchronously as soon as the result - * is available. The callbacks are called with a single argument the result or rejection reason. - * - * This method *returns a new promise* which is resolved or rejected via the return value of the - * `successCallback` or `errorCallback`. - * - * - `always(callback)` – allows you to observe either the fulfillment or rejection of a promise, - * but to do so without modifying the final value. This is useful to release resources or do some - * clean-up that needs to be done whether the promise was rejected or resolved. See the [full - * specification](https://github.com/kriskowal/q/wiki/API-Reference#promisefinallycallback) for - * more information. - * - * # Chaining promises - * - * Because calling `then` api of a promise returns a new derived promise, it is easily possible - * to create a chain of promises: - * - *
                - *   promiseB = promiseA.then(function(result) {
                - *     return result + 1;
                - *   });
                - *
                - *   // promiseB will be resolved immediately after promiseA is resolved and its value will be
                - *   // the result of promiseA incremented by 1
                - * 
                - * - * It is possible to create chains of any length and since a promise can be resolved with another - * promise (which will defer its resolution further), it is possible to pause/defer resolution of - * the promises at any point in the chain. This makes it possible to implement powerful apis like - * $http's response interceptors. - * - * - * # Differences between Kris Kowal's Q and $q - * - * There are three main differences: - * - * - $q is integrated with the {@link ng.$rootScope.Scope} Scope model observation - * mechanism in angular, which means faster propagation of resolution or rejection into your - * models and avoiding unnecessary browser repaints, which would result in flickering UI. - * - $q promises are recognized by the templating engine in angular, which means that in templates - * you can treat promises attached to a scope as if they were the resulting values. - * - Q has many more features than $q, but that comes at a cost of bytes. $q is tiny, but contains - * all the important functionality needed for common async tasks. - * - * # Testing - * - *
                - *    it('should simulate promise', inject(function($q, $rootScope) {
                - *      var deferred = $q.defer();
                - *      var promise = deferred.promise;
                - *      var resolvedValue;
                - * 
                - *      promise.then(function(value) { resolvedValue = value; });
                - *      expect(resolvedValue).toBeUndefined();
                - * 
                - *      // Simulate resolving of promise
                - *      deferred.resolve(123);
                - *      // Note that the 'then' function does not get called synchronously.
                - *      // This is because we want the promise API to always be async, whether or not
                - *      // it got called synchronously or asynchronously.
                - *      expect(resolvedValue).toBeUndefined();
                - * 
                - *      // Propagate promise resolution to 'then' functions using $apply().
                - *      $rootScope.$apply();
                - *      expect(resolvedValue).toEqual(123);
                - *    });
                - *  
                - */ -function $QProvider() { - - this.$get = ['$rootScope', '$exceptionHandler', function($rootScope, $exceptionHandler) { - return qFactory(function(callback) { - $rootScope.$evalAsync(callback); - }, $exceptionHandler); - }]; -} - - -/** - * Constructs a promise manager. - * - * @param {function(function)} nextTick Function for executing functions in the next turn. - * @param {function(...*)} exceptionHandler Function into which unexpected exceptions are passed for - * debugging purposes. - * @returns {object} Promise manager. - */ -function qFactory(nextTick, exceptionHandler) { - - /** - * @ngdoc - * @name ng.$q#defer - * @methodOf ng.$q - * @description - * Creates a `Deferred` object which represents a task which will finish in the future. - * - * @returns {Deferred} Returns a new instance of deferred. - */ - var defer = function() { - var pending = [], - value, deferred; - - deferred = { - - resolve: function(val) { - if (pending) { - var callbacks = pending; - pending = undefined; - value = ref(val); - - if (callbacks.length) { - nextTick(function() { - var callback; - for (var i = 0, ii = callbacks.length; i < ii; i++) { - callback = callbacks[i]; - value.then(callback[0], callback[1]); - } - }); - } - } - }, - - - reject: function(reason) { - deferred.resolve(reject(reason)); - }, - - - promise: { - then: function(callback, errback) { - var result = defer(); - - var wrappedCallback = function(value) { - try { - result.resolve((callback || defaultCallback)(value)); - } catch(e) { - exceptionHandler(e); - result.reject(e); - } - }; - - var wrappedErrback = function(reason) { - try { - result.resolve((errback || defaultErrback)(reason)); - } catch(e) { - exceptionHandler(e); - result.reject(e); - } - }; - - if (pending) { - pending.push([wrappedCallback, wrappedErrback]); - } else { - value.then(wrappedCallback, wrappedErrback); - } - - return result.promise; - }, - always: function(callback) { - - function makePromise(value, resolved) { - var result = defer(); - if (resolved) { - result.resolve(value); - } else { - result.reject(value); - } - return result.promise; - } - - function handleCallback(value, isResolved) { - var callbackOutput = null; - try { - callbackOutput = (callback ||defaultCallback)(); - } catch(e) { - return makePromise(e, false); - } - if (callbackOutput && callbackOutput.then) { - return callbackOutput.then(function() { - return makePromise(value, isResolved); - }, function(error) { - return makePromise(error, false); - }); - } else { - return makePromise(value, isResolved); - } - } - - return this.then(function(value) { - return handleCallback(value, true); - }, function(error) { - return handleCallback(error, false); - }); - } - } - }; - - return deferred; - }; - - - var ref = function(value) { - if (value && value.then) return value; - return { - then: function(callback) { - var result = defer(); - nextTick(function() { - result.resolve(callback(value)); - }); - return result.promise; - } - }; - }; - - - /** - * @ngdoc - * @name ng.$q#reject - * @methodOf ng.$q - * @description - * Creates a promise that is resolved as rejected with the specified `reason`. This api should be - * used to forward rejection in a chain of promises. If you are dealing with the last promise in - * a promise chain, you don't need to worry about it. - * - * When comparing deferreds/promises to the familiar behavior of try/catch/throw, think of - * `reject` as the `throw` keyword in JavaScript. This also means that if you "catch" an error via - * a promise error callback and you want to forward the error to the promise derived from the - * current promise, you have to "rethrow" the error by returning a rejection constructed via - * `reject`. - * - *
                -   *   promiseB = promiseA.then(function(result) {
                -   *     // success: do something and resolve promiseB
                -   *     //          with the old or a new result
                -   *     return result;
                -   *   }, function(reason) {
                -   *     // error: handle the error if possible and
                -   *     //        resolve promiseB with newPromiseOrValue,
                -   *     //        otherwise forward the rejection to promiseB
                -   *     if (canHandle(reason)) {
                -   *      // handle the error and recover
                -   *      return newPromiseOrValue;
                -   *     }
                -   *     return $q.reject(reason);
                -   *   });
                -   * 
                - * - * @param {*} reason Constant, message, exception or an object representing the rejection reason. - * @returns {Promise} Returns a promise that was already resolved as rejected with the `reason`. - */ - var reject = function(reason) { - return { - then: function(callback, errback) { - var result = defer(); - nextTick(function() { - result.resolve((errback || defaultErrback)(reason)); - }); - return result.promise; - } - }; - }; - - - /** - * @ngdoc - * @name ng.$q#when - * @methodOf ng.$q - * @description - * Wraps an object that might be a value or a (3rd party) then-able promise into a $q promise. - * This is useful when you are dealing with an object that might or might not be a promise, or if - * the promise comes from a source that can't be trusted. - * - * @param {*} value Value or a promise - * @returns {Promise} Returns a promise of the passed value or promise - */ - var when = function(value, callback, errback) { - var result = defer(), - done; - - var wrappedCallback = function(value) { - try { - return (callback || defaultCallback)(value); - } catch (e) { - exceptionHandler(e); - return reject(e); - } - }; - - var wrappedErrback = function(reason) { - try { - return (errback || defaultErrback)(reason); - } catch (e) { - exceptionHandler(e); - return reject(e); - } - }; - - nextTick(function() { - ref(value).then(function(value) { - if (done) return; - done = true; - result.resolve(ref(value).then(wrappedCallback, wrappedErrback)); - }, function(reason) { - if (done) return; - done = true; - result.resolve(wrappedErrback(reason)); - }); - }); - - return result.promise; - }; - - - function defaultCallback(value) { - return value; - } - - - function defaultErrback(reason) { - return reject(reason); - } - - - /** - * @ngdoc - * @name ng.$q#all - * @methodOf ng.$q - * @description - * Combines multiple promises into a single promise that is resolved when all of the input - * promises are resolved. - * - * @param {Array.|Object.} promises An array or hash of promises. - * @returns {Promise} Returns a single promise that will be resolved with an array/hash of values, - * each value corresponding to the promise at the same index/key in the `promises` array/hash. If any of - * the promises is resolved with a rejection, this resulting promise will be resolved with the - * same rejection. - */ - function all(promises) { - var deferred = defer(), - counter = 0, - results = isArray(promises) ? [] : {}; - - forEach(promises, function(promise, key) { - counter++; - ref(promise).then(function(value) { - if (results.hasOwnProperty(key)) return; - results[key] = value; - if (!(--counter)) deferred.resolve(results); - }, function(reason) { - if (results.hasOwnProperty(key)) return; - deferred.reject(reason); - }); - }); - - if (counter === 0) { - deferred.resolve(results); - } - - return deferred.promise; - } - - return { - defer: defer, - reject: reject, - when: when, - all: all - }; -} - -/** - * @ngdoc object - * @name ng.$routeProvider - * @function - * - * @description - * - * Used for configuring routes. See {@link ng.$route $route} for an example. - */ -function $RouteProvider(){ - var routes = {}; - - /** - * @ngdoc method - * @name ng.$routeProvider#when - * @methodOf ng.$routeProvider - * - * @param {string} path Route path (matched against `$location.path`). If `$location.path` - * contains redundant trailing slash or is missing one, the route will still match and the - * `$location.path` will be updated to add or drop the trailing slash to exactly match the - * route definition. - * - * * `path` can contain named groups starting with a colon (`:name`). All characters up - * to the next slash are matched and stored in `$routeParams` under the given `name` - * when the route matches. - * * `path` can contain named groups starting with a star (`*name`). All characters are - * eagerly stored in `$routeParams` under the given `name` when the route matches. - * - * For example, routes like `/color/:color/largecode/*largecode/edit` will match - * `/color/brown/largecode/code/with/slashs/edit` and extract: - * - * * `color: brown` - * * `largecode: code/with/slashs`. - * - * - * @param {Object} route Mapping information to be assigned to `$route.current` on route - * match. - * - * Object properties: - * - * - `controller` – `{(string|function()=}` – Controller fn that should be associated with newly - * created scope or the name of a {@link angular.Module#controller registered controller} - * if passed as a string. - * - `controllerAs` – `{string=}` – A controller alias name. If present the controller will be - * published to scope under the `controllerAs` name. - * - `template` – `{string=|function()=}` – html template as a string or function that returns - * an html template as a string which should be used by {@link ng.directive:ngView ngView} or - * {@link ng.directive:ngInclude ngInclude} directives. - * This property takes precedence over `templateUrl`. - * - * If `template` is a function, it will be called with the following parameters: - * - * - `{Array.}` - route parameters extracted from the current - * `$location.path()` by applying the current route - * - * - `templateUrl` – `{string=|function()=}` – path or function that returns a path to an html - * template that should be used by {@link ng.directive:ngView ngView}. - * - * If `templateUrl` is a function, it will be called with the following parameters: - * - * - `{Array.}` - route parameters extracted from the current - * `$location.path()` by applying the current route - * - * - `resolve` - `{Object.=}` - An optional map of dependencies which should - * be injected into the controller. If any of these dependencies are promises, they will be - * resolved and converted to a value before the controller is instantiated and the - * `$routeChangeSuccess` event is fired. The map object is: - * - * - `key` – `{string}`: a name of a dependency to be injected into the controller. - * - `factory` - `{string|function}`: If `string` then it is an alias for a service. - * Otherwise if function, then it is {@link api/AUTO.$injector#invoke injected} - * and the return value is treated as the dependency. If the result is a promise, it is resolved - * before its value is injected into the controller. - * - * - `redirectTo` – {(string|function())=} – value to update - * {@link ng.$location $location} path with and trigger route redirection. - * - * If `redirectTo` is a function, it will be called with the following parameters: - * - * - `{Object.}` - route parameters extracted from the current - * `$location.path()` by applying the current route templateUrl. - * - `{string}` - current `$location.path()` - * - `{Object}` - current `$location.search()` - * - * The custom `redirectTo` function is expected to return a string which will be used - * to update `$location.path()` and `$location.search()`. - * - * - `[reloadOnSearch=true]` - {boolean=} - reload route when only $location.search() - * changes. - * - * If the option is set to `false` and url in the browser changes, then - * `$routeUpdate` event is broadcasted on the root scope. - * - * - `[caseInsensitiveMatch=false]` - {boolean=} - match routes without being case sensitive - * - * If the option is set to `true`, then the particular route can be matched without being - * case sensitive - * - * @returns {Object} self - * - * @description - * Adds a new route definition to the `$route` service. - */ - this.when = function(path, route) { - routes[path] = extend({reloadOnSearch: true, caseInsensitiveMatch: false}, route); - - // create redirection for trailing slashes - if (path) { - var redirectPath = (path[path.length-1] == '/') - ? path.substr(0, path.length-1) - : path +'/'; - - routes[redirectPath] = {redirectTo: path}; - } - - return this; - }; - - /** - * @ngdoc method - * @name ng.$routeProvider#otherwise - * @methodOf ng.$routeProvider - * - * @description - * Sets route definition that will be used on route change when no other route definition - * is matched. - * - * @param {Object} params Mapping information to be assigned to `$route.current`. - * @returns {Object} self - */ - this.otherwise = function(params) { - this.when(null, params); - return this; - }; - - - this.$get = ['$rootScope', '$location', '$routeParams', '$q', '$injector', '$http', '$templateCache', - function( $rootScope, $location, $routeParams, $q, $injector, $http, $templateCache) { - - /** - * @ngdoc object - * @name ng.$route - * @requires $location - * @requires $routeParams - * - * @property {Object} current Reference to the current route definition. - * The route definition contains: - * - * - `controller`: The controller constructor as define in route definition. - * - `locals`: A map of locals which is used by {@link ng.$controller $controller} service for - * controller instantiation. The `locals` contain - * the resolved values of the `resolve` map. Additionally the `locals` also contain: - * - * - `$scope` - The current route scope. - * - `$template` - The current route template HTML. - * - * @property {Array.} routes Array of all configured routes. - * - * @description - * Is used for deep-linking URLs to controllers and views (HTML partials). - * It watches `$location.url()` and tries to map the path to an existing route definition. - * - * You can define routes through {@link ng.$routeProvider $routeProvider}'s API. - * - * The `$route` service is typically used in conjunction with {@link ng.directive:ngView ngView} - * directive and the {@link ng.$routeParams $routeParams} service. - * - * @example - This example shows how changing the URL hash causes the `$route` to match a route against the - URL, and the `ngView` pulls in the partial. - - Note that this example is using {@link ng.directive:script inlined templates} - to get it working on jsfiddle as well. - - - -
                - Choose: - Moby | - Moby: Ch1 | - Gatsby | - Gatsby: Ch4 | - Scarlet Letter
                - -
                -
                - -
                $location.path() = {{$location.path()}}
                -
                $route.current.templateUrl = {{$route.current.templateUrl}}
                -
                $route.current.params = {{$route.current.params}}
                -
                $route.current.scope.name = {{$route.current.scope.name}}
                -
                $routeParams = {{$routeParams}}
                -
                -
                - - - controller: {{name}}
                - Book Id: {{params.bookId}}
                -
                - - - controller: {{name}}
                - Book Id: {{params.bookId}}
                - Chapter Id: {{params.chapterId}} -
                - - - angular.module('ngView', [], function($routeProvider, $locationProvider) { - $routeProvider.when('/Book/:bookId', { - templateUrl: 'book.html', - controller: BookCntl, - resolve: { - // I will cause a 1 second delay - delay: function($q, $timeout) { - var delay = $q.defer(); - $timeout(delay.resolve, 1000); - return delay.promise; - } - } - }); - $routeProvider.when('/Book/:bookId/ch/:chapterId', { - templateUrl: 'chapter.html', - controller: ChapterCntl - }); - - // configure html5 to get links working on jsfiddle - $locationProvider.html5Mode(true); - }); - - function MainCntl($scope, $route, $routeParams, $location) { - $scope.$route = $route; - $scope.$location = $location; - $scope.$routeParams = $routeParams; - } - - function BookCntl($scope, $routeParams) { - $scope.name = "BookCntl"; - $scope.params = $routeParams; - } - - function ChapterCntl($scope, $routeParams) { - $scope.name = "ChapterCntl"; - $scope.params = $routeParams; - } - - - - it('should load and compile correct template', function() { - element('a:contains("Moby: Ch1")').click(); - var content = element('.doc-example-live [ng-view]').text(); - expect(content).toMatch(/controller\: ChapterCntl/); - expect(content).toMatch(/Book Id\: Moby/); - expect(content).toMatch(/Chapter Id\: 1/); - - element('a:contains("Scarlet")').click(); - sleep(2); // promises are not part of scenario waiting - content = element('.doc-example-live [ng-view]').text(); - expect(content).toMatch(/controller\: BookCntl/); - expect(content).toMatch(/Book Id\: Scarlet/); - }); - -
                - */ - - /** - * @ngdoc event - * @name ng.$route#$routeChangeStart - * @eventOf ng.$route - * @eventType broadcast on root scope - * @description - * Broadcasted before a route change. At this point the route services starts - * resolving all of the dependencies needed for the route change to occurs. - * Typically this involves fetching the view template as well as any dependencies - * defined in `resolve` route property. Once all of the dependencies are resolved - * `$routeChangeSuccess` is fired. - * - * @param {Route} next Future route information. - * @param {Route} current Current route information. - */ - - /** - * @ngdoc event - * @name ng.$route#$routeChangeSuccess - * @eventOf ng.$route - * @eventType broadcast on root scope - * @description - * Broadcasted after a route dependencies are resolved. - * {@link ng.directive:ngView ngView} listens for the directive - * to instantiate the controller and render the view. - * - * @param {Object} angularEvent Synthetic event object. - * @param {Route} current Current route information. - * @param {Route|Undefined} previous Previous route information, or undefined if current is first route entered. - */ - - /** - * @ngdoc event - * @name ng.$route#$routeChangeError - * @eventOf ng.$route - * @eventType broadcast on root scope - * @description - * Broadcasted if any of the resolve promises are rejected. - * - * @param {Route} current Current route information. - * @param {Route} previous Previous route information. - * @param {Route} rejection Rejection of the promise. Usually the error of the failed promise. - */ - - /** - * @ngdoc event - * @name ng.$route#$routeUpdate - * @eventOf ng.$route - * @eventType broadcast on root scope - * @description - * - * The `reloadOnSearch` property has been set to false, and we are reusing the same - * instance of the Controller. - */ - - var forceReload = false, - $route = { - routes: routes, - - /** - * @ngdoc method - * @name ng.$route#reload - * @methodOf ng.$route - * - * @description - * Causes `$route` service to reload the current route even if - * {@link ng.$location $location} hasn't changed. - * - * As a result of that, {@link ng.directive:ngView ngView} - * creates new scope, reinstantiates the controller. - */ - reload: function() { - forceReload = true; - $rootScope.$evalAsync(updateRoute); - } - }; - - $rootScope.$on('$locationChangeSuccess', updateRoute); - - return $route; - - ///////////////////////////////////////////////////// - - /** - * @param on {string} current url - * @param when {string} route when template to match the url against - * @param whenProperties {Object} properties to define when's matching behavior - * @return {?Object} - */ - function switchRouteMatcher(on, when, whenProperties) { - // TODO(i): this code is convoluted and inefficient, we should construct the route matching - // regex only once and then reuse it - - // Escape regexp special characters. - when = '^' + when.replace(/[-\/\\^$:*+?.()|[\]{}]/g, "\\$&") + '$'; - - var regex = '', - params = [], - dst = {}; - - var re = /\\([:*])(\w+)/g, - paramMatch, - lastMatchedIndex = 0; - - while ((paramMatch = re.exec(when)) !== null) { - // Find each :param in `when` and replace it with a capturing group. - // Append all other sections of when unchanged. - regex += when.slice(lastMatchedIndex, paramMatch.index); - switch(paramMatch[1]) { - case ':': - regex += '([^\\/]*)'; - break; - case '*': - regex += '(.*)'; - break; - } - params.push(paramMatch[2]); - lastMatchedIndex = re.lastIndex; - } - // Append trailing path part. - regex += when.substr(lastMatchedIndex); - - var match = on.match(new RegExp(regex, whenProperties.caseInsensitiveMatch ? 'i' : '')); - if (match) { - forEach(params, function(name, index) { - dst[name] = match[index + 1]; - }); - } - return match ? dst : null; - } - - function updateRoute() { - var next = parseRoute(), - last = $route.current; - - if (next && last && next.$$route === last.$$route - && equals(next.pathParams, last.pathParams) && !next.reloadOnSearch && !forceReload) { - last.params = next.params; - copy(last.params, $routeParams); - $rootScope.$broadcast('$routeUpdate', last); - } else if (next || last) { - forceReload = false; - $rootScope.$broadcast('$routeChangeStart', next, last); - $route.current = next; - if (next) { - if (next.redirectTo) { - if (isString(next.redirectTo)) { - $location.path(interpolate(next.redirectTo, next.params)).search(next.params) - .replace(); - } else { - $location.url(next.redirectTo(next.pathParams, $location.path(), $location.search())) - .replace(); - } - } - } - - $q.when(next). - then(function() { - if (next) { - var locals = extend({}, next.resolve), - template; - - forEach(locals, function(value, key) { - locals[key] = isString(value) ? $injector.get(value) : $injector.invoke(value); - }); - - if (isDefined(template = next.template)) { - if (isFunction(template)) { - template = template(next.params); - } - } else if (isDefined(template = next.templateUrl)) { - if (isFunction(template)) { - template = template(next.params); - } - if (isDefined(template)) { - next.loadedTemplateUrl = template; - template = $http.get(template, {cache: $templateCache}). - then(function(response) { return response.data; }); - } - } - if (isDefined(template)) { - locals['$template'] = template; - } - return $q.all(locals); - } - }). - // after route change - then(function(locals) { - if (next == $route.current) { - if (next) { - next.locals = locals; - copy(next.params, $routeParams); - } - $rootScope.$broadcast('$routeChangeSuccess', next, last); - } - }, function(error) { - if (next == $route.current) { - $rootScope.$broadcast('$routeChangeError', next, last, error); - } - }); - } - } - - - /** - * @returns the current active route, by matching it against the URL - */ - function parseRoute() { - // Match a route - var params, match; - forEach(routes, function(route, path) { - if (!match && (params = switchRouteMatcher($location.path(), path, route))) { - match = inherit(route, { - params: extend({}, $location.search(), params), - pathParams: params}); - match.$$route = route; - } - }); - // No route matched; fallback to "otherwise" route - return match || routes[null] && inherit(routes[null], {params: {}, pathParams:{}}); - } - - /** - * @returns interpolation of the redirect path with the parameters - */ - function interpolate(string, params) { - var result = []; - forEach((string||'').split(':'), function(segment, i) { - if (i == 0) { - result.push(segment); - } else { - var segmentMatch = segment.match(/(\w+)(.*)/); - var key = segmentMatch[1]; - result.push(params[key]); - result.push(segmentMatch[2] || ''); - delete params[key]; - } - }); - return result.join(''); - } - }]; -} - -/** - * @ngdoc object - * @name ng.$routeParams - * @requires $route - * - * @description - * Current set of route parameters. The route parameters are a combination of the - * {@link ng.$location $location} `search()`, and `path()`. The `path` parameters - * are extracted when the {@link ng.$route $route} path is matched. - * - * In case of parameter name collision, `path` params take precedence over `search` params. - * - * The service guarantees that the identity of the `$routeParams` object will remain unchanged - * (but its properties will likely change) even when a route change occurs. - * - * @example - *
                - *  // Given:
                - *  // URL: http://server.com/index.html#/Chapter/1/Section/2?search=moby
                - *  // Route: /Chapter/:chapterId/Section/:sectionId
                - *  //
                - *  // Then
                - *  $routeParams ==> {chapterId:1, sectionId:2, search:'moby'}
                - * 
                - */ -function $RouteParamsProvider() { - this.$get = valueFn({}); -} - -/** - * DESIGN NOTES - * - * The design decisions behind the scope are heavily favored for speed and memory consumption. - * - * The typical use of scope is to watch the expressions, which most of the time return the same - * value as last time so we optimize the operation. - * - * Closures construction is expensive in terms of speed as well as memory: - * - No closures, instead use prototypical inheritance for API - * - Internal state needs to be stored on scope directly, which means that private state is - * exposed as $$____ properties - * - * Loop operations are optimized by using while(count--) { ... } - * - this means that in order to keep the same order of execution as addition we have to add - * items to the array at the beginning (shift) instead of at the end (push) - * - * Child scopes are created and removed often - * - Using an array would be slow since inserts in middle are expensive so we use linked list - * - * There are few watches then a lot of observers. This is why you don't want the observer to be - * implemented in the same way as watch. Watch requires return of initialization function which - * are expensive to construct. - */ - - -/** - * @ngdoc object - * @name ng.$rootScopeProvider - * @description - * - * Provider for the $rootScope service. - */ - -/** - * @ngdoc function - * @name ng.$rootScopeProvider#digestTtl - * @methodOf ng.$rootScopeProvider - * @description - * - * Sets the number of digest iterations the scope should attempt to execute before giving up and - * assuming that the model is unstable. - * - * The current default is 10 iterations. - * - * @param {number} limit The number of digest iterations. - */ - - -/** - * @ngdoc object - * @name ng.$rootScope - * @description - * - * Every application has a single root {@link ng.$rootScope.Scope scope}. - * All other scopes are child scopes of the root scope. Scopes provide mechanism for watching the model and provide - * event processing life-cycle. See {@link guide/scope developer guide on scopes}. - */ -function $RootScopeProvider(){ - var TTL = 10; - - this.digestTtl = function(value) { - if (arguments.length) { - TTL = value; - } - return TTL; - }; - - this.$get = ['$injector', '$exceptionHandler', '$parse', - function( $injector, $exceptionHandler, $parse) { - - /** - * @ngdoc function - * @name ng.$rootScope.Scope - * - * @description - * A root scope can be retrieved using the {@link ng.$rootScope $rootScope} key from the - * {@link AUTO.$injector $injector}. Child scopes are created using the - * {@link ng.$rootScope.Scope#$new $new()} method. (Most scopes are created automatically when - * compiled HTML template is executed.) - * - * Here is a simple scope snippet to show how you can interact with the scope. - *
                -     * 
                -     * 
                - * - * # Inheritance - * A scope can inherit from a parent scope, as in this example: - *
                -         var parent = $rootScope;
                -         var child = parent.$new();
                -
                -         parent.salutation = "Hello";
                -         child.name = "World";
                -         expect(child.salutation).toEqual('Hello');
                -
                -         child.salutation = "Welcome";
                -         expect(child.salutation).toEqual('Welcome');
                -         expect(parent.salutation).toEqual('Hello');
                -     * 
                - * - * - * @param {Object.=} providers Map of service factory which need to be provided - * for the current scope. Defaults to {@link ng}. - * @param {Object.=} instanceCache Provides pre-instantiated services which should - * append/override services provided by `providers`. This is handy when unit-testing and having - * the need to override a default service. - * @returns {Object} Newly created scope. - * - */ - function Scope() { - this.$id = nextUid(); - this.$$phase = this.$parent = this.$$watchers = - this.$$nextSibling = this.$$prevSibling = - this.$$childHead = this.$$childTail = null; - this['this'] = this.$root = this; - this.$$destroyed = false; - this.$$asyncQueue = []; - this.$$listeners = {}; - this.$$isolateBindings = {}; - } - - /** - * @ngdoc property - * @name ng.$rootScope.Scope#$id - * @propertyOf ng.$rootScope.Scope - * @returns {number} Unique scope ID (monotonically increasing alphanumeric sequence) useful for - * debugging. - */ - - - Scope.prototype = { - /** - * @ngdoc function - * @name ng.$rootScope.Scope#$new - * @methodOf ng.$rootScope.Scope - * @function - * - * @description - * Creates a new child {@link ng.$rootScope.Scope scope}. - * - * The parent scope will propagate the {@link ng.$rootScope.Scope#$digest $digest()} and - * {@link ng.$rootScope.Scope#$digest $digest()} events. The scope can be removed from the scope - * hierarchy using {@link ng.$rootScope.Scope#$destroy $destroy()}. - * - * {@link ng.$rootScope.Scope#$destroy $destroy()} must be called on a scope when it is desired for - * the scope and its child scopes to be permanently detached from the parent and thus stop - * participating in model change detection and listener notification by invoking. - * - * @param {boolean} isolate if true then the scope does not prototypically inherit from the - * parent scope. The scope is isolated, as it can not see parent scope properties. - * When creating widgets it is useful for the widget to not accidentally read parent - * state. - * - * @returns {Object} The newly created child scope. - * - */ - $new: function(isolate) { - var Child, - child; - - if (isFunction(isolate)) { - // TODO: remove at some point - throw Error('API-CHANGE: Use $controller to instantiate controllers.'); - } - if (isolate) { - child = new Scope(); - child.$root = this.$root; - } else { - Child = function() {}; // should be anonymous; This is so that when the minifier munges - // the name it does not become random set of chars. These will then show up as class - // name in the debugger. - Child.prototype = this; - child = new Child(); - child.$id = nextUid(); - } - child['this'] = child; - child.$$listeners = {}; - child.$parent = this; - child.$$watchers = child.$$nextSibling = child.$$childHead = child.$$childTail = null; - child.$$prevSibling = this.$$childTail; - if (this.$$childHead) { - this.$$childTail.$$nextSibling = child; - this.$$childTail = child; - } else { - this.$$childHead = this.$$childTail = child; - } - return child; - }, - - /** - * @ngdoc function - * @name ng.$rootScope.Scope#$watch - * @methodOf ng.$rootScope.Scope - * @function - * - * @description - * Registers a `listener` callback to be executed whenever the `watchExpression` changes. - * - * - The `watchExpression` is called on every call to {@link ng.$rootScope.Scope#$digest $digest()} and - * should return the value which will be watched. (Since {@link ng.$rootScope.Scope#$digest $digest()} - * reruns when it detects changes the `watchExpression` can execute multiple times per - * {@link ng.$rootScope.Scope#$digest $digest()} and should be idempotent.) - * - The `listener` is called only when the value from the current `watchExpression` and the - * previous call to `watchExpression` are not equal (with the exception of the initial run, - * see below). The inequality is determined according to - * {@link angular.equals} function. To save the value of the object for later comparison, the - * {@link angular.copy} function is used. It also means that watching complex options will - * have adverse memory and performance implications. - * - The watch `listener` may change the model, which may trigger other `listener`s to fire. This - * is achieved by rerunning the watchers until no changes are detected. The rerun iteration - * limit is 10 to prevent an infinite loop deadlock. - * - * - * If you want to be notified whenever {@link ng.$rootScope.Scope#$digest $digest} is called, - * you can register a `watchExpression` function with no `listener`. (Since `watchExpression` - * can execute multiple times per {@link ng.$rootScope.Scope#$digest $digest} cycle when a change is - * detected, be prepared for multiple calls to your listener.) - * - * After a watcher is registered with the scope, the `listener` fn is called asynchronously - * (via {@link ng.$rootScope.Scope#$evalAsync $evalAsync}) to initialize the - * watcher. In rare cases, this is undesirable because the listener is called when the result - * of `watchExpression` didn't change. To detect this scenario within the `listener` fn, you - * can compare the `newVal` and `oldVal`. If these two values are identical (`===`) then the - * listener was called due to initialization. - * - * - * # Example - *
                -           // let's assume that scope was dependency injected as the $rootScope
                -           var scope = $rootScope;
                -           scope.name = 'misko';
                -           scope.counter = 0;
                -
                -           expect(scope.counter).toEqual(0);
                -           scope.$watch('name', function(newValue, oldValue) { scope.counter = scope.counter + 1; });
                -           expect(scope.counter).toEqual(0);
                -
                -           scope.$digest();
                -           // no variable change
                -           expect(scope.counter).toEqual(0);
                -
                -           scope.name = 'adam';
                -           scope.$digest();
                -           expect(scope.counter).toEqual(1);
                -       * 
                - * - * - * - * @param {(function()|string)} watchExpression Expression that is evaluated on each - * {@link ng.$rootScope.Scope#$digest $digest} cycle. A change in the return value triggers a - * call to the `listener`. - * - * - `string`: Evaluated as {@link guide/expression expression} - * - `function(scope)`: called with current `scope` as a parameter. - * @param {(function()|string)=} listener Callback called whenever the return value of - * the `watchExpression` changes. - * - * - `string`: Evaluated as {@link guide/expression expression} - * - `function(newValue, oldValue, scope)`: called with current and previous values as parameters. - * - * @param {boolean=} objectEquality Compare object for equality rather than for reference. - * @returns {function()} Returns a deregistration function for this listener. - */ - $watch: function(watchExp, listener, objectEquality) { - var scope = this, - get = compileToFn(watchExp, 'watch'), - array = scope.$$watchers, - watcher = { - fn: listener, - last: initWatchVal, - get: get, - exp: watchExp, - eq: !!objectEquality - }; - - // in the case user pass string, we need to compile it, do we really need this ? - if (!isFunction(listener)) { - var listenFn = compileToFn(listener || noop, 'listener'); - watcher.fn = function(newVal, oldVal, scope) {listenFn(scope);}; - } - - if (typeof watchExp == 'string' && get.constant) { - var originalFn = watcher.fn; - watcher.fn = function(newVal, oldVal, scope) { - originalFn.call(this, newVal, oldVal, scope); - arrayRemove(array, watcher); - }; - } - - if (!array) { - array = scope.$$watchers = []; - } - // we use unshift since we use a while loop in $digest for speed. - // the while loop reads in reverse order. - array.unshift(watcher); - - return function() { - arrayRemove(array, watcher); - }; - }, - - - /** - * @ngdoc function - * @name ng.$rootScope.Scope#$watchCollection - * @methodOf ng.$rootScope.Scope - * @function - * - * @description - * Shallow watches the properties of an object and fires whenever any of the properties change - * (for arrays this implies watching the array items, for object maps this implies watching the properties). - * If a change is detected the `listener` callback is fired. - * - * - The `obj` collection is observed via standard $watch operation and is examined on every call to $digest() to - * see if any items have been added, removed, or moved. - * - The `listener` is called whenever anything within the `obj` has changed. Examples include adding new items - * into the object or array, removing and moving items around. - * - * - * # Example - *
                -          $scope.names = ['igor', 'matias', 'misko', 'james'];
                -          $scope.dataCount = 4;
                -
                -          $scope.$watchCollection('names', function(newNames, oldNames) {
                -            $scope.dataCount = newNames.length;
                -          });
                -
                -          expect($scope.dataCount).toEqual(4);
                -          $scope.$digest();
                -
                -          //still at 4 ... no changes
                -          expect($scope.dataCount).toEqual(4);
                -
                -          $scope.names.pop();
                -          $scope.$digest();
                -
                -          //now there's been a change
                -          expect($scope.dataCount).toEqual(3);
                -       * 
                - * - * - * @param {string|Function(scope)} obj Evaluated as {@link guide/expression expression}. The expression value - * should evaluate to an object or an array which is observed on each - * {@link ng.$rootScope.Scope#$digest $digest} cycle. Any shallow change within the collection will trigger - * a call to the `listener`. - * - * @param {function(newCollection, oldCollection, scope)} listener a callback function that is fired with both - * the `newCollection` and `oldCollection` as parameters. - * The `newCollection` object is the newly modified data obtained from the `obj` expression and the - * `oldCollection` object is a copy of the former collection data. - * The `scope` refers to the current scope. - * - * @returns {function()} Returns a de-registration function for this listener. When the de-registration function is executed - * then the internal watch operation is terminated. - */ - $watchCollection: function(obj, listener) { - var self = this; - var oldValue; - var newValue; - var changeDetected = 0; - var objGetter = $parse(obj); - var internalArray = []; - var internalObject = {}; - var oldLength = 0; - - function $watchCollectionWatch() { - newValue = objGetter(self); - var newLength, key; - - if (!isObject(newValue)) { - if (oldValue !== newValue) { - oldValue = newValue; - changeDetected++; - } - } else if (isArrayLike(newValue)) { - if (oldValue !== internalArray) { - // we are transitioning from something which was not an array into array. - oldValue = internalArray; - oldLength = oldValue.length = 0; - changeDetected++; - } - - newLength = newValue.length; - - if (oldLength !== newLength) { - // if lengths do not match we need to trigger change notification - changeDetected++; - oldValue.length = oldLength = newLength; - } - // copy the items to oldValue and look for changes. - for (var i = 0; i < newLength; i++) { - if (oldValue[i] !== newValue[i]) { - changeDetected++; - oldValue[i] = newValue[i]; - } - } - } else { - if (oldValue !== internalObject) { - // we are transitioning from something which was not an object into object. - oldValue = internalObject = {}; - oldLength = 0; - changeDetected++; - } - // copy the items to oldValue and look for changes. - newLength = 0; - for (key in newValue) { - if (newValue.hasOwnProperty(key)) { - newLength++; - if (oldValue.hasOwnProperty(key)) { - if (oldValue[key] !== newValue[key]) { - changeDetected++; - oldValue[key] = newValue[key]; - } - } else { - oldLength++; - oldValue[key] = newValue[key]; - changeDetected++; - } - } - } - if (oldLength > newLength) { - // we used to have more keys, need to find them and destroy them. - changeDetected++; - for(key in oldValue) { - if (oldValue.hasOwnProperty(key) && !newValue.hasOwnProperty(key)) { - oldLength--; - delete oldValue[key]; - } - } - } - } - return changeDetected; - } - - function $watchCollectionAction() { - listener(newValue, oldValue, self); - } - - return this.$watch($watchCollectionWatch, $watchCollectionAction); - }, - - /** - * @ngdoc function - * @name ng.$rootScope.Scope#$digest - * @methodOf ng.$rootScope.Scope - * @function - * - * @description - * Processes all of the {@link ng.$rootScope.Scope#$watch watchers} of the current scope and its children. - * Because a {@link ng.$rootScope.Scope#$watch watcher}'s listener can change the model, the - * `$digest()` keeps calling the {@link ng.$rootScope.Scope#$watch watchers} until no more listeners are - * firing. This means that it is possible to get into an infinite loop. This function will throw - * `'Maximum iteration limit exceeded.'` if the number of iterations exceeds 10. - * - * Usually you don't call `$digest()` directly in - * {@link ng.directive:ngController controllers} or in - * {@link ng.$compileProvider#directive directives}. - * Instead a call to {@link ng.$rootScope.Scope#$apply $apply()} (typically from within a - * {@link ng.$compileProvider#directive directives}) will force a `$digest()`. - * - * If you want to be notified whenever `$digest()` is called, - * you can register a `watchExpression` function with {@link ng.$rootScope.Scope#$watch $watch()} - * with no `listener`. - * - * You may have a need to call `$digest()` from within unit-tests, to simulate the scope - * life-cycle. - * - * # Example - *
                -           var scope = ...;
                -           scope.name = 'misko';
                -           scope.counter = 0;
                -
                -           expect(scope.counter).toEqual(0);
                -           scope.$watch('name', function(newValue, oldValue) {
                -             scope.counter = scope.counter + 1;
                -           });
                -           expect(scope.counter).toEqual(0);
                -
                -           scope.$digest();
                -           // no variable change
                -           expect(scope.counter).toEqual(0);
                -
                -           scope.name = 'adam';
                -           scope.$digest();
                -           expect(scope.counter).toEqual(1);
                -       * 
                - * - */ - $digest: function() { - var watch, value, last, - watchers, - asyncQueue = this.$$asyncQueue, - length, - dirty, ttl = TTL, - next, current, target = this, - watchLog = [], - logIdx, logMsg; - - beginPhase('$digest'); - - do { // "while dirty" loop - dirty = false; - current = target; - - while(asyncQueue.length) { - try { - current.$eval(asyncQueue.shift()); - } catch (e) { - $exceptionHandler(e); - } - } - - do { // "traverse the scopes" loop - if ((watchers = current.$$watchers)) { - // process our watches - length = watchers.length; - while (length--) { - try { - watch = watchers[length]; - // Most common watches are on primitives, in which case we can short - // circuit it with === operator, only when === fails do we use .equals - if ((value = watch.get(current)) !== (last = watch.last) && - !(watch.eq - ? equals(value, last) - : (typeof value == 'number' && typeof last == 'number' - && isNaN(value) && isNaN(last)))) { - dirty = true; - watch.last = watch.eq ? copy(value) : value; - watch.fn(value, ((last === initWatchVal) ? value : last), current); - if (ttl < 5) { - logIdx = 4 - ttl; - if (!watchLog[logIdx]) watchLog[logIdx] = []; - logMsg = (isFunction(watch.exp)) - ? 'fn: ' + (watch.exp.name || watch.exp.toString()) - : watch.exp; - logMsg += '; newVal: ' + toJson(value) + '; oldVal: ' + toJson(last); - watchLog[logIdx].push(logMsg); - } - } - } catch (e) { - $exceptionHandler(e); - } - } - } - - // Insanity Warning: scope depth-first traversal - // yes, this code is a bit crazy, but it works and we have tests to prove it! - // this piece should be kept in sync with the traversal in $broadcast - if (!(next = (current.$$childHead || (current !== target && current.$$nextSibling)))) { - while(current !== target && !(next = current.$$nextSibling)) { - current = current.$parent; - } - } - } while ((current = next)); - - if(dirty && !(ttl--)) { - clearPhase(); - throw Error(TTL + ' $digest() iterations reached. Aborting!\n' + - 'Watchers fired in the last 5 iterations: ' + toJson(watchLog)); - } - } while (dirty || asyncQueue.length); - - clearPhase(); - }, - - - /** - * @ngdoc event - * @name ng.$rootScope.Scope#$destroy - * @eventOf ng.$rootScope.Scope - * @eventType broadcast on scope being destroyed - * - * @description - * Broadcasted when a scope and its children are being destroyed. - */ - - /** - * @ngdoc function - * @name ng.$rootScope.Scope#$destroy - * @methodOf ng.$rootScope.Scope - * @function - * - * @description - * Removes the current scope (and all of its children) from the parent scope. Removal implies - * that calls to {@link ng.$rootScope.Scope#$digest $digest()} will no longer - * propagate to the current scope and its children. Removal also implies that the current - * scope is eligible for garbage collection. - * - * The `$destroy()` is usually used by directives such as - * {@link ng.directive:ngRepeat ngRepeat} for managing the - * unrolling of the loop. - * - * Just before a scope is destroyed a `$destroy` event is broadcasted on this scope. - * Application code can register a `$destroy` event handler that will give it chance to - * perform any necessary cleanup. - */ - $destroy: function() { - // we can't destroy the root scope or a scope that has been already destroyed - if ($rootScope == this || this.$$destroyed) return; - var parent = this.$parent; - - this.$broadcast('$destroy'); - this.$$destroyed = true; - - if (parent.$$childHead == this) parent.$$childHead = this.$$nextSibling; - if (parent.$$childTail == this) parent.$$childTail = this.$$prevSibling; - if (this.$$prevSibling) this.$$prevSibling.$$nextSibling = this.$$nextSibling; - if (this.$$nextSibling) this.$$nextSibling.$$prevSibling = this.$$prevSibling; - - // This is bogus code that works around Chrome's GC leak - // see: https://github.com/angular/angular.js/issues/1313#issuecomment-10378451 - this.$parent = this.$$nextSibling = this.$$prevSibling = this.$$childHead = - this.$$childTail = null; - }, - - /** - * @ngdoc function - * @name ng.$rootScope.Scope#$eval - * @methodOf ng.$rootScope.Scope - * @function - * - * @description - * Executes the `expression` on the current scope returning the result. Any exceptions in the - * expression are propagated (uncaught). This is useful when evaluating Angular expressions. - * - * # Example - *
                -           var scope = ng.$rootScope.Scope();
                -           scope.a = 1;
                -           scope.b = 2;
                -
                -           expect(scope.$eval('a+b')).toEqual(3);
                -           expect(scope.$eval(function(scope){ return scope.a + scope.b; })).toEqual(3);
                -       * 
                - * - * @param {(string|function())=} expression An angular expression to be executed. - * - * - `string`: execute using the rules as defined in {@link guide/expression expression}. - * - `function(scope)`: execute the function with the current `scope` parameter. - * - * @returns {*} The result of evaluating the expression. - */ - $eval: function(expr, locals) { - return $parse(expr)(this, locals); - }, - - /** - * @ngdoc function - * @name ng.$rootScope.Scope#$evalAsync - * @methodOf ng.$rootScope.Scope - * @function - * - * @description - * Executes the expression on the current scope at a later point in time. - * - * The `$evalAsync` makes no guarantees as to when the `expression` will be executed, only that: - * - * - it will execute in the current script execution context (before any DOM rendering). - * - at least one {@link ng.$rootScope.Scope#$digest $digest cycle} will be performed after - * `expression` execution. - * - * Any exceptions from the execution of the expression are forwarded to the - * {@link ng.$exceptionHandler $exceptionHandler} service. - * - * @param {(string|function())=} expression An angular expression to be executed. - * - * - `string`: execute using the rules as defined in {@link guide/expression expression}. - * - `function(scope)`: execute the function with the current `scope` parameter. - * - */ - $evalAsync: function(expr) { - this.$$asyncQueue.push(expr); - }, - - /** - * @ngdoc function - * @name ng.$rootScope.Scope#$apply - * @methodOf ng.$rootScope.Scope - * @function - * - * @description - * `$apply()` is used to execute an expression in angular from outside of the angular framework. - * (For example from browser DOM events, setTimeout, XHR or third party libraries). - * Because we are calling into the angular framework we need to perform proper scope life-cycle - * of {@link ng.$exceptionHandler exception handling}, - * {@link ng.$rootScope.Scope#$digest executing watches}. - * - * ## Life cycle - * - * # Pseudo-Code of `$apply()` - *
                -           function $apply(expr) {
                -             try {
                -               return $eval(expr);
                -             } catch (e) {
                -               $exceptionHandler(e);
                -             } finally {
                -               $root.$digest();
                -             }
                -           }
                -       * 
                - * - * - * Scope's `$apply()` method transitions through the following stages: - * - * 1. The {@link guide/expression expression} is executed using the - * {@link ng.$rootScope.Scope#$eval $eval()} method. - * 2. Any exceptions from the execution of the expression are forwarded to the - * {@link ng.$exceptionHandler $exceptionHandler} service. - * 3. The {@link ng.$rootScope.Scope#$watch watch} listeners are fired immediately after the expression - * was executed using the {@link ng.$rootScope.Scope#$digest $digest()} method. - * - * - * @param {(string|function())=} exp An angular expression to be executed. - * - * - `string`: execute using the rules as defined in {@link guide/expression expression}. - * - `function(scope)`: execute the function with current `scope` parameter. - * - * @returns {*} The result of evaluating the expression. - */ - $apply: function(expr) { - try { - beginPhase('$apply'); - return this.$eval(expr); - } catch (e) { - $exceptionHandler(e); - } finally { - clearPhase(); - try { - $rootScope.$digest(); - } catch (e) { - $exceptionHandler(e); - throw e; - } - } - }, - - /** - * @ngdoc function - * @name ng.$rootScope.Scope#$on - * @methodOf ng.$rootScope.Scope - * @function - * - * @description - * Listens on events of a given type. See {@link ng.$rootScope.Scope#$emit $emit} for discussion of - * event life cycle. - * - * The event listener function format is: `function(event, args...)`. The `event` object - * passed into the listener has the following attributes: - * - * - `targetScope` - `{Scope}`: the scope on which the event was `$emit`-ed or `$broadcast`-ed. - * - `currentScope` - `{Scope}`: the current scope which is handling the event. - * - `name` - `{string}`: Name of the event. - * - `stopPropagation` - `{function=}`: calling `stopPropagation` function will cancel further event - * propagation (available only for events that were `$emit`-ed). - * - `preventDefault` - `{function}`: calling `preventDefault` sets `defaultPrevented` flag to true. - * - `defaultPrevented` - `{boolean}`: true if `preventDefault` was called. - * - * @param {string} name Event name to listen on. - * @param {function(event, args...)} listener Function to call when the event is emitted. - * @returns {function()} Returns a deregistration function for this listener. - */ - $on: function(name, listener) { - var namedListeners = this.$$listeners[name]; - if (!namedListeners) { - this.$$listeners[name] = namedListeners = []; - } - namedListeners.push(listener); - - return function() { - namedListeners[indexOf(namedListeners, listener)] = null; - }; - }, - - - /** - * @ngdoc function - * @name ng.$rootScope.Scope#$emit - * @methodOf ng.$rootScope.Scope - * @function - * - * @description - * Dispatches an event `name` upwards through the scope hierarchy notifying the - * registered {@link ng.$rootScope.Scope#$on} listeners. - * - * The event life cycle starts at the scope on which `$emit` was called. All - * {@link ng.$rootScope.Scope#$on listeners} listening for `name` event on this scope get notified. - * Afterwards, the event traverses upwards toward the root scope and calls all registered - * listeners along the way. The event will stop propagating if one of the listeners cancels it. - * - * Any exception emitted from the {@link ng.$rootScope.Scope#$on listeners} will be passed - * onto the {@link ng.$exceptionHandler $exceptionHandler} service. - * - * @param {string} name Event name to emit. - * @param {...*} args Optional set of arguments which will be passed onto the event listeners. - * @return {Object} Event object, see {@link ng.$rootScope.Scope#$on} - */ - $emit: function(name, args) { - var empty = [], - namedListeners, - scope = this, - stopPropagation = false, - event = { - name: name, - targetScope: scope, - stopPropagation: function() {stopPropagation = true;}, - preventDefault: function() { - event.defaultPrevented = true; - }, - defaultPrevented: false - }, - listenerArgs = concat([event], arguments, 1), - i, length; - - do { - namedListeners = scope.$$listeners[name] || empty; - event.currentScope = scope; - for (i=0, length=namedListeners.length; i 7), - hasEvent: function(event) { - // IE9 implements 'input' event it's so fubared that we rather pretend that it doesn't have - // it. In particular the event is not fired when backspace or delete key are pressed or - // when cut operation is performed. - if (event == 'input' && msie == 9) return false; - - if (isUndefined(eventSupport[event])) { - var divElm = document.createElement('div'); - eventSupport[event] = 'on' + event in divElm; - } - - return eventSupport[event]; - }, - csp: document.securityPolicy ? document.securityPolicy.isActive : false, - vendorPrefix: vendorPrefix, - transitions : transitions, - animations : animations - }; - }]; -} - -/** - * @ngdoc object - * @name ng.$window - * - * @description - * A reference to the browser's `window` object. While `window` - * is globally available in JavaScript, it causes testability problems, because - * it is a global variable. In angular we always refer to it through the - * `$window` service, so it may be overridden, removed or mocked for testing. - * - * All expressions are evaluated with respect to current scope so they don't - * suffer from window globality. - * - * @example - - - -
                - - -
                -
                - - it('should display the greeting in the input box', function() { - input('greeting').enter('Hello, E2E Tests'); - // If we click the button it will block the test runner - // element(':button').click(); - }); - -
                - */ -function $WindowProvider(){ - this.$get = valueFn(window); -} - -/** - * Parse headers into key value object - * - * @param {string} headers Raw headers as a string - * @returns {Object} Parsed headers as key value object - */ -function parseHeaders(headers) { - var parsed = {}, key, val, i; - - if (!headers) return parsed; - - forEach(headers.split('\n'), function(line) { - i = line.indexOf(':'); - key = lowercase(trim(line.substr(0, i))); - val = trim(line.substr(i + 1)); - - if (key) { - if (parsed[key]) { - parsed[key] += ', ' + val; - } else { - parsed[key] = val; - } - } - }); - - return parsed; -} - - -var IS_SAME_DOMAIN_URL_MATCH = /^(([^:]+):)?\/\/(\w+:{0,1}\w*@)?([\w\.-]*)?(:([0-9]+))?(.*)$/; - - -/** - * Parse a request and location URL and determine whether this is a same-domain request. - * - * @param {string} requestUrl The url of the request. - * @param {string} locationUrl The current browser location url. - * @returns {boolean} Whether the request is for the same domain. - */ -function isSameDomain(requestUrl, locationUrl) { - var match = IS_SAME_DOMAIN_URL_MATCH.exec(requestUrl); - // if requestUrl is relative, the regex does not match. - if (match == null) return true; - - var domain1 = { - protocol: match[2], - host: match[4], - port: int(match[6]) || DEFAULT_PORTS[match[2]] || null, - // IE8 sets unmatched groups to '' instead of undefined. - relativeProtocol: match[2] === undefined || match[2] === '' - }; - - match = SERVER_MATCH.exec(locationUrl); - var domain2 = { - protocol: match[1], - host: match[3], - port: int(match[5]) || DEFAULT_PORTS[match[1]] || null - }; - - return (domain1.protocol == domain2.protocol || domain1.relativeProtocol) && - domain1.host == domain2.host && - (domain1.port == domain2.port || (domain1.relativeProtocol && - domain2.port == DEFAULT_PORTS[domain2.protocol])); -} - - -/** - * Returns a function that provides access to parsed headers. - * - * Headers are lazy parsed when first requested. - * @see parseHeaders - * - * @param {(string|Object)} headers Headers to provide access to. - * @returns {function(string=)} Returns a getter function which if called with: - * - * - if called with single an argument returns a single header value or null - * - if called with no arguments returns an object containing all headers. - */ -function headersGetter(headers) { - var headersObj = isObject(headers) ? headers : undefined; - - return function(name) { - if (!headersObj) headersObj = parseHeaders(headers); - - if (name) { - return headersObj[lowercase(name)] || null; - } - - return headersObj; - }; -} - - -/** - * Chain all given functions - * - * This function is used for both request and response transforming - * - * @param {*} data Data to transform. - * @param {function(string=)} headers Http headers getter fn. - * @param {(function|Array.)} fns Function or an array of functions. - * @returns {*} Transformed data. - */ -function transformData(data, headers, fns) { - if (isFunction(fns)) - return fns(data, headers); - - forEach(fns, function(fn) { - data = fn(data, headers); - }); - - return data; -} - - -function isSuccess(status) { - return 200 <= status && status < 300; -} - - -function $HttpProvider() { - var JSON_START = /^\s*(\[|\{[^\{])/, - JSON_END = /[\}\]]\s*$/, - PROTECTION_PREFIX = /^\)\]\}',?\n/, - CONTENT_TYPE_APPLICATION_JSON = {'Content-Type': 'application/json;charset=utf-8'}; - - var defaults = this.defaults = { - // transform incoming response data - transformResponse: [function(data) { - if (isString(data)) { - // strip json vulnerability protection prefix - data = data.replace(PROTECTION_PREFIX, ''); - if (JSON_START.test(data) && JSON_END.test(data)) - data = fromJson(data, true); - } - return data; - }], - - // transform outgoing request data - transformRequest: [function(d) { - return isObject(d) && !isFile(d) ? toJson(d) : d; - }], - - // default headers - headers: { - common: { - 'Accept': 'application/json, text/plain, */*' - }, - post: CONTENT_TYPE_APPLICATION_JSON, - put: CONTENT_TYPE_APPLICATION_JSON, - patch: CONTENT_TYPE_APPLICATION_JSON - }, - - xsrfCookieName: 'XSRF-TOKEN', - xsrfHeaderName: 'X-XSRF-TOKEN' - }; - - /** - * Are order by request. I.E. they are applied in the same order as - * array on request, but revers order on response. - */ - var interceptorFactories = this.interceptors = []; - /** - * For historical reasons, response interceptors ordered by the order in which - * they are applied to response. (This is in revers to interceptorFactories) - */ - var responseInterceptorFactories = this.responseInterceptors = []; - - this.$get = ['$httpBackend', '$browser', '$cacheFactory', '$rootScope', '$q', '$injector', - function($httpBackend, $browser, $cacheFactory, $rootScope, $q, $injector) { - - var defaultCache = $cacheFactory('$http'); - - /** - * Interceptors stored in reverse order. Inner interceptors before outer interceptors. - * The reversal is needed so that we can build up the interception chain around the - * server request. - */ - var reversedInterceptors = []; - - forEach(interceptorFactories, function(interceptorFactory) { - reversedInterceptors.unshift(isString(interceptorFactory) - ? $injector.get(interceptorFactory) : $injector.invoke(interceptorFactory)); - }); - - forEach(responseInterceptorFactories, function(interceptorFactory, index) { - var responseFn = isString(interceptorFactory) - ? $injector.get(interceptorFactory) - : $injector.invoke(interceptorFactory); - - /** - * Response interceptors go before "around" interceptors (no real reason, just - * had to pick one.) But they are already revesed, so we can't use unshift, hence - * the splice. - */ - reversedInterceptors.splice(index, 0, { - response: function(response) { - return responseFn($q.when(response)); - }, - responseError: function(response) { - return responseFn($q.reject(response)); - } - }); - }); - - - /** - * @ngdoc function - * @name ng.$http - * @requires $httpBackend - * @requires $browser - * @requires $cacheFactory - * @requires $rootScope - * @requires $q - * @requires $injector - * - * @description - * The `$http` service is a core Angular service that facilitates communication with the remote - * HTTP servers via the browser's {@link https://developer.mozilla.org/en/xmlhttprequest - * XMLHttpRequest} object or via {@link http://en.wikipedia.org/wiki/JSONP JSONP}. - * - * For unit testing applications that use `$http` service, see - * {@link ngMock.$httpBackend $httpBackend mock}. - * - * For a higher level of abstraction, please check out the {@link ngResource.$resource - * $resource} service. - * - * The $http API is based on the {@link ng.$q deferred/promise APIs} exposed by - * the $q service. While for simple usage patterns this doesn't matter much, for advanced usage - * it is important to familiarize yourself with these APIs and the guarantees they provide. - * - * - * # General usage - * The `$http` service is a function which takes a single argument — a configuration object — - * that is used to generate an HTTP request and returns a {@link ng.$q promise} - * with two $http specific methods: `success` and `error`. - * - *
                -     *   $http({method: 'GET', url: '/someUrl'}).
                -     *     success(function(data, status, headers, config) {
                -     *       // this callback will be called asynchronously
                -     *       // when the response is available
                -     *     }).
                -     *     error(function(data, status, headers, config) {
                -     *       // called asynchronously if an error occurs
                -     *       // or server returns response with an error status.
                -     *     });
                -     * 
                - * - * Since the returned value of calling the $http function is a `promise`, you can also use - * the `then` method to register callbacks, and these callbacks will receive a single argument – - * an object representing the response. See the API signature and type info below for more - * details. - * - * A response status code between 200 and 299 is considered a success status and - * will result in the success callback being called. Note that if the response is a redirect, - * XMLHttpRequest will transparently follow it, meaning that the error callback will not be - * called for such responses. - * - * # Shortcut methods - * - * Since all invocations of the $http service require passing in an HTTP method and URL, and - * POST/PUT requests require request data to be provided as well, shortcut methods - * were created: - * - *
                -     *   $http.get('/someUrl').success(successCallback);
                -     *   $http.post('/someUrl', data).success(successCallback);
                -     * 
                - * - * Complete list of shortcut methods: - * - * - {@link ng.$http#get $http.get} - * - {@link ng.$http#head $http.head} - * - {@link ng.$http#post $http.post} - * - {@link ng.$http#put $http.put} - * - {@link ng.$http#delete $http.delete} - * - {@link ng.$http#jsonp $http.jsonp} - * - * - * # Setting HTTP Headers - * - * The $http service will automatically add certain HTTP headers to all requests. These defaults - * can be fully configured by accessing the `$httpProvider.defaults.headers` configuration - * object, which currently contains this default configuration: - * - * - `$httpProvider.defaults.headers.common` (headers that are common for all requests): - * - `Accept: application/json, text/plain, * / *` - * - `$httpProvider.defaults.headers.post`: (header defaults for POST requests) - * - `Content-Type: application/json` - * - `$httpProvider.defaults.headers.put` (header defaults for PUT requests) - * - `Content-Type: application/json` - * - * To add or overwrite these defaults, simply add or remove a property from these configuration - * objects. To add headers for an HTTP method other than POST or PUT, simply add a new object - * with the lowercased HTTP method name as the key, e.g. - * `$httpProvider.defaults.headers.get['My-Header']='value'`. - * - * Additionally, the defaults can be set at runtime via the `$http.defaults` object in the same - * fashion. - * - * - * # Transforming Requests and Responses - * - * Both requests and responses can be transformed using transform functions. By default, Angular - * applies these transformations: - * - * Request transformations: - * - * - If the `data` property of the request configuration object contains an object, serialize it into - * JSON format. - * - * Response transformations: - * - * - If XSRF prefix is detected, strip it (see Security Considerations section below). - * - If JSON response is detected, deserialize it using a JSON parser. - * - * To globally augment or override the default transforms, modify the `$httpProvider.defaults.transformRequest` and - * `$httpProvider.defaults.transformResponse` properties. These properties are by default an - * array of transform functions, which allows you to `push` or `unshift` a new transformation function into the - * transformation chain. You can also decide to completely override any default transformations by assigning your - * transformation functions to these properties directly without the array wrapper. - * - * Similarly, to locally override the request/response transforms, augment the `transformRequest` and/or - * `transformResponse` properties of the configuration object passed into `$http`. - * - * - * # Caching - * - * To enable caching, set the configuration property `cache` to `true`. When the cache is - * enabled, `$http` stores the response from the server in local cache. Next time the - * response is served from the cache without sending a request to the server. - * - * Note that even if the response is served from cache, delivery of the data is asynchronous in - * the same way that real requests are. - * - * If there are multiple GET requests for the same URL that should be cached using the same - * cache, but the cache is not populated yet, only one request to the server will be made and - * the remaining requests will be fulfilled using the response from the first request. - * - * A custom default cache built with $cacheFactory can be provided in $http.defaults.cache. - * To skip it, set configuration property `cache` to `false`. - * - * - * # Interceptors - * - * Before you start creating interceptors, be sure to understand the - * {@link ng.$q $q and deferred/promise APIs}. - * - * For purposes of global error handling, authentication, or any kind of synchronous or - * asynchronous pre-processing of request or postprocessing of responses, it is desirable to be - * able to intercept requests before they are handed to the server and - * responses before they are handed over to the application code that - * initiated these requests. The interceptors leverage the {@link ng.$q - * promise APIs} to fulfill this need for both synchronous and asynchronous pre-processing. - * - * The interceptors are service factories that are registered with the `$httpProvider` by - * adding them to the `$httpProvider.interceptors` array. The factory is called and - * injected with dependencies (if specified) and returns the interceptor. - * - * There are two kinds of interceptors (and two kinds of rejection interceptors): - * - * * `request`: interceptors get called with http `config` object. The function is free to modify - * the `config` or create a new one. The function needs to return the `config` directly or as a - * promise. - * * `requestError`: interceptor gets called when a previous interceptor threw an error or resolved - * with a rejection. - * * `response`: interceptors get called with http `response` object. The function is free to modify - * the `response` or create a new one. The function needs to return the `response` directly or as a - * promise. - * * `responseError`: interceptor gets called when a previous interceptor threw an error or resolved - * with a rejection. - * - * - *
                -     *   // register the interceptor as a service
                -     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {
                -     *     return {
                -     *       // optional method
                -     *       'request': function(config) {
                -     *         // do something on success
                -     *         return config || $q.when(config);
                -     *       },
                -     *
                -     *       // optional method
                -     *      'requestError': function(rejection) {
                -     *         // do something on error
                -     *         if (canRecover(rejection)) {
                -     *           return responseOrNewPromise
                -     *         }
                -     *         return $q.reject(rejection);
                -     *       },
                -     *
                -     *
                -     *
                -     *       // optional method
                -     *       'response': function(response) {
                -     *         // do something on success
                -     *         return response || $q.when(response);
                -     *       },
                -     *
                -     *       // optional method
                -     *      'responseError': function(rejection) {
                -     *         // do something on error
                -     *         if (canRecover(rejection)) {
                -     *           return responseOrNewPromise
                -     *         }
                -     *         return $q.reject(rejection);
                -     *       };
                -     *     }
                -     *   });
                -     *
                -     *   $httpProvider.interceptors.push('myHttpInterceptor');
                -     *
                -     *
                -     *   // register the interceptor via an anonymous factory
                -     *   $httpProvider.interceptors.push(function($q, dependency1, dependency2) {
                -     *     return {
                -     *      'request': function(config) {
                -     *          // same as above
                -     *       },
                -     *       'response': function(response) {
                -     *          // same as above
                -     *       }
                -     *   });
                -     * 
                - * - * # Response interceptors (DEPRECATED) - * - * Before you start creating interceptors, be sure to understand the - * {@link ng.$q $q and deferred/promise APIs}. - * - * For purposes of global error handling, authentication or any kind of synchronous or - * asynchronous preprocessing of received responses, it is desirable to be able to intercept - * responses for http requests before they are handed over to the application code that - * initiated these requests. The response interceptors leverage the {@link ng.$q - * promise apis} to fulfil this need for both synchronous and asynchronous preprocessing. - * - * The interceptors are service factories that are registered with the $httpProvider by - * adding them to the `$httpProvider.responseInterceptors` array. The factory is called and - * injected with dependencies (if specified) and returns the interceptor — a function that - * takes a {@link ng.$q promise} and returns the original or a new promise. - * - *
                -     *   // register the interceptor as a service
                -     *   $provide.factory('myHttpInterceptor', function($q, dependency1, dependency2) {
                -     *     return function(promise) {
                -     *       return promise.then(function(response) {
                -     *         // do something on success
                -     *       }, function(response) {
                -     *         // do something on error
                -     *         if (canRecover(response)) {
                -     *           return responseOrNewPromise
                -     *         }
                -     *         return $q.reject(response);
                -     *       });
                -     *     }
                -     *   });
                -     *
                -     *   $httpProvider.responseInterceptors.push('myHttpInterceptor');
                -     *
                -     *
                -     *   // register the interceptor via an anonymous factory
                -     *   $httpProvider.responseInterceptors.push(function($q, dependency1, dependency2) {
                -     *     return function(promise) {
                -     *       // same as above
                -     *     }
                -     *   });
                -     * 
                - * - * - * # Security Considerations - * - * When designing web applications, consider security threats from: - * - * - {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx - * JSON vulnerability} - * - {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} - * - * Both server and the client must cooperate in order to eliminate these threats. Angular comes - * pre-configured with strategies that address these issues, but for this to work backend server - * cooperation is required. - * - * ## JSON Vulnerability Protection - * - * A {@link http://haacked.com/archive/2008/11/20/anatomy-of-a-subtle-json-vulnerability.aspx - * JSON vulnerability} allows third party website to turn your JSON resource URL into - * {@link http://en.wikipedia.org/wiki/JSONP JSONP} request under some conditions. To - * counter this your server can prefix all JSON requests with following string `")]}',\n"`. - * Angular will automatically strip the prefix before processing it as JSON. - * - * For example if your server needs to return: - *
                -     * ['one','two']
                -     * 
                - * - * which is vulnerable to attack, your server can return: - *
                -     * )]}',
                -     * ['one','two']
                -     * 
                - * - * Angular will strip the prefix, before processing the JSON. - * - * - * ## Cross Site Request Forgery (XSRF) Protection - * - * {@link http://en.wikipedia.org/wiki/Cross-site_request_forgery XSRF} is a technique by which - * an unauthorized site can gain your user's private data. Angular provides a mechanism - * to counter XSRF. When performing XHR requests, the $http service reads a token from a cookie - * (by default, `XSRF-TOKEN`) and sets it as an HTTP header (`X-XSRF-TOKEN`). Since only - * JavaScript that runs on your domain could read the cookie, your server can be assured that - * the XHR came from JavaScript running on your domain. The header will not be set for - * cross-domain requests. - * - * To take advantage of this, your server needs to set a token in a JavaScript readable session - * cookie called `XSRF-TOKEN` on the first HTTP GET request. On subsequent XHR requests the - * server can verify that the cookie matches `X-XSRF-TOKEN` HTTP header, and therefore be sure - * that only JavaScript running on your domain could have sent the request. The token must be - * unique for each user and must be verifiable by the server (to prevent the JavaScript from making - * up its own tokens). We recommend that the token is a digest of your site's authentication - * cookie with a {@link https://en.wikipedia.org/wiki/Salt_(cryptography) salt} for added security. - * - * The name of the headers can be specified using the xsrfHeaderName and xsrfCookieName - * properties of either $httpProvider.defaults, or the per-request config object. - * - * - * @param {object} config Object describing the request to be made and how it should be - * processed. The object has following properties: - * - * - **method** – `{string}` – HTTP method (e.g. 'GET', 'POST', etc) - * - **url** – `{string}` – Absolute or relative URL of the resource that is being requested. - * - **params** – `{Object.}` – Map of strings or objects which will be turned to - * `?key1=value1&key2=value2` after the url. If the value is not a string, it will be JSONified. - * - **data** – `{string|Object}` – Data to be sent as the request message data. - * - **headers** – `{Object}` – Map of strings representing HTTP headers to send to the server. - * - **xsrfHeaderName** – `{string}` – Name of HTTP header to populate with the XSRF token. - * - **xsrfCookieName** – `{string}` – Name of cookie containing the XSRF token. - * - **transformRequest** – `{function(data, headersGetter)|Array.}` – - * transform function or an array of such functions. The transform function takes the http - * request body and headers and returns its transformed (typically serialized) version. - * - **transformResponse** – `{function(data, headersGetter)|Array.}` – - * transform function or an array of such functions. The transform function takes the http - * response body and headers and returns its transformed (typically deserialized) version. - * - **cache** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the - * GET request, otherwise if a cache instance built with - * {@link ng.$cacheFactory $cacheFactory}, this cache will be used for - * caching. - * - **timeout** – `{number|Promise}` – timeout in milliseconds, or {@link ng.$q promise} - * that should abort the request when resolved. - * - **withCredentials** - `{boolean}` - whether to to set the `withCredentials` flag on the - * XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5 - * requests with credentials} for more information. - * - **responseType** - `{string}` - see {@link - * https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#responseType requestType}. - * - * @returns {HttpPromise} Returns a {@link ng.$q promise} object with the - * standard `then` method and two http specific methods: `success` and `error`. The `then` - * method takes two arguments a success and an error callback which will be called with a - * response object. The `success` and `error` methods take a single argument - a function that - * will be called when the request succeeds or fails respectively. The arguments passed into - * these functions are destructured representation of the response object passed into the - * `then` method. The response object has these properties: - * - * - **data** – `{string|Object}` – The response body transformed with the transform functions. - * - **status** – `{number}` – HTTP status code of the response. - * - **headers** – `{function([headerName])}` – Header getter function. - * - **config** – `{Object}` – The configuration object that was used to generate the request. - * - * @property {Array.} pendingRequests Array of config objects for currently pending - * requests. This is primarily meant to be used for debugging purposes. - * - * - * @example - - -
                - - -
                - - - -
                http status code: {{status}}
                -
                http response data: {{data}}
                -
                -
                - - function FetchCtrl($scope, $http, $templateCache) { - $scope.method = 'GET'; - $scope.url = 'http-hello.html'; - - $scope.fetch = function() { - $scope.code = null; - $scope.response = null; - - $http({method: $scope.method, url: $scope.url, cache: $templateCache}). - success(function(data, status) { - $scope.status = status; - $scope.data = data; - }). - error(function(data, status) { - $scope.data = data || "Request failed"; - $scope.status = status; - }); - }; - - $scope.updateModel = function(method, url) { - $scope.method = method; - $scope.url = url; - }; - } - - - Hello, $http! - - - it('should make an xhr GET request', function() { - element(':button:contains("Sample GET")').click(); - element(':button:contains("fetch")').click(); - expect(binding('status')).toBe('200'); - expect(binding('data')).toMatch(/Hello, \$http!/); - }); - - it('should make a JSONP request to angularjs.org', function() { - element(':button:contains("Sample JSONP")').click(); - element(':button:contains("fetch")').click(); - expect(binding('status')).toBe('200'); - expect(binding('data')).toMatch(/Super Hero!/); - }); - - it('should make JSONP request to invalid URL and invoke the error handler', - function() { - element(':button:contains("Invalid JSONP")').click(); - element(':button:contains("fetch")').click(); - expect(binding('status')).toBe('0'); - expect(binding('data')).toBe('Request failed'); - }); - -
                - */ - function $http(requestConfig) { - var config = { - transformRequest: defaults.transformRequest, - transformResponse: defaults.transformResponse - }; - var headers = {}; - - extend(config, requestConfig); - config.headers = headers; - config.method = uppercase(config.method); - - extend(headers, - defaults.headers.common, - defaults.headers[lowercase(config.method)], - requestConfig.headers); - - var xsrfValue = isSameDomain(config.url, $browser.url()) - ? $browser.cookies()[config.xsrfCookieName || defaults.xsrfCookieName] - : undefined; - if (xsrfValue) { - headers[(config.xsrfHeaderName || defaults.xsrfHeaderName)] = xsrfValue; - } - - - var serverRequest = function(config) { - var reqData = transformData(config.data, headersGetter(headers), config.transformRequest); - - // strip content-type if data is undefined - if (isUndefined(config.data)) { - delete headers['Content-Type']; - } - - if (isUndefined(config.withCredentials) && !isUndefined(defaults.withCredentials)) { - config.withCredentials = defaults.withCredentials; - } - - // send request - return sendReq(config, reqData, headers).then(transformResponse, transformResponse); - }; - - var chain = [serverRequest, undefined]; - var promise = $q.when(config); - - // apply interceptors - forEach(reversedInterceptors, function(interceptor) { - if (interceptor.request || interceptor.requestError) { - chain.unshift(interceptor.request, interceptor.requestError); - } - if (interceptor.response || interceptor.responseError) { - chain.push(interceptor.response, interceptor.responseError); - } - }); - - while(chain.length) { - var thenFn = chain.shift(); - var rejectFn = chain.shift(); - - promise = promise.then(thenFn, rejectFn); - } - - promise.success = function(fn) { - promise.then(function(response) { - fn(response.data, response.status, response.headers, config); - }); - return promise; - }; - - promise.error = function(fn) { - promise.then(null, function(response) { - fn(response.data, response.status, response.headers, config); - }); - return promise; - }; - - return promise; - - function transformResponse(response) { - // make a copy since the response must be cacheable - var resp = extend({}, response, { - data: transformData(response.data, response.headers, config.transformResponse) - }); - return (isSuccess(response.status)) - ? resp - : $q.reject(resp); - } - } - - $http.pendingRequests = []; - - /** - * @ngdoc method - * @name ng.$http#get - * @methodOf ng.$http - * - * @description - * Shortcut method to perform `GET` request. - * - * @param {string} url Relative or absolute URL specifying the destination of the request - * @param {Object=} config Optional configuration object - * @returns {HttpPromise} Future object - */ - - /** - * @ngdoc method - * @name ng.$http#delete - * @methodOf ng.$http - * - * @description - * Shortcut method to perform `DELETE` request. - * - * @param {string} url Relative or absolute URL specifying the destination of the request - * @param {Object=} config Optional configuration object - * @returns {HttpPromise} Future object - */ - - /** - * @ngdoc method - * @name ng.$http#head - * @methodOf ng.$http - * - * @description - * Shortcut method to perform `HEAD` request. - * - * @param {string} url Relative or absolute URL specifying the destination of the request - * @param {Object=} config Optional configuration object - * @returns {HttpPromise} Future object - */ - - /** - * @ngdoc method - * @name ng.$http#jsonp - * @methodOf ng.$http - * - * @description - * Shortcut method to perform `JSONP` request. - * - * @param {string} url Relative or absolute URL specifying the destination of the request. - * Should contain `JSON_CALLBACK` string. - * @param {Object=} config Optional configuration object - * @returns {HttpPromise} Future object - */ - createShortMethods('get', 'delete', 'head', 'jsonp'); - - /** - * @ngdoc method - * @name ng.$http#post - * @methodOf ng.$http - * - * @description - * Shortcut method to perform `POST` request. - * - * @param {string} url Relative or absolute URL specifying the destination of the request - * @param {*} data Request content - * @param {Object=} config Optional configuration object - * @returns {HttpPromise} Future object - */ - - /** - * @ngdoc method - * @name ng.$http#put - * @methodOf ng.$http - * - * @description - * Shortcut method to perform `PUT` request. - * - * @param {string} url Relative or absolute URL specifying the destination of the request - * @param {*} data Request content - * @param {Object=} config Optional configuration object - * @returns {HttpPromise} Future object - */ - createShortMethodsWithData('post', 'put'); - - /** - * @ngdoc property - * @name ng.$http#defaults - * @propertyOf ng.$http - * - * @description - * Runtime equivalent of the `$httpProvider.defaults` property. Allows configuration of - * default headers, withCredentials as well as request and response transformations. - * - * See "Setting HTTP Headers" and "Transforming Requests and Responses" sections above. - */ - $http.defaults = defaults; - - - return $http; - - - function createShortMethods(names) { - forEach(arguments, function(name) { - $http[name] = function(url, config) { - return $http(extend(config || {}, { - method: name, - url: url - })); - }; - }); - } - - - function createShortMethodsWithData(name) { - forEach(arguments, function(name) { - $http[name] = function(url, data, config) { - return $http(extend(config || {}, { - method: name, - url: url, - data: data - })); - }; - }); - } - - - /** - * Makes the request. - * - * !!! ACCESSES CLOSURE VARS: - * $httpBackend, defaults, $log, $rootScope, defaultCache, $http.pendingRequests - */ - function sendReq(config, reqData, reqHeaders) { - var deferred = $q.defer(), - promise = deferred.promise, - cache, - cachedResp, - url = buildUrl(config.url, config.params); - - $http.pendingRequests.push(config); - promise.then(removePendingReq, removePendingReq); - - - if ((config.cache || defaults.cache) && config.cache !== false && config.method == 'GET') { - cache = isObject(config.cache) ? config.cache - : isObject(defaults.cache) ? defaults.cache - : defaultCache; - } - - if (cache) { - cachedResp = cache.get(url); - if (cachedResp) { - if (cachedResp.then) { - // cached request has already been sent, but there is no response yet - cachedResp.then(removePendingReq, removePendingReq); - return cachedResp; - } else { - // serving from cache - if (isArray(cachedResp)) { - resolvePromise(cachedResp[1], cachedResp[0], copy(cachedResp[2])); - } else { - resolvePromise(cachedResp, 200, {}); - } - } - } else { - // put the promise for the non-transformed response into cache as a placeholder - cache.put(url, promise); - } - } - - // if we won't have the response in cache, send the request to the backend - if (!cachedResp) { - $httpBackend(config.method, url, reqData, done, reqHeaders, config.timeout, - config.withCredentials, config.responseType); - } - - return promise; - - - /** - * Callback registered to $httpBackend(): - * - caches the response if desired - * - resolves the raw $http promise - * - calls $apply - */ - function done(status, response, headersString) { - if (cache) { - if (isSuccess(status)) { - cache.put(url, [status, response, parseHeaders(headersString)]); - } else { - // remove promise from the cache - cache.remove(url); - } - } - - resolvePromise(response, status, headersString); - if (!$rootScope.$$phase) $rootScope.$apply(); - } - - - /** - * Resolves the raw $http promise. - */ - function resolvePromise(response, status, headers) { - // normalize internal statuses to 0 - status = Math.max(status, 0); - - (isSuccess(status) ? deferred.resolve : deferred.reject)({ - data: response, - status: status, - headers: headersGetter(headers), - config: config - }); - } - - - function removePendingReq() { - var idx = indexOf($http.pendingRequests, config); - if (idx !== -1) $http.pendingRequests.splice(idx, 1); - } - } - - - function buildUrl(url, params) { - if (!params) return url; - var parts = []; - forEachSorted(params, function(value, key) { - if (value == null || value == undefined) return; - if (!isArray(value)) value = [value]; - - forEach(value, function(v) { - if (isObject(v)) { - v = toJson(v); - } - parts.push(encodeUriQuery(key) + '=' + - encodeUriQuery(v)); - }); - }); - return url + ((url.indexOf('?') == -1) ? '?' : '&') + parts.join('&'); - } - - - }]; -} - -var XHR = window.XMLHttpRequest || function() { - try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); } catch (e1) {} - try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); } catch (e2) {} - try { return new ActiveXObject("Msxml2.XMLHTTP"); } catch (e3) {} - throw new Error("This browser does not support XMLHttpRequest."); -}; - - -/** - * @ngdoc object - * @name ng.$httpBackend - * @requires $browser - * @requires $window - * @requires $document - * - * @description - * HTTP backend used by the {@link ng.$http service} that delegates to - * XMLHttpRequest object or JSONP and deals with browser incompatibilities. - * - * You should never need to use this service directly, instead use the higher-level abstractions: - * {@link ng.$http $http} or {@link ngResource.$resource $resource}. - * - * During testing this implementation is swapped with {@link ngMock.$httpBackend mock - * $httpBackend} which can be trained with responses. - */ -function $HttpBackendProvider() { - this.$get = ['$browser', '$window', '$document', function($browser, $window, $document) { - return createHttpBackend($browser, XHR, $browser.defer, $window.angular.callbacks, - $document[0], $window.location.protocol.replace(':', '')); - }]; -} - -function createHttpBackend($browser, XHR, $browserDefer, callbacks, rawDocument, locationProtocol) { - // TODO(vojta): fix the signature - return function(method, url, post, callback, headers, timeout, withCredentials, responseType) { - var status; - $browser.$$incOutstandingRequestCount(); - url = url || $browser.url(); - - if (lowercase(method) == 'jsonp') { - var callbackId = '_' + (callbacks.counter++).toString(36); - callbacks[callbackId] = function(data) { - callbacks[callbackId].data = data; - }; - - var jsonpDone = jsonpReq(url.replace('JSON_CALLBACK', 'angular.callbacks.' + callbackId), - function() { - if (callbacks[callbackId].data) { - completeRequest(callback, 200, callbacks[callbackId].data); - } else { - completeRequest(callback, status || -2); - } - delete callbacks[callbackId]; - }); - } else { - var xhr = new XHR(); - xhr.open(method, url, true); - forEach(headers, function(value, key) { - if (value) xhr.setRequestHeader(key, value); - }); - - // In IE6 and 7, this might be called synchronously when xhr.send below is called and the - // response is in the cache. the promise api will ensure that to the app code the api is - // always async - xhr.onreadystatechange = function() { - if (xhr.readyState == 4) { - var responseHeaders = xhr.getAllResponseHeaders(); - - // TODO(vojta): remove once Firefox 21 gets released. - // begin: workaround to overcome Firefox CORS http response headers bug - // https://bugzilla.mozilla.org/show_bug.cgi?id=608735 - // Firefox already patched in nightly. Should land in Firefox 21. - - // CORS "simple response headers" http://www.w3.org/TR/cors/ - var value, - simpleHeaders = ["Cache-Control", "Content-Language", "Content-Type", - "Expires", "Last-Modified", "Pragma"]; - if (!responseHeaders) { - responseHeaders = ""; - forEach(simpleHeaders, function (header) { - var value = xhr.getResponseHeader(header); - if (value) { - responseHeaders += header + ": " + value + "\n"; - } - }); - } - // end of the workaround. - - // responseText is the old-school way of retrieving response (supported by IE8 & 9) - // response and responseType properties were introduced in XHR Level2 spec (supported by IE10) - completeRequest(callback, - status || xhr.status, - (xhr.responseType ? xhr.response : xhr.responseText), - responseHeaders); - } - }; - - if (withCredentials) { - xhr.withCredentials = true; - } - - if (responseType) { - xhr.responseType = responseType; - } - - xhr.send(post || ''); - } - - if (timeout > 0) { - var timeoutId = $browserDefer(timeoutRequest, timeout); - } else if (timeout && timeout.then) { - timeout.then(timeoutRequest); - } - - - function timeoutRequest() { - status = -1; - jsonpDone && jsonpDone(); - xhr && xhr.abort(); - } - - function completeRequest(callback, status, response, headersString) { - // URL_MATCH is defined in src/service/location.js - var protocol = (url.match(SERVER_MATCH) || ['', locationProtocol])[1]; - - // cancel timeout and subsequent timeout promise resolution - timeoutId && $browserDefer.cancel(timeoutId); - jsonpDone = xhr = null; - - // fix status code for file protocol (it's always 0) - status = (protocol == 'file') ? (response ? 200 : 404) : status; - - // normalize IE bug (http://bugs.jquery.com/ticket/1450) - status = status == 1223 ? 204 : status; - - callback(status, response, headersString); - $browser.$$completeOutstandingRequest(noop); - } - }; - - function jsonpReq(url, done) { - // we can't use jQuery/jqLite here because jQuery does crazy shit with script elements, e.g.: - // - fetches local scripts via XHR and evals them - // - adds and immediately removes script elements from the document - var script = rawDocument.createElement('script'), - doneWrapper = function() { - rawDocument.body.removeChild(script); - if (done) done(); - }; - - script.type = 'text/javascript'; - script.src = url; - - if (msie) { - script.onreadystatechange = function() { - if (/loaded|complete/.test(script.readyState)) doneWrapper(); - }; - } else { - script.onload = script.onerror = doneWrapper; - } - - rawDocument.body.appendChild(script); - return doneWrapper; - } -} - -/** - * @ngdoc object - * @name ng.$locale - * - * @description - * $locale service provides localization rules for various Angular components. As of right now the - * only public api is: - * - * * `id` – `{string}` – locale id formatted as `languageId-countryId` (e.g. `en-us`) - */ -function $LocaleProvider(){ - this.$get = function() { - return { - id: 'en-us', - - NUMBER_FORMATS: { - DECIMAL_SEP: '.', - GROUP_SEP: ',', - PATTERNS: [ - { // Decimal Pattern - minInt: 1, - minFrac: 0, - maxFrac: 3, - posPre: '', - posSuf: '', - negPre: '-', - negSuf: '', - gSize: 3, - lgSize: 3 - },{ //Currency Pattern - minInt: 1, - minFrac: 2, - maxFrac: 2, - posPre: '\u00A4', - posSuf: '', - negPre: '(\u00A4', - negSuf: ')', - gSize: 3, - lgSize: 3 - } - ], - CURRENCY_SYM: '$' - }, - - DATETIME_FORMATS: { - MONTH: 'January,February,March,April,May,June,July,August,September,October,November,December' - .split(','), - SHORTMONTH: 'Jan,Feb,Mar,Apr,May,Jun,Jul,Aug,Sep,Oct,Nov,Dec'.split(','), - DAY: 'Sunday,Monday,Tuesday,Wednesday,Thursday,Friday,Saturday'.split(','), - SHORTDAY: 'Sun,Mon,Tue,Wed,Thu,Fri,Sat'.split(','), - AMPMS: ['AM','PM'], - medium: 'MMM d, y h:mm:ss a', - short: 'M/d/yy h:mm a', - fullDate: 'EEEE, MMMM d, y', - longDate: 'MMMM d, y', - mediumDate: 'MMM d, y', - shortDate: 'M/d/yy', - mediumTime: 'h:mm:ss a', - shortTime: 'h:mm a' - }, - - pluralCat: function(num) { - if (num === 1) { - return 'one'; - } - return 'other'; - } - }; - }; -} - -function $TimeoutProvider() { - this.$get = ['$rootScope', '$browser', '$q', '$exceptionHandler', - function($rootScope, $browser, $q, $exceptionHandler) { - var deferreds = {}; - - - /** - * @ngdoc function - * @name ng.$timeout - * @requires $browser - * - * @description - * Angular's wrapper for `window.setTimeout`. The `fn` function is wrapped into a try/catch - * block and delegates any exceptions to - * {@link ng.$exceptionHandler $exceptionHandler} service. - * - * The return value of registering a timeout function is a promise, which will be resolved when - * the timeout is reached and the timeout function is executed. - * - * To cancel a timeout request, call `$timeout.cancel(promise)`. - * - * In tests you can use {@link ngMock.$timeout `$timeout.flush()`} to - * synchronously flush the queue of deferred functions. - * - * @param {function()} fn A function, whose execution should be delayed. - * @param {number=} [delay=0] Delay in milliseconds. - * @param {boolean=} [invokeApply=true] If set to `false` skips model dirty checking, otherwise - * will invoke `fn` within the {@link ng.$rootScope.Scope#$apply $apply} block. - * @returns {Promise} Promise that will be resolved when the timeout is reached. The value this - * promise will be resolved with is the return value of the `fn` function. - */ - function timeout(fn, delay, invokeApply) { - var deferred = $q.defer(), - promise = deferred.promise, - skipApply = (isDefined(invokeApply) && !invokeApply), - timeoutId, cleanup; - - timeoutId = $browser.defer(function() { - try { - deferred.resolve(fn()); - } catch(e) { - deferred.reject(e); - $exceptionHandler(e); - } - - if (!skipApply) $rootScope.$apply(); - }, delay); - - cleanup = function() { - delete deferreds[promise.$$timeoutId]; - }; - - promise.$$timeoutId = timeoutId; - deferreds[timeoutId] = deferred; - promise.then(cleanup, cleanup); - - return promise; - } - - - /** - * @ngdoc function - * @name ng.$timeout#cancel - * @methodOf ng.$timeout - * - * @description - * Cancels a task associated with the `promise`. As a result of this, the promise will be - * resolved with a rejection. - * - * @param {Promise=} promise Promise returned by the `$timeout` function. - * @returns {boolean} Returns `true` if the task hasn't executed yet and was successfully - * canceled. - */ - timeout.cancel = function(promise) { - if (promise && promise.$$timeoutId in deferreds) { - deferreds[promise.$$timeoutId].reject('canceled'); - return $browser.defer.cancel(promise.$$timeoutId); - } - return false; - }; - - return timeout; - }]; -} - -/** - * @ngdoc object - * @name ng.$filterProvider - * @description - * - * Filters are just functions which transform input to an output. However filters need to be Dependency Injected. To - * achieve this a filter definition consists of a factory function which is annotated with dependencies and is - * responsible for creating a filter function. - * - *
                - *   // Filter registration
                - *   function MyModule($provide, $filterProvider) {
                - *     // create a service to demonstrate injection (not always needed)
                - *     $provide.value('greet', function(name){
                - *       return 'Hello ' + name + '!';
                - *     });
                - *
                - *     // register a filter factory which uses the
                - *     // greet service to demonstrate DI.
                - *     $filterProvider.register('greet', function(greet){
                - *       // return the filter function which uses the greet service
                - *       // to generate salutation
                - *       return function(text) {
                - *         // filters need to be forgiving so check input validity
                - *         return text && greet(text) || text;
                - *       };
                - *     });
                - *   }
                - * 
                - * - * The filter function is registered with the `$injector` under the filter name suffixe with `Filter`. - *
                - *   it('should be the same instance', inject(
                - *     function($filterProvider) {
                - *       $filterProvider.register('reverse', function(){
                - *         return ...;
                - *       });
                - *     },
                - *     function($filter, reverseFilter) {
                - *       expect($filter('reverse')).toBe(reverseFilter);
                - *     });
                - * 
                - * - * - * For more information about how angular filters work, and how to create your own filters, see - * {@link guide/dev_guide.templates.filters Understanding Angular Filters} in the angular Developer - * Guide. - */ -/** - * @ngdoc method - * @name ng.$filterProvider#register - * @methodOf ng.$filterProvider - * @description - * Register filter factory function. - * - * @param {String} name Name of the filter. - * @param {function} fn The filter factory function which is injectable. - */ - - -/** - * @ngdoc function - * @name ng.$filter - * @function - * @description - * Filters are used for formatting data displayed to the user. - * - * The general syntax in templates is as follows: - * - * {{ expression [| filter_name[:parameter_value] ... ] }} - * - * @param {String} name Name of the filter function to retrieve - * @return {Function} the filter function - */ -$FilterProvider.$inject = ['$provide']; -function $FilterProvider($provide) { - var suffix = 'Filter'; - - function register(name, factory) { - return $provide.factory(name + suffix, factory); - } - this.register = register; - - this.$get = ['$injector', function($injector) { - return function(name) { - return $injector.get(name + suffix); - } - }]; - - //////////////////////////////////////// - - register('currency', currencyFilter); - register('date', dateFilter); - register('filter', filterFilter); - register('json', jsonFilter); - register('limitTo', limitToFilter); - register('lowercase', lowercaseFilter); - register('number', numberFilter); - register('orderBy', orderByFilter); - register('uppercase', uppercaseFilter); -} - -/** - * @ngdoc filter - * @name ng.filter:filter - * @function - * - * @description - * Selects a subset of items from `array` and returns it as a new array. - * - * Note: This function is used to augment the `Array` type in Angular expressions. See - * {@link ng.$filter} for more information about Angular arrays. - * - * @param {Array} array The source array. - * @param {string|Object|function()} expression The predicate to be used for selecting items from - * `array`. - * - * Can be one of: - * - * - `string`: Predicate that results in a substring match using the value of `expression` - * string. All strings or objects with string properties in `array` that contain this string - * will be returned. The predicate can be negated by prefixing the string with `!`. - * - * - `Object`: A pattern object can be used to filter specific properties on objects contained - * by `array`. For example `{name:"M", phone:"1"}` predicate will return an array of items - * which have property `name` containing "M" and property `phone` containing "1". A special - * property name `$` can be used (as in `{$:"text"}`) to accept a match against any - * property of the object. That's equivalent to the simple substring match with a `string` - * as described above. - * - * - `function`: A predicate function can be used to write arbitrary filters. The function is - * called for each element of `array`. The final result is an array of those elements that - * the predicate returned true for. - * - * @param {function(expected, actual)|true|undefined} comparator Comparator which is used in - * determining if the expected value (from the filter expression) and actual value (from - * the object in the array) should be considered a match. - * - * Can be one of: - * - * - `function(expected, actual)`: - * The function will be given the object value and the predicate value to compare and - * should return true if the item should be included in filtered result. - * - * - `true`: A shorthand for `function(expected, actual) { return angular.equals(expected, actual)}`. - * this is essentially strict comparison of expected and actual. - * - * - `false|undefined`: A short hand for a function which will look for a substring match in case - * insensitive way. - * - * @example - - -
                - - Search: -
                - - - - - -
                NamePhone
                {{friend.name}}{{friend.phone}}
                -
                - Any:
                - Name only
                - Phone only
                - Equality
                - - - - - - -
                NamePhone
                {{friend.name}}{{friend.phone}}
                - - - it('should search across all fields when filtering with a string', function() { - input('searchText').enter('m'); - expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')). - toEqual(['Mary', 'Mike', 'Adam']); - - input('searchText').enter('76'); - expect(repeater('#searchTextResults tr', 'friend in friends').column('friend.name')). - toEqual(['John', 'Julie']); - }); - - it('should search in specific fields when filtering with a predicate object', function() { - input('search.$').enter('i'); - expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')). - toEqual(['Mary', 'Mike', 'Julie', 'Juliette']); - }); - it('should use a equal comparison when comparator is true', function() { - input('search.name').enter('Julie'); - input('strict').check(); - expect(repeater('#searchObjResults tr', 'friend in friends').column('friend.name')). - toEqual(['Julie']); - }); - - - */ -function filterFilter() { - return function(array, expression, comperator) { - if (!isArray(array)) return array; - var predicates = []; - predicates.check = function(value) { - for (var j = 0; j < predicates.length; j++) { - if(!predicates[j](value)) { - return false; - } - } - return true; - }; - switch(typeof comperator) { - case "function": - break; - case "boolean": - if(comperator == true) { - comperator = function(obj, text) { - return angular.equals(obj, text); - } - break; - } - default: - comperator = function(obj, text) { - text = (''+text).toLowerCase(); - return (''+obj).toLowerCase().indexOf(text) > -1 - }; - } - var search = function(obj, text){ - if (typeof text == 'string' && text.charAt(0) === '!') { - return !search(obj, text.substr(1)); - } - switch (typeof obj) { - case "boolean": - case "number": - case "string": - return comperator(obj, text); - case "object": - switch (typeof text) { - case "object": - return comperator(obj, text); - break; - default: - for ( var objKey in obj) { - if (objKey.charAt(0) !== '$' && search(obj[objKey], text)) { - return true; - } - } - break; - } - return false; - case "array": - for ( var i = 0; i < obj.length; i++) { - if (search(obj[i], text)) { - return true; - } - } - return false; - default: - return false; - } - }; - switch (typeof expression) { - case "boolean": - case "number": - case "string": - expression = {$:expression}; - case "object": - for (var key in expression) { - if (key == '$') { - (function() { - if (!expression[key]) return; - var path = key - predicates.push(function(value) { - return search(value, expression[path]); - }); - })(); - } else { - (function() { - if (!expression[key]) return; - var path = key; - predicates.push(function(value) { - return search(getter(value,path), expression[path]); - }); - })(); - } - } - break; - case 'function': - predicates.push(expression); - break; - default: - return array; - } - var filtered = []; - for ( var j = 0; j < array.length; j++) { - var value = array[j]; - if (predicates.check(value)) { - filtered.push(value); - } - } - return filtered; - } -} - -/** - * @ngdoc filter - * @name ng.filter:currency - * @function - * - * @description - * Formats a number as a currency (ie $1,234.56). When no currency symbol is provided, default - * symbol for current locale is used. - * - * @param {number} amount Input to filter. - * @param {string=} symbol Currency symbol or identifier to be displayed. - * @returns {string} Formatted number. - * - * - * @example - - - -
                -
                - default currency symbol ($): {{amount | currency}}
                - custom currency identifier (USD$): {{amount | currency:"USD$"}} -
                -
                - - it('should init with 1234.56', function() { - expect(binding('amount | currency')).toBe('$1,234.56'); - expect(binding('amount | currency:"USD$"')).toBe('USD$1,234.56'); - }); - it('should update', function() { - input('amount').enter('-1234'); - expect(binding('amount | currency')).toBe('($1,234.00)'); - expect(binding('amount | currency:"USD$"')).toBe('(USD$1,234.00)'); - }); - -
                - */ -currencyFilter.$inject = ['$locale']; -function currencyFilter($locale) { - var formats = $locale.NUMBER_FORMATS; - return function(amount, currencySymbol){ - if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM; - return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2). - replace(/\u00A4/g, currencySymbol); - }; -} - -/** - * @ngdoc filter - * @name ng.filter:number - * @function - * - * @description - * Formats a number as text. - * - * If the input is not a number an empty string is returned. - * - * @param {number|string} number Number to format. - * @param {(number|string)=} [fractionSize=2] Number of decimal places to round the number to. - * @returns {string} Number rounded to decimalPlaces and places a “,” after each third digit. - * - * @example - - - -
                - Enter number:
                - Default formatting: {{val | number}}
                - No fractions: {{val | number:0}}
                - Negative number: {{-val | number:4}} -
                -
                - - it('should format numbers', function() { - expect(binding('val | number')).toBe('1,234.568'); - expect(binding('val | number:0')).toBe('1,235'); - expect(binding('-val | number:4')).toBe('-1,234.5679'); - }); - - it('should update', function() { - input('val').enter('3374.333'); - expect(binding('val | number')).toBe('3,374.333'); - expect(binding('val | number:0')).toBe('3,374'); - expect(binding('-val | number:4')).toBe('-3,374.3330'); - }); - -
                - */ - - -numberFilter.$inject = ['$locale']; -function numberFilter($locale) { - var formats = $locale.NUMBER_FORMATS; - return function(number, fractionSize) { - return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP, - fractionSize); - }; -} - -var DECIMAL_SEP = '.'; -function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) { - if (isNaN(number) || !isFinite(number)) return ''; - - var isNegative = number < 0; - number = Math.abs(number); - var numStr = number + '', - formatedText = '', - parts = []; - - var hasExponent = false; - if (numStr.indexOf('e') !== -1) { - var match = numStr.match(/([\d\.]+)e(-?)(\d+)/); - if (match && match[2] == '-' && match[3] > fractionSize + 1) { - numStr = '0'; - } else { - formatedText = numStr; - hasExponent = true; - } - } - - if (!hasExponent) { - var fractionLen = (numStr.split(DECIMAL_SEP)[1] || '').length; - - // determine fractionSize if it is not specified - if (isUndefined(fractionSize)) { - fractionSize = Math.min(Math.max(pattern.minFrac, fractionLen), pattern.maxFrac); - } - - var pow = Math.pow(10, fractionSize); - number = Math.round(number * pow) / pow; - var fraction = ('' + number).split(DECIMAL_SEP); - var whole = fraction[0]; - fraction = fraction[1] || ''; - - var pos = 0, - lgroup = pattern.lgSize, - group = pattern.gSize; - - if (whole.length >= (lgroup + group)) { - pos = whole.length - lgroup; - for (var i = 0; i < pos; i++) { - if ((pos - i)%group === 0 && i !== 0) { - formatedText += groupSep; - } - formatedText += whole.charAt(i); - } - } - - for (i = pos; i < whole.length; i++) { - if ((whole.length - i)%lgroup === 0 && i !== 0) { - formatedText += groupSep; - } - formatedText += whole.charAt(i); - } - - // format fraction part. - while(fraction.length < fractionSize) { - fraction += '0'; - } - - if (fractionSize && fractionSize !== "0") formatedText += decimalSep + fraction.substr(0, fractionSize); - } - - parts.push(isNegative ? pattern.negPre : pattern.posPre); - parts.push(formatedText); - parts.push(isNegative ? pattern.negSuf : pattern.posSuf); - return parts.join(''); -} - -function padNumber(num, digits, trim) { - var neg = ''; - if (num < 0) { - neg = '-'; - num = -num; - } - num = '' + num; - while(num.length < digits) num = '0' + num; - if (trim) - num = num.substr(num.length - digits); - return neg + num; -} - - -function dateGetter(name, size, offset, trim) { - offset = offset || 0; - return function(date) { - var value = date['get' + name](); - if (offset > 0 || value > -offset) - value += offset; - if (value === 0 && offset == -12 ) value = 12; - return padNumber(value, size, trim); - }; -} - -function dateStrGetter(name, shortForm) { - return function(date, formats) { - var value = date['get' + name](); - var get = uppercase(shortForm ? ('SHORT' + name) : name); - - return formats[get][value]; - }; -} - -function timeZoneGetter(date) { - var zone = -1 * date.getTimezoneOffset(); - var paddedZone = (zone >= 0) ? "+" : ""; - - paddedZone += padNumber(Math[zone > 0 ? 'floor' : 'ceil'](zone / 60), 2) + - padNumber(Math.abs(zone % 60), 2); - - return paddedZone; -} - -function ampmGetter(date, formats) { - return date.getHours() < 12 ? formats.AMPMS[0] : formats.AMPMS[1]; -} - -var DATE_FORMATS = { - yyyy: dateGetter('FullYear', 4), - yy: dateGetter('FullYear', 2, 0, true), - y: dateGetter('FullYear', 1), - MMMM: dateStrGetter('Month'), - MMM: dateStrGetter('Month', true), - MM: dateGetter('Month', 2, 1), - M: dateGetter('Month', 1, 1), - dd: dateGetter('Date', 2), - d: dateGetter('Date', 1), - HH: dateGetter('Hours', 2), - H: dateGetter('Hours', 1), - hh: dateGetter('Hours', 2, -12), - h: dateGetter('Hours', 1, -12), - mm: dateGetter('Minutes', 2), - m: dateGetter('Minutes', 1), - ss: dateGetter('Seconds', 2), - s: dateGetter('Seconds', 1), - // while ISO 8601 requires fractions to be prefixed with `.` or `,` - // we can be just safely rely on using `sss` since we currently don't support single or two digit fractions - sss: dateGetter('Milliseconds', 3), - EEEE: dateStrGetter('Day'), - EEE: dateStrGetter('Day', true), - a: ampmGetter, - Z: timeZoneGetter -}; - -var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/, - NUMBER_STRING = /^\d+$/; - -/** - * @ngdoc filter - * @name ng.filter:date - * @function - * - * @description - * Formats `date` to a string based on the requested `format`. - * - * `format` string can be composed of the following elements: - * - * * `'yyyy'`: 4 digit representation of year (e.g. AD 1 => 0001, AD 2010 => 2010) - * * `'yy'`: 2 digit representation of year, padded (00-99). (e.g. AD 2001 => 01, AD 2010 => 10) - * * `'y'`: 1 digit representation of year, e.g. (AD 1 => 1, AD 199 => 199) - * * `'MMMM'`: Month in year (January-December) - * * `'MMM'`: Month in year (Jan-Dec) - * * `'MM'`: Month in year, padded (01-12) - * * `'M'`: Month in year (1-12) - * * `'dd'`: Day in month, padded (01-31) - * * `'d'`: Day in month (1-31) - * * `'EEEE'`: Day in Week,(Sunday-Saturday) - * * `'EEE'`: Day in Week, (Sun-Sat) - * * `'HH'`: Hour in day, padded (00-23) - * * `'H'`: Hour in day (0-23) - * * `'hh'`: Hour in am/pm, padded (01-12) - * * `'h'`: Hour in am/pm, (1-12) - * * `'mm'`: Minute in hour, padded (00-59) - * * `'m'`: Minute in hour (0-59) - * * `'ss'`: Second in minute, padded (00-59) - * * `'s'`: Second in minute (0-59) - * * `'.sss' or ',sss'`: Millisecond in second, padded (000-999) - * * `'a'`: am/pm marker - * * `'Z'`: 4 digit (+sign) representation of the timezone offset (-1200-+1200) - * - * `format` string can also be one of the following predefined - * {@link guide/i18n localizable formats}: - * - * * `'medium'`: equivalent to `'MMM d, y h:mm:ss a'` for en_US locale - * (e.g. Sep 3, 2010 12:05:08 pm) - * * `'short'`: equivalent to `'M/d/yy h:mm a'` for en_US locale (e.g. 9/3/10 12:05 pm) - * * `'fullDate'`: equivalent to `'EEEE, MMMM d,y'` for en_US locale - * (e.g. Friday, September 3, 2010) - * * `'longDate'`: equivalent to `'MMMM d, y'` for en_US locale (e.g. September 3, 2010 - * * `'mediumDate'`: equivalent to `'MMM d, y'` for en_US locale (e.g. Sep 3, 2010) - * * `'shortDate'`: equivalent to `'M/d/yy'` for en_US locale (e.g. 9/3/10) - * * `'mediumTime'`: equivalent to `'h:mm:ss a'` for en_US locale (e.g. 12:05:08 pm) - * * `'shortTime'`: equivalent to `'h:mm a'` for en_US locale (e.g. 12:05 pm) - * - * `format` string can contain literal values. These need to be quoted with single quotes (e.g. - * `"h 'in the morning'"`). In order to output single quote, use two single quotes in a sequence - * (e.g. `"h o''clock"`). - * - * @param {(Date|number|string)} date Date to format either as Date object, milliseconds (string or - * number) or various ISO 8601 datetime string formats (e.g. yyyy-MM-ddTHH:mm:ss.SSSZ and its - * shorter versions like yyyy-MM-ddTHH:mmZ, yyyy-MM-dd or yyyyMMddTHHmmssZ). If no timezone is - * specified in the string input, the time is considered to be in the local timezone. - * @param {string=} format Formatting rules (see Description). If not specified, - * `mediumDate` is used. - * @returns {string} Formatted string or the input if input is not recognized as date/millis. - * - * @example - - - {{1288323623006 | date:'medium'}}: - {{1288323623006 | date:'medium'}}
                - {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}: - {{1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'}}
                - {{1288323623006 | date:'MM/dd/yyyy @ h:mma'}}: - {{'1288323623006' | date:'MM/dd/yyyy @ h:mma'}}
                -
                - - it('should format date', function() { - expect(binding("1288323623006 | date:'medium'")). - toMatch(/Oct 2\d, 2010 \d{1,2}:\d{2}:\d{2} (AM|PM)/); - expect(binding("1288323623006 | date:'yyyy-MM-dd HH:mm:ss Z'")). - toMatch(/2010\-10\-2\d \d{2}:\d{2}:\d{2} (\-|\+)?\d{4}/); - expect(binding("'1288323623006' | date:'MM/dd/yyyy @ h:mma'")). - toMatch(/10\/2\d\/2010 @ \d{1,2}:\d{2}(AM|PM)/); - }); - -
                - */ -dateFilter.$inject = ['$locale']; -function dateFilter($locale) { - - - var R_ISO8601_STR = /^(\d{4})-?(\d\d)-?(\d\d)(?:T(\d\d)(?::?(\d\d)(?::?(\d\d)(?:\.(\d+))?)?)?(Z|([+-])(\d\d):?(\d\d))?)?$/; - // 1 2 3 4 5 6 7 8 9 10 11 - function jsonStringToDate(string) { - var match; - if (match = string.match(R_ISO8601_STR)) { - var date = new Date(0), - tzHour = 0, - tzMin = 0, - dateSetter = match[8] ? date.setUTCFullYear : date.setFullYear, - timeSetter = match[8] ? date.setUTCHours : date.setHours; - - if (match[9]) { - tzHour = int(match[9] + match[10]); - tzMin = int(match[9] + match[11]); - } - dateSetter.call(date, int(match[1]), int(match[2]) - 1, int(match[3])); - var h = int(match[4]||0) - tzHour; - var m = int(match[5]||0) - tzMin - var s = int(match[6]||0); - var ms = Math.round(parseFloat('0.' + (match[7]||0)) * 1000); - timeSetter.call(date, h, m, s, ms); - return date; - } - return string; - } - - - return function(date, format) { - var text = '', - parts = [], - fn, match; - - format = format || 'mediumDate'; - format = $locale.DATETIME_FORMATS[format] || format; - if (isString(date)) { - if (NUMBER_STRING.test(date)) { - date = int(date); - } else { - date = jsonStringToDate(date); - } - } - - if (isNumber(date)) { - date = new Date(date); - } - - if (!isDate(date)) { - return date; - } - - while(format) { - match = DATE_FORMATS_SPLIT.exec(format); - if (match) { - parts = concat(parts, match, 1); - format = parts.pop(); - } else { - parts.push(format); - format = null; - } - } - - forEach(parts, function(value){ - fn = DATE_FORMATS[value]; - text += fn ? fn(date, $locale.DATETIME_FORMATS) - : value.replace(/(^'|'$)/g, '').replace(/''/g, "'"); - }); - - return text; - }; -} - - -/** - * @ngdoc filter - * @name ng.filter:json - * @function - * - * @description - * Allows you to convert a JavaScript object into JSON string. - * - * This filter is mostly useful for debugging. When using the double curly {{value}} notation - * the binding is automatically converted to JSON. - * - * @param {*} object Any JavaScript object (including arrays and primitive types) to filter. - * @returns {string} JSON string. - * - * - * @example: - - -
                {{ {'name':'value'} | json }}
                -
                - - it('should jsonify filtered objects', function() { - expect(binding("{'name':'value'}")).toMatch(/\{\n "name": ?"value"\n}/); - }); - -
                - * - */ -function jsonFilter() { - return function(object) { - return toJson(object, true); - }; -} - - -/** - * @ngdoc filter - * @name ng.filter:lowercase - * @function - * @description - * Converts string to lowercase. - * @see angular.lowercase - */ -var lowercaseFilter = valueFn(lowercase); - - -/** - * @ngdoc filter - * @name ng.filter:uppercase - * @function - * @description - * Converts string to uppercase. - * @see angular.uppercase - */ -var uppercaseFilter = valueFn(uppercase); - -/** - * @ngdoc function - * @name ng.filter:limitTo - * @function - * - * @description - * Creates a new array or string containing only a specified number of elements. The elements - * are taken from either the beginning or the end of the source array or string, as specified by - * the value and sign (positive or negative) of `limit`. - * - * Note: This function is used to augment the `Array` type in Angular expressions. See - * {@link ng.$filter} for more information about Angular arrays. - * - * @param {Array|string} input Source array or string to be limited. - * @param {string|number} limit The length of the returned array or string. If the `limit` number - * is positive, `limit` number of items from the beginning of the source array/string are copied. - * If the number is negative, `limit` number of items from the end of the source array/string - * are copied. The `limit` will be trimmed if it exceeds `array.length` - * @returns {Array|string} A new sub-array or substring of length `limit` or less if input array - * had less than `limit` elements. - * - * @example - - - -
                - Limit {{numbers}} to: -

                Output numbers: {{ numbers | limitTo:numLimit }}

                - Limit {{letters}} to: -

                Output letters: {{ letters | limitTo:letterLimit }}

                -
                -
                - - it('should limit the number array to first three items', function() { - expect(element('.doc-example-live input[ng-model=numLimit]').val()).toBe('3'); - expect(element('.doc-example-live input[ng-model=letterLimit]').val()).toBe('3'); - expect(binding('numbers | limitTo:numLimit')).toEqual('[1,2,3]'); - expect(binding('letters | limitTo:letterLimit')).toEqual('abc'); - }); - - it('should update the output when -3 is entered', function() { - input('numLimit').enter(-3); - input('letterLimit').enter(-3); - expect(binding('numbers | limitTo:numLimit')).toEqual('[7,8,9]'); - expect(binding('letters | limitTo:letterLimit')).toEqual('ghi'); - }); - - it('should not exceed the maximum size of input array', function() { - input('numLimit').enter(100); - input('letterLimit').enter(100); - expect(binding('numbers | limitTo:numLimit')).toEqual('[1,2,3,4,5,6,7,8,9]'); - expect(binding('letters | limitTo:letterLimit')).toEqual('abcdefghi'); - }); - -
                - */ -function limitToFilter(){ - return function(input, limit) { - if (!isArray(input) && !isString(input)) return input; - - limit = int(limit); - - if (isString(input)) { - //NaN check on limit - if (limit) { - return limit >= 0 ? input.slice(0, limit) : input.slice(limit, input.length); - } else { - return ""; - } - } - - var out = [], - i, n; - - // if abs(limit) exceeds maximum length, trim it - if (limit > input.length) - limit = input.length; - else if (limit < -input.length) - limit = -input.length; - - if (limit > 0) { - i = 0; - n = limit; - } else { - i = input.length + limit; - n = input.length; - } - - for (; i} expression A predicate to be - * used by the comparator to determine the order of elements. - * - * Can be one of: - * - * - `function`: Getter function. The result of this function will be sorted using the - * `<`, `=`, `>` operator. - * - `string`: An Angular expression which evaluates to an object to order by, such as 'name' - * to sort by a property called 'name'. Optionally prefixed with `+` or `-` to control - * ascending or descending sort order (for example, +name or -name). - * - `Array`: An array of function or string predicates. The first predicate in the array - * is used for sorting, but when two items are equivalent, the next predicate is used. - * - * @param {boolean=} reverse Reverse the order the array. - * @returns {Array} Sorted copy of the source array. - * - * @example - - - -
                -
                Sorting predicate = {{predicate}}; reverse = {{reverse}}
                -
                - [ unsorted ] - - - - - - - - - - - -
                Name - (^)Phone NumberAge
                {{friend.name}}{{friend.phone}}{{friend.age}}
                -
                -
                - - it('should be reverse ordered by aged', function() { - expect(binding('predicate')).toBe('-age'); - expect(repeater('table.friend', 'friend in friends').column('friend.age')). - toEqual(['35', '29', '21', '19', '10']); - expect(repeater('table.friend', 'friend in friends').column('friend.name')). - toEqual(['Adam', 'Julie', 'Mike', 'Mary', 'John']); - }); - - it('should reorder the table when user selects different predicate', function() { - element('.doc-example-live a:contains("Name")').click(); - expect(repeater('table.friend', 'friend in friends').column('friend.name')). - toEqual(['Adam', 'John', 'Julie', 'Mary', 'Mike']); - expect(repeater('table.friend', 'friend in friends').column('friend.age')). - toEqual(['35', '10', '29', '19', '21']); - - element('.doc-example-live a:contains("Phone")').click(); - expect(repeater('table.friend', 'friend in friends').column('friend.phone')). - toEqual(['555-9876', '555-8765', '555-5678', '555-4321', '555-1212']); - expect(repeater('table.friend', 'friend in friends').column('friend.name')). - toEqual(['Mary', 'Julie', 'Adam', 'Mike', 'John']); - }); - -
                - */ -orderByFilter.$inject = ['$parse']; -function orderByFilter($parse){ - return function(array, sortPredicate, reverseOrder) { - if (!isArray(array)) return array; - if (!sortPredicate) return array; - sortPredicate = isArray(sortPredicate) ? sortPredicate: [sortPredicate]; - sortPredicate = map(sortPredicate, function(predicate){ - var descending = false, get = predicate || identity; - if (isString(predicate)) { - if ((predicate.charAt(0) == '+' || predicate.charAt(0) == '-')) { - descending = predicate.charAt(0) == '-'; - predicate = predicate.substring(1); - } - get = $parse(predicate); - } - return reverseComparator(function(a,b){ - return compare(get(a),get(b)); - }, descending); - }); - var arrayCopy = []; - for ( var i = 0; i < array.length; i++) { arrayCopy.push(array[i]); } - return arrayCopy.sort(reverseComparator(comparator, reverseOrder)); - - function comparator(o1, o2){ - for ( var i = 0; i < sortPredicate.length; i++) { - var comp = sortPredicate[i](o1, o2); - if (comp !== 0) return comp; - } - return 0; - } - function reverseComparator(comp, descending) { - return toBoolean(descending) - ? function(a,b){return comp(b,a);} - : comp; - } - function compare(v1, v2){ - var t1 = typeof v1; - var t2 = typeof v2; - if (t1 == t2) { - if (t1 == "string") v1 = v1.toLowerCase(); - if (t1 == "string") v2 = v2.toLowerCase(); - if (v1 === v2) return 0; - return v1 < v2 ? -1 : 1; - } else { - return t1 < t2 ? -1 : 1; - } - } - } -} - -function ngDirective(directive) { - if (isFunction(directive)) { - directive = { - link: directive - } - } - directive.restrict = directive.restrict || 'AC'; - return valueFn(directive); -} - -/** - * @ngdoc directive - * @name ng.directive:a - * @restrict E - * - * @description - * Modifies the default behavior of html A tag, so that the default action is prevented when href - * attribute is empty. - * - * The reasoning for this change is to allow easy creation of action links with `ngClick` directive - * without changing the location or causing page reloads, e.g.: - * `Save` - */ -var htmlAnchorDirective = valueFn({ - restrict: 'E', - compile: function(element, attr) { - - if (msie <= 8) { - - // turn link into a stylable link in IE - // but only if it doesn't have name attribute, in which case it's an anchor - if (!attr.href && !attr.name) { - attr.$set('href', ''); - } - - // add a comment node to anchors to workaround IE bug that causes element content to be reset - // to new attribute content if attribute is updated with value containing @ and element also - // contains value with @ - // see issue #1949 - element.append(document.createComment('IE fix')); - } - - return function(scope, element) { - element.bind('click', function(event){ - // if we have no href url, then don't navigate anywhere. - if (!element.attr('href')) { - event.preventDefault(); - } - }); - } - } -}); - -/** - * @ngdoc directive - * @name ng.directive:ngHref - * @restrict A - * - * @description - * Using Angular markup like {{hash}} in an href attribute makes - * the page open to a wrong URL, if the user clicks that link before - * angular has a chance to replace the {{hash}} with actual URL, the - * link will be broken and will most likely return a 404 error. - * The `ngHref` directive solves this problem. - * - * The buggy way to write it: - *
                - * 
                - * 
                - * - * The correct way to write it: - *
                - * 
                - * 
                - * - * @element A - * @param {template} ngHref any string which can contain `{{}}` markup. - * - * @example - * This example uses `link` variable inside `href` attribute: - - -
                -
                link 1 (link, don't reload)
                - link 2 (link, don't reload)
                - link 3 (link, reload!)
                - anchor (link, don't reload)
                - anchor (no link)
                - link (link, change location) - - - it('should execute ng-click but not reload when href without value', function() { - element('#link-1').click(); - expect(input('value').val()).toEqual('1'); - expect(element('#link-1').attr('href')).toBe(""); - }); - - it('should execute ng-click but not reload when href empty string', function() { - element('#link-2').click(); - expect(input('value').val()).toEqual('2'); - expect(element('#link-2').attr('href')).toBe(""); - }); - - it('should execute ng-click and change url when ng-href specified', function() { - expect(element('#link-3').attr('href')).toBe("/123"); - - element('#link-3').click(); - expect(browser().window().path()).toEqual('/123'); - }); - - it('should execute ng-click but not reload when href empty string and name specified', function() { - element('#link-4').click(); - expect(input('value').val()).toEqual('4'); - expect(element('#link-4').attr('href')).toBe(''); - }); - - it('should execute ng-click but not reload when no href but name specified', function() { - element('#link-5').click(); - expect(input('value').val()).toEqual('5'); - expect(element('#link-5').attr('href')).toBe(undefined); - }); - - it('should only change url when only ng-href', function() { - input('value').enter('6'); - expect(element('#link-6').attr('href')).toBe('6'); - - element('#link-6').click(); - expect(browser().location().url()).toEqual('/6'); - }); - - - */ - -/** - * @ngdoc directive - * @name ng.directive:ngSrc - * @restrict A - * - * @description - * Using Angular markup like `{{hash}}` in a `src` attribute doesn't - * work right: The browser will fetch from the URL with the literal - * text `{{hash}}` until Angular replaces the expression inside - * `{{hash}}`. The `ngSrc` directive solves this problem. - * - * The buggy way to write it: - *
                - * 
                - * 
                - * - * The correct way to write it: - *
                - * 
                - * 
                - * - * @element IMG - * @param {template} ngSrc any string which can contain `{{}}` markup. - */ - -/** - * @ngdoc directive - * @name ng.directive:ngSrcset - * @restrict A - * - * @description - * Using Angular markup like `{{hash}}` in a `srcset` attribute doesn't - * work right: The browser will fetch from the URL with the literal - * text `{{hash}}` until Angular replaces the expression inside - * `{{hash}}`. The `ngSrcset` directive solves this problem. - * - * The buggy way to write it: - *
                - * 
                - * 
                - * - * The correct way to write it: - *
                - * 
                - * 
                - * - * @element IMG - * @param {template} ngSrcset any string which can contain `{{}}` markup. - */ - -/** - * @ngdoc directive - * @name ng.directive:ngDisabled - * @restrict A - * - * @description - * - * The following markup will make the button enabled on Chrome/Firefox but not on IE8 and older IEs: - *
                - * 
                - * - *
                - *
                - * - * The HTML specs do not require browsers to preserve the special attributes such as disabled. - * (The presence of them means true and absence means false) - * This prevents the angular compiler from correctly retrieving the binding expression. - * To solve this problem, we introduce the `ngDisabled` directive. - * - * @example - - - Click me to toggle:
                - -
                - - it('should toggle button', function() { - expect(element('.doc-example-live :button').prop('disabled')).toBeFalsy(); - input('checked').check(); - expect(element('.doc-example-live :button').prop('disabled')).toBeTruthy(); - }); - -
                - * - * @element INPUT - * @param {expression} ngDisabled Angular expression that will be evaluated. - */ - - -/** - * @ngdoc directive - * @name ng.directive:ngChecked - * @restrict A - * - * @description - * The HTML specs do not require browsers to preserve the special attributes such as checked. - * (The presence of them means true and absence means false) - * This prevents the angular compiler from correctly retrieving the binding expression. - * To solve this problem, we introduce the `ngChecked` directive. - * @example - - - Check me to check both:
                - -
                - - it('should check both checkBoxes', function() { - expect(element('.doc-example-live #checkSlave').prop('checked')).toBeFalsy(); - input('master').check(); - expect(element('.doc-example-live #checkSlave').prop('checked')).toBeTruthy(); - }); - -
                - * - * @element INPUT - * @param {expression} ngChecked Angular expression that will be evaluated. - */ - - -/** - * @ngdoc directive - * @name ng.directive:ngMultiple - * @restrict A - * - * @description - * The HTML specs do not require browsers to preserve the special attributes such as multiple. - * (The presence of them means true and absence means false) - * This prevents the angular compiler from correctly retrieving the binding expression. - * To solve this problem, we introduce the `ngMultiple` directive. - * - * @example - - - Check me check multiple:
                - -
                - - it('should toggle multiple', function() { - expect(element('.doc-example-live #select').prop('multiple')).toBeFalsy(); - input('checked').check(); - expect(element('.doc-example-live #select').prop('multiple')).toBeTruthy(); - }); - -
                - * - * @element SELECT - * @param {expression} ngMultiple Angular expression that will be evaluated. - */ - - -/** - * @ngdoc directive - * @name ng.directive:ngReadonly - * @restrict A - * - * @description - * The HTML specs do not require browsers to preserve the special attributes such as readonly. - * (The presence of them means true and absence means false) - * This prevents the angular compiler from correctly retrieving the binding expression. - * To solve this problem, we introduce the `ngReadonly` directive. - * @example - - - Check me to make text readonly:
                - -
                - - it('should toggle readonly attr', function() { - expect(element('.doc-example-live :text').prop('readonly')).toBeFalsy(); - input('checked').check(); - expect(element('.doc-example-live :text').prop('readonly')).toBeTruthy(); - }); - -
                - * - * @element INPUT - * @param {string} expression Angular expression that will be evaluated. - */ - - -/** - * @ngdoc directive - * @name ng.directive:ngSelected - * @restrict A - * - * @description - * The HTML specs do not require browsers to preserve the special attributes such as selected. - * (The presence of them means true and absence means false) - * This prevents the angular compiler from correctly retrieving the binding expression. - * To solve this problem, we introduced the `ngSelected` directive. - * @example - - - Check me to select:
                - -
                - - it('should select Greetings!', function() { - expect(element('.doc-example-live #greet').prop('selected')).toBeFalsy(); - input('selected').check(); - expect(element('.doc-example-live #greet').prop('selected')).toBeTruthy(); - }); - -
                - * - * @element OPTION - * @param {string} expression Angular expression that will be evaluated. - */ - -/** - * @ngdoc directive - * @name ng.directive:ngOpen - * @restrict A - * - * @description - * The HTML specs do not require browsers to preserve the special attributes such as open. - * (The presence of them means true and absence means false) - * This prevents the angular compiler from correctly retrieving the binding expression. - * To solve this problem, we introduce the `ngOpen` directive. - * - * @example - - - Check me check multiple:
                -
                - Show/Hide me -
                -
                - - it('should toggle open', function() { - expect(element('#details').prop('open')).toBeFalsy(); - input('open').check(); - expect(element('#details').prop('open')).toBeTruthy(); - }); - -
                - * - * @element DETAILS - * @param {string} expression Angular expression that will be evaluated. - */ - -var ngAttributeAliasDirectives = {}; - - -// boolean attrs are evaluated -forEach(BOOLEAN_ATTR, function(propName, attrName) { - var normalized = directiveNormalize('ng-' + attrName); - ngAttributeAliasDirectives[normalized] = function() { - return { - priority: 100, - compile: function() { - return function(scope, element, attr) { - scope.$watch(attr[normalized], function ngBooleanAttrWatchAction(value) { - attr.$set(attrName, !!value); - }); - }; - } - }; - }; -}); - - -// ng-src, ng-srcset, ng-href are interpolated -forEach(['src', 'srcset', 'href'], function(attrName) { - var normalized = directiveNormalize('ng-' + attrName); - ngAttributeAliasDirectives[normalized] = function() { - return { - priority: 99, // it needs to run after the attributes are interpolated - link: function(scope, element, attr) { - attr.$observe(normalized, function(value) { - if (!value) - return; - - attr.$set(attrName, value); - - // on IE, if "ng:src" directive declaration is used and "src" attribute doesn't exist - // then calling element.setAttribute('src', 'foo') doesn't do anything, so we need - // to set the property as well to achieve the desired effect. - // we use attr[attrName] value since $set can sanitize the url. - if (msie) element.prop(attrName, attr[attrName]); - }); - } - }; - }; -}); - -var nullFormCtrl = { - $addControl: noop, - $removeControl: noop, - $setValidity: noop, - $setDirty: noop, - $setPristine: noop -}; - -/** - * @ngdoc object - * @name ng.directive:form.FormController - * - * @property {boolean} $pristine True if user has not interacted with the form yet. - * @property {boolean} $dirty True if user has already interacted with the form. - * @property {boolean} $valid True if all of the containing forms and controls are valid. - * @property {boolean} $invalid True if at least one containing control or form is invalid. - * - * @property {Object} $error Is an object hash, containing references to all invalid controls or - * forms, where: - * - * - keys are validation tokens (error names) — such as `required`, `url` or `email`), - * - values are arrays of controls or forms that are invalid with given error. - * - * @description - * `FormController` keeps track of all its controls and nested forms as well as state of them, - * such as being valid/invalid or dirty/pristine. - * - * Each {@link ng.directive:form form} directive creates an instance - * of `FormController`. - * - */ -//asks for $scope to fool the BC controller module -FormController.$inject = ['$element', '$attrs', '$scope']; -function FormController(element, attrs) { - var form = this, - parentForm = element.parent().controller('form') || nullFormCtrl, - invalidCount = 0, // used to easily determine if we are valid - errors = form.$error = {}, - controls = []; - - // init state - form.$name = attrs.name; - form.$dirty = false; - form.$pristine = true; - form.$valid = true; - form.$invalid = false; - - parentForm.$addControl(form); - - // Setup initial state of the control - element.addClass(PRISTINE_CLASS); - toggleValidCss(true); - - // convenience method for easy toggling of classes - function toggleValidCss(isValid, validationErrorKey) { - validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : ''; - element. - removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey). - addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey); - } - - form.$addControl = function(control) { - controls.push(control); - - if (control.$name && !form.hasOwnProperty(control.$name)) { - form[control.$name] = control; - } - }; - - form.$removeControl = function(control) { - if (control.$name && form[control.$name] === control) { - delete form[control.$name]; - } - forEach(errors, function(queue, validationToken) { - form.$setValidity(validationToken, true, control); - }); - - arrayRemove(controls, control); - }; - - form.$setValidity = function(validationToken, isValid, control) { - var queue = errors[validationToken]; - - if (isValid) { - if (queue) { - arrayRemove(queue, control); - if (!queue.length) { - invalidCount--; - if (!invalidCount) { - toggleValidCss(isValid); - form.$valid = true; - form.$invalid = false; - } - errors[validationToken] = false; - toggleValidCss(true, validationToken); - parentForm.$setValidity(validationToken, true, form); - } - } - - } else { - if (!invalidCount) { - toggleValidCss(isValid); - } - if (queue) { - if (includes(queue, control)) return; - } else { - errors[validationToken] = queue = []; - invalidCount++; - toggleValidCss(false, validationToken); - parentForm.$setValidity(validationToken, false, form); - } - queue.push(control); - - form.$valid = false; - form.$invalid = true; - } - }; - - form.$setDirty = function() { - element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS); - form.$dirty = true; - form.$pristine = false; - parentForm.$setDirty(); - }; - - /** - * @ngdoc function - * @name ng.directive:form.FormController#$setPristine - * @methodOf ng.directive:form.FormController - * - * @description - * Sets the form to its pristine state. - * - * This method can be called to remove the 'ng-dirty' class and set the form to its pristine - * state (ng-pristine class). This method will also propagate to all the controls contained - * in this form. - * - * Setting a form back to a pristine state is often useful when we want to 'reuse' a form after - * saving or resetting it. - */ - form.$setPristine = function () { - element.removeClass(DIRTY_CLASS).addClass(PRISTINE_CLASS); - form.$dirty = false; - form.$pristine = true; - forEach(controls, function(control) { - control.$setPristine(); - }); - }; -} - - -/** - * @ngdoc directive - * @name ng.directive:ngForm - * @restrict EAC - * - * @description - * Nestable alias of {@link ng.directive:form `form`} directive. HTML - * does not allow nesting of form elements. It is useful to nest forms, for example if the validity of a - * sub-group of controls needs to be determined. - * - * @param {string=} name|ngForm Name of the form. If specified, the form controller will be published into - * related scope, under this name. - * - */ - - /** - * @ngdoc directive - * @name ng.directive:form - * @restrict E - * - * @description - * Directive that instantiates - * {@link ng.directive:form.FormController FormController}. - * - * If `name` attribute is specified, the form controller is published onto the current scope under - * this name. - * - * # Alias: {@link ng.directive:ngForm `ngForm`} - * - * In angular forms can be nested. This means that the outer form is valid when all of the child - * forms are valid as well. However browsers do not allow nesting of `
                ` elements, for this - * reason angular provides {@link ng.directive:ngForm `ngForm`} alias - * which behaves identical to `` but allows form nesting. - * - * - * # CSS classes - * - `ng-valid` Is set if the form is valid. - * - `ng-invalid` Is set if the form is invalid. - * - `ng-pristine` Is set if the form is pristine. - * - `ng-dirty` Is set if the form is dirty. - * - * - * # Submitting a form and preventing default action - * - * Since the role of forms in client-side Angular applications is different than in classical - * roundtrip apps, it is desirable for the browser not to translate the form submission into a full - * page reload that sends the data to the server. Instead some javascript logic should be triggered - * to handle the form submission in application specific way. - * - * For this reason, Angular prevents the default action (form submission to the server) unless the - * `` element has an `action` attribute specified. - * - * You can use one of the following two ways to specify what javascript method should be called when - * a form is submitted: - * - * - {@link ng.directive:ngSubmit ngSubmit} directive on the form element - * - {@link ng.directive:ngClick ngClick} directive on the first - * button or input field of type submit (input[type=submit]) - * - * To prevent double execution of the handler, use only one of ngSubmit or ngClick directives. This - * is because of the following form submission rules coming from the html spec: - * - * - If a form has only one input field then hitting enter in this field triggers form submit - * (`ngSubmit`) - * - if a form has has 2+ input fields and no buttons or input[type=submit] then hitting enter - * doesn't trigger submit - * - if a form has one or more input fields and one or more buttons or input[type=submit] then - * hitting enter in any of the input fields will trigger the click handler on the *first* button or - * input[type=submit] (`ngClick`) *and* a submit handler on the enclosing form (`ngSubmit`) - * - * @param {string=} name Name of the form. If specified, the form controller will be published into - * related scope, under this name. - * - * @example - - - - - userType: - Required!
                - userType = {{userType}}
                - myForm.input.$valid = {{myForm.input.$valid}}
                - myForm.input.$error = {{myForm.input.$error}}
                - myForm.$valid = {{myForm.$valid}}
                - myForm.$error.required = {{!!myForm.$error.required}}
                - -
                - - it('should initialize to model', function() { - expect(binding('userType')).toEqual('guest'); - expect(binding('myForm.input.$valid')).toEqual('true'); - }); - - it('should be invalid if empty', function() { - input('userType').enter(''); - expect(binding('userType')).toEqual(''); - expect(binding('myForm.input.$valid')).toEqual('false'); - }); - -
                - */ -var formDirectiveFactory = function(isNgForm) { - return ['$timeout', function($timeout) { - var formDirective = { - name: 'form', - restrict: 'E', - controller: FormController, - compile: function() { - return { - pre: function(scope, formElement, attr, controller) { - if (!attr.action) { - // we can't use jq events because if a form is destroyed during submission the default - // action is not prevented. see #1238 - // - // IE 9 is not affected because it doesn't fire a submit event and try to do a full - // page reload if the form was destroyed by submission of the form via a click handler - // on a button in the form. Looks like an IE9 specific bug. - var preventDefaultListener = function(event) { - event.preventDefault - ? event.preventDefault() - : event.returnValue = false; // IE - }; - - addEventListenerFn(formElement[0], 'submit', preventDefaultListener); - - // unregister the preventDefault listener so that we don't not leak memory but in a - // way that will achieve the prevention of the default action. - formElement.bind('$destroy', function() { - $timeout(function() { - removeEventListenerFn(formElement[0], 'submit', preventDefaultListener); - }, 0, false); - }); - } - - var parentFormCtrl = formElement.parent().controller('form'), - alias = attr.name || attr.ngForm; - - if (alias) { - scope[alias] = controller; - } - if (parentFormCtrl) { - formElement.bind('$destroy', function() { - parentFormCtrl.$removeControl(controller); - if (alias) { - scope[alias] = undefined; - } - extend(controller, nullFormCtrl); //stop propagating child destruction handlers upwards - }); - } - } - }; - } - }; - - return isNgForm ? extend(copy(formDirective), {restrict: 'EAC'}) : formDirective; - }]; -}; - -var formDirective = formDirectiveFactory(); -var ngFormDirective = formDirectiveFactory(true); - -var URL_REGEXP = /^(ftp|http|https):\/\/(\w+:{0,1}\w*@)?(\S+)(:[0-9]+)?(\/|\/([\w#!:.?+=&%@!\-\/]))?$/; -var EMAIL_REGEXP = /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}$/; -var NUMBER_REGEXP = /^\s*(\-|\+)?(\d+|(\d*(\.\d*)))\s*$/; - -var inputType = { - - /** - * @ngdoc inputType - * @name ng.directive:input.text - * - * @description - * Standard HTML text input with angular data binding. - * - * @param {string} ngModel Assignable angular expression to data-bind to. - * @param {string=} name Property name of the form under which the control is published. - * @param {string=} required Adds `required` validation error key if the value is not entered. - * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to - * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of - * `required` when you want to data-bind to the `required` attribute. - * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than - * minlength. - * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than - * maxlength. - * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the - * RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for - * patterns defined as scope expressions. - * @param {string=} ngChange Angular expression to be executed when input changes due to user - * interaction with the input element. - * @param {boolean=} [ngTrim=true] If set to false Angular will not automatically trimming the - * input. - * - * @example - - - -
                - Single word: - - Required! - - Single word only! - - text = {{text}}
                - myForm.input.$valid = {{myForm.input.$valid}}
                - myForm.input.$error = {{myForm.input.$error}}
                - myForm.$valid = {{myForm.$valid}}
                - myForm.$error.required = {{!!myForm.$error.required}}
                -
                -
                - - it('should initialize to model', function() { - expect(binding('text')).toEqual('guest'); - expect(binding('myForm.input.$valid')).toEqual('true'); - }); - - it('should be invalid if empty', function() { - input('text').enter(''); - expect(binding('text')).toEqual(''); - expect(binding('myForm.input.$valid')).toEqual('false'); - }); - - it('should be invalid if multi word', function() { - input('text').enter('hello world'); - expect(binding('myForm.input.$valid')).toEqual('false'); - }); - - it('should not be trimmed', function() { - input('text').enter('untrimmed '); - expect(binding('text')).toEqual('untrimmed '); - expect(binding('myForm.input.$valid')).toEqual('true'); - }); - -
                - */ - 'text': textInputType, - - - /** - * @ngdoc inputType - * @name ng.directive:input.number - * - * @description - * Text input with number validation and transformation. Sets the `number` validation - * error if not a valid number. - * - * @param {string} ngModel Assignable angular expression to data-bind to. - * @param {string=} name Property name of the form under which the control is published. - * @param {string=} min Sets the `min` validation error key if the value entered is less than `min`. - * @param {string=} max Sets the `max` validation error key if the value entered is greater than `max`. - * @param {string=} required Sets `required` validation error key if the value is not entered. - * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to - * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of - * `required` when you want to data-bind to the `required` attribute. - * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than - * minlength. - * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than - * maxlength. - * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the - * RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for - * patterns defined as scope expressions. - * @param {string=} ngChange Angular expression to be executed when input changes due to user - * interaction with the input element. - * - * @example - - - -
                - Number: - - Required! - - Not valid number! - value = {{value}}
                - myForm.input.$valid = {{myForm.input.$valid}}
                - myForm.input.$error = {{myForm.input.$error}}
                - myForm.$valid = {{myForm.$valid}}
                - myForm.$error.required = {{!!myForm.$error.required}}
                -
                -
                - - it('should initialize to model', function() { - expect(binding('value')).toEqual('12'); - expect(binding('myForm.input.$valid')).toEqual('true'); - }); - - it('should be invalid if empty', function() { - input('value').enter(''); - expect(binding('value')).toEqual(''); - expect(binding('myForm.input.$valid')).toEqual('false'); - }); - - it('should be invalid if over max', function() { - input('value').enter('123'); - expect(binding('value')).toEqual(''); - expect(binding('myForm.input.$valid')).toEqual('false'); - }); - -
                - */ - 'number': numberInputType, - - - /** - * @ngdoc inputType - * @name ng.directive:input.url - * - * @description - * Text input with URL validation. Sets the `url` validation error key if the content is not a - * valid URL. - * - * @param {string} ngModel Assignable angular expression to data-bind to. - * @param {string=} name Property name of the form under which the control is published. - * @param {string=} required Sets `required` validation error key if the value is not entered. - * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to - * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of - * `required` when you want to data-bind to the `required` attribute. - * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than - * minlength. - * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than - * maxlength. - * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the - * RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for - * patterns defined as scope expressions. - * @param {string=} ngChange Angular expression to be executed when input changes due to user - * interaction with the input element. - * - * @example - - - -
                - URL: - - Required! - - Not valid url! - text = {{text}}
                - myForm.input.$valid = {{myForm.input.$valid}}
                - myForm.input.$error = {{myForm.input.$error}}
                - myForm.$valid = {{myForm.$valid}}
                - myForm.$error.required = {{!!myForm.$error.required}}
                - myForm.$error.url = {{!!myForm.$error.url}}
                -
                -
                - - it('should initialize to model', function() { - expect(binding('text')).toEqual('http://google.com'); - expect(binding('myForm.input.$valid')).toEqual('true'); - }); - - it('should be invalid if empty', function() { - input('text').enter(''); - expect(binding('text')).toEqual(''); - expect(binding('myForm.input.$valid')).toEqual('false'); - }); - - it('should be invalid if not url', function() { - input('text').enter('xxx'); - expect(binding('myForm.input.$valid')).toEqual('false'); - }); - -
                - */ - 'url': urlInputType, - - - /** - * @ngdoc inputType - * @name ng.directive:input.email - * - * @description - * Text input with email validation. Sets the `email` validation error key if not a valid email - * address. - * - * @param {string} ngModel Assignable angular expression to data-bind to. - * @param {string=} name Property name of the form under which the control is published. - * @param {string=} required Sets `required` validation error key if the value is not entered. - * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to - * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of - * `required` when you want to data-bind to the `required` attribute. - * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than - * minlength. - * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than - * maxlength. - * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the - * RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for - * patterns defined as scope expressions. - * - * @example - - - -
                - Email: - - Required! - - Not valid email! - text = {{text}}
                - myForm.input.$valid = {{myForm.input.$valid}}
                - myForm.input.$error = {{myForm.input.$error}}
                - myForm.$valid = {{myForm.$valid}}
                - myForm.$error.required = {{!!myForm.$error.required}}
                - myForm.$error.email = {{!!myForm.$error.email}}
                -
                -
                - - it('should initialize to model', function() { - expect(binding('text')).toEqual('me@example.com'); - expect(binding('myForm.input.$valid')).toEqual('true'); - }); - - it('should be invalid if empty', function() { - input('text').enter(''); - expect(binding('text')).toEqual(''); - expect(binding('myForm.input.$valid')).toEqual('false'); - }); - - it('should be invalid if not email', function() { - input('text').enter('xxx'); - expect(binding('myForm.input.$valid')).toEqual('false'); - }); - -
                - */ - 'email': emailInputType, - - - /** - * @ngdoc inputType - * @name ng.directive:input.radio - * - * @description - * HTML radio button. - * - * @param {string} ngModel Assignable angular expression to data-bind to. - * @param {string} value The value to which the expression should be set when selected. - * @param {string=} name Property name of the form under which the control is published. - * @param {string=} ngChange Angular expression to be executed when input changes due to user - * interaction with the input element. - * - * @example - - - -
                - Red
                - Green
                - Blue
                - color = {{color}}
                -
                -
                - - it('should change state', function() { - expect(binding('color')).toEqual('blue'); - - input('color').select('red'); - expect(binding('color')).toEqual('red'); - }); - -
                - */ - 'radio': radioInputType, - - - /** - * @ngdoc inputType - * @name ng.directive:input.checkbox - * - * @description - * HTML checkbox. - * - * @param {string} ngModel Assignable angular expression to data-bind to. - * @param {string=} name Property name of the form under which the control is published. - * @param {string=} ngTrueValue The value to which the expression should be set when selected. - * @param {string=} ngFalseValue The value to which the expression should be set when not selected. - * @param {string=} ngChange Angular expression to be executed when input changes due to user - * interaction with the input element. - * - * @example - - - -
                - Value1:
                - Value2:
                - value1 = {{value1}}
                - value2 = {{value2}}
                -
                -
                - - it('should change state', function() { - expect(binding('value1')).toEqual('true'); - expect(binding('value2')).toEqual('YES'); - - input('value1').check(); - input('value2').check(); - expect(binding('value1')).toEqual('false'); - expect(binding('value2')).toEqual('NO'); - }); - -
                - */ - 'checkbox': checkboxInputType, - - 'hidden': noop, - 'button': noop, - 'submit': noop, - 'reset': noop -}; - - -function isEmpty(value) { - return isUndefined(value) || value === '' || value === null || value !== value; -} - - -function textInputType(scope, element, attr, ctrl, $sniffer, $browser) { - - var listener = function() { - var value = element.val(); - - // By default we will trim the value - // If the attribute ng-trim exists we will avoid trimming - // e.g. - if (toBoolean(attr.ngTrim || 'T')) { - value = trim(value); - } - - if (ctrl.$viewValue !== value) { - scope.$apply(function() { - ctrl.$setViewValue(value); - }); - } - }; - - // if the browser does support "input" event, we are fine - except on IE9 which doesn't fire the - // input event on backspace, delete or cut - if ($sniffer.hasEvent('input')) { - element.bind('input', listener); - } else { - var timeout; - - var deferListener = function() { - if (!timeout) { - timeout = $browser.defer(function() { - listener(); - timeout = null; - }); - } - }; - - element.bind('keydown', function(event) { - var key = event.keyCode; - - // ignore - // command modifiers arrows - if (key === 91 || (15 < key && key < 19) || (37 <= key && key <= 40)) return; - - deferListener(); - }); - - // if user paste into input using mouse, we need "change" event to catch it - element.bind('change', listener); - - // if user modifies input value using context menu in IE, we need "paste" and "cut" events to catch it - if ($sniffer.hasEvent('paste')) { - element.bind('paste cut', deferListener); - } - } - - - ctrl.$render = function() { - element.val(isEmpty(ctrl.$viewValue) ? '' : ctrl.$viewValue); - }; - - // pattern validator - var pattern = attr.ngPattern, - patternValidator, - match; - - var validate = function(regexp, value) { - if (isEmpty(value) || regexp.test(value)) { - ctrl.$setValidity('pattern', true); - return value; - } else { - ctrl.$setValidity('pattern', false); - return undefined; - } - }; - - if (pattern) { - match = pattern.match(/^\/(.*)\/([gim]*)$/); - if (match) { - pattern = new RegExp(match[1], match[2]); - patternValidator = function(value) { - return validate(pattern, value) - }; - } else { - patternValidator = function(value) { - var patternObj = scope.$eval(pattern); - - if (!patternObj || !patternObj.test) { - throw new Error('Expected ' + pattern + ' to be a RegExp but was ' + patternObj); - } - return validate(patternObj, value); - }; - } - - ctrl.$formatters.push(patternValidator); - ctrl.$parsers.push(patternValidator); - } - - // min length validator - if (attr.ngMinlength) { - var minlength = int(attr.ngMinlength); - var minLengthValidator = function(value) { - if (!isEmpty(value) && value.length < minlength) { - ctrl.$setValidity('minlength', false); - return undefined; - } else { - ctrl.$setValidity('minlength', true); - return value; - } - }; - - ctrl.$parsers.push(minLengthValidator); - ctrl.$formatters.push(minLengthValidator); - } - - // max length validator - if (attr.ngMaxlength) { - var maxlength = int(attr.ngMaxlength); - var maxLengthValidator = function(value) { - if (!isEmpty(value) && value.length > maxlength) { - ctrl.$setValidity('maxlength', false); - return undefined; - } else { - ctrl.$setValidity('maxlength', true); - return value; - } - }; - - ctrl.$parsers.push(maxLengthValidator); - ctrl.$formatters.push(maxLengthValidator); - } -} - -function numberInputType(scope, element, attr, ctrl, $sniffer, $browser) { - textInputType(scope, element, attr, ctrl, $sniffer, $browser); - - ctrl.$parsers.push(function(value) { - var empty = isEmpty(value); - if (empty || NUMBER_REGEXP.test(value)) { - ctrl.$setValidity('number', true); - return value === '' ? null : (empty ? value : parseFloat(value)); - } else { - ctrl.$setValidity('number', false); - return undefined; - } - }); - - ctrl.$formatters.push(function(value) { - return isEmpty(value) ? '' : '' + value; - }); - - if (attr.min) { - var min = parseFloat(attr.min); - var minValidator = function(value) { - if (!isEmpty(value) && value < min) { - ctrl.$setValidity('min', false); - return undefined; - } else { - ctrl.$setValidity('min', true); - return value; - } - }; - - ctrl.$parsers.push(minValidator); - ctrl.$formatters.push(minValidator); - } - - if (attr.max) { - var max = parseFloat(attr.max); - var maxValidator = function(value) { - if (!isEmpty(value) && value > max) { - ctrl.$setValidity('max', false); - return undefined; - } else { - ctrl.$setValidity('max', true); - return value; - } - }; - - ctrl.$parsers.push(maxValidator); - ctrl.$formatters.push(maxValidator); - } - - ctrl.$formatters.push(function(value) { - - if (isEmpty(value) || isNumber(value)) { - ctrl.$setValidity('number', true); - return value; - } else { - ctrl.$setValidity('number', false); - return undefined; - } - }); -} - -function urlInputType(scope, element, attr, ctrl, $sniffer, $browser) { - textInputType(scope, element, attr, ctrl, $sniffer, $browser); - - var urlValidator = function(value) { - if (isEmpty(value) || URL_REGEXP.test(value)) { - ctrl.$setValidity('url', true); - return value; - } else { - ctrl.$setValidity('url', false); - return undefined; - } - }; - - ctrl.$formatters.push(urlValidator); - ctrl.$parsers.push(urlValidator); -} - -function emailInputType(scope, element, attr, ctrl, $sniffer, $browser) { - textInputType(scope, element, attr, ctrl, $sniffer, $browser); - - var emailValidator = function(value) { - if (isEmpty(value) || EMAIL_REGEXP.test(value)) { - ctrl.$setValidity('email', true); - return value; - } else { - ctrl.$setValidity('email', false); - return undefined; - } - }; - - ctrl.$formatters.push(emailValidator); - ctrl.$parsers.push(emailValidator); -} - -function radioInputType(scope, element, attr, ctrl) { - // make the name unique, if not defined - if (isUndefined(attr.name)) { - element.attr('name', nextUid()); - } - - element.bind('click', function() { - if (element[0].checked) { - scope.$apply(function() { - ctrl.$setViewValue(attr.value); - }); - } - }); - - ctrl.$render = function() { - var value = attr.value; - element[0].checked = (value == ctrl.$viewValue); - }; - - attr.$observe('value', ctrl.$render); -} - -function checkboxInputType(scope, element, attr, ctrl) { - var trueValue = attr.ngTrueValue, - falseValue = attr.ngFalseValue; - - if (!isString(trueValue)) trueValue = true; - if (!isString(falseValue)) falseValue = false; - - element.bind('click', function() { - scope.$apply(function() { - ctrl.$setViewValue(element[0].checked); - }); - }); - - ctrl.$render = function() { - element[0].checked = ctrl.$viewValue; - }; - - ctrl.$formatters.push(function(value) { - return value === trueValue; - }); - - ctrl.$parsers.push(function(value) { - return value ? trueValue : falseValue; - }); -} - - -/** - * @ngdoc directive - * @name ng.directive:textarea - * @restrict E - * - * @description - * HTML textarea element control with angular data-binding. The data-binding and validation - * properties of this element are exactly the same as those of the - * {@link ng.directive:input input element}. - * - * @param {string} ngModel Assignable angular expression to data-bind to. - * @param {string=} name Property name of the form under which the control is published. - * @param {string=} required Sets `required` validation error key if the value is not entered. - * @param {string=} ngRequired Adds `required` attribute and `required` validation constraint to - * the element when the ngRequired expression evaluates to true. Use `ngRequired` instead of - * `required` when you want to data-bind to the `required` attribute. - * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than - * minlength. - * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than - * maxlength. - * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the - * RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for - * patterns defined as scope expressions. - * @param {string=} ngChange Angular expression to be executed when input changes due to user - * interaction with the input element. - */ - - -/** - * @ngdoc directive - * @name ng.directive:input - * @restrict E - * - * @description - * HTML input element control with angular data-binding. Input control follows HTML5 input types - * and polyfills the HTML5 validation behavior for older browsers. - * - * @param {string} ngModel Assignable angular expression to data-bind to. - * @param {string=} name Property name of the form under which the control is published. - * @param {string=} required Sets `required` validation error key if the value is not entered. - * @param {boolean=} ngRequired Sets `required` attribute if set to true - * @param {number=} ngMinlength Sets `minlength` validation error key if the value is shorter than - * minlength. - * @param {number=} ngMaxlength Sets `maxlength` validation error key if the value is longer than - * maxlength. - * @param {string=} ngPattern Sets `pattern` validation error key if the value does not match the - * RegExp pattern expression. Expected value is `/regexp/` for inline patterns or `regexp` for - * patterns defined as scope expressions. - * @param {string=} ngChange Angular expression to be executed when input changes due to user - * interaction with the input element. - * - * @example - - - -
                -
                - User name: - - Required!
                - Last name: - - Too short! - - Too long!
                -
                -
                - user = {{user}}
                - myForm.userName.$valid = {{myForm.userName.$valid}}
                - myForm.userName.$error = {{myForm.userName.$error}}
                - myForm.lastName.$valid = {{myForm.lastName.$valid}}
                - myForm.lastName.$error = {{myForm.lastName.$error}}
                - myForm.$valid = {{myForm.$valid}}
                - myForm.$error.required = {{!!myForm.$error.required}}
                - myForm.$error.minlength = {{!!myForm.$error.minlength}}
                - myForm.$error.maxlength = {{!!myForm.$error.maxlength}}
                -
                -
                - - it('should initialize to model', function() { - expect(binding('user')).toEqual('{"name":"guest","last":"visitor"}'); - expect(binding('myForm.userName.$valid')).toEqual('true'); - expect(binding('myForm.$valid')).toEqual('true'); - }); - - it('should be invalid if empty when required', function() { - input('user.name').enter(''); - expect(binding('user')).toEqual('{"last":"visitor"}'); - expect(binding('myForm.userName.$valid')).toEqual('false'); - expect(binding('myForm.$valid')).toEqual('false'); - }); - - it('should be valid if empty when min length is set', function() { - input('user.last').enter(''); - expect(binding('user')).toEqual('{"name":"guest","last":""}'); - expect(binding('myForm.lastName.$valid')).toEqual('true'); - expect(binding('myForm.$valid')).toEqual('true'); - }); - - it('should be invalid if less than required min length', function() { - input('user.last').enter('xx'); - expect(binding('user')).toEqual('{"name":"guest"}'); - expect(binding('myForm.lastName.$valid')).toEqual('false'); - expect(binding('myForm.lastName.$error')).toMatch(/minlength/); - expect(binding('myForm.$valid')).toEqual('false'); - }); - - it('should be invalid if longer than max length', function() { - input('user.last').enter('some ridiculously long name'); - expect(binding('user')) - .toEqual('{"name":"guest"}'); - expect(binding('myForm.lastName.$valid')).toEqual('false'); - expect(binding('myForm.lastName.$error')).toMatch(/maxlength/); - expect(binding('myForm.$valid')).toEqual('false'); - }); - -
                - */ -var inputDirective = ['$browser', '$sniffer', function($browser, $sniffer) { - return { - restrict: 'E', - require: '?ngModel', - link: function(scope, element, attr, ctrl) { - if (ctrl) { - (inputType[lowercase(attr.type)] || inputType.text)(scope, element, attr, ctrl, $sniffer, - $browser); - } - } - }; -}]; - -var VALID_CLASS = 'ng-valid', - INVALID_CLASS = 'ng-invalid', - PRISTINE_CLASS = 'ng-pristine', - DIRTY_CLASS = 'ng-dirty'; - -/** - * @ngdoc object - * @name ng.directive:ngModel.NgModelController - * - * @property {string} $viewValue Actual string value in the view. - * @property {*} $modelValue The value in the model, that the control is bound to. - * @property {Array.} $parsers Whenever the control reads value from the DOM, it executes - * all of these functions to sanitize / convert the value as well as validate. - * - * @property {Array.} $formatters Whenever the model value changes, it executes all of - * these functions to convert the value as well as validate. - * - * @property {Object} $error An object hash with all errors as keys. - * - * @property {boolean} $pristine True if user has not interacted with the control yet. - * @property {boolean} $dirty True if user has already interacted with the control. - * @property {boolean} $valid True if there is no error. - * @property {boolean} $invalid True if at least one error on the control. - * - * @description - * - * `NgModelController` provides API for the `ng-model` directive. The controller contains - * services for data-binding, validation, CSS update, value formatting and parsing. It - * specifically does not contain any logic which deals with DOM rendering or listening to - * DOM events. The `NgModelController` is meant to be extended by other directives where, the - * directive provides DOM manipulation and the `NgModelController` provides the data-binding. - * - * This example shows how to use `NgModelController` with a custom control to achieve - * data-binding. Notice how different directives (`contenteditable`, `ng-model`, and `required`) - * collaborate together to achieve the desired result. - * - * - - [contenteditable] { - border: 1px solid black; - background-color: white; - min-height: 20px; - } - - .ng-invalid { - border: 1px solid red; - } - - - - angular.module('customControl', []). - directive('contenteditable', function() { - return { - restrict: 'A', // only activate on element attribute - require: '?ngModel', // get a hold of NgModelController - link: function(scope, element, attrs, ngModel) { - if(!ngModel) return; // do nothing if no ng-model - - // Specify how UI should be updated - ngModel.$render = function() { - element.html(ngModel.$viewValue || ''); - }; - - // Listen for change events to enable binding - element.bind('blur keyup change', function() { - scope.$apply(read); - }); - read(); // initialize - - // Write data to the model - function read() { - ngModel.$setViewValue(element.html()); - } - } - }; - }); - - -
                -
                Change me!
                - Required! -
                - -
                -
                - - it('should data-bind and become invalid', function() { - var contentEditable = element('[contenteditable]'); - - expect(contentEditable.text()).toEqual('Change me!'); - input('userContent').enter(''); - expect(contentEditable.text()).toEqual(''); - expect(contentEditable.prop('className')).toMatch(/ng-invalid-required/); - }); - - *
                - * - */ -var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$parse', - function($scope, $exceptionHandler, $attr, $element, $parse) { - this.$viewValue = Number.NaN; - this.$modelValue = Number.NaN; - this.$parsers = []; - this.$formatters = []; - this.$viewChangeListeners = []; - this.$pristine = true; - this.$dirty = false; - this.$valid = true; - this.$invalid = false; - this.$name = $attr.name; - - var ngModelGet = $parse($attr.ngModel), - ngModelSet = ngModelGet.assign; - - if (!ngModelSet) { - throw Error(NON_ASSIGNABLE_MODEL_EXPRESSION + $attr.ngModel + - ' (' + startingTag($element) + ')'); - } - - /** - * @ngdoc function - * @name ng.directive:ngModel.NgModelController#$render - * @methodOf ng.directive:ngModel.NgModelController - * - * @description - * Called when the view needs to be updated. It is expected that the user of the ng-model - * directive will implement this method. - */ - this.$render = noop; - - var parentForm = $element.inheritedData('$formController') || nullFormCtrl, - invalidCount = 0, // used to easily determine if we are valid - $error = this.$error = {}; // keep invalid keys here - - - // Setup initial state of the control - $element.addClass(PRISTINE_CLASS); - toggleValidCss(true); - - // convenience method for easy toggling of classes - function toggleValidCss(isValid, validationErrorKey) { - validationErrorKey = validationErrorKey ? '-' + snake_case(validationErrorKey, '-') : ''; - $element. - removeClass((isValid ? INVALID_CLASS : VALID_CLASS) + validationErrorKey). - addClass((isValid ? VALID_CLASS : INVALID_CLASS) + validationErrorKey); - } - - /** - * @ngdoc function - * @name ng.directive:ngModel.NgModelController#$setValidity - * @methodOf ng.directive:ngModel.NgModelController - * - * @description - * Change the validity state, and notifies the form when the control changes validity. (i.e. it - * does not notify form if given validator is already marked as invalid). - * - * This method should be called by validators - i.e. the parser or formatter functions. - * - * @param {string} validationErrorKey Name of the validator. the `validationErrorKey` will assign - * to `$error[validationErrorKey]=isValid` so that it is available for data-binding. - * The `validationErrorKey` should be in camelCase and will get converted into dash-case - * for class name. Example: `myError` will result in `ng-valid-my-error` and `ng-invalid-my-error` - * class and can be bound to as `{{someForm.someControl.$error.myError}}` . - * @param {boolean} isValid Whether the current state is valid (true) or invalid (false). - */ - this.$setValidity = function(validationErrorKey, isValid) { - if ($error[validationErrorKey] === !isValid) return; - - if (isValid) { - if ($error[validationErrorKey]) invalidCount--; - if (!invalidCount) { - toggleValidCss(true); - this.$valid = true; - this.$invalid = false; - } - } else { - toggleValidCss(false); - this.$invalid = true; - this.$valid = false; - invalidCount++; - } - - $error[validationErrorKey] = !isValid; - toggleValidCss(isValid, validationErrorKey); - - parentForm.$setValidity(validationErrorKey, isValid, this); - }; - - /** - * @ngdoc function - * @name ng.directive:ngModel.NgModelController#$setPristine - * @methodOf ng.directive:ngModel.NgModelController - * - * @description - * Sets the control to its pristine state. - * - * This method can be called to remove the 'ng-dirty' class and set the control to its pristine - * state (ng-pristine class). - */ - this.$setPristine = function () { - this.$dirty = false; - this.$pristine = true; - $element.removeClass(DIRTY_CLASS).addClass(PRISTINE_CLASS); - }; - - /** - * @ngdoc function - * @name ng.directive:ngModel.NgModelController#$setViewValue - * @methodOf ng.directive:ngModel.NgModelController - * - * @description - * Read a value from view. - * - * This method should be called from within a DOM event handler. - * For example {@link ng.directive:input input} or - * {@link ng.directive:select select} directives call it. - * - * It internally calls all `parsers` and if resulted value is valid, updates the model and - * calls all registered change listeners. - * - * @param {string} value Value from the view. - */ - this.$setViewValue = function(value) { - this.$viewValue = value; - - // change to dirty - if (this.$pristine) { - this.$dirty = true; - this.$pristine = false; - $element.removeClass(PRISTINE_CLASS).addClass(DIRTY_CLASS); - parentForm.$setDirty(); - } - - forEach(this.$parsers, function(fn) { - value = fn(value); - }); - - if (this.$modelValue !== value) { - this.$modelValue = value; - ngModelSet($scope, value); - forEach(this.$viewChangeListeners, function(listener) { - try { - listener(); - } catch(e) { - $exceptionHandler(e); - } - }) - } - }; - - // model -> value - var ctrl = this; - - $scope.$watch(function ngModelWatch() { - var value = ngModelGet($scope); - - // if scope model value and ngModel value are out of sync - if (ctrl.$modelValue !== value) { - - var formatters = ctrl.$formatters, - idx = formatters.length; - - ctrl.$modelValue = value; - while(idx--) { - value = formatters[idx](value); - } - - if (ctrl.$viewValue !== value) { - ctrl.$viewValue = value; - ctrl.$render(); - } - } - }); -}]; - - -/** - * @ngdoc directive - * @name ng.directive:ngModel - * - * @element input - * - * @description - * Is directive that tells Angular to do two-way data binding. It works together with `input`, - * `select`, `textarea`. You can easily write your own directives to use `ngModel` as well. - * - * `ngModel` is responsible for: - * - * - binding the view into the model, which other directives such as `input`, `textarea` or `select` - * require, - * - providing validation behavior (i.e. required, number, email, url), - * - keeping state of the control (valid/invalid, dirty/pristine, validation errors), - * - setting related css class onto the element (`ng-valid`, `ng-invalid`, `ng-dirty`, `ng-pristine`), - * - register the control with parent {@link ng.directive:form form}. - * - * For basic examples, how to use `ngModel`, see: - * - * - {@link ng.directive:input input} - * - {@link ng.directive:input.text text} - * - {@link ng.directive:input.checkbox checkbox} - * - {@link ng.directive:input.radio radio} - * - {@link ng.directive:input.number number} - * - {@link ng.directive:input.email email} - * - {@link ng.directive:input.url url} - * - {@link ng.directive:select select} - * - {@link ng.directive:textarea textarea} - * - */ -var ngModelDirective = function() { - return { - require: ['ngModel', '^?form'], - controller: NgModelController, - link: function(scope, element, attr, ctrls) { - // notify others, especially parent forms - - var modelCtrl = ctrls[0], - formCtrl = ctrls[1] || nullFormCtrl; - - formCtrl.$addControl(modelCtrl); - - element.bind('$destroy', function() { - formCtrl.$removeControl(modelCtrl); - }); - } - }; -}; - - -/** - * @ngdoc directive - * @name ng.directive:ngChange - * @restrict E - * - * @description - * Evaluate given expression when user changes the input. - * The expression is not evaluated when the value change is coming from the model. - * - * Note, this directive requires `ngModel` to be present. - * - * @element input - * - * @example - * - * - * - *
                - * - * - *
                - * debug = {{confirmed}}
                - * counter = {{counter}} - *
                - *
                - * - * it('should evaluate the expression if changing from view', function() { - * expect(binding('counter')).toEqual('0'); - * element('#ng-change-example1').click(); - * expect(binding('counter')).toEqual('1'); - * expect(binding('confirmed')).toEqual('true'); - * }); - * - * it('should not evaluate the expression if changing from model', function() { - * element('#ng-change-example2').click(); - * expect(binding('counter')).toEqual('0'); - * expect(binding('confirmed')).toEqual('true'); - * }); - * - *
                - */ -var ngChangeDirective = valueFn({ - require: 'ngModel', - link: function(scope, element, attr, ctrl) { - ctrl.$viewChangeListeners.push(function() { - scope.$eval(attr.ngChange); - }); - } -}); - - -var requiredDirective = function() { - return { - require: '?ngModel', - link: function(scope, elm, attr, ctrl) { - if (!ctrl) return; - attr.required = true; // force truthy in case we are on non input element - - var validator = function(value) { - if (attr.required && (isEmpty(value) || value === false)) { - ctrl.$setValidity('required', false); - return; - } else { - ctrl.$setValidity('required', true); - return value; - } - }; - - ctrl.$formatters.push(validator); - ctrl.$parsers.unshift(validator); - - attr.$observe('required', function() { - validator(ctrl.$viewValue); - }); - } - }; -}; - - -/** - * @ngdoc directive - * @name ng.directive:ngList - * - * @description - * Text input that converts between comma-separated string into an array of strings. - * - * @element input - * @param {string=} ngList optional delimiter that should be used to split the value. If - * specified in form `/something/` then the value will be converted into a regular expression. - * - * @example - - - -
                - List: - - Required! - names = {{names}}
                - myForm.namesInput.$valid = {{myForm.namesInput.$valid}}
                - myForm.namesInput.$error = {{myForm.namesInput.$error}}
                - myForm.$valid = {{myForm.$valid}}
                - myForm.$error.required = {{!!myForm.$error.required}}
                -
                -
                - - it('should initialize to model', function() { - expect(binding('names')).toEqual('["igor","misko","vojta"]'); - expect(binding('myForm.namesInput.$valid')).toEqual('true'); - }); - - it('should be invalid if empty', function() { - input('names').enter(''); - expect(binding('names')).toEqual('[]'); - expect(binding('myForm.namesInput.$valid')).toEqual('false'); - }); - -
                - */ -var ngListDirective = function() { - return { - require: 'ngModel', - link: function(scope, element, attr, ctrl) { - var match = /\/(.*)\//.exec(attr.ngList), - separator = match && new RegExp(match[1]) || attr.ngList || ','; - - var parse = function(viewValue) { - var list = []; - - if (viewValue) { - forEach(viewValue.split(separator), function(value) { - if (value) list.push(trim(value)); - }); - } - - return list; - }; - - ctrl.$parsers.push(parse); - ctrl.$formatters.push(function(value) { - if (isArray(value)) { - return value.join(', '); - } - - return undefined; - }); - } - }; -}; - - -var CONSTANT_VALUE_REGEXP = /^(true|false|\d+)$/; - -var ngValueDirective = function() { - return { - priority: 100, - compile: function(tpl, tplAttr) { - if (CONSTANT_VALUE_REGEXP.test(tplAttr.ngValue)) { - return function(scope, elm, attr) { - attr.$set('value', scope.$eval(attr.ngValue)); - }; - } else { - return function(scope, elm, attr) { - scope.$watch(attr.ngValue, function valueWatchAction(value) { - attr.$set('value', value, false); - }); - }; - } - } - }; -}; - -/** - * @ngdoc directive - * @name ng.directive:ngBind - * - * @description - * The `ngBind` attribute tells Angular to replace the text content of the specified HTML element - * with the value of a given expression, and to update the text content when the value of that - * expression changes. - * - * Typically, you don't use `ngBind` directly, but instead you use the double curly markup like - * `{{ expression }}` which is similar but less verbose. - * - * One scenario in which the use of `ngBind` is preferred over `{{ expression }}` binding is when - * it's desirable to put bindings into template that is momentarily displayed by the browser in its - * raw state before Angular compiles it. Since `ngBind` is an element attribute, it makes the - * bindings invisible to the user while the page is loading. - * - * An alternative solution to this problem would be using the - * {@link ng.directive:ngCloak ngCloak} directive. - * - * - * @element ANY - * @param {expression} ngBind {@link guide/expression Expression} to evaluate. - * - * @example - * Enter a name in the Live Preview text box; the greeting below the text box changes instantly. - - - -
                - Enter name:
                - Hello ! -
                -
                - - it('should check ng-bind', function() { - expect(using('.doc-example-live').binding('name')).toBe('Whirled'); - using('.doc-example-live').input('name').enter('world'); - expect(using('.doc-example-live').binding('name')).toBe('world'); - }); - -
                - */ -var ngBindDirective = ngDirective(function(scope, element, attr) { - element.addClass('ng-binding').data('$binding', attr.ngBind); - scope.$watch(attr.ngBind, function ngBindWatchAction(value) { - element.text(value == undefined ? '' : value); - }); -}); - - -/** - * @ngdoc directive - * @name ng.directive:ngBindTemplate - * - * @description - * The `ngBindTemplate` directive specifies that the element - * text should be replaced with the template in ngBindTemplate. - * Unlike ngBind the ngBindTemplate can contain multiple `{{` `}}` - * expressions. (This is required since some HTML elements - * can not have SPAN elements such as TITLE, or OPTION to name a few.) - * - * @element ANY - * @param {string} ngBindTemplate template of form - * {{ expression }} to eval. - * - * @example - * Try it here: enter text in text box and watch the greeting change. - - - -
                - Salutation:
                - Name:
                -
                
                -       
                -
                - - it('should check ng-bind', function() { - expect(using('.doc-example-live').binding('salutation')). - toBe('Hello'); - expect(using('.doc-example-live').binding('name')). - toBe('World'); - using('.doc-example-live').input('salutation').enter('Greetings'); - using('.doc-example-live').input('name').enter('user'); - expect(using('.doc-example-live').binding('salutation')). - toBe('Greetings'); - expect(using('.doc-example-live').binding('name')). - toBe('user'); - }); - -
                - */ -var ngBindTemplateDirective = ['$interpolate', function($interpolate) { - return function(scope, element, attr) { - // TODO: move this to scenario runner - var interpolateFn = $interpolate(element.attr(attr.$attr.ngBindTemplate)); - element.addClass('ng-binding').data('$binding', interpolateFn); - attr.$observe('ngBindTemplate', function(value) { - element.text(value); - }); - } -}]; - - -/** - * @ngdoc directive - * @name ng.directive:ngBindHtmlUnsafe - * - * @description - * Creates a binding that will innerHTML the result of evaluating the `expression` into the current - * element. *The innerHTML-ed content will not be sanitized!* You should use this directive only if - * {@link ngSanitize.directive:ngBindHtml ngBindHtml} directive is too - * restrictive and when you absolutely trust the source of the content you are binding to. - * - * See {@link ngSanitize.$sanitize $sanitize} docs for examples. - * - * @element ANY - * @param {expression} ngBindHtmlUnsafe {@link guide/expression Expression} to evaluate. - */ -var ngBindHtmlUnsafeDirective = [function() { - return function(scope, element, attr) { - element.addClass('ng-binding').data('$binding', attr.ngBindHtmlUnsafe); - scope.$watch(attr.ngBindHtmlUnsafe, function ngBindHtmlUnsafeWatchAction(value) { - element.html(value || ''); - }); - }; -}]; - -function classDirective(name, selector) { - name = 'ngClass' + name; - return ngDirective(function(scope, element, attr) { - var oldVal = undefined; - - scope.$watch(attr[name], ngClassWatchAction, true); - - attr.$observe('class', function(value) { - var ngClass = scope.$eval(attr[name]); - ngClassWatchAction(ngClass, ngClass); - }); - - - if (name !== 'ngClass') { - scope.$watch('$index', function($index, old$index) { - var mod = $index & 1; - if (mod !== old$index & 1) { - if (mod === selector) { - addClass(scope.$eval(attr[name])); - } else { - removeClass(scope.$eval(attr[name])); - } - } - }); - } - - - function ngClassWatchAction(newVal) { - if (selector === true || scope.$index % 2 === selector) { - if (oldVal && !equals(newVal,oldVal)) { - removeClass(oldVal); - } - addClass(newVal); - } - oldVal = copy(newVal); - } - - - function removeClass(classVal) { - if (isObject(classVal) && !isArray(classVal)) { - classVal = map(classVal, function(v, k) { if (v) return k }); - } - element.removeClass(isArray(classVal) ? classVal.join(' ') : classVal); - } - - - function addClass(classVal) { - if (isObject(classVal) && !isArray(classVal)) { - classVal = map(classVal, function(v, k) { if (v) return k }); - } - if (classVal) { - element.addClass(isArray(classVal) ? classVal.join(' ') : classVal); - } - } - }); -} - -/** - * @ngdoc directive - * @name ng.directive:ngClass - * - * @description - * The `ngClass` allows you to set CSS class on HTML element dynamically by databinding an - * expression that represents all classes to be added. - * - * The directive won't add duplicate classes if a particular class was already set. - * - * When the expression changes, the previously added classes are removed and only then the - * new classes are added. - * - * @element ANY - * @param {expression} ngClass {@link guide/expression Expression} to eval. The result - * of the evaluation can be a string representing space delimited class - * names, an array, or a map of class names to boolean values. - * - * @example - - - - -
                - Sample Text -
                - - .my-class { - color: red; - } - - - it('should check ng-class', function() { - expect(element('.doc-example-live span').prop('className')).not(). - toMatch(/my-class/); - - using('.doc-example-live').element(':button:first').click(); - - expect(element('.doc-example-live span').prop('className')). - toMatch(/my-class/); - - using('.doc-example-live').element(':button:last').click(); - - expect(element('.doc-example-live span').prop('className')).not(). - toMatch(/my-class/); - }); - -
                - */ -var ngClassDirective = classDirective('', true); - -/** - * @ngdoc directive - * @name ng.directive:ngClassOdd - * - * @description - * The `ngClassOdd` and `ngClassEven` directives work exactly as - * {@link ng.directive:ngClass ngClass}, except it works in - * conjunction with `ngRepeat` and takes affect only on odd (even) rows. - * - * This directive can be applied only within a scope of an - * {@link ng.directive:ngRepeat ngRepeat}. - * - * @element ANY - * @param {expression} ngClassOdd {@link guide/expression Expression} to eval. The result - * of the evaluation can be a string representing space delimited class names or an array. - * - * @example - - -
                  -
                1. - - {{name}} - -
                2. -
                -
                - - .odd { - color: red; - } - .even { - color: blue; - } - - - it('should check ng-class-odd and ng-class-even', function() { - expect(element('.doc-example-live li:first span').prop('className')). - toMatch(/odd/); - expect(element('.doc-example-live li:last span').prop('className')). - toMatch(/even/); - }); - -
                - */ -var ngClassOddDirective = classDirective('Odd', 0); - -/** - * @ngdoc directive - * @name ng.directive:ngClassEven - * - * @description - * The `ngClassOdd` and `ngClassEven` directives work exactly as - * {@link ng.directive:ngClass ngClass}, except it works in - * conjunction with `ngRepeat` and takes affect only on odd (even) rows. - * - * This directive can be applied only within a scope of an - * {@link ng.directive:ngRepeat ngRepeat}. - * - * @element ANY - * @param {expression} ngClassEven {@link guide/expression Expression} to eval. The - * result of the evaluation can be a string representing space delimited class names or an array. - * - * @example - - -
                  -
                1. - - {{name}}       - -
                2. -
                -
                - - .odd { - color: red; - } - .even { - color: blue; - } - - - it('should check ng-class-odd and ng-class-even', function() { - expect(element('.doc-example-live li:first span').prop('className')). - toMatch(/odd/); - expect(element('.doc-example-live li:last span').prop('className')). - toMatch(/even/); - }); - -
                - */ -var ngClassEvenDirective = classDirective('Even', 1); - -/** - * @ngdoc directive - * @name ng.directive:ngCloak - * - * @description - * The `ngCloak` directive is used to prevent the Angular html template from being briefly - * displayed by the browser in its raw (uncompiled) form while your application is loading. Use this - * directive to avoid the undesirable flicker effect caused by the html template display. - * - * The directive can be applied to the `` element, but typically a fine-grained application is - * preferred in order to benefit from progressive rendering of the browser view. - * - * `ngCloak` works in cooperation with a css rule that is embedded within `angular.js` and - * `angular.min.js` files. Following is the css rule: - * - *
                - * [ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak], .ng-cloak, .x-ng-cloak {
                - *   display: none;
                - * }
                - * 
                - * - * When this css rule is loaded by the browser, all html elements (including their children) that - * are tagged with the `ng-cloak` directive are hidden. When Angular comes across this directive - * during the compilation of the template it deletes the `ngCloak` element attribute, which - * makes the compiled element visible. - * - * For the best result, `angular.js` script must be loaded in the head section of the html file; - * alternatively, the css rule (above) must be included in the external stylesheet of the - * application. - * - * Legacy browsers, like IE7, do not provide attribute selector support (added in CSS 2.1) so they - * cannot match the `[ng\:cloak]` selector. To work around this limitation, you must add the css - * class `ngCloak` in addition to `ngCloak` directive as shown in the example below. - * - * @element ANY - * - * @example - - -
                {{ 'hello' }}
                -
                {{ 'hello IE7' }}
                -
                - - it('should remove the template directive and css class', function() { - expect(element('.doc-example-live #template1').attr('ng-cloak')). - not().toBeDefined(); - expect(element('.doc-example-live #template2').attr('ng-cloak')). - not().toBeDefined(); - }); - -
                - * - */ -var ngCloakDirective = ngDirective({ - compile: function(element, attr) { - attr.$set('ngCloak', undefined); - element.removeClass('ng-cloak'); - } -}); - -/** - * @ngdoc directive - * @name ng.directive:ngController - * - * @description - * The `ngController` directive assigns behavior to a scope. This is a key aspect of how angular - * supports the principles behind the Model-View-Controller design pattern. - * - * MVC components in angular: - * - * * Model — The Model is data in scope properties; scopes are attached to the DOM. - * * View — The template (HTML with data bindings) is rendered into the View. - * * Controller — The `ngController` directive specifies a Controller class; the class has - * methods that typically express the business logic behind the application. - * - * Note that an alternative way to define controllers is via the {@link ng.$route $route} service. - * - * @element ANY - * @scope - * @param {expression} ngController Name of a globally accessible constructor function or an - * {@link guide/expression expression} that on the current scope evaluates to a - * constructor function. The controller instance can further be published into the scope - * by adding `as localName` the controller name attribute. - * - * @example - * Here is a simple form for editing user contact information. Adding, removing, clearing, and - * greeting are methods declared on the controller (see source tab). These methods can - * easily be called from the angular markup. Notice that the scope becomes the `this` for the - * controller's instance. This allows for easy access to the view data from the controller. Also - * notice that any changes to the data are automatically reflected in the View without the need - * for a manual update. The example is included in two different declaration styles based on - * your style preferences. - - - -
                - Name: - [ greet ]
                - Contact: -
                  -
                • - - - [ clear - | X ] -
                • -
                • [ add ]
                • -
                -
                -
                - - it('should check controller', function() { - expect(element('.doc-example-live div>:input').val()).toBe('John Smith'); - expect(element('.doc-example-live li:nth-child(1) input').val()) - .toBe('408 555 1212'); - expect(element('.doc-example-live li:nth-child(2) input').val()) - .toBe('john.smith@example.org'); - - element('.doc-example-live li:first a:contains("clear")').click(); - expect(element('.doc-example-live li:first input').val()).toBe(''); - - element('.doc-example-live li:last a:contains("add")').click(); - expect(element('.doc-example-live li:nth-child(3) input').val()) - .toBe('yourname@example.org'); - }); - -
                - - - - - - -
                - Name: - [ greet ]
                - Contact: -
                  -
                • - - - [ clear - | X ] -
                • -
                • [ add ]
                • -
                -
                -
                - - it('should check controller', function() { - expect(element('.doc-example-live div>:input').val()).toBe('John Smith'); - expect(element('.doc-example-live li:nth-child(1) input').val()) - .toBe('408 555 1212'); - expect(element('.doc-example-live li:nth-child(2) input').val()) - .toBe('john.smith@example.org'); - - element('.doc-example-live li:first a:contains("clear")').click(); - expect(element('.doc-example-live li:first input').val()).toBe(''); - - element('.doc-example-live li:last a:contains("add")').click(); - expect(element('.doc-example-live li:nth-child(3) input').val()) - .toBe('yourname@example.org'); - }); - -
                - - */ -var ngControllerDirective = [function() { - return { - scope: true, - controller: '@' - }; -}]; - -/** - * @ngdoc directive - * @name ng.directive:ngCsp - * @priority 1000 - * - * @element html - * @description - * Enables [CSP (Content Security Policy)](https://developer.mozilla.org/en/Security/CSP) support. - * - * This is necessary when developing things like Google Chrome Extensions. - * - * CSP forbids apps to use `eval` or `Function(string)` generated functions (among other things). - * For us to be compatible, we just need to implement the "getterFn" in $parse without violating - * any of these restrictions. - * - * AngularJS uses `Function(string)` generated functions as a speed optimization. By applying `ngCsp` - * it is be possible to opt into the CSP compatible mode. When this mode is on AngularJS will - * evaluate all expressions up to 30% slower than in non-CSP mode, but no security violations will - * be raised. - * - * In order to use this feature put `ngCsp` directive on the root element of the application. - * - * @example - * This example shows how to apply the `ngCsp` directive to the `html` tag. -
                -     
                -     
                -     ...
                -     ...
                -     
                -   
                - */ - -var ngCspDirective = ['$sniffer', function($sniffer) { - return { - priority: 1000, - compile: function() { - $sniffer.csp = true; - } - }; -}]; - -/** - * @ngdoc directive - * @name ng.directive:ngClick - * - * @description - * The ngClick allows you to specify custom behavior when - * element is clicked. - * - * @element ANY - * @param {expression} ngClick {@link guide/expression Expression} to evaluate upon - * click. (Event object is available as `$event`) - * - * @example - - - - count: {{count}} - - - it('should check ng-click', function() { - expect(binding('count')).toBe('0'); - element('.doc-example-live :button').click(); - expect(binding('count')).toBe('1'); - }); - - - */ -/* - * A directive that allows creation of custom onclick handlers that are defined as angular - * expressions and are compiled and executed within the current scope. - * - * Events that are handled via these handler are always configured not to propagate further. - */ -var ngEventDirectives = {}; -forEach( - 'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup keypress'.split(' '), - function(name) { - var directiveName = directiveNormalize('ng-' + name); - ngEventDirectives[directiveName] = ['$parse', function($parse) { - return function(scope, element, attr) { - var fn = $parse(attr[directiveName]); - element.bind(lowercase(name), function(event) { - scope.$apply(function() { - fn(scope, {$event:event}); - }); - }); - }; - }]; - } -); - -/** - * @ngdoc directive - * @name ng.directive:ngDblclick - * - * @description - * The `ngDblclick` directive allows you to specify custom behavior on dblclick event. - * - * @element ANY - * @param {expression} ngDblclick {@link guide/expression Expression} to evaluate upon - * dblclick. (Event object is available as `$event`) - * - * @example - * See {@link ng.directive:ngClick ngClick} - */ - - -/** - * @ngdoc directive - * @name ng.directive:ngMousedown - * - * @description - * The ngMousedown directive allows you to specify custom behavior on mousedown event. - * - * @element ANY - * @param {expression} ngMousedown {@link guide/expression Expression} to evaluate upon - * mousedown. (Event object is available as `$event`) - * - * @example - * See {@link ng.directive:ngClick ngClick} - */ - - -/** - * @ngdoc directive - * @name ng.directive:ngMouseup - * - * @description - * Specify custom behavior on mouseup event. - * - * @element ANY - * @param {expression} ngMouseup {@link guide/expression Expression} to evaluate upon - * mouseup. (Event object is available as `$event`) - * - * @example - * See {@link ng.directive:ngClick ngClick} - */ - -/** - * @ngdoc directive - * @name ng.directive:ngMouseover - * - * @description - * Specify custom behavior on mouseover event. - * - * @element ANY - * @param {expression} ngMouseover {@link guide/expression Expression} to evaluate upon - * mouseover. (Event object is available as `$event`) - * - * @example - * See {@link ng.directive:ngClick ngClick} - */ - - -/** - * @ngdoc directive - * @name ng.directive:ngMouseenter - * - * @description - * Specify custom behavior on mouseenter event. - * - * @element ANY - * @param {expression} ngMouseenter {@link guide/expression Expression} to evaluate upon - * mouseenter. (Event object is available as `$event`) - * - * @example - * See {@link ng.directive:ngClick ngClick} - */ - - -/** - * @ngdoc directive - * @name ng.directive:ngMouseleave - * - * @description - * Specify custom behavior on mouseleave event. - * - * @element ANY - * @param {expression} ngMouseleave {@link guide/expression Expression} to evaluate upon - * mouseleave. (Event object is available as `$event`) - * - * @example - * See {@link ng.directive:ngClick ngClick} - */ - - -/** - * @ngdoc directive - * @name ng.directive:ngMousemove - * - * @description - * Specify custom behavior on mousemove event. - * - * @element ANY - * @param {expression} ngMousemove {@link guide/expression Expression} to evaluate upon - * mousemove. (Event object is available as `$event`) - * - * @example - * See {@link ng.directive:ngClick ngClick} - */ - - -/** - * @ngdoc directive - * @name ng.directive:ngKeydown - * - * @description - * Specify custom behavior on keydown event. - * - * @element ANY - * @param {expression} ngKeydown {@link guide/expression Expression} to evaluate upon - * keydown. (Event object is available as `$event` and can be interrogated for keyCode, altKey, etc.) - * - * @example - * See {@link ng.directive:ngClick ngClick} - */ - - -/** - * @ngdoc directive - * @name ng.directive:ngKeyup - * - * @description - * Specify custom behavior on keyup event. - * - * @element ANY - * @param {expression} ngKeyup {@link guide/expression Expression} to evaluate upon - * keyup. (Event object is available as `$event` and can be interrogated for keyCode, altKey, etc.) - * - * @example - * See {@link ng.directive:ngClick ngClick} - */ - - -/** - * @ngdoc directive - * @name ng.directive:ngKeypress - * - * @description - * Specify custom behavior on keypress event. - * - * @element ANY - * @param {expression} ngKeypress {@link guide/expression Expression} to evaluate upon - * keypress. (Event object is available as `$event` and can be interrogated for keyCode, altKey, etc.) - * - * @example - * See {@link ng.directive:ngClick ngClick} - */ - - -/** - * @ngdoc directive - * @name ng.directive:ngSubmit - * - * @description - * Enables binding angular expressions to onsubmit events. - * - * Additionally it prevents the default action (which for form means sending the request to the - * server and reloading the current page). - * - * @element form - * @param {expression} ngSubmit {@link guide/expression Expression} to eval. - * - * @example - - - -
                - Enter text and hit enter: - - -
                list={{list}}
                -
                -
                - - it('should check ng-submit', function() { - expect(binding('list')).toBe('[]'); - element('.doc-example-live #submit').click(); - expect(binding('list')).toBe('["hello"]'); - expect(input('text').val()).toBe(''); - }); - it('should ignore empty strings', function() { - expect(binding('list')).toBe('[]'); - element('.doc-example-live #submit').click(); - element('.doc-example-live #submit').click(); - expect(binding('list')).toBe('["hello"]'); - }); - -
                - */ -var ngSubmitDirective = ngDirective(function(scope, element, attrs) { - element.bind('submit', function() { - scope.$apply(attrs.ngSubmit); - }); -}); - -/** - * @ngdoc directive - * @name ng.directive:ngIf - * @restrict A - * - * @description - * The `ngIf` directive removes and recreates a portion of the DOM tree (HTML) - * conditionally based on **"falsy"** and **"truthy"** values, respectively, evaluated within - * an {expression}. In other words, if the expression assigned to **ngIf evaluates to a false - * value** then **the element is removed from the DOM** and **if true** then **a clone of the - * element is reinserted into the DOM**. - * - * `ngIf` differs from `ngShow` and `ngHide` in that `ngIf` completely removes and recreates the - * element in the DOM rather than changing its visibility via the `display` css property. A common - * case when this difference is significant is when using css selectors that rely on an element's - * position within the DOM (HTML), such as the `:first-child` or `:last-child` pseudo-classes. - * - * Note that **when an element is removed using ngIf its scope is destroyed** and **a new scope - * is created when the element is restored**. The scope created within `ngIf` inherits from - * its parent scope using - * {@link https://github.com/angular/angular.js/wiki/The-Nuances-of-Scope-Prototypal-Inheritance prototypal inheritance}. - * An important implication of this is if `ngModel` is used within `ngIf` to bind to - * a javascript primitive defined in the parent scope. In this case any modifications made to the - * variable within the child scope will override (hide) the value in the parent scope. - * - * Also, `ngIf` recreates elements using their compiled state. An example scenario of this behavior - * is if an element's class attribute is directly modified after it's compiled, using something like - * jQuery's `.addClass()` method, and the element is later removed. When `ngIf` recreates the element - * the added class will be lost because the original compiled state is used to regenerate the element. - * - * Additionally, you can provide animations via the ngAnimate attribute to animate the **enter** - * and **leave** effects. - * - * @animations - * enter - happens just after the ngIf contents change and a new DOM element is created and injected into the ngIf container - * leave - happens just before the ngIf contents are removed from the DOM - * - * @element ANY - * @scope - * @param {expression} ngIf If the {@link guide/expression expression} is falsy then - * the element is removed from the DOM tree (HTML). - * - * @example - - - Click me:
                - Show when checked: - - I'm removed when the checkbox is unchecked. - -
                - - .example-leave, .example-enter { - -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s; - -moz-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s; - -ms-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s; - -o-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s; - transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s; - } - - .example-enter { - opacity:0; - } - .example-enter.example-enter-active { - opacity:1; - } - - .example-leave { - opacity:1; - } - .example-leave.example-leave-active { - opacity:0; - } - -
                - */ -var ngIfDirective = ['$animator', function($animator) { - return { - transclude: 'element', - priority: 1000, - terminal: true, - restrict: 'A', - compile: function (element, attr, transclude) { - return function ($scope, $element, $attr) { - var animate = $animator($scope, $attr); - var childElement, childScope; - $scope.$watch($attr.ngIf, function ngIfWatchAction(value) { - if (childElement) { - animate.leave(childElement); - childElement = undefined; - } - if (childScope) { - childScope.$destroy(); - childScope = undefined; - } - if (toBoolean(value)) { - childScope = $scope.$new(); - transclude(childScope, function (clone) { - childElement = clone; - animate.enter(clone, $element.parent(), $element); - }); - } - }); - } - } - } -}]; - -/** - * @ngdoc directive - * @name ng.directive:ngInclude - * @restrict ECA - * - * @description - * Fetches, compiles and includes an external HTML fragment. - * - * Keep in mind that Same Origin Policy applies to included resources - * (e.g. ngInclude won't work for cross-domain requests on all browsers and for - * file:// access on some browsers). - * - * Additionally, you can also provide animations via the ngAnimate attribute to animate the **enter** - * and **leave** effects. - * - * @animations - * enter - happens just after the ngInclude contents change and a new DOM element is created and injected into the ngInclude container - * leave - happens just after the ngInclude contents change and just before the former contents are removed from the DOM - * - * @scope - * - * @param {string} ngInclude|src angular expression evaluating to URL. If the source is a string constant, - * make sure you wrap it in quotes, e.g. `src="'myPartialTemplate.html'"`. - * @param {string=} onload Expression to evaluate when a new partial is loaded. - * - * @param {string=} autoscroll Whether `ngInclude` should call {@link ng.$anchorScroll - * $anchorScroll} to scroll the viewport after the content is loaded. - * - * - If the attribute is not set, disable scrolling. - * - If the attribute is set without value, enable scrolling. - * - Otherwise enable scrolling only if the expression evaluates to truthy value. - * - * @example - - -
                - - url of the template: {{template.url}} -
                -
                -
                -
                - - function Ctrl($scope) { - $scope.templates = - [ { name: 'template1.html', url: 'template1.html'} - , { name: 'template2.html', url: 'template2.html'} ]; - $scope.template = $scope.templates[0]; - } - - -
                Content of template1.html
                -
                - -
                Content of template2.html
                -
                - - .example-leave, - .example-enter { - -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s; - -moz-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s; - -ms-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s; - -o-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s; - transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s; - - position:absolute; - top:0; - left:0; - right:0; - bottom:0; - } - - .example-animate-container > * { - display:block; - padding:10px; - } - - .example-enter { - top:-50px; - } - .example-enter.example-enter-active { - top:0; - } - - .example-leave { - top:0; - } - .example-leave.example-leave-active { - top:50px; - } - - - it('should load template1.html', function() { - expect(element('.doc-example-live [ng-include]').text()). - toMatch(/Content of template1.html/); - }); - it('should load template2.html', function() { - select('template').option('1'); - expect(element('.doc-example-live [ng-include]').text()). - toMatch(/Content of template2.html/); - }); - it('should change to blank', function() { - select('template').option(''); - expect(element('.doc-example-live [ng-include]').text()).toEqual(''); - }); - -
                - */ - - -/** - * @ngdoc event - * @name ng.directive:ngInclude#$includeContentRequested - * @eventOf ng.directive:ngInclude - * @eventType emit on the scope ngInclude was declared in - * @description - * Emitted every time the ngInclude content is requested. - */ - - -/** - * @ngdoc event - * @name ng.directive:ngInclude#$includeContentLoaded - * @eventOf ng.directive:ngInclude - * @eventType emit on the current ngInclude scope - * @description - * Emitted every time the ngInclude content is reloaded. - */ -var ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile', '$animator', - function($http, $templateCache, $anchorScroll, $compile, $animator) { - return { - restrict: 'ECA', - terminal: true, - compile: function(element, attr) { - var srcExp = attr.ngInclude || attr.src, - onloadExp = attr.onload || '', - autoScrollExp = attr.autoscroll; - - return function(scope, element, attr) { - var animate = $animator(scope, attr); - var changeCounter = 0, - childScope; - - var clearContent = function() { - if (childScope) { - childScope.$destroy(); - childScope = null; - } - animate.leave(element.contents(), element); - }; - - scope.$watch(srcExp, function ngIncludeWatchAction(src) { - var thisChangeId = ++changeCounter; - - if (src) { - $http.get(src, {cache: $templateCache}).success(function(response) { - if (thisChangeId !== changeCounter) return; - - if (childScope) childScope.$destroy(); - childScope = scope.$new(); - animate.leave(element.contents(), element); - - var contents = jqLite('
                ').html(response).contents(); - - animate.enter(contents, element); - $compile(contents)(childScope); - - if (isDefined(autoScrollExp) && (!autoScrollExp || scope.$eval(autoScrollExp))) { - $anchorScroll(); - } - - childScope.$emit('$includeContentLoaded'); - scope.$eval(onloadExp); - }).error(function() { - if (thisChangeId === changeCounter) clearContent(); - }); - scope.$emit('$includeContentRequested'); - } else { - clearContent(); - } - }); - }; - } - }; -}]; - -/** - * @ngdoc directive - * @name ng.directive:ngInit - * - * @description - * The `ngInit` directive specifies initialization tasks to be executed - * before the template enters execution mode during bootstrap. - * - * @element ANY - * @param {expression} ngInit {@link guide/expression Expression} to eval. - * - * @example - - -
                - {{greeting}} {{person}}! -
                -
                - - it('should check greeting', function() { - expect(binding('greeting')).toBe('Hello'); - expect(binding('person')).toBe('World'); - }); - -
                - */ -var ngInitDirective = ngDirective({ - compile: function() { - return { - pre: function(scope, element, attrs) { - scope.$eval(attrs.ngInit); - } - } - } -}); - -/** - * @ngdoc directive - * @name ng.directive:ngNonBindable - * @priority 1000 - * - * @description - * Sometimes it is necessary to write code which looks like bindings but which should be left alone - * by angular. Use `ngNonBindable` to make angular ignore a chunk of HTML. - * - * @element ANY - * - * @example - * In this example there are two location where a simple binding (`{{}}`) is present, but the one - * wrapped in `ngNonBindable` is left alone. - * - * @example - - -
                Normal: {{1 + 2}}
                -
                Ignored: {{1 + 2}}
                -
                - - it('should check ng-non-bindable', function() { - expect(using('.doc-example-live').binding('1 + 2')).toBe('3'); - expect(using('.doc-example-live').element('div:last').text()). - toMatch(/1 \+ 2/); - }); - -
                - */ -var ngNonBindableDirective = ngDirective({ terminal: true, priority: 1000 }); - -/** - * @ngdoc directive - * @name ng.directive:ngPluralize - * @restrict EA - * - * @description - * # Overview - * `ngPluralize` is a directive that displays messages according to en-US localization rules. - * These rules are bundled with angular.js and the rules can be overridden - * (see {@link guide/i18n Angular i18n} dev guide). You configure ngPluralize directive - * by specifying the mappings between - * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html - * plural categories} and the strings to be displayed. - * - * # Plural categories and explicit number rules - * There are two - * {@link http://unicode.org/repos/cldr-tmp/trunk/diff/supplemental/language_plural_rules.html - * plural categories} in Angular's default en-US locale: "one" and "other". - * - * While a plural category may match many numbers (for example, in en-US locale, "other" can match - * any number that is not 1), an explicit number rule can only match one number. For example, the - * explicit number rule for "3" matches the number 3. You will see the use of plural categories - * and explicit number rules throughout later parts of this documentation. - * - * # Configuring ngPluralize - * You configure ngPluralize by providing 2 attributes: `count` and `when`. - * You can also provide an optional attribute, `offset`. - * - * The value of the `count` attribute can be either a string or an {@link guide/expression - * Angular expression}; these are evaluated on the current scope for its bound value. - * - * The `when` attribute specifies the mappings between plural categories and the actual - * string to be displayed. The value of the attribute should be a JSON object so that Angular - * can interpret it correctly. - * - * The following example shows how to configure ngPluralize: - * - *
                - * 
                - * 
                - *
                - * - * In the example, `"0: Nobody is viewing."` is an explicit number rule. If you did not - * specify this rule, 0 would be matched to the "other" category and "0 people are viewing" - * would be shown instead of "Nobody is viewing". You can specify an explicit number rule for - * other numbers, for example 12, so that instead of showing "12 people are viewing", you can - * show "a dozen people are viewing". - * - * You can use a set of closed braces(`{}`) as a placeholder for the number that you want substituted - * into pluralized strings. In the previous example, Angular will replace `{}` with - * `{{personCount}}`. The closed braces `{}` is a placeholder - * for {{numberExpression}}. - * - * # Configuring ngPluralize with offset - * The `offset` attribute allows further customization of pluralized text, which can result in - * a better user experience. For example, instead of the message "4 people are viewing this document", - * you might display "John, Kate and 2 others are viewing this document". - * The offset attribute allows you to offset a number by any desired value. - * Let's take a look at an example: - * - *
                - * 
                - * 
                - * 
                - * - * Notice that we are still using two plural categories(one, other), but we added - * three explicit number rules 0, 1 and 2. - * When one person, perhaps John, views the document, "John is viewing" will be shown. - * When three people view the document, no explicit number rule is found, so - * an offset of 2 is taken off 3, and Angular uses 1 to decide the plural category. - * In this case, plural category 'one' is matched and "John, Marry and one other person are viewing" - * is shown. - * - * Note that when you specify offsets, you must provide explicit number rules for - * numbers from 0 up to and including the offset. If you use an offset of 3, for example, - * you must provide explicit number rules for 0, 1, 2 and 3. You must also provide plural strings for - * plural categories "one" and "other". - * - * @param {string|expression} count The variable to be bounded to. - * @param {string} when The mapping between plural category to its corresponding strings. - * @param {number=} offset Offset to deduct from the total number. - * - * @example - - - -
                - Person 1:
                - Person 2:
                - Number of People:
                - - - Without Offset: - -
                - - - With Offset(2): - - -
                -
                - - it('should show correct pluralized string', function() { - expect(element('.doc-example-live ng-pluralize:first').text()). - toBe('1 person is viewing.'); - expect(element('.doc-example-live ng-pluralize:last').text()). - toBe('Igor is viewing.'); - - using('.doc-example-live').input('personCount').enter('0'); - expect(element('.doc-example-live ng-pluralize:first').text()). - toBe('Nobody is viewing.'); - expect(element('.doc-example-live ng-pluralize:last').text()). - toBe('Nobody is viewing.'); - - using('.doc-example-live').input('personCount').enter('2'); - expect(element('.doc-example-live ng-pluralize:first').text()). - toBe('2 people are viewing.'); - expect(element('.doc-example-live ng-pluralize:last').text()). - toBe('Igor and Misko are viewing.'); - - using('.doc-example-live').input('personCount').enter('3'); - expect(element('.doc-example-live ng-pluralize:first').text()). - toBe('3 people are viewing.'); - expect(element('.doc-example-live ng-pluralize:last').text()). - toBe('Igor, Misko and one other person are viewing.'); - - using('.doc-example-live').input('personCount').enter('4'); - expect(element('.doc-example-live ng-pluralize:first').text()). - toBe('4 people are viewing.'); - expect(element('.doc-example-live ng-pluralize:last').text()). - toBe('Igor, Misko and 2 other people are viewing.'); - }); - - it('should show data-binded names', function() { - using('.doc-example-live').input('personCount').enter('4'); - expect(element('.doc-example-live ng-pluralize:last').text()). - toBe('Igor, Misko and 2 other people are viewing.'); - - using('.doc-example-live').input('person1').enter('Di'); - using('.doc-example-live').input('person2').enter('Vojta'); - expect(element('.doc-example-live ng-pluralize:last').text()). - toBe('Di, Vojta and 2 other people are viewing.'); - }); - -
                - */ -var ngPluralizeDirective = ['$locale', '$interpolate', function($locale, $interpolate) { - var BRACE = /{}/g; - return { - restrict: 'EA', - link: function(scope, element, attr) { - var numberExp = attr.count, - whenExp = element.attr(attr.$attr.when), // this is because we have {{}} in attrs - offset = attr.offset || 0, - whens = scope.$eval(whenExp), - whensExpFns = {}, - startSymbol = $interpolate.startSymbol(), - endSymbol = $interpolate.endSymbol(); - - forEach(whens, function(expression, key) { - whensExpFns[key] = - $interpolate(expression.replace(BRACE, startSymbol + numberExp + '-' + - offset + endSymbol)); - }); - - scope.$watch(function ngPluralizeWatch() { - var value = parseFloat(scope.$eval(numberExp)); - - if (!isNaN(value)) { - //if explicit number rule such as 1, 2, 3... is defined, just use it. Otherwise, - //check it against pluralization rules in $locale service - if (!(value in whens)) value = $locale.pluralCat(value - offset); - return whensExpFns[value](scope, element, true); - } else { - return ''; - } - }, function ngPluralizeWatchAction(newVal) { - element.text(newVal); - }); - } - }; -}]; - -/** - * @ngdoc directive - * @name ng.directive:ngRepeat - * - * @description - * The `ngRepeat` directive instantiates a template once per item from a collection. Each template - * instance gets its own scope, where the given loop variable is set to the current collection item, - * and `$index` is set to the item index or key. - * - * Special properties are exposed on the local scope of each template instance, including: - * - * * `$index` – `{number}` – iterator offset of the repeated element (0..length-1) - * * `$first` – `{boolean}` – true if the repeated element is first in the iterator. - * * `$middle` – `{boolean}` – true if the repeated element is between the first and last in the iterator. - * * `$last` – `{boolean}` – true if the repeated element is last in the iterator. - * - * Additionally, you can also provide animations via the ngAnimate attribute to animate the **enter**, - * **leave** and **move** effects. - * - * @animations - * enter - when a new item is added to the list or when an item is revealed after a filter - * leave - when an item is removed from the list or when an item is filtered out - * move - when an adjacent item is filtered out causing a reorder or when the item contents are reordered - * - * @element ANY - * @scope - * @priority 1000 - * @param {repeat_expression} ngRepeat The expression indicating how to enumerate a collection. These - * formats are currently supported: - * - * * `variable in expression` – where variable is the user defined loop variable and `expression` - * is a scope expression giving the collection to enumerate. - * - * For example: `track in cd.tracks`. - * - * * `(key, value) in expression` – where `key` and `value` can be any user defined identifiers, - * and `expression` is the scope expression giving the collection to enumerate. - * - * For example: `(name, age) in {'adam':10, 'amalie':12}`. - * - * * `variable in expression track by tracking_expression` – You can also provide an optional tracking function - * which can be used to associate the objects in the collection with the DOM elements. If no tractking function - * is specified the ng-repeat associates elements by identity in the collection. It is an error to have - * more then one tractking function to resolve to the same key. (This would mean that two distinct objects are - * mapped to the same DOM element, which is not possible.) - * - * For example: `item in items` is equivalent to `item in items track by $id(item)'. This implies that the DOM elements - * will be associated by item identity in the array. - * - * For example: `item in items track by $id(item)`. A built in `$id()` function can be used to assign a unique - * `$$hashKey` property to each item in the array. This property is then used as a key to associated DOM elements - * with the corresponding item in the array by identity. Moving the same object in array would move the DOM - * element in the same way ian the DOM. - * - * For example: `item in items track by item.id` Is a typical pattern when the items come from the database. In this - * case the object identity does not matter. Two objects are considered equivalent as long as their `id` - * property is same. - * - * @example - * This example initializes the scope to a list of names and - * then uses `ngRepeat` to display every person: - - -
                - I have {{friends.length}} friends. They are: - -
                  -
                • - [{{$index + 1}}] {{friend.name}} who is {{friend.age}} years old. -
                • -
                -
                -
                - - .example-repeat-enter, - .example-repeat-leave, - .example-repeat-move { - -webkit-transition:all linear 0.5s; - -moz-transition:all linear 0.5s; - -ms-transition:all linear 0.5s; - -o-transition:all linear 0.5s; - transition:all linear 0.5s; - } - - .example-repeat-enter { - line-height:0; - opacity:0; - } - .example-repeat-enter.example-repeat-enter-active { - line-height:20px; - opacity:1; - } - - .example-repeat-leave { - opacity:1; - line-height:20px; - } - .example-repeat-leave.example-repeat-leave-active { - opacity:0; - line-height:0; - } - - .example-repeat-move { } - .example-repeat-move.example-repeat-move-active { } - - - it('should render initial data set', function() { - var r = using('.doc-example-live').repeater('ul li'); - expect(r.count()).toBe(10); - expect(r.row(0)).toEqual(["1","John","25"]); - expect(r.row(1)).toEqual(["2","Jessie","30"]); - expect(r.row(9)).toEqual(["10","Samantha","60"]); - expect(binding('friends.length')).toBe("10"); - }); - - it('should update repeater when filter predicate changes', function() { - var r = using('.doc-example-live').repeater('ul li'); - expect(r.count()).toBe(10); - - input('q').enter('ma'); - - expect(r.count()).toBe(2); - expect(r.row(0)).toEqual(["1","Mary","28"]); - expect(r.row(1)).toEqual(["2","Samantha","60"]); - }); - -
                - */ -var ngRepeatDirective = ['$parse', '$animator', function($parse, $animator) { - var NG_REMOVED = '$$NG_REMOVED'; - return { - transclude: 'element', - priority: 1000, - terminal: true, - compile: function(element, attr, linker) { - return function($scope, $element, $attr){ - var animate = $animator($scope, $attr); - var expression = $attr.ngRepeat; - var match = expression.match(/^\s*(.+)\s+in\s+(.*?)\s*(\s+track\s+by\s+(.+)\s*)?$/), - trackByExp, trackByExpGetter, trackByIdFn, lhs, rhs, valueIdentifier, keyIdentifier, - hashFnLocals = {$id: hashKey}; - - if (!match) { - throw Error("Expected ngRepeat in form of '_item_ in _collection_[ track by _id_]' but got '" + - expression + "'."); - } - - lhs = match[1]; - rhs = match[2]; - trackByExp = match[4]; - - if (trackByExp) { - trackByExpGetter = $parse(trackByExp); - trackByIdFn = function(key, value, index) { - // assign key, value, and $index to the locals so that they can be used in hash functions - if (keyIdentifier) hashFnLocals[keyIdentifier] = key; - hashFnLocals[valueIdentifier] = value; - hashFnLocals.$index = index; - return trackByExpGetter($scope, hashFnLocals); - }; - } else { - trackByIdFn = function(key, value) { - return hashKey(value); - } - } - - match = lhs.match(/^(?:([\$\w]+)|\(([\$\w]+)\s*,\s*([\$\w]+)\))$/); - if (!match) { - throw Error("'item' in 'item in collection' should be identifier or (key, value) but got '" + - lhs + "'."); - } - valueIdentifier = match[3] || match[1]; - keyIdentifier = match[2]; - - // Store a list of elements from previous run. This is a hash where key is the item from the - // iterator, and the value is objects with following properties. - // - scope: bound scope - // - element: previous element. - // - index: position - var lastBlockMap = {}; - - //watch props - $scope.$watchCollection(rhs, function ngRepeatAction(collection){ - var index, length, - cursor = $element, // current position of the node - nextCursor, - // Same as lastBlockMap but it has the current state. It will become the - // lastBlockMap on the next iteration. - nextBlockMap = {}, - arrayLength, - childScope, - key, value, // key/value of iteration - trackById, - collectionKeys, - block, // last object information {scope, element, id} - nextBlockOrder = []; - - - if (isArrayLike(collection)) { - collectionKeys = collection; - } else { - // if object, extract keys, sort them and use to determine order of iteration over obj props - collectionKeys = []; - for (key in collection) { - if (collection.hasOwnProperty(key) && key.charAt(0) != '$') { - collectionKeys.push(key); - } - } - collectionKeys.sort(); - } - - arrayLength = collectionKeys.length; - - // locate existing items - length = nextBlockOrder.length = collectionKeys.length; - for(index = 0; index < length; index++) { - key = (collection === collectionKeys) ? index : collectionKeys[index]; - value = collection[key]; - trackById = trackByIdFn(key, value, index); - if(lastBlockMap.hasOwnProperty(trackById)) { - block = lastBlockMap[trackById] - delete lastBlockMap[trackById]; - nextBlockMap[trackById] = block; - nextBlockOrder[index] = block; - } else if (nextBlockMap.hasOwnProperty(trackById)) { - // restore lastBlockMap - forEach(nextBlockOrder, function(block) { - if (block && block.element) lastBlockMap[block.id] = block; - }); - // This is a duplicate and we need to throw an error - throw new Error('Duplicates in a repeater are not allowed. Repeater: ' + expression + - ' key: ' + trackById); - } else { - // new never before seen block - nextBlockOrder[index] = { id: trackById }; - nextBlockMap[trackById] = false; - } - } - - // remove existing items - for (key in lastBlockMap) { - if (lastBlockMap.hasOwnProperty(key)) { - block = lastBlockMap[key]; - animate.leave(block.element); - block.element[0][NG_REMOVED] = true; - block.scope.$destroy(); - } - } - - // we are not using forEach for perf reasons (trying to avoid #call) - for (index = 0, length = collectionKeys.length; index < length; index++) { - key = (collection === collectionKeys) ? index : collectionKeys[index]; - value = collection[key]; - block = nextBlockOrder[index]; - - if (block.element) { - // if we have already seen this object, then we need to reuse the - // associated scope/element - childScope = block.scope; - - nextCursor = cursor[0]; - do { - nextCursor = nextCursor.nextSibling; - } while(nextCursor && nextCursor[NG_REMOVED]); - - if (block.element[0] == nextCursor) { - // do nothing - cursor = block.element; - } else { - // existing item which got moved - animate.move(block.element, null, cursor); - cursor = block.element; - } - } else { - // new item which we don't know about - childScope = $scope.$new(); - } - - childScope[valueIdentifier] = value; - if (keyIdentifier) childScope[keyIdentifier] = key; - childScope.$index = index; - childScope.$first = (index === 0); - childScope.$last = (index === (arrayLength - 1)); - childScope.$middle = !(childScope.$first || childScope.$last); - - if (!block.element) { - linker(childScope, function(clone) { - animate.enter(clone, null, cursor); - cursor = clone; - block.scope = childScope; - block.element = clone; - nextBlockMap[block.id] = block; - }); - } - } - lastBlockMap = nextBlockMap; - }); - }; - } - }; -}]; - -/** - * @ngdoc directive - * @name ng.directive:ngShow - * - * @description - * The `ngShow` and `ngHide` directives show or hide a portion of the DOM tree (HTML) - * conditionally based on **"truthy"** values evaluated within an {expression}. In other - * words, if the expression assigned to **ngShow evaluates to a true value** then **the element is set to visible** - * (via `display:block` in css) and **if false** then **the element is set to hidden** (so display:none). - * With ngHide this is the reverse whereas true values cause the element itself to become - * hidden. - * - * Additionally, you can also provide animations via the ngAnimate attribute to animate the **show** - * and **hide** effects. - * - * @animations - * show - happens after the ngShow expression evaluates to a truthy value and the contents are set to visible - * hide - happens before the ngShow expression evaluates to a non truthy value and just before the contents are set to hidden - * - * @element ANY - * @param {expression} ngShow If the {@link guide/expression expression} is truthy - * then the element is shown or hidden respectively. - * - * @example - - - Click me:
                -
                - Show: - - I show up when your checkbox is checked. - -
                -
                - Hide: - - I hide when your checkbox is checked. - -
                -
                - - .example-show, .example-hide { - -webkit-transition:all linear 0.5s; - -moz-transition:all linear 0.5s; - -ms-transition:all linear 0.5s; - -o-transition:all linear 0.5s; - transition:all linear 0.5s; - } - - .example-show { - line-height:0; - opacity:0; - padding:0 10px; - } - .example-show-active.example-show-active { - line-height:20px; - opacity:1; - padding:10px; - border:1px solid black; - background:white; - } - - .example-hide { - line-height:20px; - opacity:1; - padding:10px; - border:1px solid black; - background:white; - } - .example-hide-active.example-hide-active { - line-height:0; - opacity:0; - padding:0 10px; - } - - .check-element { - padding:10px; - border:1px solid black; - background:white; - } - - - it('should check ng-show / ng-hide', function() { - expect(element('.doc-example-live span:first:hidden').count()).toEqual(1); - expect(element('.doc-example-live span:last:visible').count()).toEqual(1); - - input('checked').check(); - - expect(element('.doc-example-live span:first:visible').count()).toEqual(1); - expect(element('.doc-example-live span:last:hidden').count()).toEqual(1); - }); - -
                - */ -//TODO(misko): refactor to remove element from the DOM -var ngShowDirective = ['$animator', function($animator) { - return function(scope, element, attr) { - var animate = $animator(scope, attr); - scope.$watch(attr.ngShow, function ngShowWatchAction(value){ - animate[toBoolean(value) ? 'show' : 'hide'](element); - }); - }; -}]; - - -/** - * @ngdoc directive - * @name ng.directive:ngHide - * - * @description - * The `ngShow` and `ngHide` directives show or hide a portion of the DOM tree (HTML) - * conditionally based on **"truthy"** values evaluated within an {expression}. In other - * words, if the expression assigned to **ngShow evaluates to a true value** then **the element is set to visible** - * (via `display:block` in css) and **if false** then **the element is set to hidden** (so display:none). - * With ngHide this is the reverse whereas true values cause the element itself to become - * hidden. - * - * Additionally, you can also provide animations via the ngAnimate attribute to animate the **show** - * and **hide** effects. - * - * @animations - * show - happens after the ngHide expression evaluates to a non truthy value and the contents are set to visible - * hide - happens after the ngHide expression evaluates to a truthy value and just before the contents are set to hidden - * - * @element ANY - * @param {expression} ngHide If the {@link guide/expression expression} is truthy then - * the element is shown or hidden respectively. - * - * @example - - - Click me:
                -
                - Show: - - I show up when your checkbox is checked. - -
                -
                - Hide: - - I hide when your checkbox is checked. - -
                -
                - - .example-show, .example-hide { - -webkit-transition:all linear 0.5s; - -moz-transition:all linear 0.5s; - -ms-transition:all linear 0.5s; - -o-transition:all linear 0.5s; - transition:all linear 0.5s; - } - - .example-show { - line-height:0; - opacity:0; - padding:0 10px; - } - .example-show.example-show-active { - line-height:20px; - opacity:1; - padding:10px; - border:1px solid black; - background:white; - } - - .example-hide { - line-height:20px; - opacity:1; - padding:10px; - border:1px solid black; - background:white; - } - .example-hide.example-hide-active { - line-height:0; - opacity:0; - padding:0 10px; - } - - .check-element { - padding:10px; - border:1px solid black; - background:white; - } - - - it('should check ng-show / ng-hide', function() { - expect(element('.doc-example-live .check-element:first:hidden').count()).toEqual(1); - expect(element('.doc-example-live .check-element:last:visible').count()).toEqual(1); - - input('checked').check(); - - expect(element('.doc-example-live .check-element:first:visible').count()).toEqual(1); - expect(element('.doc-example-live .check-element:last:hidden').count()).toEqual(1); - }); - -
                - */ -//TODO(misko): refactor to remove element from the DOM -var ngHideDirective = ['$animator', function($animator) { - return function(scope, element, attr) { - var animate = $animator(scope, attr); - scope.$watch(attr.ngHide, function ngHideWatchAction(value){ - animate[toBoolean(value) ? 'hide' : 'show'](element); - }); - }; -}]; - -/** - * @ngdoc directive - * @name ng.directive:ngStyle - * - * @description - * The `ngStyle` directive allows you to set CSS style on an HTML element conditionally. - * - * @element ANY - * @param {expression} ngStyle {@link guide/expression Expression} which evals to an - * object whose keys are CSS style names and values are corresponding values for those CSS - * keys. - * - * @example - - - - -
                - Sample Text -
                myStyle={{myStyle}}
                -
                - - span { - color: black; - } - - - it('should check ng-style', function() { - expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)'); - element('.doc-example-live :button[value=set]').click(); - expect(element('.doc-example-live span').css('color')).toBe('rgb(255, 0, 0)'); - element('.doc-example-live :button[value=clear]').click(); - expect(element('.doc-example-live span').css('color')).toBe('rgb(0, 0, 0)'); - }); - -
                - */ -var ngStyleDirective = ngDirective(function(scope, element, attr) { - scope.$watch(attr.ngStyle, function ngStyleWatchAction(newStyles, oldStyles) { - if (oldStyles && (newStyles !== oldStyles)) { - forEach(oldStyles, function(val, style) { element.css(style, '');}); - } - if (newStyles) element.css(newStyles); - }, true); -}); - -/** - * @ngdoc directive - * @name ng.directive:ngSwitch - * @restrict EA - * - * @description - * The ngSwitch directive is used to conditionally swap DOM structure on your template based on a scope expression. - * Elements within ngSwitch but without ngSwitchWhen or ngSwitchDefault directives will be preserved at the location - * as specified in the template. - * - * The directive itself works similar to ngInclude, however, instead of downloading template code (or loading it - * from the template cache), ngSwitch simply choses one of the nested elements and makes it visible based on which element - * matches the value obtained from the evaluated expression. In other words, you define a container element - * (where you place the directive), place an expression on the **on="..." attribute** - * (or the **ng-switch="..." attribute**), define any inner elements inside of the directive and place - * a when attribute per element. The when attribute is used to inform ngSwitch which element to display when the on - * expression is evaluated. If a matching expression is not found via a when attribute then an element with the default - * attribute is displayed. - * - * Additionally, you can also provide animations via the ngAnimate attribute to animate the **enter** - * and **leave** effects. - * - * @animations - * enter - happens after the ngSwtich contents change and the matched child element is placed inside the container - * leave - happens just after the ngSwitch contents change and just before the former contents are removed from the DOM - * - * @usage - * - * ... - * ... - * ... - * - * - * @scope - * @param {*} ngSwitch|on expression to match against ng-switch-when. - * @paramDescription - * On child elements add: - * - * * `ngSwitchWhen`: the case statement to match against. If match then this - * case will be displayed. If the same match appears multiple times, all the - * elements will be displayed. - * * `ngSwitchDefault`: the default case when no other case match. If there - * are multiple default cases, all of them will be displayed when no other - * case match. - * - * - * @example - - -
                - - selection={{selection}} -
                -
                -
                Settings Div
                -
                Home Span
                -
                default
                -
                -
                -
                - - function Ctrl($scope) { - $scope.items = ['settings', 'home', 'other']; - $scope.selection = $scope.items[0]; - } - - - .example-leave, .example-enter { - -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s; - -moz-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s; - -ms-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s; - -o-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s; - transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 0.5s; - - position:absolute; - top:0; - left:0; - right:0; - bottom:0; - } - - .example-animate-container > * { - display:block; - padding:10px; - } - - .example-enter { - top:-50px; - } - .example-enter.example-enter-active { - top:0; - } - - .example-leave { - top:0; - } - .example-leave.example-leave-active { - top:50px; - } - - - it('should start in settings', function() { - expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Settings Div/); - }); - it('should change to home', function() { - select('selection').option('home'); - expect(element('.doc-example-live [ng-switch]').text()).toMatch(/Home Span/); - }); - it('should select default', function() { - select('selection').option('other'); - expect(element('.doc-example-live [ng-switch]').text()).toMatch(/default/); - }); - -
                - */ -var ngSwitchDirective = ['$animator', function($animator) { - return { - restrict: 'EA', - require: 'ngSwitch', - - // asks for $scope to fool the BC controller module - controller: ['$scope', function ngSwitchController() { - this.cases = {}; - }], - link: function(scope, element, attr, ngSwitchController) { - var animate = $animator(scope, attr); - var watchExpr = attr.ngSwitch || attr.on, - selectedTranscludes, - selectedElements, - selectedScopes = []; - - scope.$watch(watchExpr, function ngSwitchWatchAction(value) { - for (var i= 0, ii=selectedScopes.length; i - - -
                -
                -
                - {{text}} -
                -
                - - it('should have transcluded', function() { - input('title').enter('TITLE'); - input('text').enter('TEXT'); - expect(binding('title')).toEqual('TITLE'); - expect(binding('text')).toEqual('TEXT'); - }); - - - * - */ -var ngTranscludeDirective = ngDirective({ - controller: ['$transclude', '$element', function($transclude, $element) { - $transclude(function(clone) { - $element.append(clone); - }); - }] -}); - -/** - * @ngdoc directive - * @name ng.directive:ngView - * @restrict ECA - * - * @description - * # Overview - * `ngView` is a directive that complements the {@link ng.$route $route} service by - * including the rendered template of the current route into the main layout (`index.html`) file. - * Every time the current route changes, the included view changes with it according to the - * configuration of the `$route` service. - * - * Additionally, you can also provide animations via the ngAnimate attribute to animate the **enter** - * and **leave** effects. - * - * @animations - * enter - happens just after the ngView contents are changed (when the new view DOM element is inserted into the DOM) - * leave - happens just after the current ngView contents change and just before the former contents are removed from the DOM - * - * @scope - * @example - - -
                - Choose: - Moby | - Moby: Ch1 | - Gatsby | - Gatsby: Ch4 | - Scarlet Letter
                - -
                -
                - -
                $location.path() = {{main.$location.path()}}
                -
                $route.current.templateUrl = {{main.$route.current.templateUrl}}
                -
                $route.current.params = {{main.$route.current.params}}
                -
                $route.current.scope.name = {{main.$route.current.scope.name}}
                -
                $routeParams = {{main.$routeParams}}
                -
                -
                - - -
                - controller: {{book.name}}
                - Book Id: {{book.params.bookId}}
                -
                -
                - - -
                - controller: {{chapter.name}}
                - Book Id: {{chapter.params.bookId}}
                - Chapter Id: {{chapter.params.chapterId}} -
                -
                - - - .example-leave, .example-enter { - -webkit-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s; - -moz-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s; - -ms-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s; - -o-transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s; - transition:all cubic-bezier(0.250, 0.460, 0.450, 0.940) 1.5s; - } - - .example-animate-container { - position:relative; - height:100px; - } - - .example-animate-container > * { - display:block; - width:100%; - border-left:1px solid black; - - position:absolute; - top:0; - left:0; - right:0; - bottom:0; - padding:10px; - } - - .example-enter { - left:100%; - } - .example-enter.example-enter-active { - left:0; - } - - .example-leave { } - .example-leave.example-leave-active { - left:-100%; - } - - - - angular.module('ngView', [], function($routeProvider, $locationProvider) { - $routeProvider.when('/Book/:bookId', { - templateUrl: 'book.html', - controller: BookCntl, - controllerAs: 'book' - }); - $routeProvider.when('/Book/:bookId/ch/:chapterId', { - templateUrl: 'chapter.html', - controller: ChapterCntl, - controllerAs: 'chapter' - }); - - // configure html5 to get links working on jsfiddle - $locationProvider.html5Mode(true); - }); - - function MainCntl($route, $routeParams, $location) { - this.$route = $route; - this.$location = $location; - this.$routeParams = $routeParams; - } - - function BookCntl($routeParams) { - this.name = "BookCntl"; - this.params = $routeParams; - } - - function ChapterCntl($routeParams) { - this.name = "ChapterCntl"; - this.params = $routeParams; - } - - - - it('should load and compile correct template', function() { - element('a:contains("Moby: Ch1")').click(); - var content = element('.doc-example-live [ng-view]').text(); - expect(content).toMatch(/controller\: ChapterCntl/); - expect(content).toMatch(/Book Id\: Moby/); - expect(content).toMatch(/Chapter Id\: 1/); - - element('a:contains("Scarlet")').click(); - content = element('.doc-example-live [ng-view]').text(); - expect(content).toMatch(/controller\: BookCntl/); - expect(content).toMatch(/Book Id\: Scarlet/); - }); - -
                - */ - - -/** - * @ngdoc event - * @name ng.directive:ngView#$viewContentLoaded - * @eventOf ng.directive:ngView - * @eventType emit on the current ngView scope - * @description - * Emitted every time the ngView content is reloaded. - */ -var ngViewDirective = ['$http', '$templateCache', '$route', '$anchorScroll', '$compile', - '$controller', '$animator', - function($http, $templateCache, $route, $anchorScroll, $compile, - $controller, $animator) { - return { - restrict: 'ECA', - terminal: true, - link: function(scope, element, attr) { - var lastScope, - onloadExp = attr.onload || '', - animate = $animator(scope, attr); - - scope.$on('$routeChangeSuccess', update); - update(); - - - function destroyLastScope() { - if (lastScope) { - lastScope.$destroy(); - lastScope = null; - } - } - - function clearContent() { - animate.leave(element.contents(), element); - destroyLastScope(); - } - - function update() { - var locals = $route.current && $route.current.locals, - template = locals && locals.$template; - - if (template) { - clearContent(); - var enterElements = jqLite('
                ').html(template).contents(); - animate.enter(enterElements, element); - - var link = $compile(enterElements), - current = $route.current, - controller; - - lastScope = current.scope = scope.$new(); - if (current.controller) { - locals.$scope = lastScope; - controller = $controller(current.controller, locals); - if (current.controllerAs) { - lastScope[current.controllerAs] = controller; - } - element.children().data('$ngControllerController', controller); - } - - link(lastScope); - lastScope.$emit('$viewContentLoaded'); - lastScope.$eval(onloadExp); - - // $anchorScroll might listen on event... - $anchorScroll(); - } else { - clearContent(); - } - } - } - }; -}]; - -/** - * @ngdoc directive - * @name ng.directive:script - * - * @description - * Load content of a script tag, with type `text/ng-template`, into `$templateCache`, so that the - * template can be used by `ngInclude`, `ngView` or directive templates. - * - * @restrict E - * @param {'text/ng-template'} type must be set to `'text/ng-template'` - * - * @example - - - - - Load inlined template -
                -
                - - it('should load template defined inside script tag', function() { - element('#tpl-link').click(); - expect(element('#tpl-content').text()).toMatch(/Content of the template/); - }); - -
                - */ -var scriptDirective = ['$templateCache', function($templateCache) { - return { - restrict: 'E', - terminal: true, - compile: function(element, attr) { - if (attr.type == 'text/ng-template') { - var templateUrl = attr.id, - // IE is not consistent, in scripts we have to read .text but in other nodes we have to read .textContent - text = element[0].text; - - $templateCache.put(templateUrl, text); - } - } - }; -}]; - -/** - * @ngdoc directive - * @name ng.directive:select - * @restrict E - * - * @description - * HTML `SELECT` element with angular data-binding. - * - * # `ngOptions` - * - * Optionally `ngOptions` attribute can be used to dynamically generate a list of `
                - - - it('should check ng-options', function() { - expect(binding('{selected_color:color}')).toMatch('red'); - select('color').option('0'); - expect(binding('{selected_color:color}')).toMatch('black'); - using('.nullable').select('color').option(''); - expect(binding('{selected_color:color}')).toMatch('null'); - }); - - - */ - -var ngOptionsDirective = valueFn({ terminal: true }); -var selectDirective = ['$compile', '$parse', function($compile, $parse) { - //0000111110000000000022220000000000000000000000333300000000000000444444444444444440000000005555555555555555500000006666666666666666600000000000000007777000000000000000000088888 - var NG_OPTIONS_REGEXP = /^\s*(.*?)(?:\s+as\s+(.*?))?(?:\s+group\s+by\s+(.*))?\s+for\s+(?:([\$\w][\$\w\d]*)|(?:\(\s*([\$\w][\$\w\d]*)\s*,\s*([\$\w][\$\w\d]*)\s*\)))\s+in\s+(.*?)(?:\s+track\s+by\s+(.*?))?$/, - nullModelCtrl = {$setViewValue: noop}; - - return { - restrict: 'E', - require: ['select', '?ngModel'], - controller: ['$element', '$scope', '$attrs', function($element, $scope, $attrs) { - var self = this, - optionsMap = {}, - ngModelCtrl = nullModelCtrl, - nullOption, - unknownOption; - - - self.databound = $attrs.ngModel; - - - self.init = function(ngModelCtrl_, nullOption_, unknownOption_) { - ngModelCtrl = ngModelCtrl_; - nullOption = nullOption_; - unknownOption = unknownOption_; - } - - - self.addOption = function(value) { - optionsMap[value] = true; - - if (ngModelCtrl.$viewValue == value) { - $element.val(value); - if (unknownOption.parent()) unknownOption.remove(); - } - }; - - - self.removeOption = function(value) { - if (this.hasOption(value)) { - delete optionsMap[value]; - if (ngModelCtrl.$viewValue == value) { - this.renderUnknownOption(value); - } - } - }; - - - self.renderUnknownOption = function(val) { - var unknownVal = '? ' + hashKey(val) + ' ?'; - unknownOption.val(unknownVal); - $element.prepend(unknownOption); - $element.val(unknownVal); - unknownOption.prop('selected', true); // needed for IE - } - - - self.hasOption = function(value) { - return optionsMap.hasOwnProperty(value); - } - - $scope.$on('$destroy', function() { - // disable unknown option so that we don't do work when the whole select is being destroyed - self.renderUnknownOption = noop; - }); - }], - - link: function(scope, element, attr, ctrls) { - // if ngModel is not defined, we don't need to do anything - if (!ctrls[1]) return; - - var selectCtrl = ctrls[0], - ngModelCtrl = ctrls[1], - multiple = attr.multiple, - optionsExp = attr.ngOptions, - nullOption = false, // if false, user will not be able to select it (used by ngOptions) - emptyOption, - // we can't just jqLite('