Compare commits
156 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7fa2fdba3b | |||
| b871be1392 | |||
| 65bfce7d68 | |||
| 67126bd3a0 | |||
| ce6558fd80 | |||
| 64f6a616d4 | |||
| 07b8761233 | |||
| 2e7121b8e4 | |||
| da3f2df163 | |||
| 51944b3999 | |||
| 612589d0bc | |||
| 1b32fad833 | |||
| 3bf758063e | |||
| 82ea2de3fb | |||
| 8ace661ba5 | |||
| 8a9cd3e01d | |||
| 9ea37de0f5 | |||
| b44432a719 | |||
| ac0e10d287 | |||
| 1237c77850 | |||
| 9a9b07dea8 | |||
| 8b913b99d9 | |||
| 4edd2d95c1 | |||
| 353e3a6cd8 | |||
| 6ce2913d99 | |||
| 6a24885771 | |||
| 367da583bc | |||
| 68fb70ed29 | |||
| e8e8186d40 | |||
| 0f3385d45d | |||
| 4897430559 | |||
| 098b6f519a | |||
| 549edc9d01 | |||
| 6ed4c61e72 | |||
| f83c3dea23 | |||
| f60254f79a | |||
| d2a57b9dff | |||
| 33a693ea62 | |||
| dd1a957bb3 | |||
| 775c247085 | |||
| 4d753d197a | |||
| 8b51d03c83 | |||
| b1bc25169e | |||
| 9f10428651 | |||
| 6b28705dbf | |||
| 802cdf6ccb | |||
| a19d026bff | |||
| d23512c7f3 | |||
| 8e58e22d93 | |||
| 42cff065b8 | |||
| 2c852cf62a | |||
| bf4f51573d | |||
| 5a7dc50f26 | |||
| f9e7dabb2a | |||
| 296da4b561 | |||
| 9019c2dac5 | |||
| 83a12a54a2 | |||
| 9fdb4f8c51 | |||
| fcce237902 | |||
| d7e31b5dc7 | |||
| b014607030 | |||
| fd46fc80ee | |||
| d26ba3b941 | |||
| 6fa1bb03db | |||
| 8ebd716c57 | |||
| cb94d562df | |||
| d31b3a65b6 | |||
| 5a70888153 | |||
| 3475b19482 | |||
| 00a30fad82 | |||
| 22b669407c | |||
| 99a063f9cb | |||
| 27db9f018e | |||
| 2ed2399d49 | |||
| 9d2de344f5 | |||
| 9c0659ca27 | |||
| 3b9963c54a | |||
| 26db937377 | |||
| 1d0e582b3f | |||
| a6b58019e1 | |||
| 38fd896b74 | |||
| f96d553822 | |||
| f4149b70bc | |||
| 8a8c94c3d5 | |||
| d9de526059 | |||
| 0318761f7a | |||
| 74f7b57823 | |||
| 995ccfc9f6 | |||
| 72c244564a | |||
| 4bfe7e8663 | |||
| 63fe144397 | |||
| 0f551e6109 | |||
| 541f4ba21f | |||
| 6e7d04ddb2 | |||
| 06fb391687 | |||
| 203dd4d1e3 | |||
| c991f93817 | |||
| 52ddc13bee | |||
| 1645924d49 | |||
| 6bee655679 | |||
| acd455181d | |||
| a89b6e27a9 | |||
| 46d559dc8d | |||
| 26212fb204 | |||
| 244cfc7cd5 | |||
| c6074dc34c | |||
| 4930ef2bfe | |||
| 1778d347cd | |||
| 4724d56c93 | |||
| 70fcffc375 | |||
| 181e44019e | |||
| 5ce859bcdd | |||
| fb994e4d90 | |||
| 55f26fc246 | |||
| 1161002857 | |||
| 7ccfe92bed | |||
| a126fcfee3 | |||
| f22af2b874 | |||
| 2ca4170903 | |||
| fd57df1235 | |||
| 3010ed4ee5 | |||
| de59ca7107 | |||
| fa3214cfb8 | |||
| a8cacfe938 | |||
| 1a387ba5dd | |||
| 98e4a220fe | |||
| 9001ae2822 | |||
| c405f88bbc | |||
| 159a68ec7b | |||
| b9a56d588f | |||
| f797f83cd6 | |||
| 6df970eb3c | |||
| f88b4be92f | |||
| a7bcc01581 | |||
| 40ed8094d1 | |||
| 1a722f7b19 | |||
| 4991207c7c | |||
| 33514ec384 | |||
| 28bd20ed30 | |||
| c3bfd7f59d | |||
| 553cccdb85 | |||
| c7dd2c24f4 | |||
| fbf5aebda2 | |||
| ab35c16ccf | |||
| 37b6a71678 | |||
| e79ebff223 | |||
| 36b38e1355 | |||
| 3168d95793 | |||
| 538c63f057 | |||
| a9a1461351 | |||
| 29190f9318 | |||
| ca7d2b3b3f | |||
| 81676f8323 | |||
| 6f9d07d9c7 | |||
| 5201b8146a | |||
| 6aa83d04b7 |
@@ -0,0 +1,11 @@
|
||||
bower_components/**
|
||||
build/**
|
||||
docs/bower_components/**
|
||||
docs/app/assets/js/angular-bootstrap/**
|
||||
docs/config/templates/**
|
||||
node_modules/**
|
||||
lib/htmlparser/**
|
||||
src/angular.bind.js
|
||||
src/ngParseExt/ucd.js
|
||||
i18n/closure/**
|
||||
tmp/**
|
||||
@@ -0,0 +1,117 @@
|
||||
{
|
||||
"rules": {
|
||||
// Rules are divided into sections from http://eslint.org/docs/rules/
|
||||
|
||||
// Possible errors
|
||||
"comma-dangle": ["error", "never"],
|
||||
"no-cond-assign": ["error", "except-parens"],
|
||||
"no-constant-condition": ["error", {"checkLoops": false}],
|
||||
"no-control-regex": "error",
|
||||
"no-debugger": "error",
|
||||
"no-dupe-args": "error",
|
||||
"no-dupe-keys": "error",
|
||||
"no-duplicate-case": "error",
|
||||
"no-empty-character-class": "error",
|
||||
"no-empty": "error",
|
||||
"no-ex-assign": "error",
|
||||
"no-extra-boolean-cast": "error",
|
||||
"no-extra-semi": "error",
|
||||
"no-func-assign": "error",
|
||||
"no-inner-declarations": "error",
|
||||
"no-invalid-regexp": "error",
|
||||
"no-irregular-whitespace": "error",
|
||||
"no-negated-in-lhs": "error",
|
||||
"no-obj-calls": "error",
|
||||
"no-regex-spaces": "error",
|
||||
"no-sparse-arrays": "error",
|
||||
"no-unreachable": "error",
|
||||
"use-isnan": "error",
|
||||
"no-unsafe-finally": "error",
|
||||
"valid-typeof": "error",
|
||||
"no-unexpected-multiline": "error",
|
||||
|
||||
// Best practices
|
||||
"accessor-pairs": "error",
|
||||
"array-callback-return": "error",
|
||||
"eqeqeq": ["error", "allow-null"],
|
||||
"no-alert": "error",
|
||||
"no-caller": "error",
|
||||
"no-case-declarations": "error",
|
||||
"no-eval": "error",
|
||||
"no-extend-native": "error",
|
||||
"no-extra-bind": "error",
|
||||
"no-extra-label": "error",
|
||||
"no-fallthrough": "error",
|
||||
"no-floating-decimal": "error",
|
||||
"no-implied-eval": "error",
|
||||
"no-invalid-this": "error",
|
||||
"no-iterator": "error",
|
||||
"no-multi-str": "error",
|
||||
"no-new-func": "error",
|
||||
"no-new-wrappers": "error",
|
||||
"no-new": "error",
|
||||
"no-octal-escape": "error",
|
||||
"no-octal": "error",
|
||||
"no-proto": "error",
|
||||
"no-redeclare": "error",
|
||||
"no-return-assign": "error",
|
||||
"no-script-url": "error",
|
||||
"no-self-assign": "error",
|
||||
"no-self-compare": "error",
|
||||
"no-sequences": "error",
|
||||
"no-throw-literal": "error",
|
||||
"no-unmodified-loop-condition": "error",
|
||||
"no-unused-expressions": "error",
|
||||
"no-unused-labels": "error",
|
||||
"no-useless-call": "error",
|
||||
"no-useless-concat": "error",
|
||||
"no-useless-escape": "error",
|
||||
"no-void": "error",
|
||||
"no-with": "error",
|
||||
"radix": "error",
|
||||
"wrap-iife": ["error", "inside"],
|
||||
|
||||
// Strict mode
|
||||
"strict": ["error", "global"],
|
||||
|
||||
// Variables
|
||||
"no-delete-var": "error",
|
||||
"no-label-var": "error",
|
||||
"no-restricted-globals": ["error", "event"],
|
||||
"no-shadow-restricted-names": "error",
|
||||
"no-undef-init": "error",
|
||||
"no-undef": "error",
|
||||
"no-unused-vars": ["error", { "vars": "local", "args": "none" }],
|
||||
|
||||
// Node.js
|
||||
"handle-callback-err": "error",
|
||||
|
||||
// Stylistic issues
|
||||
"array-bracket-spacing": ["error", "never"],
|
||||
"brace-style": ["error", "1tbs", { "allowSingleLine": true }],
|
||||
"comma-style": ["error", "last"],
|
||||
"eol-last": "error",
|
||||
"keyword-spacing": "error",
|
||||
"linebreak-style": ["error", "unix"],
|
||||
"max-len": ["error", { "code": 200, "ignoreComments": true, "ignoreUrls": true }],
|
||||
"new-cap": "error",
|
||||
"new-parens": "error",
|
||||
"no-array-constructor": "error",
|
||||
"no-bitwise": "error",
|
||||
"no-mixed-spaces-and-tabs": "error",
|
||||
"no-multiple-empty-lines": ["error", { "max": 3, "maxEOF": 1 }],
|
||||
"no-whitespace-before-property": "error",
|
||||
"no-spaced-func": "error",
|
||||
"no-trailing-spaces": "error",
|
||||
"no-unneeded-ternary": "error",
|
||||
"quotes": ["error", "single"],
|
||||
"semi-spacing": "error",
|
||||
"semi": "error",
|
||||
"space-before-blocks": ["error", "always"],
|
||||
"space-before-function-paren": ["error", "never"],
|
||||
"space-in-parens": ["error", "never"],
|
||||
"space-infix-ops": "error",
|
||||
"space-unary-ops": ["error", { "words": true, "nonwords": false }],
|
||||
"unicode-bom": ["error", "never"]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
{
|
||||
"extends": "./.eslintrc-base.json",
|
||||
|
||||
"env": {
|
||||
// Note: don't set `"browser": true`; code in "src/" should be compatible with
|
||||
// non-browser environments like Node.js with a custom window implementation
|
||||
// like jsdom. All browser globals should be taken from window.
|
||||
"browser": false,
|
||||
"node": false
|
||||
},
|
||||
|
||||
"globals": {
|
||||
"window": false,
|
||||
|
||||
"angular": false
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"extends": "./.eslintrc-base.json",
|
||||
|
||||
"env": {
|
||||
"browser": false,
|
||||
"node": true
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
{
|
||||
// This config contains proposed rules that we'd like to have enabled but haven't
|
||||
// converted the code to adhere yet. If a decision comes to not enable one of these
|
||||
// rules, it should be removed from the file. Every rule that got enabled in the
|
||||
// end should be moved from here to a respective section in .eslintrc.json
|
||||
|
||||
"rules": {
|
||||
// Rules are divided into sections from http://eslint.org/docs/rules/
|
||||
|
||||
// Best practices
|
||||
"complexity": ["error", 10],
|
||||
"dot-notation": "error",
|
||||
"dot-location": ["error", "property"],
|
||||
|
||||
// Stylistic issues
|
||||
"block-spacing": ["error", "always"],
|
||||
"comma-spacing": "error",
|
||||
"id-blacklist": ["error", "event"],
|
||||
"indent": ["error", 2],
|
||||
"key-spacing": ["error", { "beforeColon": false, "afterColon": true, "mode": "minimum" }],
|
||||
"object-curly-spacing": ["error", "never"],
|
||||
"object-property-newline": ["error", { "allowMultiplePropertiesPerLine": true }],
|
||||
"operator-linebreak": ["error", "after", { "overrides": { "?": "before", ":": "before" }}]
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"root": true,
|
||||
"extends": "./.eslintrc-node.json"
|
||||
}
|
||||
@@ -1,48 +0,0 @@
|
||||
{
|
||||
"excludeFiles": ["src/ngLocale/**"],
|
||||
"disallowKeywords": ["with"],
|
||||
"disallowKeywordsOnNewLine": ["else"],
|
||||
"disallowMixedSpacesAndTabs": true,
|
||||
"disallowMultipleLineStrings": true,
|
||||
"disallowNewlineBeforeBlockStatements": true,
|
||||
"disallowSpaceAfterObjectKeys": true,
|
||||
"disallowSpaceAfterPrefixUnaryOperators": ["++", "--", "+", "-", "~", "!"],
|
||||
"disallowSpaceBeforeBinaryOperators": [","],
|
||||
"disallowSpaceBeforePostfixUnaryOperators": ["++", "--"],
|
||||
"disallowSpacesInAnonymousFunctionExpression": {
|
||||
"beforeOpeningRoundBrace": true
|
||||
},
|
||||
"disallowSpacesInCallExpression": true,
|
||||
"disallowSpacesInFunctionDeclaration": {
|
||||
"beforeOpeningRoundBrace": true
|
||||
},
|
||||
"disallowSpacesInNamedFunctionExpression": {
|
||||
"beforeOpeningRoundBrace": true
|
||||
},
|
||||
"disallowSpacesInsideArrayBrackets": true,
|
||||
"requireSpaceBeforeKeywords": [
|
||||
"else",
|
||||
"while",
|
||||
"catch"
|
||||
],
|
||||
"disallowSpacesInsideParentheses": true,
|
||||
"disallowTrailingComma": true,
|
||||
"disallowTrailingWhitespace": true,
|
||||
"requireCommaBeforeLineBreak": true,
|
||||
"requireLineFeedAtFileEnd": true,
|
||||
"requireSpaceAfterBinaryOperators": ["?", ":", "+", "-", "/", "*", "%", "==", "===", "!=", "!==", ">", ">=", "<", "<=", "&&", "||"],
|
||||
"requireSpaceBeforeBinaryOperators": ["?", ":", "+", "-", "/", "*", "%", "==", "===", "!=", "!==", ">", ">=", "<", "<=", "&&", "||"],
|
||||
"requireSpaceAfterKeywords": ["if", "else", "for", "while", "do", "switch", "return", "try", "catch"],
|
||||
"requireSpaceBeforeBlockStatements": true,
|
||||
"requireSpacesInConditionalExpression": {
|
||||
"afterTest": true,
|
||||
"beforeConsequent": true,
|
||||
"afterConsequent": true,
|
||||
"beforeAlternate": true
|
||||
},
|
||||
"requireSpacesInForStatement": true,
|
||||
"requireSpacesInFunction": {
|
||||
"beforeOpeningCurlyBrace": true
|
||||
},
|
||||
"validateLineBreaks": "LF"
|
||||
}
|
||||
@@ -1,2 +0,0 @@
|
||||
node_modules/**
|
||||
lib/htmlparser/**
|
||||
@@ -1,24 +0,0 @@
|
||||
{
|
||||
"bitwise": true,
|
||||
"esversion": 6,
|
||||
"immed": true,
|
||||
"newcap": true,
|
||||
"noarg": true,
|
||||
"noempty": true,
|
||||
"nonew": true,
|
||||
"maxlen": 200,
|
||||
"boss": true,
|
||||
"eqnull": true,
|
||||
"expr": true,
|
||||
"laxbreak": true,
|
||||
"loopfunc": true,
|
||||
"strict": "global",
|
||||
"sub": true,
|
||||
"undef": true,
|
||||
"indent": 2,
|
||||
|
||||
"globals": {
|
||||
"ArrayBuffer": false,
|
||||
"Uint8Array": false
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,6 @@ env:
|
||||
- JOB=unit BROWSER_PROVIDER=saucelabs
|
||||
- JOB=docs-e2e BROWSER_PROVIDER=saucelabs
|
||||
- JOB=e2e TEST_TARGET=jqlite BROWSER_PROVIDER=saucelabs
|
||||
- JOB=e2e TEST_TARGET=jquery-2.1 BROWSER_PROVIDER=saucelabs
|
||||
- JOB=e2e TEST_TARGET=jquery BROWSER_PROVIDER=saucelabs
|
||||
global:
|
||||
- CXX=g++-4.8 # node 4 likes the G++ v4.8 compiler
|
||||
|
||||
+188
-1
@@ -1,3 +1,178 @@
|
||||
<a name="1.5.8"></a>
|
||||
# 1.5.8 arbitrary-fallbacks (2016-07-22)
|
||||
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- **$animate:** do not get affected by custom, enumerable properties on `Object.prototype`
|
||||
([181e4401](https://github.com/angular/angular.js/commit/181e44019e850e5253378e29415cddf8d768bbef),
|
||||
[#14804](https://github.com/angular/angular.js/issues/14804), [#14830](https://github.com/angular/angular.js/issues/14830))
|
||||
- **$compile:** ensure `$doCheck` hooks can be defined in the controller constructor
|
||||
([3010ed4e](https://github.com/angular/angular.js/commit/3010ed4ee5c2c18b9848b5664639971b9fdc8919),
|
||||
[#14811](https://github.com/angular/angular.js/issues/14811))
|
||||
- **$injector:** fix class detection RegExp
|
||||
([4724d56c](https://github.com/angular/angular.js/commit/4724d56c939d02675433e7fe554608dff97ecf81),
|
||||
[#14533](https://github.com/angular/angular.js/issues/14533))
|
||||
- **$jsonpCallbacks:** do not overwrite callbacks added by other apps
|
||||
([1778d347](https://github.com/angular/angular.js/commit/1778d347cd3c91335e3840eaa49f1e387db8602f),
|
||||
[#14824](https://github.com/angular/angular.js/issues/14824))
|
||||
- **$timeout:** make $flush handle new $timeouts added in $timeout callbacks
|
||||
([1a387ba5](https://github.com/angular/angular.js/commit/1a387ba5dd1a8a831486fce23f6795bd1eef3d8b),
|
||||
[#5420](https://github.com/angular/angular.js/issues/5420), [#14686](https://github.com/angular/angular.js/issues/14686))
|
||||
- **copy:** fix handling of typed subarrays
|
||||
([1645924d](https://github.com/angular/angular.js/commit/1645924d49a7905ce55cced4c4276654970bb226),
|
||||
[#14842](https://github.com/angular/angular.js/issues/14842), [#14845](https://github.com/angular/angular.js/issues/14845))
|
||||
- **modules:** allow modules to be loaded in any order when using `angular-loader`
|
||||
([98e4a220](https://github.com/angular/angular.js/commit/98e4a220fe8301cec35498ae592adc0266f12437),
|
||||
[#9140](https://github.com/angular/angular.js/issues/9140), [#14794](https://github.com/angular/angular.js/issues/14794))
|
||||
- **ngAnimate:** allow removal of class that is scheduled to be added with requestAnimationFrame
|
||||
([7ccfe92b](https://github.com/angular/angular.js/commit/7ccfe92bed7361832f1b8d25b1a8411eb24d3fb5),
|
||||
[#14582](https://github.com/angular/angular.js/issues/14582))
|
||||
- **ngMocks:** allow `ErrorAddingDeclarationLocationStack` to be recognized as an `Error`
|
||||
([c6074dc3](https://github.com/angular/angular.js/commit/c6074dc34c31a07269bf7f628b971ef6dc805f17),
|
||||
[#13821](https://github.com/angular/angular.js/issues/13821), [#14344](https://github.com/angular/angular.js/issues/14344))
|
||||
- **ngOptions:** don't duplicate groups with falsy values
|
||||
([c3bfd7f5](https://github.com/angular/angular.js/commit/c3bfd7f59d0ecbf4ba3253fb407e683c7bb0766c))
|
||||
- **ngTransclude:**
|
||||
- ensure that fallback content is compiled and linked correctly
|
||||
([c405f88b](https://github.com/angular/angular.js/commit/c405f88bbc743f41591f6f3cfc022eea3c6c34ad),
|
||||
[#14787](https://github.com/angular/angular.js/issues/14787))
|
||||
- only compile fallback content if necessary
|
||||
([159a68ec](https://github.com/angular/angular.js/commit/159a68ec7ba77e9128b0d0516b813ed3d223b6e3),
|
||||
[#14768](https://github.com/angular/angular.js/issues/14768), [#14765](https://github.com/angular/angular.js/issues/14765), [#14775](https://github.com/angular/angular.js/issues/14775))
|
||||
|
||||
|
||||
## Features
|
||||
|
||||
- **$compile:** backport $doCheck
|
||||
([de59ca71](https://github.com/angular/angular.js/commit/de59ca71072eac95ee68de308f92bc5f921dd07b),
|
||||
[#14656](https://github.com/angular/angular.js/issues/14656))
|
||||
- **$jsonpCallbacks:** new service to abstract how JSONP callbacks are handled
|
||||
([a8cacfe9](https://github.com/angular/angular.js/commit/a8cacfe938287c54ce7099125cb735ad53f4c7c2),
|
||||
[#14795](https://github.com/angular/angular.js/issues/14795))
|
||||
- **$q:** implement $q.race
|
||||
([b9a56d58](https://github.com/angular/angular.js/commit/b9a56d588f8b597b1dff30d8e184b7c37d94cdcf),
|
||||
[#12929](https://github.com/angular/angular.js/issues/12929), [#14757](https://github.com/angular/angular.js/issues/14757))
|
||||
- **$resource:** pass the resource to a dynamic param functions
|
||||
([a126fcfe](https://github.com/angular/angular.js/commit/a126fcfee3bd8b02869bd2542c73e1eb21afe927),
|
||||
[#4899](https://github.com/angular/angular.js/issues/4899))
|
||||
- **$swipe:** add pointer support
|
||||
([f797f83c](https://github.com/angular/angular.js/commit/f797f83cd66f1fd11b3c9399e7894217ffa06c38),
|
||||
[#14061](https://github.com/angular/angular.js/issues/14061), [#14791](https://github.com/angular/angular.js/issues/14791))
|
||||
- **filterFilter:** allow overwriting the special `$` property name
|
||||
([33514ec3](https://github.com/angular/angular.js/commit/33514ec384d676d84b2a445bc15bae38c8c3ac8d),
|
||||
[#13313](https://github.com/angular/angular.js/issues/13313))
|
||||
|
||||
|
||||
## Performance Improvements
|
||||
|
||||
- **$compile:** wrap try/catch of collect comment directives into a function to avoid V8 deopt
|
||||
([acd45518](https://github.com/angular/angular.js/commit/acd455181de1cfa6b34d75f8d71a6c0b6995a777),
|
||||
[#14848](https://github.com/angular/angular.js/issues/14848))
|
||||
|
||||
|
||||
<a name="1.2.30"></a>
|
||||
# 1.2.30 patronal-resurrection (2016-07-21)
|
||||
|
||||
|
||||
_**Note:** This release contains some security fixes that required breaking changes. Since the
|
||||
legacy 1.2.x branch is the only version branch that supports IE8, it was necessary to introduce a
|
||||
couple of low-impact breaking changes in a patch release - something we generally avoid - in order
|
||||
to make the fixes available to people that still need IE8 support._
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- **$compile:**
|
||||
- secure `link[href]` as a `RESOURCE_URL`s in `$sce`
|
||||
([f35f334b](https://github.com/angular/angular.js/commit/f35f334bd3197585bdf034f4b6d9ffa3122dac62),
|
||||
[#14687](https://github.com/angular/angular.js/issues/14687))
|
||||
- properly sanitize `xlink:href` attribute interoplation
|
||||
([f2fa1ed8](https://github.com/angular/angular.js/commit/f2fa1ed83d18d4e79a36f8c0db1c2524d762e513),
|
||||
[2687c261](https://github.com/angular/angular.js/commit/2687c26140585d9e3716f9f559390f5d8d598fdf))
|
||||
- **ngSanitize:** blacklist the attribute `usemap` as it can be used as a security exploit
|
||||
([ac0d5286](https://github.com/angular/angular.js/commit/ac0d5286b8931633d774080d6396fb4825d8be33),
|
||||
[#14903](https://github.com/angular/angular.js/issues/14903))
|
||||
- **ngAnimate:** do not use event.timeStamp anymore for time tracking
|
||||
([8d83b563](https://github.com/angular/angular.js/commit/8d83b5633471c847d58f337426fe069797dd49d9),
|
||||
[#13494](https://github.com/angular/angular.js/issues/13494), [#13495](https://github.com/angular/angular.js/issues/13495))
|
||||
|
||||
|
||||
## Breaking Changes
|
||||
|
||||
- **$compile:** due to [f35f334b](https://github.com/angular/angular.js/commit/f35f334bd3197585bdf034f4b6d9ffa3122dac62),
|
||||
|
||||
`link[href]` attributes are now protected via `$sce`, which prevents interpolated values that fail
|
||||
the `RESOURCE_URL` context tests from being used in interpolation. For example if the application is
|
||||
running at `https://mydomain.org/` then the following will fail:
|
||||
|
||||
```html
|
||||
<link rel="stylesheet" href="{{ 'https://otherdomain.org/unsafe.css' }}" />
|
||||
```
|
||||
|
||||
By default, `RESOURCE_URL` safe URLs are only allowed from the same domain and protocol as the
|
||||
application document. To use URLs from other domains and/or protocols, you may either whitelist them
|
||||
using `$sceDelegateProvider.resourceUrlWhitelist(...)` or wrap them into a trusted value by calling
|
||||
`$sce.trustAsResourceUrl(url)`.
|
||||
|
||||
- **ngSanitize:** due to [234053fc](https://github.com/angular/angular.js/commit/234053fc9ad90e0d05be7e8359c6af66be94c094),
|
||||
|
||||
The `$sanitize` service will now remove instances of the `usemap` attribute from any elements passed
|
||||
to it.
|
||||
|
||||
This attribute is used to reference another element by `name` or `id`. Since the `name` and `id`
|
||||
attributes are already blacklisted, a sanitized `usemap` attribute could only reference unsanitized
|
||||
content, which is a security risk.
|
||||
|
||||
|
||||
<a name="1.5.7"></a>
|
||||
# 1.5.7 hexagonal-circumvolution (2016-06-15)
|
||||
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- **$compile:**
|
||||
- don't add merged attributes twice to $attrs
|
||||
([ebbaa4ac](https://github.com/angular/angular.js/commit/ebbaa4ac5e3559df9267203438a0bb18c2d3b7d8),
|
||||
[#8159](https://github.com/angular/angular.js/issues/8159), [#14737](https://github.com/angular/angular.js/issues/14737))
|
||||
- cope with `$onChanges` hooks throwing
|
||||
([3749c858](https://github.com/angular/angular.js/commit/3749c85829406ca57cc5729e80696c7f34134068),
|
||||
[#14444](https://github.com/angular/angular.js/issues/14444), [#14463](https://github.com/angular/angular.js/issues/14463))
|
||||
- **$parse:** allow arguments to contain filter chains
|
||||
([cc6dcb4b](https://github.com/angular/angular.js/commit/cc6dcb4bc28aadff4f62d76d6451b0f80b928e69),
|
||||
[#4175](https://github.com/angular/angular.js/issues/4175), [#4168](https://github.com/angular/angular.js/issues/4168), [#14720](https://github.com/angular/angular.js/issues/14720))
|
||||
- **$routeProvider:** do not deep-copy route definition objects
|
||||
([6d0dcca6](https://github.com/angular/angular.js/commit/6d0dcca6f18a353a12c356dc96e05475d351b795),
|
||||
[#14478](https://github.com/angular/angular.js/issues/14478), [#14699](https://github.com/angular/angular.js/issues/14699), [#14750](https://github.com/angular/angular.js/issues/14750))
|
||||
- **input[email]:** improve email address validation
|
||||
([f423dc6b](https://github.com/angular/angular.js/commit/f423dc6b51a9b4a09728a287a2cabda7d45f192e),
|
||||
[#14719](https://github.com/angular/angular.js/issues/14719))
|
||||
- **ngMessages:** create new scope for ngMessage, clean it up correctly
|
||||
([56f33af8](https://github.com/angular/angular.js/commit/56f33af89045e2ec18d144d9d1ef73affbe51959),
|
||||
[#14307](https://github.com/angular/angular.js/issues/14307))
|
||||
- **ngMessagesInclude:** don't break on empty (or whitespace-only) templates
|
||||
([01b8772c](https://github.com/angular/angular.js/commit/01b8772cca55916376355a2ae58d3ab7832a4bc2),
|
||||
[#12941](https://github.com/angular/angular.js/issues/12941), [#14726](https://github.com/angular/angular.js/issues/14726))
|
||||
- **ngMock#$controller:** properly assign bindings to all types of controllers (e.g. class-based)
|
||||
([db58801a](https://github.com/angular/angular.js/commit/db58801a55c91df755414387dc00fee5902bb5f3),
|
||||
[#14437](https://github.com/angular/angular.js/issues/14437), [#14439](https://github.com/angular/angular.js/issues/14439))
|
||||
- **ngMockE2E:** allow $httpBackend.passThrough() to work when ngMock is loaded
|
||||
([6685043a](https://github.com/angular/angular.js/commit/6685043ad40acc50d7088f87e2a71f76d2265306),
|
||||
[#1434](https://github.com/angular/angular.js/issues/1434), [#13124](https://github.com/angular/angular.js/issues/13124))
|
||||
- **ngSanitize:** call attribute setter in linky for all links
|
||||
([c4fad6ad](https://github.com/angular/angular.js/commit/c4fad6ad617af025984ca401054f7b402aa28f1d),
|
||||
[#14707](https://github.com/angular/angular.js/issues/14707))
|
||||
|
||||
|
||||
## Features
|
||||
|
||||
- **limitTo:** add support for array-like objects
|
||||
([b03957f0](https://github.com/angular/angular.js/commit/b03957f0047fcfe996abc8efe97f9e2be2c2e13a),
|
||||
[#14657](https://github.com/angular/angular.js/issues/14657), [#14694](https://github.com/angular/angular.js/issues/14694))
|
||||
- **orderBy:** add support for custom comparators
|
||||
([2e33d170](https://github.com/angular/angular.js/commit/2e33d170be7eb72f40fd57a8f66631583572fbf2),
|
||||
[#13238](https://github.com/angular/angular.js/issues/13238), [#14455](https://github.com/angular/angular.js/issues/14455), [#5123](https://github.com/angular/angular.js/issues/5123), [#8112](https://github.com/angular/angular.js/issues/8112), [#10368](https://github.com/angular/angular.js/issues/10368), [#14468](https://github.com/angular/angular.js/issues/14468))
|
||||
|
||||
|
||||
<a name="1.5.6"></a>
|
||||
# 1.5.6 arrow-stringification (2016-05-27)
|
||||
|
||||
@@ -512,7 +687,8 @@ changes section for more information
|
||||
|
||||
- **ngSanitize:** due to [234053fc](https://github.com/angular/angular.js/commit/234053fc9ad90e0d05be7e8359c6af66be94c094),
|
||||
|
||||
The `$sanitize` service will now remove instances of the `usemap` attribute from any elements passed to it.
|
||||
The `$sanitize` service will now remove instances of the `usemap` attribute from any elements passed
|
||||
to it.
|
||||
|
||||
This attribute is used to reference another element by `name` or `id`. Since the `name` and `id`
|
||||
attributes are already blacklisted, a sanitized `usemap` attribute could only reference unsanitized
|
||||
@@ -1443,6 +1619,17 @@ requirement more strict and alerts the developer explicitly.
|
||||
[#9936](https://github.com/angular/angular.js/issues/9936))
|
||||
|
||||
|
||||
<a name="1.5.0-beta.0"></a>
|
||||
|
||||
# 1.5.0-beta.0 intialization-processation (2015-09-17)
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- **jqLite:**: properly handle dash-delimited node names in `jqLiteBuildFragment`
|
||||
([cdd1227a3](https://github.com/angular/angular.js/commit/cdd1227a308edd34d31b67f338083b6e0c4c0db9),
|
||||
[#10617](https://github.com/angular/angular.js/issues/10617))
|
||||
|
||||
|
||||
<a name="1.4.6"></a>
|
||||
# 1.4.6 multiplicative-elevation (2015-09-17)
|
||||
|
||||
|
||||
+53
-40
@@ -14,14 +14,17 @@ today! Here are the guidelines we'd like you to follow:
|
||||
- [Further Info](#info)
|
||||
|
||||
## <a name="coc"></a> Code of Conduct
|
||||
|
||||
Help us keep Angular open and inclusive. Please read and follow our [Code of Conduct][coc].
|
||||
|
||||
## <a name="question"></a> Got a Question or Problem?
|
||||
|
||||
If you have questions about how to use AngularJS, please direct these to the [Google Group][groups]
|
||||
discussion list or [StackOverflow][stackoverflow]. We are also available on [IRC][irc] and [Gitter][gitter].
|
||||
discussion list or [StackOverflow][stackoverflow]. We are also available on [IRC][irc] and
|
||||
[Gitter][gitter].
|
||||
|
||||
## <a name="issue"></a> Found an Issue?
|
||||
|
||||
If you find a bug in the source code or a mistake in the documentation, you can help us by
|
||||
submitting an issue to our [GitHub Repository][github]. Even better you can submit a Pull Request
|
||||
with a fix.
|
||||
@@ -30,46 +33,53 @@ with a fix.
|
||||
any changes to these files would be lost the next time that we import the library. The recommended
|
||||
approach is to submit a patch to the I18N project directly, instead of submitting it here.*
|
||||
|
||||
**Please see the Submission Guidelines below**.
|
||||
**Please see the [Submission Guidelines](#submit) below.**
|
||||
|
||||
## <a name="feature"></a> Want a Feature?
|
||||
|
||||
You can request a new feature by submitting an issue to our [GitHub Repository][github]. If you
|
||||
would like to implement a new feature then consider what kind of change it is:
|
||||
|
||||
* **Major Changes** that you wish to contribute to the project should be discussed first on our
|
||||
[dev mailing list][angular-dev] or [IRC][irc] so that we can better coordinate our efforts, prevent
|
||||
duplication of work, and help you to craft the change so that it is successfully accepted into the
|
||||
project.
|
||||
* **Small Changes** can be crafted and submitted to the [GitHub Repository][github] as a Pull Request.
|
||||
[dev mailing list][angular-dev] or [IRC][irc] so that we can better coordinate our efforts,
|
||||
prevent duplication of work, and help you to craft the change so that it is successfully accepted
|
||||
into the project.
|
||||
* **Small Changes** can be crafted and submitted to the [GitHub Repository][github] as a Pull
|
||||
Request.
|
||||
|
||||
|
||||
## <a name="docs"></a> Want a Doc Fix?
|
||||
|
||||
If you want to help improve the docs, it's a good idea to let others know what you're working on to
|
||||
minimize duplication of effort. Before starting, check out the issue queue for
|
||||
[Milestone:Docs Only](https://github.com/angular/angular.js/issues?milestone=24&state=open).
|
||||
Comment on an issue to let others know what you're working on, or create a new issue if your work
|
||||
doesn't fit within the scope of any of the existing doc fix projects.
|
||||
minimize duplication of effort. Create a new issue (or comment on a related existing one) to let
|
||||
others know what you're working on.
|
||||
|
||||
For large fixes, please build and test the documentation before submitting the PR to be sure you haven't
|
||||
accidentally introduced any layout or formatting issues. You should also make sure that your commit message
|
||||
is labeled "docs:" and follows the **Git Commit Guidelines** outlined below.
|
||||
For large fixes, please build and test the documentation before submitting the PR to be sure you
|
||||
haven't accidentally introduced any layout or formatting issues. You should also make sure that your
|
||||
commit message starts with "docs" and follows the **[Commit Message Guidelines](#commit)** outlined
|
||||
below.
|
||||
|
||||
If you're just making a small change, don't worry about filing an issue first. Use the friendly blue "Improve this doc" button at the top right of the doc page to fork the repository in-place and make a quick change on the fly. When naming the commit, it is advised to still label it according to the commit guidelines below, by starting the commit message with **docs** and referencing the filename. Since this is not obvious and some changes are made on the fly, this is not strictly necessary and we will understand if this isn't done the first few times.
|
||||
If you're just making a small change, don't worry about filing an issue first. Use the friendly blue
|
||||
"Improve this doc" button at the top right of the doc page to fork the repository in-place and make
|
||||
a quick change on the fly. When naming the commit, it is advised to follow the commit message
|
||||
guidelines below, by starting the commit message with **docs** and referencing the filename. Since
|
||||
this is not obvious and some changes are made on the fly, this is not strictly necessary and we will
|
||||
understand if this isn't done the first few times.
|
||||
|
||||
## <a name="submit"></a> Submission Guidelines
|
||||
|
||||
### Submitting an Issue
|
||||
Before you submit your issue search the archive, maybe your question was already answered.
|
||||
|
||||
If your issue appears to be a bug, and hasn't been reported, open a new issue.
|
||||
Help us to maximize the effort we can spend fixing issues and adding new
|
||||
features, by not reporting duplicate issues. Providing the following information will increase the
|
||||
chances of your issue being dealt with quickly:
|
||||
If your issue appears to be a bug, and hasn't been reported, open a new issue. Help us to maximize
|
||||
the effort we can spend fixing issues and adding new features, by not reporting duplicate issues.
|
||||
Providing the following information will increase the chances of your issue being dealt with
|
||||
quickly:
|
||||
|
||||
* **Overview of the Issue** - if an error is being thrown a non-minified stack trace helps
|
||||
* **Motivation for or Use Case** - explain why this is a bug for you
|
||||
* **Angular Version(s)** - is it a regression?
|
||||
* **Browsers and Operating System** - is this a problem with all browsers or only IE8?
|
||||
* **Browsers and Operating System** - is this a problem with all browsers or only specific ones?
|
||||
* **Reproduce the Error** - provide a live example (using [Plunker][plunker] or
|
||||
[JSFiddle][jsfiddle]) or an unambiguous set of steps.
|
||||
* **Related Issues** - has a similar issue been reported before?
|
||||
@@ -89,22 +99,22 @@ Before you submit your pull request consider the following guidelines:
|
||||
requests. We cannot accept code without this.
|
||||
* Make your changes in a new git branch:
|
||||
|
||||
```shell
|
||||
git checkout -b my-fix-branch master
|
||||
```
|
||||
```shell
|
||||
git checkout -b my-fix-branch master
|
||||
```
|
||||
|
||||
* Create your patch, **including appropriate test cases**.
|
||||
* Follow our [Coding Rules](#rules).
|
||||
* Run the full Angular test suite, as described in the [developer documentation][dev-doc],
|
||||
and ensure that all tests pass.
|
||||
* Commit your changes using a descriptive commit message that follows our
|
||||
[commit message conventions](#commit-message-format) and passes our commit message presubmit hook
|
||||
`validate-commit-msg.js`. Adherence to the [commit message conventions](#commit-message-format)
|
||||
is required because release notes are automatically generated from these messages.
|
||||
[commit message conventions](#commit) and passes our commit message presubmit hook
|
||||
(`validate-commit-msg.js`). Adherence to the [commit message conventions](#commit) is required,
|
||||
because release notes are automatically generated from these messages.
|
||||
|
||||
```shell
|
||||
git commit -a
|
||||
```
|
||||
```shell
|
||||
git commit -a
|
||||
```
|
||||
Note: the optional commit `-a` command line option will automatically "add" and "rm" edited files.
|
||||
|
||||
* Build your changes locally to ensure all the tests pass:
|
||||
@@ -119,22 +129,24 @@ Before you submit your pull request consider the following guidelines:
|
||||
git push origin my-fix-branch
|
||||
```
|
||||
|
||||
* In GitHub, send a pull request to `angular:master`.
|
||||
* If we suggest changes then:
|
||||
* Make the required updates.
|
||||
* Re-run the Angular test suite to ensure tests are still passing.
|
||||
* Commit your changes to your branch (e.g. `my-fix-branch`).
|
||||
* Push the changes to your GitHub repository (this will update your Pull Request).
|
||||
In GitHub, send a pull request to `angular:master`.
|
||||
If we suggest changes, then:
|
||||
|
||||
* Make the required updates.
|
||||
* Re-run the Angular test suite to ensure tests are still passing.
|
||||
* Commit your changes to your branch (e.g. `my-fix-branch`).
|
||||
* Push the changes to your GitHub repository (this will update your Pull Request).
|
||||
|
||||
If the PR gets too outdated we may ask you to rebase and force push to update the PR:
|
||||
|
||||
```shell
|
||||
git rebase master -i
|
||||
git push origin my-fix-branch -f
|
||||
```
|
||||
```shell
|
||||
git rebase master -i
|
||||
git push origin my-fix-branch -f
|
||||
```
|
||||
|
||||
*WARNING. Squashing or reverting commits and forced push thereafter may remove GitHub comments
|
||||
on code that were previously made by you and others in your commits.*
|
||||
_WARNING: Squashing or reverting commits and force-pushing thereafter may remove GitHub comments
|
||||
on code that were previously made by you or others in your commits. Avoid any form of rebasing
|
||||
unless necessary._
|
||||
|
||||
That's it! Thank you for your contribution!
|
||||
|
||||
@@ -168,6 +180,7 @@ from the main (upstream) repository:
|
||||
```
|
||||
|
||||
## <a name="rules"></a> Coding Rules
|
||||
|
||||
To ensure consistency throughout the source code, keep these rules in mind as you are working:
|
||||
|
||||
* All features or bug fixes **must be tested** by one or more [specs][unit-testing].
|
||||
|
||||
+41
-75
@@ -1,5 +1,8 @@
|
||||
'use strict';
|
||||
|
||||
var serveFavicon = require('serve-favicon');
|
||||
var serveStatic = require('serve-static');
|
||||
var serveIndex = require('serve-index');
|
||||
var files = require('./angularFiles').files;
|
||||
var util = require('./lib/grunt/utils.js');
|
||||
var versionInfo = require('./lib/versions/version-info');
|
||||
@@ -15,7 +18,11 @@ module.exports = function(grunt) {
|
||||
|
||||
var NG_VERSION = versionInfo.currentVersion;
|
||||
NG_VERSION.cdn = versionInfo.cdnVersion;
|
||||
var dist = 'angular-'+ NG_VERSION.full;
|
||||
var dist = 'angular-' + NG_VERSION.full;
|
||||
|
||||
if (versionInfo.cdnVersion == null) {
|
||||
throw new Error('Unable to read CDN version, are you offline or has the CDN not been properly pushed?');
|
||||
}
|
||||
|
||||
//config
|
||||
grunt.initConfig({
|
||||
@@ -34,15 +41,15 @@ module.exports = function(grunt) {
|
||||
hostname: '0.0.0.0',
|
||||
base: '.',
|
||||
keepalive: true,
|
||||
middleware: function(connect, options){
|
||||
middleware: function(connect, options) {
|
||||
var base = Array.isArray(options.base) ? options.base[options.base.length - 1] : options.base;
|
||||
return [
|
||||
util.conditionalCsp(),
|
||||
util.rewrite(),
|
||||
e2e.middleware(),
|
||||
connect.favicon('images/favicon.ico'),
|
||||
connect.static(base),
|
||||
connect.directory(base)
|
||||
serveFavicon('images/favicon.ico'),
|
||||
serveStatic(base),
|
||||
serveIndex(base)
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -54,7 +61,7 @@ module.exports = function(grunt) {
|
||||
// to avoid https://github.com/joyent/libuv/issues/826
|
||||
port: 8000,
|
||||
hostname: '0.0.0.0',
|
||||
middleware: function(connect, options){
|
||||
middleware: function(connect, options) {
|
||||
var base = Array.isArray(options.base) ? options.base[options.base.length - 1] : options.base;
|
||||
return [
|
||||
function(req, resp, next) {
|
||||
@@ -67,8 +74,8 @@ module.exports = function(grunt) {
|
||||
},
|
||||
util.conditionalCsp(),
|
||||
e2e.middleware(),
|
||||
connect.favicon('images/favicon.ico'),
|
||||
connect.static(base)
|
||||
serveFavicon('images/favicon.ico'),
|
||||
serveStatic(base)
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -79,6 +86,7 @@ module.exports = function(grunt) {
|
||||
tests: {
|
||||
jqlite: 'karma-jqlite.conf.js',
|
||||
jquery: 'karma-jquery.conf.js',
|
||||
'jquery-2.2': 'karma-jquery-2.2.conf.js',
|
||||
'jquery-2.1': 'karma-jquery-2.1.conf.js',
|
||||
docs: 'karma-docs.conf.js',
|
||||
modules: 'karma-modules.conf.js'
|
||||
@@ -88,6 +96,7 @@ module.exports = function(grunt) {
|
||||
autotest: {
|
||||
jqlite: 'karma-jqlite.conf.js',
|
||||
jquery: 'karma-jquery.conf.js',
|
||||
'jquery-2.2': 'karma-jquery-2.2.conf.js',
|
||||
'jquery-2.1': 'karma-jquery-2.1.conf.js',
|
||||
modules: 'karma-modules.conf.js',
|
||||
docs: 'karma-docs.conf.js'
|
||||
@@ -106,68 +115,24 @@ module.exports = function(grunt) {
|
||||
tmp: ['tmp']
|
||||
},
|
||||
|
||||
jshint: {
|
||||
options: {
|
||||
jshintrc: true,
|
||||
},
|
||||
node: {
|
||||
files: { src: ['*.js', 'lib/**/*.js'] },
|
||||
},
|
||||
tests: {
|
||||
files: { src: 'test/**/*.js' },
|
||||
},
|
||||
ng: {
|
||||
files: { src: files['angularSrc'].concat('!src/angular.bind.js') },
|
||||
},
|
||||
ngAnimate: {
|
||||
files: { src: 'src/ngAnimate/**/*.js' },
|
||||
},
|
||||
ngCookies: {
|
||||
files: { src: 'src/ngCookies/**/*.js' },
|
||||
},
|
||||
ngLocale: {
|
||||
files: { src: 'src/ngLocale/**/*.js' },
|
||||
},
|
||||
ngMessageFormat: {
|
||||
files: { src: 'src/ngMessageFormat/**/*.js' },
|
||||
},
|
||||
ngMessages: {
|
||||
files: { src: 'src/ngMessages/**/*.js' },
|
||||
},
|
||||
ngMock: {
|
||||
files: { src: 'src/ngMock/**/*.js' },
|
||||
},
|
||||
ngParseExt: {
|
||||
files: { src: 'src/ngParseExt/**/*.js' },
|
||||
},
|
||||
ngResource: {
|
||||
files: { src: 'src/ngResource/**/*.js' },
|
||||
},
|
||||
ngRoute: {
|
||||
files: { src: 'src/ngRoute/**/*.js' },
|
||||
},
|
||||
ngSanitize: {
|
||||
files: { src: 'src/ngSanitize/**/*.js' },
|
||||
},
|
||||
ngScenario: {
|
||||
files: { src: 'src/ngScenario/**/*.js' },
|
||||
},
|
||||
ngTouch: {
|
||||
files: { src: 'src/ngTouch/**/*.js' },
|
||||
},
|
||||
ngAria: {
|
||||
files: {src: 'src/ngAria/**/*.js'},
|
||||
}
|
||||
},
|
||||
|
||||
jscs: {
|
||||
src: [
|
||||
'src/**/*.js',
|
||||
'test/**/*.js',
|
||||
'!src/angular.bind.js' // we ignore this file since contains an early return statement
|
||||
],
|
||||
options: {
|
||||
config: '.jscsrc'
|
||||
eslint: {
|
||||
all: {
|
||||
src: [
|
||||
'*.js',
|
||||
'benchmarks/**/*.js',
|
||||
'docs/**/*.js',
|
||||
'lib/**/*.js',
|
||||
'scripts/**/*.js',
|
||||
'src/**/*.js',
|
||||
'test/**/*.js',
|
||||
'i18n/**/*.js',
|
||||
'!docs/app/assets/js/angular-bootstrap/**',
|
||||
'!docs/bower_components/**',
|
||||
'!docs/config/templates/**',
|
||||
'!src/angular.bind.js',
|
||||
'!i18n/closure/**',
|
||||
'!src/ngParseExt/ucd.js'
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
@@ -240,7 +205,7 @@ module.exports = function(grunt) {
|
||||
dest: 'build/angular-parse-ext.js',
|
||||
src: util.wrap(files['angularModules']['ngParseExt'], 'module')
|
||||
},
|
||||
"promises-aplus-adapter": {
|
||||
'promises-aplus-adapter': {
|
||||
dest:'tmp/promises-aplus-adapter++.js',
|
||||
src:['src/ng/q.js', 'lib/promises-aplus/promises-aplus-test-adapter.js']
|
||||
}
|
||||
@@ -309,7 +274,7 @@ module.exports = function(grunt) {
|
||||
|
||||
compress: {
|
||||
build: {
|
||||
options: {archive: 'build/' + dist +'.zip', mode: 'zip'},
|
||||
options: {archive: 'build/' + dist + '.zip', mode: 'zip'},
|
||||
src: ['**'],
|
||||
cwd: 'build',
|
||||
expand: true,
|
||||
@@ -357,13 +322,14 @@ module.exports = function(grunt) {
|
||||
|
||||
|
||||
//alias tasks
|
||||
grunt.registerTask('test', 'Run unit, docs and e2e tests with Karma', ['jshint', 'jscs', 'package', 'test:unit', 'test:promises-aplus', 'tests:docs', 'test:protractor']);
|
||||
grunt.registerTask('test', 'Run unit, docs and e2e tests with Karma', ['eslint', 'package', 'test:unit', 'test:promises-aplus', 'tests:docs', 'test:protractor']);
|
||||
grunt.registerTask('test:jqlite', 'Run the unit tests with Karma' , ['tests:jqlite']);
|
||||
grunt.registerTask('test:jquery', 'Run the jQuery (latest) unit tests with Karma', ['tests:jquery']);
|
||||
grunt.registerTask('test:jquery-2.2', 'Run the jQuery 2.2 unit tests with Karma', ['tests:jquery-2.2']);
|
||||
grunt.registerTask('test:jquery-2.1', 'Run the jQuery 2.1 unit tests with Karma', ['tests:jquery-2.1']);
|
||||
grunt.registerTask('test:modules', 'Run the Karma module tests with Karma', ['build', 'tests:modules']);
|
||||
grunt.registerTask('test:docs', 'Run the doc-page tests with Karma', ['package', 'tests:docs']);
|
||||
grunt.registerTask('test:unit', 'Run unit, jQuery and Karma module tests with Karma', ['test:jqlite', 'test:jquery', 'test:jquery-2.1', 'test:modules']);
|
||||
grunt.registerTask('test:unit', 'Run unit, jQuery and Karma module tests with Karma', ['test:jqlite', 'test:jquery', 'test:jquery-2.2', 'test:jquery-2.1', 'test:modules']);
|
||||
grunt.registerTask('test:protractor', 'Run the end to end tests with Protractor and keep a test server running in the background', ['webdriver', 'connect:testserver', 'protractor:normal']);
|
||||
grunt.registerTask('test:travis-protractor', 'Run the end to end tests with Protractor for Travis CI builds', ['connect:testserver', 'protractor:travis']);
|
||||
grunt.registerTask('test:ci-protractor', 'Run the end to end tests with Protractor for Jenkins CI builds', ['webdriver', 'connect:testserver', 'protractor:jenkins']);
|
||||
@@ -373,6 +339,6 @@ module.exports = function(grunt) {
|
||||
grunt.registerTask('minify', ['bower', 'clean', 'build', 'minall']);
|
||||
grunt.registerTask('webserver', ['connect:devserver']);
|
||||
grunt.registerTask('package', ['bower', 'validate-angular-files', 'clean', 'buildall', 'minall', 'collect-errors', 'docs', 'copy', 'write', 'compress']);
|
||||
grunt.registerTask('ci-checks', ['ddescribe-iit', 'merge-conflict', 'jshint', 'jscs']);
|
||||
grunt.registerTask('ci-checks', ['ddescribe-iit', 'merge-conflict', 'eslint']);
|
||||
grunt.registerTask('default', ['package']);
|
||||
};
|
||||
|
||||
Vendored
+14
-12
@@ -28,6 +28,7 @@ var angularFiles = {
|
||||
'src/ng/httpBackend.js',
|
||||
'src/ng/interpolate.js',
|
||||
'src/ng/interval.js',
|
||||
'src/ng/jsonpCallbacks.js',
|
||||
'src/ng/locale.js',
|
||||
'src/ng/location.js',
|
||||
'src/ng/log.js',
|
||||
@@ -79,7 +80,6 @@ var angularFiles = {
|
||||
'src/ng/directive/ngTransclude.js',
|
||||
'src/ng/directive/script.js',
|
||||
'src/ng/directive/select.js',
|
||||
'src/ng/directive/style.js',
|
||||
'src/ng/directive/validators.js',
|
||||
'src/angular.bind.js',
|
||||
'src/publishExternalApis.js',
|
||||
@@ -209,7 +209,7 @@ var angularFiles = {
|
||||
'build/docs/docs-scenario.js'
|
||||
],
|
||||
|
||||
"karmaModules": [
|
||||
'karmaModules': [
|
||||
'build/angular.js',
|
||||
'@angularSrcModules',
|
||||
'test/modules/no_bootstrap.js',
|
||||
@@ -236,15 +236,6 @@ var angularFiles = {
|
||||
'@angularTest'
|
||||
],
|
||||
|
||||
'karmaJqueryOld': [
|
||||
'bower_components/jquery-2.1/dist/jquery.js',
|
||||
'test/jquery_alias.js',
|
||||
'@angularSrc',
|
||||
'@angularSrcModules',
|
||||
'@angularScenario',
|
||||
'@angularTest'
|
||||
],
|
||||
|
||||
'karmaJqueryExclude': [
|
||||
'src/angular-bootstrap.js',
|
||||
'src/ngScenario/angular-bootstrap.js',
|
||||
@@ -253,6 +244,17 @@ var angularFiles = {
|
||||
]
|
||||
};
|
||||
|
||||
['2.1', '2.2'].forEach(function(jQueryVersion) {
|
||||
angularFiles['karmaJquery' + jQueryVersion] = []
|
||||
.concat(angularFiles.karmaJquery)
|
||||
.map(function(path) {
|
||||
if (path.startsWith('bower_components/jquery')) {
|
||||
return path.replace(/^bower_components\/jquery/, 'bower_components/jquery-' + jQueryVersion);
|
||||
}
|
||||
return path;
|
||||
});
|
||||
});
|
||||
|
||||
angularFiles['angularSrcModules'] = [].concat(
|
||||
angularFiles['angularModules']['ngAnimate'],
|
||||
angularFiles['angularModules']['ngMessageFormat'],
|
||||
@@ -274,7 +276,7 @@ if (exports) {
|
||||
Array.prototype.slice.call(arguments, 0).forEach(function(filegroup) {
|
||||
angularFiles[filegroup].forEach(function(file) {
|
||||
// replace @ref
|
||||
var match = file.match(/^\@(.*)/);
|
||||
var match = file.match(/^@(.*)/);
|
||||
if (match) {
|
||||
files = files.concat(angularFiles[match[1]]);
|
||||
} else {
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
{
|
||||
"root": true,
|
||||
"extends": "../.eslintrc-browser.json",
|
||||
|
||||
"globals": {
|
||||
"benchmarkSteps": false,
|
||||
|
||||
// Benchmarks are not run in IE 9 so we're fine.
|
||||
"console": false
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
'use strict';
|
||||
|
||||
var app = angular.module('boostrapCompileBenchmark', []);
|
||||
|
||||
var commentDirectivesEnabled;
|
||||
var cssClassDirectivesEnabled;
|
||||
|
||||
app.config(function($compileProvider) {
|
||||
$compileProvider.debugInfoEnabled(false);
|
||||
|
||||
commentDirectivesEnabled = window.location.toString().indexOf('comment=disabled') === -1;
|
||||
cssClassDirectivesEnabled = window.location.toString().indexOf('css=disabled') === -1;
|
||||
|
||||
$compileProvider
|
||||
.commentDirectivesEnabled(commentDirectivesEnabled)
|
||||
.cssClassDirectivesEnabled(cssClassDirectivesEnabled);
|
||||
})
|
||||
.controller('DataController', function DataController($compile, $http, $rootScope) {
|
||||
|
||||
this.isEA = !commentDirectivesEnabled && !cssClassDirectivesEnabled;
|
||||
this.isEAC = !commentDirectivesEnabled && cssClassDirectivesEnabled;
|
||||
this.isEAM = commentDirectivesEnabled && !cssClassDirectivesEnabled;
|
||||
this.isEACM = commentDirectivesEnabled && cssClassDirectivesEnabled;
|
||||
|
||||
this.repeats = 50;
|
||||
|
||||
this.templates = [
|
||||
'bootstrap-carousel.tpl.html',
|
||||
'bootstrap-theme.tpl.html'
|
||||
];
|
||||
|
||||
this.html = null;
|
||||
this.loadTemplate = function() {
|
||||
this.html = null;
|
||||
$http.get(window.location.pathname + this.selectedTemplate)
|
||||
.then(function(response) { this.html = response.data; }.bind(this));
|
||||
};
|
||||
|
||||
this.selectedTemplate = this.templates[0];
|
||||
this.loadTemplate();
|
||||
|
||||
|
||||
var linkers = [];
|
||||
benchmarkSteps.push({
|
||||
name: 'create',
|
||||
fn: function() {
|
||||
for (var i = 0; i < this.repeats; i++) {
|
||||
var linker = $compile(this.html);
|
||||
linkers.push(linker);
|
||||
}
|
||||
}.bind(this)
|
||||
});
|
||||
|
||||
benchmarkSteps.push({
|
||||
name: 'destroy',
|
||||
fn: function() {
|
||||
linkers.length = 0;
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
@@ -0,0 +1,172 @@
|
||||
<!-- code from http://getbootstrap.com/examples/carousel -->
|
||||
<div class="navbar-wrapper">
|
||||
<div class="container">
|
||||
|
||||
<nav class="navbar navbar-inverse navbar-static-top">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a class="navbar-brand" href="#">Project name</a>
|
||||
</div>
|
||||
<div id="navbar" class="navbar-collapse collapse">
|
||||
<ul class="nav navbar-nav">
|
||||
<li class="active"><a href="#">Home</a></li>
|
||||
<li><a href="#about">About</a></li>
|
||||
<li><a href="#contact">Contact</a></li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="#">Action</a></li>
|
||||
<li><a href="#">Another action</a></li>
|
||||
<li><a href="#">Something else here</a></li>
|
||||
<li role="separator" class="divider"></li>
|
||||
<li class="dropdown-header">Nav header</li>
|
||||
<li><a href="#">Separated link</a></li>
|
||||
<li><a href="#">One more separated link</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Carousel
|
||||
================================================== -->
|
||||
<div id="myCarousel" class="carousel slide" data-ride="carousel">
|
||||
<!-- Indicators -->
|
||||
<ol class="carousel-indicators">
|
||||
<li data-target="#myCarousel" data-slide-to="0" class="active"></li>
|
||||
<li data-target="#myCarousel" data-slide-to="1"></li>
|
||||
<li data-target="#myCarousel" data-slide-to="2"></li>
|
||||
</ol>
|
||||
<div class="carousel-inner" role="listbox">
|
||||
<div class="item active">
|
||||
<img class="first-slide" src="data:image/gif;base64,R0lGODlhAQABAIAAAHd3dwAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==" alt="First slide">
|
||||
<div class="container">
|
||||
<div class="carousel-caption">
|
||||
<h1>Example headline.</h1>
|
||||
<p>Note: If you're viewing this page via a <code>file://</code> URL, the "next" and "previous" Glyphicon buttons on the left and right might not load/display properly due to web browser security rules.</p>
|
||||
<p><a class="btn btn-lg btn-primary" href="#" role="button">Sign up today</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<img class="second-slide" src="data:image/gif;base64,R0lGODlhAQABAIAAAHd3dwAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==" alt="Second slide">
|
||||
<div class="container">
|
||||
<div class="carousel-caption">
|
||||
<h1>Another example headline.</h1>
|
||||
<p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ultricies vehicula ut id elit.</p>
|
||||
<p><a class="btn btn-lg btn-primary" href="#" role="button">Learn more</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="item">
|
||||
<img class="third-slide" src="data:image/gif;base64,R0lGODlhAQABAIAAAHd3dwAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==" alt="Third slide">
|
||||
<div class="container">
|
||||
<div class="carousel-caption">
|
||||
<h1>One more for good measure.</h1>
|
||||
<p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ultricies vehicula ut id elit.</p>
|
||||
<p><a class="btn btn-lg btn-primary" href="#" role="button">Browse gallery</a></p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<a class="left carousel-control" href="#myCarousel" role="button" data-slide="prev">
|
||||
<span class="glyphicon glyphicon-chevron-left" aria-hidden="true"></span>
|
||||
<span class="sr-only">Previous</span>
|
||||
</a>
|
||||
<a class="right carousel-control" href="#myCarousel" role="button" data-slide="next">
|
||||
<span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span>
|
||||
<span class="sr-only">Next</span>
|
||||
</a>
|
||||
</div><!-- /.carousel -->
|
||||
|
||||
|
||||
<!-- Marketing messaging and featurettes
|
||||
================================================== -->
|
||||
<!-- Wrap the rest of the page in another container to center all the content. -->
|
||||
|
||||
<div class="container marketing">
|
||||
|
||||
<!-- Three columns of text below the carousel -->
|
||||
<div class="row">
|
||||
<div class="col-lg-4">
|
||||
<img class="img-circle" src="data:image/gif;base64,R0lGODlhAQABAIAAAHd3dwAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==" alt="Generic placeholder image" width="140" height="140">
|
||||
<h2>Heading</h2>
|
||||
<p>Donec sed odio dui. Etiam porta sem malesuada magna mollis euismod. Nullam id dolor id nibh ultricies vehicula ut id elit. Morbi leo risus, porta ac consectetur ac, vestibulum at eros. Praesent commodo cursus magna.</p>
|
||||
<p><a class="btn btn-default" href="#" role="button">View details »</a></p>
|
||||
</div><!-- /.col-lg-4 -->
|
||||
<div class="col-lg-4">
|
||||
<img class="img-circle" src="data:image/gif;base64,R0lGODlhAQABAIAAAHd3dwAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==" alt="Generic placeholder image" width="140" height="140">
|
||||
<h2>Heading</h2>
|
||||
<p>Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Cras mattis consectetur purus sit amet fermentum. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh.</p>
|
||||
<p><a class="btn btn-default" href="#" role="button">View details »</a></p>
|
||||
</div><!-- /.col-lg-4 -->
|
||||
<div class="col-lg-4">
|
||||
<img class="img-circle" src="data:image/gif;base64,R0lGODlhAQABAIAAAHd3dwAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==" alt="Generic placeholder image" width="140" height="140">
|
||||
<h2>Heading</h2>
|
||||
<p>Donec sed odio dui. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Vestibulum id ligula porta felis euismod semper. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus.</p>
|
||||
<p><a class="btn btn-default" href="#" role="button">View details »</a></p>
|
||||
</div><!-- /.col-lg-4 -->
|
||||
</div><!-- /.row -->
|
||||
|
||||
|
||||
<!-- START THE FEATURETTES -->
|
||||
|
||||
<hr class="featurette-divider">
|
||||
|
||||
<div class="row featurette">
|
||||
<div class="col-md-7">
|
||||
<h2 class="featurette-heading">First featurette heading. <span class="text-muted">It'll blow your mind.</span></h2>
|
||||
<p class="lead">Donec ullamcorper nulla non metus auctor fringilla. Vestibulum id ligula porta felis euismod semper. Praesent commodo cursus magna, vel scelerisque nisl consectetur. Fusce dapibus, tellus ac cursus commodo.</p>
|
||||
</div>
|
||||
<div class="col-md-5">
|
||||
<img class="featurette-image img-responsive center-block" data-src="holder.js/500x500/auto" alt="Generic placeholder image">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr class="featurette-divider">
|
||||
|
||||
<div class="row featurette">
|
||||
<div class="col-md-7 col-md-push-5">
|
||||
<h2 class="featurette-heading">Oh yeah, it's that good. <span class="text-muted">See for yourself.</span></h2>
|
||||
<p class="lead">Donec ullamcorper nulla non metus auctor fringilla. Vestibulum id ligula porta felis euismod semper. Praesent commodo cursus magna, vel scelerisque nisl consectetur. Fusce dapibus, tellus ac cursus commodo.</p>
|
||||
</div>
|
||||
<div class="col-md-5 col-md-pull-7">
|
||||
<img class="featurette-image img-responsive center-block" data-src="holder.js/500x500/auto" alt="Generic placeholder image">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr class="featurette-divider">
|
||||
|
||||
<div class="row featurette">
|
||||
<div class="col-md-7">
|
||||
<h2 class="featurette-heading">And lastly, this one. <span class="text-muted">Checkmate.</span></h2>
|
||||
<p class="lead">Donec ullamcorper nulla non metus auctor fringilla. Vestibulum id ligula porta felis euismod semper. Praesent commodo cursus magna, vel scelerisque nisl consectetur. Fusce dapibus, tellus ac cursus commodo.</p>
|
||||
</div>
|
||||
<div class="col-md-5">
|
||||
<img class="featurette-image img-responsive center-block" data-src="holder.js/500x500/auto" alt="Generic placeholder image">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<hr class="featurette-divider">
|
||||
|
||||
<!-- /END THE FEATURETTES -->
|
||||
|
||||
|
||||
<!-- FOOTER -->
|
||||
<footer>
|
||||
<p class="pull-right"><a href="#">Back to top</a></p>
|
||||
<p>© 2016 Company, Inc. · <a href="#">Privacy</a> · <a href="#">Terms</a></p>
|
||||
</footer>
|
||||
|
||||
</div><!-- /.container -->
|
||||
@@ -0,0 +1,595 @@
|
||||
<!-- Fixed navbar -->
|
||||
<nav class="navbar navbar-inverse navbar-fixed-top">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a class="navbar-brand" href="#">Bootstrap theme</a>
|
||||
</div>
|
||||
<div id="navbar" class="navbar-collapse collapse">
|
||||
<ul class="nav navbar-nav">
|
||||
<li class="active"><a href="#">Home</a></li>
|
||||
<li><a href="#about">About</a></li>
|
||||
<li><a href="#contact">Contact</a></li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="#">Action</a></li>
|
||||
<li><a href="#">Another action</a></li>
|
||||
<li><a href="#">Something else here</a></li>
|
||||
<li role="separator" class="divider"></li>
|
||||
<li class="dropdown-header">Nav header</li>
|
||||
<li><a href="#">Separated link</a></li>
|
||||
<li><a href="#">One more separated link</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div><!--/.nav-collapse -->
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<div class="container theme-showcase" role="main">
|
||||
|
||||
<!-- Main jumbotron for a primary marketing message or call to action -->
|
||||
<div class="jumbotron">
|
||||
<h1>Theme example</h1>
|
||||
<p>This is a template showcasing the optional theme stylesheet included in Bootstrap. Use it as a starting point to create something more unique by building on or modifying it.</p>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="page-header">
|
||||
<h1>Buttons</h1>
|
||||
</div>
|
||||
<p>
|
||||
<button type="button" class="btn btn-lg btn-default">Default</button>
|
||||
<button type="button" class="btn btn-lg btn-primary">Primary</button>
|
||||
<button type="button" class="btn btn-lg btn-success">Success</button>
|
||||
<button type="button" class="btn btn-lg btn-info">Info</button>
|
||||
<button type="button" class="btn btn-lg btn-warning">Warning</button>
|
||||
<button type="button" class="btn btn-lg btn-danger">Danger</button>
|
||||
<button type="button" class="btn btn-lg btn-link">Link</button>
|
||||
</p>
|
||||
<p>
|
||||
<button type="button" class="btn btn-default">Default</button>
|
||||
<button type="button" class="btn btn-primary">Primary</button>
|
||||
<button type="button" class="btn btn-success">Success</button>
|
||||
<button type="button" class="btn btn-info">Info</button>
|
||||
<button type="button" class="btn btn-warning">Warning</button>
|
||||
<button type="button" class="btn btn-danger">Danger</button>
|
||||
<button type="button" class="btn btn-link">Link</button>
|
||||
</p>
|
||||
<p>
|
||||
<button type="button" class="btn btn-sm btn-default">Default</button>
|
||||
<button type="button" class="btn btn-sm btn-primary">Primary</button>
|
||||
<button type="button" class="btn btn-sm btn-success">Success</button>
|
||||
<button type="button" class="btn btn-sm btn-info">Info</button>
|
||||
<button type="button" class="btn btn-sm btn-warning">Warning</button>
|
||||
<button type="button" class="btn btn-sm btn-danger">Danger</button>
|
||||
<button type="button" class="btn btn-sm btn-link">Link</button>
|
||||
</p>
|
||||
<p>
|
||||
<button type="button" class="btn btn-xs btn-default">Default</button>
|
||||
<button type="button" class="btn btn-xs btn-primary">Primary</button>
|
||||
<button type="button" class="btn btn-xs btn-success">Success</button>
|
||||
<button type="button" class="btn btn-xs btn-info">Info</button>
|
||||
<button type="button" class="btn btn-xs btn-warning">Warning</button>
|
||||
<button type="button" class="btn btn-xs btn-danger">Danger</button>
|
||||
<button type="button" class="btn btn-xs btn-link">Link</button>
|
||||
</p>
|
||||
|
||||
|
||||
<div class="page-header">
|
||||
<h1>Tables</h1>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>First Name</th>
|
||||
<th>Last Name</th>
|
||||
<th>Username</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>1</td>
|
||||
<td>Mark</td>
|
||||
<td>Otto</td>
|
||||
<td>@mdo</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>2</td>
|
||||
<td>Jacob</td>
|
||||
<td>Thornton</td>
|
||||
<td>@fat</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>3</td>
|
||||
<td>Larry</td>
|
||||
<td>the Bird</td>
|
||||
<td>@twitter</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<table class="table table-striped">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>First Name</th>
|
||||
<th>Last Name</th>
|
||||
<th>Username</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>1</td>
|
||||
<td>Mark</td>
|
||||
<td>Otto</td>
|
||||
<td>@mdo</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>2</td>
|
||||
<td>Jacob</td>
|
||||
<td>Thornton</td>
|
||||
<td>@fat</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>3</td>
|
||||
<td>Larry</td>
|
||||
<td>the Bird</td>
|
||||
<td>@twitter</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<table class="table table-bordered">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>First Name</th>
|
||||
<th>Last Name</th>
|
||||
<th>Username</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td rowspan="2">1</td>
|
||||
<td>Mark</td>
|
||||
<td>Otto</td>
|
||||
<td>@mdo</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>Mark</td>
|
||||
<td>Otto</td>
|
||||
<td>@TwBootstrap</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>2</td>
|
||||
<td>Jacob</td>
|
||||
<td>Thornton</td>
|
||||
<td>@fat</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>3</td>
|
||||
<td colspan="2">Larry the Bird</td>
|
||||
<td>@twitter</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<table class="table table-condensed">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>#</th>
|
||||
<th>First Name</th>
|
||||
<th>Last Name</th>
|
||||
<th>Username</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>1</td>
|
||||
<td>Mark</td>
|
||||
<td>Otto</td>
|
||||
<td>@mdo</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>2</td>
|
||||
<td>Jacob</td>
|
||||
<td>Thornton</td>
|
||||
<td>@fat</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>3</td>
|
||||
<td colspan="2">Larry the Bird</td>
|
||||
<td>@twitter</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="page-header">
|
||||
<h1>Thumbnails</h1>
|
||||
</div>
|
||||
<img data-src="holder.js/200x200" class="img-thumbnail" alt="200x200" src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9InllcyI/PjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB3aWR0aD0iMjAwIiBoZWlnaHQ9IjIwMCIgdmlld0JveD0iMCAwIDIwMCAyMDAiIHByZXNlcnZlQXNwZWN0UmF0aW89Im5vbmUiPjwhLS0KU291cmNlIFVSTDogaG9sZGVyLmpzLzIwMHgyMDAKQ3JlYXRlZCB3aXRoIEhvbGRlci5qcyAyLjYuMC4KTGVhcm4gbW9yZSBhdCBodHRwOi8vaG9sZGVyanMuY29tCihjKSAyMDEyLTIwMTUgSXZhbiBNYWxvcGluc2t5IC0gaHR0cDovL2ltc2t5LmNvCi0tPjxkZWZzPjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+PCFbQ0RBVEFbI2hvbGRlcl8xNTYyY2ExYjA3YiB0ZXh0IHsgZmlsbDojQUFBQUFBO2ZvbnQtd2VpZ2h0OmJvbGQ7Zm9udC1mYW1pbHk6QXJpYWwsIEhlbHZldGljYSwgT3BlbiBTYW5zLCBzYW5zLXNlcmlmLCBtb25vc3BhY2U7Zm9udC1zaXplOjEwcHQgfSBdXT48L3N0eWxlPjwvZGVmcz48ZyBpZD0iaG9sZGVyXzE1NjJjYTFiMDdiIj48cmVjdCB3aWR0aD0iMjAwIiBoZWlnaHQ9IjIwMCIgZmlsbD0iI0VFRUVFRSIvPjxnPjx0ZXh0IHg9Ijc0LjY5NTMxMjUiIHk9IjEwNC41Ij4yMDB4MjAwPC90ZXh0PjwvZz48L2c+PC9zdmc+" data-holder-rendered="true" style="width: 200px; height: 200px;">
|
||||
|
||||
|
||||
<div class="page-header">
|
||||
<h1>Labels</h1>
|
||||
</div>
|
||||
<h1>
|
||||
<span class="label label-default">Default</span>
|
||||
<span class="label label-primary">Primary</span>
|
||||
<span class="label label-success">Success</span>
|
||||
<span class="label label-info">Info</span>
|
||||
<span class="label label-warning">Warning</span>
|
||||
<span class="label label-danger">Danger</span>
|
||||
</h1>
|
||||
<h2>
|
||||
<span class="label label-default">Default</span>
|
||||
<span class="label label-primary">Primary</span>
|
||||
<span class="label label-success">Success</span>
|
||||
<span class="label label-info">Info</span>
|
||||
<span class="label label-warning">Warning</span>
|
||||
<span class="label label-danger">Danger</span>
|
||||
</h2>
|
||||
<h3>
|
||||
<span class="label label-default">Default</span>
|
||||
<span class="label label-primary">Primary</span>
|
||||
<span class="label label-success">Success</span>
|
||||
<span class="label label-info">Info</span>
|
||||
<span class="label label-warning">Warning</span>
|
||||
<span class="label label-danger">Danger</span>
|
||||
</h3>
|
||||
<h4>
|
||||
<span class="label label-default">Default</span>
|
||||
<span class="label label-primary">Primary</span>
|
||||
<span class="label label-success">Success</span>
|
||||
<span class="label label-info">Info</span>
|
||||
<span class="label label-warning">Warning</span>
|
||||
<span class="label label-danger">Danger</span>
|
||||
</h4>
|
||||
<h5>
|
||||
<span class="label label-default">Default</span>
|
||||
<span class="label label-primary">Primary</span>
|
||||
<span class="label label-success">Success</span>
|
||||
<span class="label label-info">Info</span>
|
||||
<span class="label label-warning">Warning</span>
|
||||
<span class="label label-danger">Danger</span>
|
||||
</h5>
|
||||
<h6>
|
||||
<span class="label label-default">Default</span>
|
||||
<span class="label label-primary">Primary</span>
|
||||
<span class="label label-success">Success</span>
|
||||
<span class="label label-info">Info</span>
|
||||
<span class="label label-warning">Warning</span>
|
||||
<span class="label label-danger">Danger</span>
|
||||
</h6>
|
||||
<p>
|
||||
<span class="label label-default">Default</span>
|
||||
<span class="label label-primary">Primary</span>
|
||||
<span class="label label-success">Success</span>
|
||||
<span class="label label-info">Info</span>
|
||||
<span class="label label-warning">Warning</span>
|
||||
<span class="label label-danger">Danger</span>
|
||||
</p>
|
||||
|
||||
|
||||
<div class="page-header">
|
||||
<h1>Badges</h1>
|
||||
</div>
|
||||
<p>
|
||||
<a href="#">Inbox <span class="badge">42</span></a>
|
||||
</p>
|
||||
<ul class="nav nav-pills" role="tablist">
|
||||
<li role="presentation" class="active"><a href="#">Home <span class="badge">42</span></a></li>
|
||||
<li role="presentation"><a href="#">Profile</a></li>
|
||||
<li role="presentation"><a href="#">Messages <span class="badge">3</span></a></li>
|
||||
</ul>
|
||||
|
||||
|
||||
<div class="page-header">
|
||||
<h1>Dropdown menus</h1>
|
||||
</div>
|
||||
<div class="dropdown theme-dropdown clearfix">
|
||||
<a id="dropdownMenu1" href="#" class="sr-only dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
|
||||
<li class="active"><a href="#">Action</a></li>
|
||||
<li><a href="#">Another action</a></li>
|
||||
<li><a href="#">Something else here</a></li>
|
||||
<li role="separator" class="divider"></li>
|
||||
<li><a href="#">Separated link</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="page-header">
|
||||
<h1>Navs</h1>
|
||||
</div>
|
||||
<ul class="nav nav-tabs" role="tablist">
|
||||
<li role="presentation" class="active"><a href="#">Home</a></li>
|
||||
<li role="presentation"><a href="#">Profile</a></li>
|
||||
<li role="presentation"><a href="#">Messages</a></li>
|
||||
</ul>
|
||||
<ul class="nav nav-pills" role="tablist">
|
||||
<li role="presentation" class="active"><a href="#">Home</a></li>
|
||||
<li role="presentation"><a href="#">Profile</a></li>
|
||||
<li role="presentation"><a href="#">Messages</a></li>
|
||||
</ul>
|
||||
|
||||
|
||||
<div class="page-header">
|
||||
<h1>Navbars</h1>
|
||||
</div>
|
||||
|
||||
<nav class="navbar navbar-default">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target=".navbar-collapse">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a class="navbar-brand" href="#">Project name</a>
|
||||
</div>
|
||||
<div class="navbar-collapse collapse">
|
||||
<ul class="nav navbar-nav">
|
||||
<li class="active"><a href="#">Home</a></li>
|
||||
<li><a href="#about">About</a></li>
|
||||
<li><a href="#contact">Contact</a></li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="#">Action</a></li>
|
||||
<li><a href="#">Another action</a></li>
|
||||
<li><a href="#">Something else here</a></li>
|
||||
<li role="separator" class="divider"></li>
|
||||
<li class="dropdown-header">Nav header</li>
|
||||
<li><a href="#">Separated link</a></li>
|
||||
<li><a href="#">One more separated link</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div><!--/.nav-collapse -->
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<nav class="navbar navbar-inverse">
|
||||
<div class="container">
|
||||
<div class="navbar-header">
|
||||
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target=".navbar-collapse">
|
||||
<span class="sr-only">Toggle navigation</span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
<span class="icon-bar"></span>
|
||||
</button>
|
||||
<a class="navbar-brand" href="#">Project name</a>
|
||||
</div>
|
||||
<div class="navbar-collapse collapse">
|
||||
<ul class="nav navbar-nav">
|
||||
<li class="active"><a href="#">Home</a></li>
|
||||
<li><a href="#about">About</a></li>
|
||||
<li><a href="#contact">Contact</a></li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="#">Action</a></li>
|
||||
<li><a href="#">Another action</a></li>
|
||||
<li><a href="#">Something else here</a></li>
|
||||
<li role="separator" class="divider"></li>
|
||||
<li class="dropdown-header">Nav header</li>
|
||||
<li><a href="#">Separated link</a></li>
|
||||
<li><a href="#">One more separated link</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
</ul>
|
||||
</div><!--/.nav-collapse -->
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
|
||||
<div class="page-header">
|
||||
<h1>Alerts</h1>
|
||||
</div>
|
||||
<div class="alert alert-success" role="alert">
|
||||
<strong>Well done!</strong> You successfully read this important alert message.
|
||||
</div>
|
||||
<div class="alert alert-info" role="alert">
|
||||
<strong>Heads up!</strong> This alert needs your attention, but it's not super important.
|
||||
</div>
|
||||
<div class="alert alert-warning" role="alert">
|
||||
<strong>Warning!</strong> Best check yo self, you're not looking too good.
|
||||
</div>
|
||||
<div class="alert alert-danger" role="alert">
|
||||
<strong>Oh snap!</strong> Change a few things up and try submitting again.
|
||||
</div>
|
||||
|
||||
|
||||
<div class="page-header">
|
||||
<h1>Progress bars</h1>
|
||||
</div>
|
||||
<div class="progress">
|
||||
<div class="progress-bar" role="progressbar" aria-valuenow="60" aria-valuemin="0" aria-valuemax="100" style="width: 60%;"><span class="sr-only">60% Complete</span></div>
|
||||
</div>
|
||||
<div class="progress">
|
||||
<div class="progress-bar progress-bar-success" role="progressbar" aria-valuenow="40" aria-valuemin="0" aria-valuemax="100" style="width: 40%"><span class="sr-only">40% Complete (success)</span></div>
|
||||
</div>
|
||||
<div class="progress">
|
||||
<div class="progress-bar progress-bar-info" role="progressbar" aria-valuenow="20" aria-valuemin="0" aria-valuemax="100" style="width: 20%"><span class="sr-only">20% Complete</span></div>
|
||||
</div>
|
||||
<div class="progress">
|
||||
<div class="progress-bar progress-bar-warning" role="progressbar" aria-valuenow="60" aria-valuemin="0" aria-valuemax="100" style="width: 60%"><span class="sr-only">60% Complete (warning)</span></div>
|
||||
</div>
|
||||
<div class="progress">
|
||||
<div class="progress-bar progress-bar-danger" role="progressbar" aria-valuenow="80" aria-valuemin="0" aria-valuemax="100" style="width: 80%"><span class="sr-only">80% Complete (danger)</span></div>
|
||||
</div>
|
||||
<div class="progress">
|
||||
<div class="progress-bar progress-bar-striped" role="progressbar" aria-valuenow="60" aria-valuemin="0" aria-valuemax="100" style="width: 60%"><span class="sr-only">60% Complete</span></div>
|
||||
</div>
|
||||
<div class="progress">
|
||||
<div class="progress-bar progress-bar-success" style="width: 35%"><span class="sr-only">35% Complete (success)</span></div>
|
||||
<div class="progress-bar progress-bar-warning" style="width: 20%"><span class="sr-only">20% Complete (warning)</span></div>
|
||||
<div class="progress-bar progress-bar-danger" style="width: 10%"><span class="sr-only">10% Complete (danger)</span></div>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="page-header">
|
||||
<h1>List groups</h1>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-4">
|
||||
<ul class="list-group">
|
||||
<li class="list-group-item">Cras justo odio</li>
|
||||
<li class="list-group-item">Dapibus ac facilisis in</li>
|
||||
<li class="list-group-item">Morbi leo risus</li>
|
||||
<li class="list-group-item">Porta ac consectetur ac</li>
|
||||
<li class="list-group-item">Vestibulum at eros</li>
|
||||
</ul>
|
||||
</div><!-- /.col-sm-4 -->
|
||||
<div class="col-sm-4">
|
||||
<div class="list-group">
|
||||
<a href="#" class="list-group-item active">
|
||||
Cras justo odio
|
||||
</a>
|
||||
<a href="#" class="list-group-item">Dapibus ac facilisis in</a>
|
||||
<a href="#" class="list-group-item">Morbi leo risus</a>
|
||||
<a href="#" class="list-group-item">Porta ac consectetur ac</a>
|
||||
<a href="#" class="list-group-item">Vestibulum at eros</a>
|
||||
</div>
|
||||
</div><!-- /.col-sm-4 -->
|
||||
<div class="col-sm-4">
|
||||
<div class="list-group">
|
||||
<a href="#" class="list-group-item active">
|
||||
<h4 class="list-group-item-heading">List group item heading</h4>
|
||||
<p class="list-group-item-text">Donec id elit non mi porta gravida at eget metus. Maecenas sed diam eget risus varius blandit.</p>
|
||||
</a>
|
||||
<a href="#" class="list-group-item">
|
||||
<h4 class="list-group-item-heading">List group item heading</h4>
|
||||
<p class="list-group-item-text">Donec id elit non mi porta gravida at eget metus. Maecenas sed diam eget risus varius blandit.</p>
|
||||
</a>
|
||||
<a href="#" class="list-group-item">
|
||||
<h4 class="list-group-item-heading">List group item heading</h4>
|
||||
<p class="list-group-item-text">Donec id elit non mi porta gravida at eget metus. Maecenas sed diam eget risus varius blandit.</p>
|
||||
</a>
|
||||
</div>
|
||||
</div><!-- /.col-sm-4 -->
|
||||
</div>
|
||||
|
||||
|
||||
<div class="page-header">
|
||||
<h1>Panels</h1>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-4">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">Panel title</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
Panel content
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-primary">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">Panel title</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
Panel content
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- /.col-sm-4 -->
|
||||
<div class="col-sm-4">
|
||||
<div class="panel panel-success">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">Panel title</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
Panel content
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-info">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">Panel title</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
Panel content
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- /.col-sm-4 -->
|
||||
<div class="col-sm-4">
|
||||
<div class="panel panel-warning">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">Panel title</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
Panel content
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-danger">
|
||||
<div class="panel-heading">
|
||||
<h3 class="panel-title">Panel title</h3>
|
||||
</div>
|
||||
<div class="panel-body">
|
||||
Panel content
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- /.col-sm-4 -->
|
||||
</div>
|
||||
|
||||
|
||||
<div class="page-header">
|
||||
<h1>Wells</h1>
|
||||
</div>
|
||||
<div class="well">
|
||||
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas sed diam eget risus varius blandit sit amet non magna. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Cras mattis consectetur purus sit amet fermentum. Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Aenean lacinia bibendum nulla sed consectetur.</p>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="page-header">
|
||||
<h1>Carousel</h1>
|
||||
</div>
|
||||
<div id="carousel-example-generic" class="carousel slide" data-ride="carousel">
|
||||
<ol class="carousel-indicators">
|
||||
<li data-target="#carousel-example-generic" data-slide-to="0" class=""></li>
|
||||
<li data-target="#carousel-example-generic" data-slide-to="1" class=""></li>
|
||||
<li data-target="#carousel-example-generic" data-slide-to="2" class="active"></li>
|
||||
</ol>
|
||||
<div class="carousel-inner" role="listbox">
|
||||
<div class="item">
|
||||
<img data-src="holder.js/1140x500/auto/#777:#555/text:First slide" alt="First slide [1140x500]" src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9InllcyI/PjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB3aWR0aD0iMTE0MCIgaGVpZ2h0PSI1MDAiIHZpZXdCb3g9IjAgMCAxMTQwIDUwMCIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+PCEtLQpTb3VyY2UgVVJMOiBob2xkZXIuanMvMTE0MHg1MDAvYXV0by8jNzc3OiM1NTUvdGV4dDpGaXJzdCBzbGlkZQpDcmVhdGVkIHdpdGggSG9sZGVyLmpzIDIuNi4wLgpMZWFybiBtb3JlIGF0IGh0dHA6Ly9ob2xkZXJqcy5jb20KKGMpIDIwMTItMjAxNSBJdmFuIE1hbG9waW5za3kgLSBodHRwOi8vaW1za3kuY28KLS0+PGRlZnM+PHN0eWxlIHR5cGU9InRleHQvY3NzIj48IVtDREFUQVsjaG9sZGVyXzE1NjJjYTIxYzRkIHRleHQgeyBmaWxsOiM1NTU7Zm9udC13ZWlnaHQ6Ym9sZDtmb250LWZhbWlseTpBcmlhbCwgSGVsdmV0aWNhLCBPcGVuIFNhbnMsIHNhbnMtc2VyaWYsIG1vbm9zcGFjZTtmb250LXNpemU6NTdwdCB9IF1dPjwvc3R5bGU+PC9kZWZzPjxnIGlkPSJob2xkZXJfMTU2MmNhMjFjNGQiPjxyZWN0IHdpZHRoPSIxMTQwIiBoZWlnaHQ9IjUwMCIgZmlsbD0iIzc3NyIvPjxnPjx0ZXh0IHg9IjM5MC41MDc4MTI1IiB5PSIyNzUuNSI+Rmlyc3Qgc2xpZGU8L3RleHQ+PC9nPjwvZz48L3N2Zz4=" data-holder-rendered="true">
|
||||
</div>
|
||||
<div class="item active left">
|
||||
<img data-src="holder.js/1140x500/auto/#666:#444/text:Second slide" alt="Second slide [1140x500]" src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9InllcyI/PjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB3aWR0aD0iMTE0MCIgaGVpZ2h0PSI1MDAiIHZpZXdCb3g9IjAgMCAxMTQwIDUwMCIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+PCEtLQpTb3VyY2UgVVJMOiBob2xkZXIuanMvMTE0MHg1MDAvYXV0by8jNjY2OiM0NDQvdGV4dDpTZWNvbmQgc2xpZGUKQ3JlYXRlZCB3aXRoIEhvbGRlci5qcyAyLjYuMC4KTGVhcm4gbW9yZSBhdCBodHRwOi8vaG9sZGVyanMuY29tCihjKSAyMDEyLTIwMTUgSXZhbiBNYWxvcGluc2t5IC0gaHR0cDovL2ltc2t5LmNvCi0tPjxkZWZzPjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+PCFbQ0RBVEFbI2hvbGRlcl8xNTYyY2ExZTY3NCB0ZXh0IHsgZmlsbDojNDQ0O2ZvbnQtd2VpZ2h0OmJvbGQ7Zm9udC1mYW1pbHk6QXJpYWwsIEhlbHZldGljYSwgT3BlbiBTYW5zLCBzYW5zLXNlcmlmLCBtb25vc3BhY2U7Zm9udC1zaXplOjU3cHQgfSBdXT48L3N0eWxlPjwvZGVmcz48ZyBpZD0iaG9sZGVyXzE1NjJjYTFlNjc0Ij48cmVjdCB3aWR0aD0iMTE0MCIgaGVpZ2h0PSI1MDAiIGZpbGw9IiM2NjYiLz48Zz48dGV4dCB4PSIzMzUuNjAxNTYyNSIgeT0iMjc1LjUiPlNlY29uZCBzbGlkZTwvdGV4dD48L2c+PC9nPjwvc3ZnPg==" data-holder-rendered="true">
|
||||
</div>
|
||||
<div class="item next left">
|
||||
<img data-src="holder.js/1140x500/auto/#555:#333/text:Third slide" alt="Third slide [1140x500]" src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9InllcyI/PjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB3aWR0aD0iMTE0MCIgaGVpZ2h0PSI1MDAiIHZpZXdCb3g9IjAgMCAxMTQwIDUwMCIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+PCEtLQpTb3VyY2UgVVJMOiBob2xkZXIuanMvMTE0MHg1MDAvYXV0by8jNTU1OiMzMzMvdGV4dDpUaGlyZCBzbGlkZQpDcmVhdGVkIHdpdGggSG9sZGVyLmpzIDIuNi4wLgpMZWFybiBtb3JlIGF0IGh0dHA6Ly9ob2xkZXJqcy5jb20KKGMpIDIwMTItMjAxNSBJdmFuIE1hbG9waW5za3kgLSBodHRwOi8vaW1za3kuY28KLS0+PGRlZnM+PHN0eWxlIHR5cGU9InRleHQvY3NzIj48IVtDREFUQVsjaG9sZGVyXzE1NjJjYTFiNTg5IHRleHQgeyBmaWxsOiMzMzM7Zm9udC13ZWlnaHQ6Ym9sZDtmb250LWZhbWlseTpBcmlhbCwgSGVsdmV0aWNhLCBPcGVuIFNhbnMsIHNhbnMtc2VyaWYsIG1vbm9zcGFjZTtmb250LXNpemU6NTdwdCB9IF1dPjwvc3R5bGU+PC9kZWZzPjxnIGlkPSJob2xkZXJfMTU2MmNhMWI1ODkiPjxyZWN0IHdpZHRoPSIxMTQwIiBoZWlnaHQ9IjUwMCIgZmlsbD0iIzU1NSIvPjxnPjx0ZXh0IHg9IjM3Ny44NjcxODc1IiB5PSIyNzUuNSI+VGhpcmQgc2xpZGU8L3RleHQ+PC9nPjwvZz48L3N2Zz4=" data-holder-rendered="true">
|
||||
</div>
|
||||
</div>
|
||||
<a class="left carousel-control" href="#carousel-example-generic" role="button" data-slide="prev">
|
||||
<span class="glyphicon glyphicon-chevron-left" aria-hidden="true"></span>
|
||||
<span class="sr-only">Previous</span>
|
||||
</a>
|
||||
<a class="right carousel-control" href="#carousel-example-generic" role="button" data-slide="next">
|
||||
<span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span>
|
||||
<span class="sr-only">Next</span>
|
||||
</a>
|
||||
</div>
|
||||
|
||||
|
||||
</div> <!-- /container -->
|
||||
@@ -0,0 +1,15 @@
|
||||
/* eslint-env node */
|
||||
|
||||
'use strict';
|
||||
|
||||
module.exports = function(config) {
|
||||
config.set({
|
||||
scripts: [{
|
||||
id: 'angular',
|
||||
src: '/build/angular.js'
|
||||
},
|
||||
{
|
||||
src: 'app.js'
|
||||
}]
|
||||
});
|
||||
};
|
||||
@@ -0,0 +1,40 @@
|
||||
<div ng-app="boostrapCompileBenchmark" ng-cloak>
|
||||
<div ng-controller="DataController as config">
|
||||
<p>Please, select which configuration you want to use:</p>
|
||||
<ul>
|
||||
<li>
|
||||
<a href="?comment=disabled&css=disabled">Only EA</a>
|
||||
<span ng-show="config.isEA">(active)</span>
|
||||
</li>
|
||||
<li>
|
||||
<a href="?comment=disabled">Active EA and classes directives</a>
|
||||
<span ng-show="config.isEAC">(active)</span>
|
||||
</li>
|
||||
<li>
|
||||
<a href="?css=disabled">Active EA and comment directives</a>
|
||||
<span ng-show="config.isEAM">(active)</span>
|
||||
</li>
|
||||
<li>
|
||||
<a href="?">Active all directives</a>
|
||||
<span ng-show="config.isEACM">(active)</span>
|
||||
</li>
|
||||
</ul>
|
||||
|
||||
<hr>
|
||||
<p>How many repetitions do you want to do?</p>
|
||||
<input type="number" ng-model="config.repeats">
|
||||
|
||||
<hr>
|
||||
<p>Template to $compile:</p>
|
||||
<select
|
||||
ng-options="template for template in config.templates"
|
||||
ng-model="config.selectedTemplate"
|
||||
ng-change="config.loadTemplate()"></select>
|
||||
|
||||
<p>The benchmark is
|
||||
<span ng-show="config.html">Ready!</span>
|
||||
<span ng-hide="config.html">LOADING!</span>
|
||||
</p>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
@@ -1,3 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
var app = angular.module('eventDelegationBenchmark', []);
|
||||
|
||||
app.directive('noopDir', function() {
|
||||
@@ -5,7 +7,7 @@ app.directive('noopDir', function() {
|
||||
compile: function($element, $attrs) {
|
||||
return function($scope, $element) {
|
||||
return 1;
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -13,12 +15,12 @@ app.directive('noopDir', function() {
|
||||
app.directive('nativeClick', ['$parse', function($parse) {
|
||||
return {
|
||||
compile: function($element, $attrs) {
|
||||
var expr = $parse($attrs.tstEvent);
|
||||
$parse($attrs.tstEvent);
|
||||
return function($scope, $element) {
|
||||
$element[0].addEventListener('click', function() {
|
||||
console.log('clicked');
|
||||
}, false);
|
||||
}
|
||||
};
|
||||
}
|
||||
};
|
||||
}]);
|
||||
@@ -26,13 +28,12 @@ app.directive('nativeClick', ['$parse', function($parse) {
|
||||
app.directive('dlgtClick', function() {
|
||||
return {
|
||||
compile: function($element, $attrs) {
|
||||
var evt = $attrs.dlgtClick;
|
||||
// We don't setup the global event listeners as the costs are small and one time only...
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
app.controller('DataController', function($rootScope) {
|
||||
app.controller('DataController', function DataController($rootScope) {
|
||||
this.ngRepeatCount = 1000;
|
||||
this.rows = [];
|
||||
var self = this;
|
||||
@@ -47,8 +48,8 @@ app.controller('DataController', function($rootScope) {
|
||||
self.rows = oldRows;
|
||||
if (self.rows.length !== self.ngRepeatCount) {
|
||||
self.rows = [];
|
||||
for (var i=0; i<self.ngRepeatCount; i++) {
|
||||
self.rows.push('row'+i);
|
||||
for (var i = 0; i < self.ngRepeatCount; i++) {
|
||||
self.rows.push('row' + i);
|
||||
}
|
||||
}
|
||||
$rootScope.$apply();
|
||||
|
||||
@@ -1,10 +1,14 @@
|
||||
/* eslint-env node */
|
||||
|
||||
'use strict';
|
||||
|
||||
module.exports = function(config) {
|
||||
config.set({
|
||||
scripts: [{
|
||||
id: 'angular',
|
||||
src: '/build/angular.js'
|
||||
},{
|
||||
src: 'app.js',
|
||||
}, {
|
||||
src: 'app.js'
|
||||
}]
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
var app = angular.module('largetableBenchmark', []);
|
||||
|
||||
app.config(function($compileProvider) {
|
||||
@@ -12,21 +14,23 @@ app.filter('noop', function() {
|
||||
};
|
||||
});
|
||||
|
||||
app.controller('DataController', function($scope, $rootScope) {
|
||||
app.controller('DataController', function DataController($scope, $rootScope) {
|
||||
var totalRows = 1000;
|
||||
var totalColumns = 20;
|
||||
|
||||
var data = $scope.data = [];
|
||||
$scope.digestDuration = '?';
|
||||
$scope.numberOfBindings = totalRows*totalColumns*2 + totalRows + 1;
|
||||
$scope.numberOfBindings = totalRows * totalColumns * 2 + totalRows + 1;
|
||||
$scope.numberOfWatches = '?';
|
||||
|
||||
/** @this */
|
||||
function iGetter() { return this.i; }
|
||||
/** @this */
|
||||
function jGetter() { return this.j; }
|
||||
|
||||
for (var i=0; i<totalRows; i++) {
|
||||
for (var i = 0; i < totalRows; i++) {
|
||||
data[i] = [];
|
||||
for (var j=0; j<totalColumns; j++) {
|
||||
for (var j = 0; j < totalColumns; j++) {
|
||||
data[i][j] = {
|
||||
i: i, j: j,
|
||||
iFn: iGetter,
|
||||
@@ -64,14 +68,13 @@ app.controller('DataController', function($scope, $rootScope) {
|
||||
});
|
||||
});
|
||||
|
||||
var fn = function() { return 'x'};
|
||||
|
||||
|
||||
app.directive('baselineBindingTable', function() {
|
||||
return {
|
||||
restrict: 'E',
|
||||
link: function ($scope, $element) {
|
||||
link: function($scope, $element) {
|
||||
var i, j, row, cell, comment;
|
||||
var document = window.document;
|
||||
var template = document.createElement('span');
|
||||
template.setAttribute('ng-repeat', 'foo in foos');
|
||||
template.classList.add('ng-scope');
|
||||
@@ -104,8 +107,9 @@ app.directive('baselineBindingTable', function() {
|
||||
app.directive('baselineInterpolationTable', function() {
|
||||
return {
|
||||
restrict: 'E',
|
||||
link: function ($scope, $element) {
|
||||
link: function($scope, $element) {
|
||||
var i, j, row, cell, comment;
|
||||
var document = window.document;
|
||||
var template = document.createElement('span');
|
||||
template.setAttribute('ng-repeat', 'foo in foos');
|
||||
template.classList.add('ng-scope');
|
||||
@@ -180,4 +184,4 @@ app.directive('baselineTable', function() {
|
||||
};
|
||||
});
|
||||
|
||||
*/
|
||||
*/
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
/* eslint-env node */
|
||||
|
||||
'use strict';
|
||||
|
||||
module.exports = function(config) {
|
||||
config.set({
|
||||
scripts: [{
|
||||
@@ -9,7 +13,7 @@ module.exports = function(config) {
|
||||
src: '/build/angular.js'
|
||||
},
|
||||
{
|
||||
src: 'app.js',
|
||||
src: 'app.js'
|
||||
}]
|
||||
});
|
||||
};
|
||||
|
||||
+1
-1
@@ -1 +1 @@
|
||||
//Override me with ?jquery=/bower_components/jquery/dist/jquery.js
|
||||
// Override me with ?jquery=/bower_components/jquery/dist/jquery.js
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
"use strict";
|
||||
'use strict';
|
||||
|
||||
/* globals angular, benchmarkSteps */
|
||||
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
/* eslint-env node */
|
||||
|
||||
'use strict';
|
||||
|
||||
module.exports = function(config) {
|
||||
config.set({
|
||||
scripts: [ {
|
||||
scripts: [{
|
||||
id: 'angular',
|
||||
src: '/build/angular.js'
|
||||
},
|
||||
{
|
||||
src: 'app.js',
|
||||
src: 'app.js'
|
||||
}]
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
'use strict';
|
||||
|
||||
var app = angular.module('orderByBenchmark', []);
|
||||
|
||||
app.controller('DataController', function($rootScope, $scope) {
|
||||
app.controller('DataController', function DataController($rootScope, $scope) {
|
||||
this.ngRepeatCount = 5000;
|
||||
this.rows = [];
|
||||
var self = this;
|
||||
@@ -37,7 +39,7 @@ app.controller('DataController', function($rootScope, $scope) {
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
});
|
||||
|
||||
benchmarkSteps.push({
|
||||
name: '$apply',
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
/* eslint-env node */
|
||||
|
||||
'use strict';
|
||||
|
||||
module.exports = function(config) {
|
||||
config.set({
|
||||
scripts: [
|
||||
{
|
||||
"id": "jquery",
|
||||
"src": "jquery-noop.js"
|
||||
},{
|
||||
'id': 'jquery',
|
||||
'src': 'jquery-noop.js'
|
||||
}, {
|
||||
id: 'angular',
|
||||
src: '/build/angular.js'
|
||||
},{
|
||||
src: 'app.js',
|
||||
}, {
|
||||
src: 'app.js'
|
||||
}]
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
var app = angular.module('parsedExpressionBenchmark', []);
|
||||
|
||||
app.config(function($compileProvider) {
|
||||
@@ -17,11 +19,10 @@ app.directive('bmPeWatch', function() {
|
||||
return {
|
||||
restrict: 'A',
|
||||
compile: function($element, $attrs) {
|
||||
$element.text( $attrs.bmPeWatch );
|
||||
$element.text($attrs.bmPeWatch);
|
||||
return function($scope, $element, $attrs) {
|
||||
$scope.$watch($attrs.bmPeWatch, function(val) {
|
||||
$element.text(val);
|
||||
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -38,9 +39,9 @@ app.directive('bmPeWatchLiteral', function($parse) {
|
||||
return {
|
||||
restrict: 'A',
|
||||
compile: function($element, $attrs) {
|
||||
$element.text( $attrs.bmPeWatchLiteral );
|
||||
$element.text($attrs.bmPeWatchLiteral);
|
||||
return function($scope, $element, $attrs) {
|
||||
$scope.$watch( $parse($attrs.bmPeWatchLiteral, retZero) );
|
||||
$scope.$watch($parse($attrs.bmPeWatchLiteral, retZero));
|
||||
};
|
||||
}
|
||||
};
|
||||
@@ -53,33 +54,33 @@ app.controller('DataController', function($scope, $rootScope) {
|
||||
|
||||
var star = '*';
|
||||
|
||||
$scope.func = function() { return star;};
|
||||
$scope.func = function() { return star; };
|
||||
|
||||
for (var i=0; i<totalRows; i++) {
|
||||
for (var i = 0; i < totalRows; i++) {
|
||||
data.push({
|
||||
index: i,
|
||||
odd: i%2 === 0,
|
||||
even: i%2 === 1,
|
||||
str0: "foo-" + Math.random()*Date.now(),
|
||||
str1: "bar-" + Math.random()*Date.now(),
|
||||
str2: "baz-" + Math.random()*Date.now(),
|
||||
num0: Math.random()*Date.now(),
|
||||
num1: Math.random()*Date.now(),
|
||||
num2: Math.random()*Date.now(),
|
||||
date0: new Date(Math.random()*Date.now()),
|
||||
date1: new Date(Math.random()*Date.now()),
|
||||
date2: new Date(Math.random()*Date.now()),
|
||||
func: function(){ return star; },
|
||||
obj: data[i-1],
|
||||
keys: data[i-1] && (data[i-1].keys || Object.keys(data[i-1])),
|
||||
constructor: data[i-1]
|
||||
odd: i % 2 === 0,
|
||||
even: i % 2 === 1,
|
||||
str0: 'foo-' + Math.random() * Date.now(),
|
||||
str1: 'bar-' + Math.random() * Date.now(),
|
||||
str2: 'baz-' + Math.random() * Date.now(),
|
||||
num0: Math.random() * Date.now(),
|
||||
num1: Math.random() * Date.now(),
|
||||
num2: Math.random() * Date.now(),
|
||||
date0: new Date(Math.random() * Date.now()),
|
||||
date1: new Date(Math.random() * Date.now()),
|
||||
date2: new Date(Math.random() * Date.now()),
|
||||
func: function() { return star; },
|
||||
obj: data[i - 1],
|
||||
keys: data[i - 1] && (data[i - 1].keys || Object.keys(data[i - 1])),
|
||||
constructor: data[i - 1]
|
||||
});
|
||||
}
|
||||
|
||||
benchmarkSteps.push({
|
||||
name: '$apply',
|
||||
fn: function() {
|
||||
for (var i=0; i<50; i++) {
|
||||
for (var i = 0; i < 50; i++) {
|
||||
$rootScope.$digest();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,15 @@
|
||||
/* eslint-env node */
|
||||
|
||||
'use strict';
|
||||
|
||||
module.exports = function(config) {
|
||||
config.set({
|
||||
scripts: [ {
|
||||
scripts: [{
|
||||
id: 'angular',
|
||||
src: '/build/angular.js'
|
||||
},
|
||||
{
|
||||
src: 'app.js',
|
||||
src: 'app.js'
|
||||
}]
|
||||
});
|
||||
};
|
||||
|
||||
@@ -52,6 +52,11 @@
|
||||
<label for="functionCalls">Function calls</label>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<input type="radio" ng-model="expressionType" value="assignment" id="assignment">
|
||||
<label for="assignment">Assignment</label>
|
||||
</li>
|
||||
|
||||
<li>
|
||||
<input type="radio" ng-model="expressionType" value="objectLiterals" id="objectLiterals">
|
||||
<label for="objectLiterals">Object Literals</label>
|
||||
@@ -197,6 +202,18 @@
|
||||
<span bm-pe-watch="row.func(row.func(), row.func())"></span>
|
||||
</li>
|
||||
|
||||
<li ng-switch-when="assignment" ng-repeat="(rowIdx, row) in ::data">
|
||||
<span bm-pe-watch="row.foo = row.str0"></span>
|
||||
<span bm-pe-watch="row.obj.foo = row.str1"></span>
|
||||
<span bm-pe-watch="row.obj.obj.foo = row.str2"></span>
|
||||
<span bm-pe-watch="row['bar'] = row.num0"></span>
|
||||
<span bm-pe-watch="row.obj['bar'] = row.num1"></span>
|
||||
<span bm-pe-watch="row.obj.obj['bar'] = row.num2"></span>
|
||||
<span bm-pe-watch="row[0] = row.date0"></span>
|
||||
<span bm-pe-watch="row.obj[0] = row.date1"></span>
|
||||
<span bm-pe-watch="row.obj.obj[0] = row.date2"></span>
|
||||
</li>
|
||||
|
||||
<li ng-switch-when="objectLiterals" ng-repeat="(rowIdx, row) in ::data">
|
||||
<span bm-pe-watch-literal="{foo: rowIdx}"></span>
|
||||
<span bm-pe-watch-literal="{foo: row, bar: rowIdx}"></span>
|
||||
|
||||
+3
-2
@@ -1,8 +1,9 @@
|
||||
{
|
||||
"name": "AngularJS",
|
||||
"name": "angularjs",
|
||||
"license": "MIT",
|
||||
"devDependencies": {
|
||||
"jquery": "2.2.3",
|
||||
"jquery": "3.1.0",
|
||||
"jquery-2.2": "jquery#2.2.4",
|
||||
"jquery-2.1": "jquery#2.1.4",
|
||||
"closure-compiler": "https://dl.google.com/closure-compiler/compiler-20140814.zip",
|
||||
"ng-closure-runner": "https://raw.github.com/angular/ng-closure-runner/v0.2.3/assets/ng-closure-runner.zip"
|
||||
|
||||
+3
-5
@@ -38,7 +38,7 @@ var parseRawCommit = function(raw) {
|
||||
|
||||
lines.forEach(function(line) {
|
||||
match = line.match(/(?:Closes|Fixes)\s#(\d+)/);
|
||||
if (match) msg.closes.push(parseInt(match[1]));
|
||||
if (match) msg.closes.push(parseInt(match[1], 10));
|
||||
});
|
||||
|
||||
match = raw.match(/BREAKING CHANGE:([\s\S]*)/);
|
||||
@@ -48,7 +48,7 @@ var parseRawCommit = function(raw) {
|
||||
|
||||
|
||||
msg.body = lines.join('\n');
|
||||
match = msg.subject.match(/^(.*)\((.*)\)\:\s(.*)$/);
|
||||
match = msg.subject.match(/^(.*)\((.*)\):\s(.*)$/);
|
||||
|
||||
if (!match || !match[1] || !match[3]) {
|
||||
warn('Incorrect message: %s %s', msg.hash, msg.subject);
|
||||
@@ -148,8 +148,6 @@ var writeChangelog = function(stream, commits, version) {
|
||||
breaks: {}
|
||||
};
|
||||
|
||||
sections.breaks[EMPTY_COMPONENT] = [];
|
||||
|
||||
commits.forEach(function(commit) {
|
||||
var section = sections[commit.type];
|
||||
var component = commit.component || EMPTY_COMPONENT;
|
||||
@@ -162,7 +160,7 @@ var writeChangelog = function(stream, commits, version) {
|
||||
if (commit.breaking) {
|
||||
sections.breaks[component] = sections.breaks[component] || [];
|
||||
sections.breaks[component].push({
|
||||
subject: util.format("due to %s,\n %s", linkToCommit(commit.hash), commit.breaking),
|
||||
subject: util.format('due to %s,\n %s', linkToCommit(commit.hash), commit.breaking),
|
||||
hash: commit.hash,
|
||||
closes: []
|
||||
});
|
||||
|
||||
+2
-2
@@ -67,7 +67,7 @@ describe('changelog.js', function() {
|
||||
module2: [{subject: 'breaking change 2'}]
|
||||
};
|
||||
var expectedOutput =
|
||||
'\n' + '## test\n\n' +
|
||||
'\n## test\n\n' +
|
||||
'- **module1:** breaking change 1\n' +
|
||||
'- **module2:** breaking change 2\n' +
|
||||
'\n';
|
||||
@@ -92,7 +92,7 @@ describe('changelog.js', function() {
|
||||
]
|
||||
};
|
||||
var expectedOutput =
|
||||
'\n' + '## test\n\n' +
|
||||
'\n## test\n\n' +
|
||||
'- **module1:**\n' +
|
||||
' - breaking change 1.1\n' +
|
||||
' - breaking change 1.2\n' +
|
||||
|
||||
+40
-41
@@ -9,72 +9,72 @@ var Q = require('q');
|
||||
var _ = require('lodash');
|
||||
var semver = require('semver');
|
||||
|
||||
var exec = function (cmd) {
|
||||
return function () {
|
||||
var exec = function(cmd) {
|
||||
return function() {
|
||||
var args = Array.prototype.slice.call(arguments, 0);
|
||||
args.unshift(cmd);
|
||||
var fullCmd = util.format.apply(util, args);
|
||||
return Q.nfcall(cp.exec, fullCmd).then(function (out) {
|
||||
return Q.nfcall(cp.exec, fullCmd).then(function(out) {
|
||||
return out[0].split('\n');
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
var andThen = function (fn, after) {
|
||||
return function () {
|
||||
var andThen = function(fn, after) {
|
||||
return /** @this */ function() {
|
||||
return fn.apply(this, arguments).then(after);
|
||||
};
|
||||
};
|
||||
|
||||
var oneArg = function (fn) {
|
||||
return function (arg) {
|
||||
var oneArg = function(fn) {
|
||||
return function(arg) {
|
||||
return fn(arg);
|
||||
};
|
||||
};
|
||||
|
||||
var oneLine = function (lines) {
|
||||
var oneLine = function(lines) {
|
||||
return lines[0].trim();
|
||||
};
|
||||
|
||||
var noArgs = function (fn) {
|
||||
return function () {
|
||||
var noArgs = function(fn) {
|
||||
return function() {
|
||||
return fn();
|
||||
};
|
||||
};
|
||||
|
||||
var identity = function (i) { return i; };
|
||||
var identity = function(i) { return i; };
|
||||
|
||||
// like Q.all, but runs the commands in series
|
||||
// useful for ensuring env state (like which branch is checked out)
|
||||
var allInSeries = function (fn) {
|
||||
return function (args) {
|
||||
var allInSeries = function(fn) {
|
||||
return function(args) {
|
||||
var results = [];
|
||||
var def;
|
||||
while (args.length > 0) {
|
||||
(function (arg) {
|
||||
(function(arg) {
|
||||
if (def) {
|
||||
def = def.then(function () {
|
||||
def = def.then(function() {
|
||||
return fn(arg);
|
||||
});
|
||||
} else {
|
||||
def = fn(arg);
|
||||
}
|
||||
def = def.then(function (res) {
|
||||
def = def.then(function(res) {
|
||||
results.push(res);
|
||||
});
|
||||
}(args.pop()));
|
||||
})(args.pop());
|
||||
}
|
||||
return def.then(function () {
|
||||
return def.then(function() {
|
||||
return results;
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
var compareBranches = function (left, right) {
|
||||
var compareBranches = function(left, right) {
|
||||
console.log('# These commits are in ' + left.name + ' but not in ' + right.name + '\n');
|
||||
console.log(_(left.log).
|
||||
difference(right.log).
|
||||
map(function (line) {
|
||||
map(function(line) {
|
||||
return left.full[left.log.indexOf(line)]; // lol O(n^2)
|
||||
}).
|
||||
value().
|
||||
@@ -85,44 +85,43 @@ var checkout = oneArg(exec('git checkout %s'));
|
||||
|
||||
var getCurrentBranch = andThen(noArgs(exec('git rev-parse --abbrev-ref HEAD')), oneLine);
|
||||
var getTags = noArgs(exec('git tag'));
|
||||
var getShaOfTag = oneArg(exec('git rev-list %s | head -n 1'));
|
||||
var getTheLog = oneArg(exec('git log --pretty=oneline %s..HEAD | cat'));
|
||||
|
||||
// remember this so we can restore state
|
||||
var currentBranch;
|
||||
|
||||
getCurrentBranch().
|
||||
then(function (branch) {
|
||||
then(function(branch) {
|
||||
currentBranch = branch;
|
||||
}).
|
||||
then(getTags).
|
||||
then(function (tags) {
|
||||
then(function(tags) {
|
||||
return tags.
|
||||
filter(semver.valid).
|
||||
map(semver.clean).
|
||||
sort(semver.rcompare);
|
||||
}).
|
||||
then(function (tags) {
|
||||
var major = tags[0].split('.')[0];
|
||||
then(function(tags) {
|
||||
var major = semver(tags[0]).major;
|
||||
return tags.
|
||||
filter(function (ver) {
|
||||
return semver(ver).major == major;
|
||||
filter(function(ver) {
|
||||
return semver(ver).major === major;
|
||||
});
|
||||
}).
|
||||
then(function (tags) {
|
||||
then(function(tags) {
|
||||
return _(tags).
|
||||
groupBy(function (tag) {
|
||||
groupBy(function(tag) {
|
||||
return tag.split('.')[1];
|
||||
}).
|
||||
map(function (group) {
|
||||
map(function(group) {
|
||||
return _.first(group);
|
||||
}).
|
||||
map(function (tag) {
|
||||
map(function(tag) {
|
||||
return 'v' + tag;
|
||||
}).
|
||||
value();
|
||||
}).
|
||||
then(function (tags) {
|
||||
then(function(tags) {
|
||||
var master = tags.pop();
|
||||
var stable = tags.pop();
|
||||
|
||||
@@ -131,38 +130,38 @@ then(function (tags) {
|
||||
{ name: 'master', tag: master}
|
||||
];
|
||||
}).
|
||||
then(allInSeries(function (branch) {
|
||||
then(allInSeries(function(branch) {
|
||||
return checkout(branch.name).
|
||||
then(function () {
|
||||
then(function() {
|
||||
return getTheLog(branch.tag);
|
||||
}).
|
||||
then(function (log) {
|
||||
then(function(log) {
|
||||
return log.
|
||||
filter(identity);
|
||||
}).
|
||||
then(function (log) {
|
||||
branch.full = log.map(function (line) {
|
||||
then(function(log) {
|
||||
branch.full = log.map(function(line) {
|
||||
line = line.split(' ');
|
||||
var sha = line.shift();
|
||||
var msg = line.join(' ');
|
||||
return sha + ((/fix\([^\)]+\):/i.test(msg)) ? ' * ' : ' ') + msg;
|
||||
});
|
||||
branch.log = log.map(function (line) {
|
||||
branch.log = log.map(function(line) {
|
||||
return line.substr(41);
|
||||
});
|
||||
return branch;
|
||||
});
|
||||
})).
|
||||
then(function (pairs) {
|
||||
then(function(pairs) {
|
||||
compareBranches(pairs[0], pairs[1]);
|
||||
console.log('\n');
|
||||
compareBranches(pairs[1], pairs[0]);
|
||||
return pairs;
|
||||
}).
|
||||
then(function () {
|
||||
then(function() {
|
||||
return checkout(currentBranch);
|
||||
}).
|
||||
catch(function (e) {
|
||||
catch(function(e) {
|
||||
console.log(e.stack);
|
||||
});
|
||||
|
||||
|
||||
@@ -1,17 +1,18 @@
|
||||
"use strict";
|
||||
/* jshint browser: true */
|
||||
/* global importScripts, onmessage: true, postMessage, lunr */
|
||||
'use strict';
|
||||
|
||||
/* eslint-env worker */
|
||||
/* global importScripts, lunr */
|
||||
|
||||
// Load up the lunr library
|
||||
importScripts('../components/lunr.js-0.5.12/lunr.min.js');
|
||||
|
||||
// Create the lunr index - the docs should be an array of object, each object containing
|
||||
// the path and search terms for a page
|
||||
var index = lunr(function() {
|
||||
var index = lunr(/** @this */function() {
|
||||
this.ref('path');
|
||||
this.field('titleWords', {boost: 50});
|
||||
this.field('members', { boost: 40});
|
||||
this.field('keywords', { boost : 20 });
|
||||
this.field('members', {boost: 40});
|
||||
this.field('keywords', {boost: 20});
|
||||
});
|
||||
|
||||
// Retrieve the searchData which contains the information about each page to be indexed
|
||||
@@ -25,13 +26,13 @@ searchDataRequest.onload = function() {
|
||||
searchData.forEach(function(page) {
|
||||
index.add(page);
|
||||
});
|
||||
postMessage({ e: 'index-ready' });
|
||||
self.postMessage({e: 'index-ready'});
|
||||
};
|
||||
searchDataRequest.open('GET', 'search-data.json');
|
||||
searchDataRequest.send();
|
||||
|
||||
// The worker receives a message everytime the web app wants to query the index
|
||||
onmessage = function(oEvent) {
|
||||
self.onmessage = function(oEvent) {
|
||||
var q = oEvent.data.q;
|
||||
var hits = index.search(q);
|
||||
var results = [];
|
||||
@@ -40,5 +41,5 @@ onmessage = function(oEvent) {
|
||||
results.push(hit.ref);
|
||||
});
|
||||
// The results of the query are sent back to the web app via a new message
|
||||
postMessage({ e: 'query-ready', q: q, d: results });
|
||||
};
|
||||
self.postMessage({e: 'query-ready', q: q, d: results});
|
||||
};
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
{
|
||||
"root": true,
|
||||
"extends": "../../../.eslintrc-node.json",
|
||||
|
||||
|
||||
"env": {
|
||||
"jasmine": true,
|
||||
"protractor": true
|
||||
},
|
||||
|
||||
"globals": {
|
||||
/* testabilityPatch / matchers */
|
||||
"inject": false,
|
||||
"module": false,
|
||||
"dealoc": false,
|
||||
"_jQuery": false,
|
||||
"_jqLiteMode": false,
|
||||
"sortedHtml": false,
|
||||
"childrenTagsOf": false,
|
||||
"assertHidden": false,
|
||||
"assertVisible": false,
|
||||
"provideLog": false,
|
||||
"spyOnlyCallsWithArgs": false,
|
||||
"createMockStyleSheet": false,
|
||||
"browserTrigger": false,
|
||||
"jqLiteCacheSize": false
|
||||
}
|
||||
}
|
||||
@@ -1,45 +0,0 @@
|
||||
{
|
||||
"extends": "../../../.jshintrc-base",
|
||||
|
||||
"globals": {
|
||||
|
||||
/* jasmine / karma */
|
||||
"it": false,
|
||||
"iit": false,
|
||||
"describe": false,
|
||||
"ddescribe": false,
|
||||
"beforeEach": false,
|
||||
"afterEach": false,
|
||||
"expect": false,
|
||||
"jasmine": false,
|
||||
"spyOn": false,
|
||||
"waits": false,
|
||||
"waitsFor": false,
|
||||
"runs": false,
|
||||
"dump": false,
|
||||
|
||||
/* e2e */
|
||||
"protractor": false,
|
||||
"browser": false,
|
||||
"element": false,
|
||||
"by": false,
|
||||
"$": false,
|
||||
"$$": false,
|
||||
|
||||
/* testabilityPatch / matchers */
|
||||
"inject": false,
|
||||
"module": false,
|
||||
"dealoc": false,
|
||||
"_jQuery": false,
|
||||
"_jqLiteMode": false,
|
||||
"sortedHtml": false,
|
||||
"childrenTagsOf": false,
|
||||
"assertHidden": false,
|
||||
"assertVisible": false,
|
||||
"provideLog": false,
|
||||
"spyOnlyCallsWithArgs": false,
|
||||
"createMockStyleSheet": false,
|
||||
"browserTrigger": false,
|
||||
"jqLiteCacheSize": false
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
'use strict';
|
||||
|
||||
describe("doc.angularjs.org", function() {
|
||||
describe('doc.angularjs.org', function() {
|
||||
|
||||
describe("API pages", function() {
|
||||
describe('API pages', function() {
|
||||
|
||||
it("should display links to code on GitHub", function() {
|
||||
it('should display links to code on GitHub', function() {
|
||||
browser.get('build/docs/index.html#!/api/ng/service/$http');
|
||||
expect(element(by.css('.improve-docs')).getAttribute('href')).toMatch(/https?:\/\/github\.com\/angular\/angular\.js\/edit\/.+\/src\/ng\/http\.js/);
|
||||
|
||||
@@ -12,7 +12,7 @@ describe("doc.angularjs.org", function() {
|
||||
expect(element(by.css('.view-source')).getAttribute('href')).toMatch(/https?:\/\/github\.com\/angular\/angular\.js\/tree\/.+\/src\/ng\/http\.js#L\d+/);
|
||||
});
|
||||
|
||||
it('should change the page content when clicking a link to a service', function () {
|
||||
it('should change the page content when clicking a link to a service', function() {
|
||||
browser.get('build/docs/index.html');
|
||||
|
||||
var ngBindLink = element(by.css('.definition-table td a[href="api/ng/directive/ngClick"]'));
|
||||
@@ -23,7 +23,7 @@ describe("doc.angularjs.org", function() {
|
||||
});
|
||||
|
||||
|
||||
it('should show the functioning input directive example', function () {
|
||||
it('should show the functioning input directive example', function() {
|
||||
browser.get('build/docs/index.html#!/api/ng/directive/input');
|
||||
|
||||
// Ensure that the page is loaded before trying to switch frames.
|
||||
@@ -38,7 +38,7 @@ describe("doc.angularjs.org", function() {
|
||||
expect(code.getText()).toContain('guest!!!');
|
||||
});
|
||||
|
||||
it("should trim indentation from code blocks", function() {
|
||||
it('should trim indentation from code blocks', function() {
|
||||
browser.get('build/docs/index.html#!/api/ng/type/$rootScope.Scope');
|
||||
|
||||
var codeBlocks = element.all(by.css('pre > code.lang-js'));
|
||||
@@ -48,4 +48,4 @@ describe("doc.angularjs.org", function() {
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
'use strict';
|
||||
|
||||
describe("provider pages", function() {
|
||||
describe('provider pages', function() {
|
||||
|
||||
it("should show the related service", function() {
|
||||
it('should show the related service', function() {
|
||||
browser.get('build/docs/index.html#!/api/ng/provider/$compileProvider');
|
||||
var serviceLink = element.all(by.css('ol.api-profile-header-structure li a')).first();
|
||||
expect(serviceLink.getText()).toEqual('- $compile');
|
||||
expect(serviceLink.getAttribute('href')).toMatch(/api\/ng\/service\/\$compile/);
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
'use strict';
|
||||
|
||||
describe("service pages", function() {
|
||||
describe('service pages', function() {
|
||||
|
||||
it("should show the related provider if there is one", function() {
|
||||
it('should show the related provider if there is one', function() {
|
||||
browser.get('build/docs/index.html#!/api/ng/service/$compile');
|
||||
var providerLink = element.all(by.css('ol.api-profile-header-structure li a')).first();
|
||||
expect(providerLink.getText()).toEqual('- $compileProvider');
|
||||
@@ -14,9 +14,9 @@ describe("service pages", function() {
|
||||
expect(providerLink.getAttribute('href')).not.toMatch(/api\/ng\/provider\/\$compileProvider/);
|
||||
});
|
||||
|
||||
it("should show parameter defaults", function() {
|
||||
it('should show parameter defaults', function() {
|
||||
browser.get('build/docs/index.html#!/api/ng/service/$timeout');
|
||||
expect(element.all(by.css('.input-arguments p em')).first().getText()).toContain('(default: 0)');
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
'use strict';
|
||||
|
||||
var webdriver = require('protractor/node_modules/selenium-webdriver');
|
||||
var webdriver = require('selenium-webdriver');
|
||||
|
||||
describe('docs.angularjs.org', function () {
|
||||
describe('docs.angularjs.org', function() {
|
||||
|
||||
beforeEach(function() {
|
||||
// read and clear logs from previous tests
|
||||
@@ -24,7 +24,7 @@ describe('docs.angularjs.org', function () {
|
||||
});
|
||||
|
||||
|
||||
describe('App', function () {
|
||||
describe('App', function() {
|
||||
// it('should filter the module list when searching', function () {
|
||||
// browser.get();
|
||||
// browser.waitForAngular();
|
||||
@@ -38,8 +38,8 @@ describe('docs.angularjs.org', function () {
|
||||
// });
|
||||
|
||||
|
||||
it('should change the page content when clicking a link to a service', function () {
|
||||
browser.get('build/docs/index.html');
|
||||
it('should change the page content when clicking a link to a service', function() {
|
||||
browser.get('build/docs/index-production.html');
|
||||
|
||||
var ngBindLink = element(by.css('.definition-table td a[href="api/ng/directive/ngClick"]'));
|
||||
ngBindLink.click();
|
||||
@@ -51,36 +51,36 @@ describe('docs.angularjs.org', function () {
|
||||
|
||||
|
||||
it('should be resilient to trailing slashes', function() {
|
||||
browser.get('build/docs/index.html#!/api/ng/function/angular.noop/');
|
||||
browser.get('build/docs/index-production.html#!/api/ng/function/angular.noop/');
|
||||
var pageBody = element(by.css('h1'));
|
||||
expect(pageBody.getText()).toEqual('angular.noop');
|
||||
});
|
||||
|
||||
|
||||
it('should be resilient to trailing "index"', function() {
|
||||
browser.get('build/docs/index.html#!/api/ng/function/angular.noop/index');
|
||||
browser.get('build/docs/index-production.html#!/api/ng/function/angular.noop/index');
|
||||
var pageBody = element(by.css('h1'));
|
||||
expect(pageBody.getText()).toEqual('angular.noop');
|
||||
});
|
||||
|
||||
|
||||
it('should be resilient to trailing "index/"', function() {
|
||||
browser.get('build/docs/index.html#!/api/ng/function/angular.noop/index/');
|
||||
browser.get('build/docs/index-production.html#!/api/ng/function/angular.noop/index/');
|
||||
var pageBody = element(by.css('h1'));
|
||||
expect(pageBody.getText()).toEqual('angular.noop');
|
||||
});
|
||||
|
||||
|
||||
it('should display formatted error messages on error doc pages', function() {
|
||||
browser.get('build/docs/index.html#!error/ng/areq?p0=Missing&p1=not%20a%20function,%20got%20undefined');
|
||||
expect(element(by.css('.minerr-errmsg')).getText()).toEqual("Argument 'Missing' is not a function, got undefined");
|
||||
browser.get('build/docs/index-production.html#!error/ng/areq?p0=Missing&p1=not%20a%20function,%20got%20undefined');
|
||||
expect(element(by.css('.minerr-errmsg')).getText()).toEqual('Argument \'Missing\' is not a function, got undefined');
|
||||
});
|
||||
|
||||
it("should display an error if the page does not exist", function() {
|
||||
browser.get('build/docs/index.html#!/api/does/not/exist');
|
||||
it('should display an error if the page does not exist', function() {
|
||||
browser.get('build/docs/index-production.html#!/api/does/not/exist');
|
||||
expect(element(by.css('h1')).getText()).toBe('Oops!');
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"root": true,
|
||||
"extends": "../../../.eslintrc-browser.json",
|
||||
|
||||
"globals": {
|
||||
"lunr": false
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
angular.module('docsApp', [
|
||||
'ngRoute',
|
||||
'ngCookies',
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
angular.module('directives', [])
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
angular.module('DocsController', [])
|
||||
|
||||
.controller('DocsController', [
|
||||
@@ -27,9 +29,9 @@ angular.module('DocsController', [])
|
||||
|
||||
path = path.replace(/^\/?(.+?)(\/index)?\/?$/, '$1');
|
||||
|
||||
currentPage = $scope.currentPage = NG_PAGES[path];
|
||||
var currentPage = $scope.currentPage = NG_PAGES[path];
|
||||
|
||||
if ( currentPage ) {
|
||||
if (currentPage) {
|
||||
$scope.partialPath = 'partials/' + path + '.html';
|
||||
$scope.currentArea = NG_NAVIGATION[currentPage.area];
|
||||
var pathParts = currentPage.path.split('/');
|
||||
@@ -37,7 +39,7 @@ angular.module('DocsController', [])
|
||||
var breadcrumbPath = '';
|
||||
angular.forEach(pathParts, function(part) {
|
||||
breadcrumbPath += part;
|
||||
breadcrumb.push({ name: (NG_PAGES[breadcrumbPath]&&NG_PAGES[breadcrumbPath].name) || part, url: breadcrumbPath });
|
||||
breadcrumb.push({ name: (NG_PAGES[breadcrumbPath] && NG_PAGES[breadcrumbPath].name) || part, url: breadcrumbPath });
|
||||
breadcrumbPath += '/';
|
||||
});
|
||||
} else {
|
||||
@@ -52,7 +54,7 @@ angular.module('DocsController', [])
|
||||
***********************************/
|
||||
|
||||
$scope.versionNumber = angular.version.full;
|
||||
$scope.version = angular.version.full + " " + angular.version.codeName;
|
||||
$scope.version = angular.version.full + ' ' + angular.version.codeName;
|
||||
$scope.loading = 0;
|
||||
|
||||
|
||||
|
||||
+16
-14
@@ -1,23 +1,25 @@
|
||||
'use strict';
|
||||
|
||||
angular.module('errors', ['ngSanitize'])
|
||||
|
||||
.filter('errorLink', ['$sanitize', function ($sanitize) {
|
||||
var LINKY_URL_REGEXP = /((ftp|https?):\/\/|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s\.\;\,\(\)\{\}<>]/g,
|
||||
.filter('errorLink', ['$sanitize', function($sanitize) {
|
||||
var LINKY_URL_REGEXP = /((ftp|https?):\/\/|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s\.;,\(\)\{\}<>]/g,
|
||||
MAILTO_REGEXP = /^mailto:/,
|
||||
STACK_TRACE_REGEXP = /:\d+:\d+$/;
|
||||
|
||||
var truncate = function (text, nchars) {
|
||||
var truncate = function(text, nchars) {
|
||||
if (text.length > nchars) {
|
||||
return text.substr(0, nchars - 3) + '...';
|
||||
}
|
||||
return text;
|
||||
};
|
||||
|
||||
return function (text, target) {
|
||||
return function(text, target) {
|
||||
if (!text) return text;
|
||||
|
||||
var targetHtml = target ? ' target="' + target + '"' : '';
|
||||
|
||||
return $sanitize(text.replace(LINKY_URL_REGEXP, function (url) {
|
||||
return $sanitize(text.replace(LINKY_URL_REGEXP, function(url) {
|
||||
if (STACK_TRACE_REGEXP.test(url)) {
|
||||
return url;
|
||||
}
|
||||
@@ -25,7 +27,7 @@ angular.module('errors', ['ngSanitize'])
|
||||
// if we did not match ftp/http/mailto then assume mailto
|
||||
if (!/^((ftp|https?):\/\/|mailto:)/.test(url)) url = 'mailto:' + url;
|
||||
|
||||
return '<a' + targetHtml + ' href="' + url +'">' +
|
||||
return '<a' + targetHtml + ' href="' + url + '">' +
|
||||
truncate(url.replace(MAILTO_REGEXP, ''), 60) +
|
||||
'</a>';
|
||||
}));
|
||||
@@ -33,33 +35,33 @@ angular.module('errors', ['ngSanitize'])
|
||||
}])
|
||||
|
||||
|
||||
.directive('errorDisplay', ['$location', 'errorLinkFilter', function ($location, errorLinkFilter) {
|
||||
var encodeAngleBrackets = function (text) {
|
||||
.directive('errorDisplay', ['$location', 'errorLinkFilter', function($location, errorLinkFilter) {
|
||||
var encodeAngleBrackets = function(text) {
|
||||
return text.replace(/</g, '<').replace(/>/g, '>');
|
||||
};
|
||||
|
||||
var interpolate = function (formatString) {
|
||||
var interpolate = function(formatString) {
|
||||
var formatArgs = arguments;
|
||||
return formatString.replace(/\{\d+\}/g, function (match) {
|
||||
return formatString.replace(/\{\d+\}/g, function(match) {
|
||||
// Drop the braces and use the unary plus to convert to an integer.
|
||||
// The index will be off by one because of the formatString.
|
||||
var index = +match.slice(1, -1);
|
||||
if (index + 1 >= formatArgs.length) {
|
||||
return match;
|
||||
}
|
||||
return formatArgs[index+1];
|
||||
return formatArgs[index + 1];
|
||||
});
|
||||
};
|
||||
|
||||
return {
|
||||
link: function (scope, element, attrs) {
|
||||
link: function(scope, element, attrs) {
|
||||
var search = $location.search(),
|
||||
formatArgs = [attrs.errorDisplay],
|
||||
formattedText,
|
||||
i;
|
||||
|
||||
for (i = 0; angular.isDefined(search['p'+i]); i++) {
|
||||
formatArgs.push(search['p'+i]);
|
||||
for (i = 0; angular.isDefined(search['p' + i]); i++) {
|
||||
formatArgs.push(search['p' + i]);
|
||||
}
|
||||
|
||||
formattedText = encodeAngleBrackets(interpolate.apply(null, formatArgs));
|
||||
|
||||
+12
-11
@@ -1,8 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
angular.module('examples', [])
|
||||
|
||||
.directive('runnableExample', ['$templateCache', '$document', function($templateCache, $document) {
|
||||
.directive('runnableExample', [function() {
|
||||
var exampleClassNameSelector = '.runnable-example-file';
|
||||
var doc = $document[0];
|
||||
var tpl =
|
||||
'<nav class="runnable-example-tabs" ng-if="tabs">' +
|
||||
' <a ng-class="{active:$index==activeTabIndex}"' +
|
||||
@@ -29,12 +30,12 @@ angular.module('examples', [])
|
||||
return function(scope, element) {
|
||||
var node = element[0];
|
||||
var examples = node.querySelectorAll(exampleClassNameSelector);
|
||||
var tabs = [], now = Date.now();
|
||||
var tabs = [];
|
||||
angular.forEach(examples, function(child, index) {
|
||||
tabs.push(child.getAttribute('name'));
|
||||
});
|
||||
|
||||
if(tabs.length > 0) {
|
||||
if (tabs.length > 0) {
|
||||
scope.tabs = tabs;
|
||||
scope.$on('tabChange', function(e, index, title) {
|
||||
angular.forEach(examples, function(child) {
|
||||
@@ -101,7 +102,7 @@ angular.module('examples', [])
|
||||
},
|
||||
controllerAs: 'plnkr',
|
||||
template: '<button ng-click="plnkr.open($event)" class="btn pull-right"> <i class="glyphicon glyphicon-edit"> </i> Edit in Plunker</button> ',
|
||||
controller: [function() {
|
||||
controller: [function PlnkrOpenerCtrl() {
|
||||
var ctrl = this;
|
||||
|
||||
ctrl.example = {
|
||||
@@ -137,8 +138,8 @@ angular.module('examples', [])
|
||||
var newWindow = clickEvent.ctrlKey || clickEvent.metaKey;
|
||||
|
||||
var postData = {
|
||||
'tags[0]': "angularjs",
|
||||
'tags[1]': "example",
|
||||
'tags[0]': 'angularjs',
|
||||
'tags[1]': 'example',
|
||||
'private': true
|
||||
};
|
||||
|
||||
@@ -167,7 +168,7 @@ angular.module('examples', [])
|
||||
}])
|
||||
|
||||
.factory('getExampleData', ['$http', '$q', function($http, $q) {
|
||||
return function(exampleFolder){
|
||||
return function(exampleFolder) {
|
||||
// Load the manifest for the example
|
||||
return $http.get(exampleFolder + '/manifest.json')
|
||||
.then(function(response) {
|
||||
@@ -182,8 +183,8 @@ angular.module('examples', [])
|
||||
|
||||
// The manifests provide the production index file but Plunkr wants
|
||||
// a straight index.html
|
||||
if (filename === "index-production.html") {
|
||||
filename = "index.html";
|
||||
if (filename === 'index-production.html') {
|
||||
filename = 'index.html';
|
||||
}
|
||||
|
||||
return {
|
||||
@@ -199,4 +200,4 @@ angular.module('examples', [])
|
||||
});
|
||||
});
|
||||
};
|
||||
}]);
|
||||
}]);
|
||||
|
||||
+23
-21
@@ -1,3 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
angular.module('search', [])
|
||||
|
||||
.controller('DocsSearchCtrl', ['$scope', '$location', 'docsSearch', function($scope, $location, docsSearch) {
|
||||
@@ -9,7 +11,7 @@ angular.module('search', [])
|
||||
|
||||
$scope.search = function(q) {
|
||||
var MIN_SEARCH_LENGTH = 2;
|
||||
if(q.length >= MIN_SEARCH_LENGTH) {
|
||||
if (q.length >= MIN_SEARCH_LENGTH) {
|
||||
docsSearch(q).then(function(hits) {
|
||||
// Make sure the areas are always in the same order
|
||||
var results = {
|
||||
@@ -23,28 +25,24 @@ angular.module('search', [])
|
||||
angular.forEach(hits, function(hit) {
|
||||
var area = hit.area;
|
||||
|
||||
var limit = (area == 'api') ? 40 : 14;
|
||||
var limit = (area === 'api') ? 40 : 14;
|
||||
results[area] = results[area] || [];
|
||||
if(results[area].length < limit) {
|
||||
if (results[area].length < limit) {
|
||||
results[area].push(hit);
|
||||
}
|
||||
});
|
||||
|
||||
var totalAreas = 0;
|
||||
for(var i in results) {
|
||||
++totalAreas;
|
||||
}
|
||||
if(totalAreas > 0) {
|
||||
var totalAreas = Object.keys(results).length;
|
||||
if (totalAreas > 0) {
|
||||
$scope.colClassName = 'cols-' + totalAreas;
|
||||
}
|
||||
$scope.hasResults = totalAreas > 0;
|
||||
$scope.results = results;
|
||||
});
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
clearResults();
|
||||
}
|
||||
if(!$scope.$$phase) $scope.$apply();
|
||||
if (!$scope.$$phase) $scope.$apply();
|
||||
};
|
||||
|
||||
$scope.submit = function() {
|
||||
@@ -52,14 +50,14 @@ angular.module('search', [])
|
||||
if ($scope.results.api) {
|
||||
result = $scope.results.api[0];
|
||||
} else {
|
||||
for(var i in $scope.results) {
|
||||
for (var i in $scope.results) {
|
||||
result = $scope.results[i][0];
|
||||
if(result) {
|
||||
if (result) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if(result) {
|
||||
if (result) {
|
||||
$location.path(result.path);
|
||||
$scope.hideResults();
|
||||
}
|
||||
@@ -92,10 +90,12 @@ angular.module('search', [])
|
||||
// It should only be used where the browser does not support WebWorkers
|
||||
function localSearchFactory($http, $timeout, NG_PAGES) {
|
||||
|
||||
console.log('Using Local Search Index');
|
||||
if (window.console && window.console.log) {
|
||||
window.console.log('Using Local Search Index');
|
||||
}
|
||||
|
||||
// Create the lunr index
|
||||
var index = lunr(function() {
|
||||
var index = lunr(/** @this */ function() {
|
||||
this.ref('path');
|
||||
this.field('titleWords', {boost: 50});
|
||||
this.field('members', { boost: 40});
|
||||
@@ -136,12 +136,14 @@ angular.module('search', [])
|
||||
// It should only be used where the browser does support WebWorkers
|
||||
function webWorkerSearchFactory($q, $rootScope, NG_PAGES) {
|
||||
|
||||
console.log('Using WebWorker Search Index')
|
||||
if (window.console && window.console.log) {
|
||||
window.console.log('Using WebWorker Search Index');
|
||||
}
|
||||
|
||||
var searchIndex = $q.defer();
|
||||
var results;
|
||||
|
||||
var worker = new Worker('js/search-worker.js');
|
||||
var worker = new window.Worker('js/search-worker.js');
|
||||
|
||||
// The worker will send us a message in two situations:
|
||||
// - when the index has been built, ready to run a query
|
||||
@@ -149,7 +151,7 @@ angular.module('search', [])
|
||||
worker.onmessage = function(oEvent) {
|
||||
$rootScope.$apply(function() {
|
||||
|
||||
switch(oEvent.data.e) {
|
||||
switch (oEvent.data.e) {
|
||||
case 'index-ready':
|
||||
searchIndex.resolve();
|
||||
break;
|
||||
@@ -206,7 +208,7 @@ angular.module('search', [])
|
||||
FORWARD_SLASH_KEYCODE = 191;
|
||||
angular.element($document[0].body).on('keydown', function(event) {
|
||||
var input = element[0];
|
||||
if(event.keyCode == FORWARD_SLASH_KEYCODE && document.activeElement != input) {
|
||||
if (event.keyCode === FORWARD_SLASH_KEYCODE && window.document.activeElement !== input) {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
input.focus();
|
||||
@@ -214,7 +216,7 @@ angular.module('search', [])
|
||||
});
|
||||
|
||||
element.on('keydown', function(event) {
|
||||
if(event.keyCode == ESCAPE_KEY_KEYCODE) {
|
||||
if (event.keyCode === ESCAPE_KEY_KEYCODE) {
|
||||
event.stopPropagation();
|
||||
event.preventDefault();
|
||||
scope.$apply(function() {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
angular.module('tutorials', [])
|
||||
|
||||
.directive('docTutorialNav', function() {
|
||||
@@ -20,7 +22,7 @@ angular.module('tutorials', [])
|
||||
scope.seq = seq;
|
||||
scope.prev = pages[seq];
|
||||
scope.next = pages[2 + seq];
|
||||
scope.diffLo = seq ? (seq - 1): '0~1';
|
||||
scope.diffLo = seq ? (seq - 1) : '0~1';
|
||||
scope.diffHi = seq;
|
||||
|
||||
element.addClass('btn-group');
|
||||
@@ -40,7 +42,7 @@ angular.module('tutorials', [])
|
||||
'<div class="alert alert-info" ng-show="show">\n' +
|
||||
' <p>Reset the workspace to step {{step}}.</p>' +
|
||||
' <p><pre>git checkout -f step-{{step}}</pre></p>\n' +
|
||||
' <p>Refresh your browser or check out this step online: '+
|
||||
' <p>Refresh your browser or check out this step online: ' +
|
||||
'<a href="http://angular.github.io/angular-phonecat/step-{{step}}/app">Step {{step}} Live Demo</a>.</p>\n' +
|
||||
'</div>\n' +
|
||||
'<p>The most important changes are listed below. You can see the full diff on ' +
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
"use strict";
|
||||
'use strict';
|
||||
|
||||
angular.module('versions', [])
|
||||
|
||||
@@ -6,7 +6,7 @@ angular.module('versions', [])
|
||||
$scope.docs_version = NG_VERSIONS[0];
|
||||
$scope.docs_versions = NG_VERSIONS;
|
||||
|
||||
for(var i=0, minor = NaN; i < NG_VERSIONS.length; i++) {
|
||||
for (var i = 0, minor = NaN; i < NG_VERSIONS.length; i++) {
|
||||
var version = NG_VERSIONS[i];
|
||||
// NaN will give false here
|
||||
if (minor <= version.minor) {
|
||||
@@ -25,7 +25,7 @@ angular.module('versions', [])
|
||||
url = '';
|
||||
if (version.isOldDocsUrl) {
|
||||
url = version.docsUrl;
|
||||
}else{
|
||||
} else {
|
||||
url = version.docsUrl + currentPagePath;
|
||||
}
|
||||
$window.location = url;
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"root": true,
|
||||
"extends": "../../../.eslintrc-browser.json",
|
||||
|
||||
"env": {
|
||||
"jasmine": true
|
||||
},
|
||||
|
||||
"rules": {
|
||||
// Some rules are not that important in tests and conflict with
|
||||
// Jasmine or would make it easier to write some tests; we disable
|
||||
// those ones here.
|
||||
"no-invalid-this": "off",
|
||||
"no-throw-literal": "off",
|
||||
"no-unused-vars": "off"
|
||||
},
|
||||
|
||||
"globals": {
|
||||
// ngMocks
|
||||
"module": false,
|
||||
"inject": true
|
||||
}
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
{
|
||||
"extends": "../../../.jshintrc-base",
|
||||
"browser": true,
|
||||
"globals": {
|
||||
// AngularJS
|
||||
"angular": false,
|
||||
|
||||
// ngMocks
|
||||
"module": false,
|
||||
"inject": true,
|
||||
|
||||
// Jasmine
|
||||
"jasmine": false,
|
||||
"describe": false,
|
||||
"ddescribe": false,
|
||||
"xdescribe": false,
|
||||
"it": false,
|
||||
"iit": false,
|
||||
"xit": false,
|
||||
"beforeEach": false,
|
||||
"afterEach": false,
|
||||
"spyOn": false,
|
||||
"expect": false
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,6 @@
|
||||
describe("code", function() {
|
||||
'use strict';
|
||||
|
||||
describe('code', function() {
|
||||
var prettyPrintOne, oldPP;
|
||||
var compile, scope;
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
describe("DocsController", function() {
|
||||
'use strict';
|
||||
|
||||
describe('DocsController', function() {
|
||||
var $scope;
|
||||
|
||||
angular.module('fake', [])
|
||||
@@ -15,7 +17,7 @@ describe("DocsController", function() {
|
||||
|
||||
|
||||
describe('afterPartialLoaded', function() {
|
||||
it("should update the Google Analytics with currentPage path if currentPage exists", inject(function($window) {
|
||||
it('should update the Google Analytics with currentPage path if currentPage exists', inject(function($window) {
|
||||
$window._gaq = [];
|
||||
$scope.currentPage = { path: 'a/b/c' };
|
||||
$scope.$broadcast('$includeContentLoaded');
|
||||
@@ -23,7 +25,7 @@ describe("DocsController", function() {
|
||||
}));
|
||||
|
||||
|
||||
it("should update the Google Analytics with $location.path if currentPage is missing", inject(function($window, $location) {
|
||||
it('should update the Google Analytics with $location.path if currentPage is missing', inject(function($window, $location) {
|
||||
$window._gaq = [];
|
||||
spyOn($location, 'path').and.returnValue('x/y/z');
|
||||
$scope.$broadcast('$includeContentLoaded');
|
||||
|
||||
@@ -135,7 +135,7 @@ describe('errors', function() {
|
||||
}));
|
||||
|
||||
|
||||
it('should set the element\s HTML', function() {
|
||||
it('should set the element\'s HTML', function() {
|
||||
var elem = $compile('<span error-display="bar">foo</span>')($rootScope);
|
||||
expect(elem.html()).toBe('bar');
|
||||
});
|
||||
@@ -152,7 +152,7 @@ describe('errors', function() {
|
||||
it('should pass the interpolated text through `errorLinkFilter`', function() {
|
||||
$location.search = jasmine.createSpy('search').and.returnValue({p0: 'foo'});
|
||||
|
||||
var elem = $compile('<span error-display="foo = {0}"></span>')($rootScope);
|
||||
$compile('<span error-display="foo = {0}"></span>')($rootScope);
|
||||
expect(errorLinkFilter).toHaveBeenCalledTimes(1);
|
||||
expect(errorLinkFilter).toHaveBeenCalledWith('foo = foo', '_blank');
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
"use strict";
|
||||
'use strict';
|
||||
|
||||
var path = require('canonical-path');
|
||||
var packagePath = __dirname;
|
||||
@@ -55,6 +55,7 @@ module.exports = new Package('angularjs', [
|
||||
parseTagsProcessor.tagDefinitions.push(require('./tag-defs/tutorial-step'));
|
||||
parseTagsProcessor.tagDefinitions.push(require('./tag-defs/sortOrder'));
|
||||
parseTagsProcessor.tagDefinitions.push(require('./tag-defs/installation'));
|
||||
parseTagsProcessor.tagDefinitions.push(require('./tag-defs/this'));
|
||||
})
|
||||
|
||||
|
||||
@@ -87,7 +88,7 @@ module.exports = new Package('angularjs', [
|
||||
docTypes: ['overview', 'tutorial'],
|
||||
getPath: function(doc) {
|
||||
var docPath = path.dirname(doc.fileInfo.relativePath);
|
||||
if ( doc.fileInfo.baseName !== 'index' ) {
|
||||
if (doc.fileInfo.baseName !== 'index') {
|
||||
docPath = path.join(docPath, doc.fileInfo.baseName);
|
||||
}
|
||||
return docPath;
|
||||
@@ -108,12 +109,12 @@ module.exports = new Package('angularjs', [
|
||||
});
|
||||
|
||||
computePathsProcessor.pathTemplates.push({
|
||||
docTypes: ['module' ],
|
||||
docTypes: ['module'],
|
||||
pathTemplate: '${area}/${name}',
|
||||
outputPathTemplate: 'partials/${area}/${name}.html'
|
||||
});
|
||||
computePathsProcessor.pathTemplates.push({
|
||||
docTypes: ['componentGroup' ],
|
||||
docTypes: ['componentGroup'],
|
||||
pathTemplate: '${area}/${moduleName}/${groupType}',
|
||||
outputPathTemplate: 'partials/${area}/${moduleName}/${groupType}.html'
|
||||
});
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
"use strict";
|
||||
'use strict';
|
||||
|
||||
// eslint-disable-next-line new-cap
|
||||
var encoder = new require('node-html-encoder').Encoder();
|
||||
|
||||
/**
|
||||
@@ -11,7 +12,7 @@ module.exports = function typeInlineTagDef(getTypeClass) {
|
||||
return {
|
||||
name: 'type',
|
||||
handler: function(doc, tagName, tagDescription) {
|
||||
return '<a href="" class="' + getTypeClass(tagDescription) + '">'+encoder.htmlEncode(tagDescription) + '</a>';
|
||||
return '<a href="" class="' + getTypeClass(tagDescription) + '">' + encoder.htmlEncode(tagDescription) + '</a>';
|
||||
}
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
"use strict";
|
||||
|
||||
var _ = require('lodash');
|
||||
var path = require('canonical-path');
|
||||
'use strict';
|
||||
|
||||
/**
|
||||
* @dgProcessor errorDocsProcessor
|
||||
@@ -18,7 +15,7 @@ module.exports = function errorDocsProcessor(errorNamespaceMap, getMinerrInfo) {
|
||||
docs.forEach(function(doc) {
|
||||
var parts, namespaceDoc;
|
||||
|
||||
if ( doc.docType === 'error' ) {
|
||||
if (doc.docType === 'error') {
|
||||
|
||||
// Parse out the error info from the id
|
||||
parts = doc.name.split(':');
|
||||
@@ -27,7 +24,7 @@ module.exports = function errorDocsProcessor(errorNamespaceMap, getMinerrInfo) {
|
||||
|
||||
// Get or create the relevant errorNamespace doc
|
||||
namespaceDoc = errorNamespaceMap.get(doc.namespace);
|
||||
if ( !namespaceDoc ) {
|
||||
if (!namespaceDoc) {
|
||||
namespaceDoc = {
|
||||
area: 'error',
|
||||
name: doc.namespace,
|
||||
@@ -49,4 +46,4 @@ module.exports = function errorDocsProcessor(errorNamespaceMap, getMinerrInfo) {
|
||||
});
|
||||
}
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
"use strict";
|
||||
'use strict';
|
||||
|
||||
var _ = require('lodash');
|
||||
var path = require('canonical-path');
|
||||
|
||||
/**
|
||||
* @dgProcessor generateIndexPagesProcessor
|
||||
@@ -21,7 +20,7 @@ module.exports = function generateIndexPagesProcessor() {
|
||||
// Collect up all the areas in the docs
|
||||
var areas = {};
|
||||
docs.forEach(function(doc) {
|
||||
if ( doc.area ) {
|
||||
if (doc.area) {
|
||||
areas[doc.area] = doc.area;
|
||||
}
|
||||
});
|
||||
@@ -40,4 +39,4 @@ module.exports = function generateIndexPagesProcessor() {
|
||||
});
|
||||
}
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
"use strict";
|
||||
'use strict';
|
||||
|
||||
var _ = require('lodash');
|
||||
var fs = require('fs');
|
||||
@@ -37,7 +37,7 @@ module.exports = function generateKeywordsProcessor(log, readFilesProcessor) {
|
||||
var KEYWORD_REGEX = /^((ng:|[\$_a-z])[\w\-_]+)/;
|
||||
|
||||
// Load up the keywords to ignore, if specified in the config
|
||||
if ( this.ignoreWordsFile ) {
|
||||
if (this.ignoreWordsFile) {
|
||||
|
||||
var ignoreWordsPath = path.resolve(readFilesProcessor.basePath, this.ignoreWordsFile);
|
||||
wordsToIgnore = fs.readFileSync(ignoreWordsPath, 'utf8').toString().split(/[,\s\n\r]+/gm);
|
||||
@@ -59,7 +59,7 @@ module.exports = function generateKeywordsProcessor(log, readFilesProcessor) {
|
||||
// without the ng to the title text, e.g. "controller".
|
||||
function extractTitleWords(title) {
|
||||
var match = /ng([A-Z]\w*)/.exec(title);
|
||||
if ( match ) {
|
||||
if (match) {
|
||||
title = title + ' ' + match[1].toLowerCase();
|
||||
}
|
||||
return title;
|
||||
@@ -68,11 +68,11 @@ module.exports = function generateKeywordsProcessor(log, readFilesProcessor) {
|
||||
function extractWords(text, words, keywordMap) {
|
||||
|
||||
var tokens = text.toLowerCase().split(/[\.\s,`'"#]+/mg);
|
||||
_.forEach(tokens, function(token){
|
||||
_.forEach(tokens, function(token) {
|
||||
var match = token.match(KEYWORD_REGEX);
|
||||
if (match){
|
||||
if (match) {
|
||||
var key = match[1];
|
||||
if ( !keywordMap[key]) {
|
||||
if (!keywordMap[key]) {
|
||||
keywordMap[key] = true;
|
||||
words.push(key);
|
||||
}
|
||||
@@ -96,11 +96,11 @@ module.exports = function generateKeywordsProcessor(log, readFilesProcessor) {
|
||||
// Search each top level property of the document for search terms
|
||||
_.forEach(doc, function(value, key) {
|
||||
|
||||
if ( _.isString(value) && !propertiesToIgnore[key] ) {
|
||||
if (_.isString(value) && !propertiesToIgnore[key]) {
|
||||
extractWords(value, words, keywordMap);
|
||||
}
|
||||
|
||||
if ( key === 'methods' || key === 'properties' || key === 'events' ) {
|
||||
if (key === 'methods' || key === 'properties' || key === 'events') {
|
||||
_.forEach(value, function(member) {
|
||||
extractWords(member.name, members, membersMap);
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
"use strict";
|
||||
'use strict';
|
||||
|
||||
var _ = require('lodash');
|
||||
var path = require('canonical-path');
|
||||
@@ -67,7 +67,7 @@ module.exports = function generatePagesDataProcessor(log) {
|
||||
})
|
||||
|
||||
.tap(function(docTypes) {
|
||||
if ( docTypes.input ) {
|
||||
if (docTypes.input) {
|
||||
docTypes.directive = docTypes.directive || [];
|
||||
// Combine input docTypes into directive docTypes
|
||||
docTypes.directive = docTypes.directive.concat(docTypes.input);
|
||||
@@ -79,7 +79,7 @@ module.exports = function generatePagesDataProcessor(log) {
|
||||
|
||||
sectionPages = _.sortBy(sectionPages, 'name');
|
||||
|
||||
if ( sectionPages.length > 0 ) {
|
||||
if (sectionPages.length > 0) {
|
||||
// Push a navItem for this section
|
||||
navItems.push({
|
||||
name: sectionName,
|
||||
@@ -158,7 +158,7 @@ module.exports = function generatePagesDataProcessor(log) {
|
||||
|
||||
// We are only interested in pages that are not landing pages
|
||||
var navPages = _.filter(pages, function(page) {
|
||||
return page.docType != 'componentGroup';
|
||||
return page.docType !== 'componentGroup';
|
||||
});
|
||||
|
||||
// Generate an object collection of pages that is grouped by area e.g.
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
"use strict";
|
||||
'use strict';
|
||||
|
||||
var _ = require('lodash');
|
||||
|
||||
@@ -31,4 +31,4 @@ module.exports = function generateVersionDocProcessor(gitData) {
|
||||
docs.push(versionDoc);
|
||||
}
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
"use strict";
|
||||
'use strict';
|
||||
|
||||
module.exports = function debugDeployment(getVersion) {
|
||||
return {
|
||||
name: 'debug',
|
||||
examples: {
|
||||
commonFiles: {
|
||||
scripts: [ '../../../angular.js' ]
|
||||
scripts: ['../../../angular.js']
|
||||
},
|
||||
dependencyPath: '../../../'
|
||||
},
|
||||
@@ -35,4 +35,4 @@ module.exports = function debugDeployment(getVersion) {
|
||||
'css/animations.css'
|
||||
]
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
"use strict";
|
||||
'use strict';
|
||||
|
||||
module.exports = function defaultDeployment(getVersion) {
|
||||
return {
|
||||
name: 'default',
|
||||
examples: {
|
||||
commonFiles: {
|
||||
scripts: [ '../../../angular.min.js' ]
|
||||
scripts: ['../../../angular.min.js']
|
||||
},
|
||||
dependencyPath: '../../../'
|
||||
},
|
||||
@@ -35,4 +35,4 @@ module.exports = function defaultDeployment(getVersion) {
|
||||
'css/animations.css'
|
||||
]
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
"use strict";
|
||||
'use strict';
|
||||
|
||||
module.exports = function jqueryDeployment(getVersion) {
|
||||
return {
|
||||
@@ -39,4 +39,4 @@ module.exports = function jqueryDeployment(getVersion) {
|
||||
'css/animations.css'
|
||||
]
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
"use strict";
|
||||
'use strict';
|
||||
|
||||
var versionInfo = require('../../../../lib/versions/version-info');
|
||||
var cdnUrl = "//ajax.googleapis.com/ajax/libs/angularjs/" + versionInfo.cdnVersion;
|
||||
var cdnUrl = '//ajax.googleapis.com/ajax/libs/angularjs/' + versionInfo.cdnVersion;
|
||||
|
||||
module.exports = function productionDeployment(getVersion) {
|
||||
return {
|
||||
name: 'production',
|
||||
examples: {
|
||||
commonFiles: {
|
||||
scripts: [ cdnUrl + '/angular.min.js' ]
|
||||
scripts: [cdnUrl + '/angular.min.js']
|
||||
},
|
||||
dependencyPath: cdnUrl + '/'
|
||||
},
|
||||
@@ -38,4 +38,4 @@ module.exports = function productionDeployment(getVersion) {
|
||||
'css/animations.css'
|
||||
]
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
"use strict";
|
||||
'use strict';
|
||||
var StringMap = require('stringmap');
|
||||
|
||||
/**
|
||||
@@ -7,4 +7,4 @@ var StringMap = require('stringmap');
|
||||
*/
|
||||
module.exports = function errorNamespaceMap() {
|
||||
return new StringMap();
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
"use strict";
|
||||
'use strict';
|
||||
|
||||
var path = require('canonical-path');
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
"use strict";
|
||||
'use strict';
|
||||
var path = require('canonical-path');
|
||||
|
||||
/**
|
||||
@@ -14,4 +14,4 @@ module.exports = function getVersion(readFilesProcessor) {
|
||||
packageFile = packageFile || 'bower.json';
|
||||
return require(path.join(sourceFolder,component,packageFile)).version;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = {
|
||||
name: 'installation'
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = {
|
||||
name: 'sortOrder',
|
||||
transforms: function(doc, tag, value) {
|
||||
return parseInt(value, 10);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = {
|
||||
name: 'this'
|
||||
};
|
||||
@@ -1,7 +1,9 @@
|
||||
'use strict';
|
||||
|
||||
module.exports = {
|
||||
name: 'step',
|
||||
transforms: function(doc, tag, value) {
|
||||
if ( doc.docType !== 'tutorial' ) {
|
||||
if (doc.docType !== 'tutorial') {
|
||||
throw new Error('Invalid tag, step. You should only use this tag on tutorial docs');
|
||||
}
|
||||
return parseInt(value,10);
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
</li>
|
||||
<li>
|
||||
<a href="http://bower.io">Bower</a> e.g.
|
||||
{% code %}bower install {$ doc.packageName $}@X.Y.Z{% endcode %}
|
||||
{% code %}bower install {$ doc.packageName $}#X.Y.Z{% endcode %}
|
||||
</li>
|
||||
<li>
|
||||
<a href="https://code.angularjs.org/">code.angularjs.org</a>
|
||||
@@ -69,6 +69,7 @@
|
||||
{% endif %}
|
||||
|
||||
|
||||
{% if doc.componentGroups.length %}
|
||||
<div class="component-breakdown">
|
||||
<h2>Module Components</h2>
|
||||
{% for componentGroup in doc.componentGroups %}
|
||||
@@ -89,6 +90,7 @@
|
||||
</div>
|
||||
{% endfor %}
|
||||
</div>
|
||||
{% endif %}
|
||||
|
||||
{% if doc.usage %}
|
||||
<h2>Usage</h2>
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
// Meta data used by the AngularJS docs app
|
||||
angular.module('navData', [])
|
||||
.value('NG_NAVIGATION', {$ doc.areas | json $});
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
// Meta data used by the AngularJS docs app
|
||||
angular.module('pagesData', [])
|
||||
.value('NG_PAGES', {$ doc.pages | json $});
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
'use strict';
|
||||
|
||||
// Meta data used by the AngularJS docs app
|
||||
angular.module('versionsData', [])
|
||||
.value('NG_VERSION', {$ doc.currentVersion | json $})
|
||||
|
||||
@@ -8,6 +8,8 @@ Welcome to the AngularJS API docs page. These pages contain the AngularJS refere
|
||||
The documentation is organized into **{@link guide/module modules}** which contain various components of an AngularJS application.
|
||||
These components are {@link guide/directive directives}, {@link guide/services services}, {@link guide/filter filters}, {@link guide/providers providers}, {@link guide/templates templates}, global APIs, and testing mocks.
|
||||
|
||||
There is also a {@link guide/index guide} with articles on various topics, and a list of external resources.
|
||||
|
||||
<div class="alert alert-info">
|
||||
**Angular Prefixes `$` and `$$`**:
|
||||
|
||||
|
||||
@@ -14,7 +14,7 @@ Also you can make a transclusion slot optional with a `?` prefix.
|
||||
|
||||
var componentConfig = {
|
||||
template: 'path/to/template.html',
|
||||
tranclude: {
|
||||
transclude: {
|
||||
importantSlot: 'importantComponent', // mandatory transclusion
|
||||
optionalSlot: '?optionalComponent', // optional transclusion
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
@ngdoc error
|
||||
@name $location:badpath
|
||||
@fullName Invalid Path
|
||||
@description
|
||||
|
||||
This error occurs when the path of a location contains invalid characters.
|
||||
The most common fault is when the path starts with double slashes (`//`) or backslashes ('\\').
|
||||
For example if the base path of an application is `https://a.b.c/` then the following path is
|
||||
invalid `https://a.b.c///d/e/f`.
|
||||
@@ -0,0 +1,12 @@
|
||||
@ngdoc error
|
||||
@name $parse:isecaf
|
||||
@fullName Assigning to Fields of Disallowed Context
|
||||
@description
|
||||
|
||||
Occurs when an expression attempts to assign a value on a field of any of the `Boolean`, `Number`,
|
||||
`String`, `Array`, `Object`, or `Function` constructors or the corresponding prototypes.
|
||||
|
||||
Angular bans the modification of these constructors or their prototypes from within expressions,
|
||||
since it is a known way to modify the behaviour of existing functions/operations.
|
||||
|
||||
To resolve this error, avoid assigning to fields of constructors or their prototypes in expressions.
|
||||
@@ -222,7 +222,7 @@ value of its attribute becomes true.
|
||||
angular.module('app', []).directive('setFocusIf', function() {
|
||||
return function link($scope, $element, $attr) {
|
||||
$scope.$watch($attr.setFocusIf, function(value) {
|
||||
if ( value ) { $element[0].focus(); }
|
||||
if (value) { $element[0].focus(); }
|
||||
});
|
||||
};
|
||||
});
|
||||
|
||||
@@ -3,7 +3,8 @@
|
||||
@fullName Model is not of type `number`
|
||||
@description
|
||||
|
||||
The number input directive `<input type="number">` requires the model to be a `number`.
|
||||
The `input[type="number"]` and `input[type="range"][ng-input-range]` directives require the model to
|
||||
be a `number`.
|
||||
|
||||
If the model is something else, this error will be thrown.
|
||||
|
||||
@@ -17,10 +18,10 @@ pipeline.
|
||||
## Example
|
||||
|
||||
In this example, our model stores the number as a string, so we provide the `stringToNumber`
|
||||
directive to convert it into the format the `input[number]` directive expects.
|
||||
directive to convert it into the format the `input[type="number"]` directive expects.
|
||||
|
||||
|
||||
<example module="numfmt-error-module">
|
||||
<example module="numfmt-error-module" name="number-format-error">
|
||||
<file name="index.html">
|
||||
<table>
|
||||
<tr ng-repeat="x in ['0', '1']">
|
||||
@@ -47,10 +48,10 @@ directive to convert it into the format the `input[number]` directive expects.
|
||||
return '' + value;
|
||||
});
|
||||
ngModel.$formatters.push(function(value) {
|
||||
return parseFloat(value, 10);
|
||||
return parseFloat(value);
|
||||
});
|
||||
}
|
||||
};
|
||||
});
|
||||
</file>
|
||||
</example>
|
||||
</example>
|
||||
|
||||
@@ -227,18 +227,18 @@ it('should show example', inject(
|
||||
},
|
||||
function($location) {
|
||||
// open http://example.com/base/index.html#!/a
|
||||
$location.absUrl() == 'http://example.com/base/index.html#!/a'
|
||||
$location.path() == '/a'
|
||||
$location.absUrl() === 'http://example.com/base/index.html#!/a'
|
||||
$location.path() === '/a'
|
||||
|
||||
$location.path('/foo')
|
||||
$location.absUrl() == 'http://example.com/base/index.html#!/foo'
|
||||
$location.absUrl() === 'http://example.com/base/index.html#!/foo'
|
||||
|
||||
$location.search() == {}
|
||||
$location.search() === {}
|
||||
$location.search({a: 'b', c: true});
|
||||
$location.absUrl() == 'http://example.com/base/index.html#!/foo?a=b&c'
|
||||
$location.absUrl() === 'http://example.com/base/index.html#!/foo?a=b&c'
|
||||
|
||||
$location.path('/new').search('x=y');
|
||||
$location.absUrl() == 'http://example.com/base/index.html#!/new?x=y'
|
||||
$location.absUrl() === 'http://example.com/base/index.html#!/new?x=y'
|
||||
}
|
||||
));
|
||||
```
|
||||
@@ -271,29 +271,29 @@ it('should show example', inject(
|
||||
// in browser with HTML5 history support:
|
||||
// open http://example.com/#!/a -> rewrite to http://example.com/a
|
||||
// (replacing the http://example.com/#!/a history record)
|
||||
$location.path() == '/a'
|
||||
$location.path() === '/a'
|
||||
|
||||
$location.path('/foo');
|
||||
$location.absUrl() == 'http://example.com/foo'
|
||||
$location.absUrl() === 'http://example.com/foo'
|
||||
|
||||
$location.search() == {}
|
||||
$location.search() === {}
|
||||
$location.search({a: 'b', c: true});
|
||||
$location.absUrl() == 'http://example.com/foo?a=b&c'
|
||||
$location.absUrl() === 'http://example.com/foo?a=b&c'
|
||||
|
||||
$location.path('/new').search('x=y');
|
||||
$location.url() == 'new?x=y'
|
||||
$location.absUrl() == 'http://example.com/new?x=y'
|
||||
$location.url() === 'new?x=y'
|
||||
$location.absUrl() === 'http://example.com/new?x=y'
|
||||
|
||||
// in browser without html5 history support:
|
||||
// open http://example.com/new?x=y -> redirect to http://example.com/#!/new?x=y
|
||||
// (again replacing the http://example.com/new?x=y history item)
|
||||
$location.path() == '/new'
|
||||
$location.search() == {x: 'y'}
|
||||
$location.path() === '/new'
|
||||
$location.search() === {x: 'y'}
|
||||
|
||||
$location.path('/foo/bar');
|
||||
$location.path() == '/foo/bar'
|
||||
$location.url() == '/foo/bar?x=y'
|
||||
$location.absUrl() == 'http://example.com/#!/foo/bar?x=y'
|
||||
$location.path() === '/foo/bar'
|
||||
$location.url() === '/foo/bar?x=y'
|
||||
$location.absUrl() === 'http://example.com/#!/foo/bar?x=y'
|
||||
}
|
||||
));
|
||||
```
|
||||
@@ -409,11 +409,11 @@ In these examples we use `<base href="/base/index.html" />`. The inputs represen
|
||||
.constant('baseHref', '/base/index.html')
|
||||
.value('$sniffer', { history: true })
|
||||
|
||||
.controller("LocationController", function($scope, $location) {
|
||||
.controller('LocationController', function($scope, $location) {
|
||||
$scope.$location = {};
|
||||
angular.forEach("protocol host port path search hash".split(" "), function(method){
|
||||
$scope.$location[method] = function(){
|
||||
var result = $location[method].call($location);
|
||||
angular.forEach('protocol host port path search hash'.split(' '), function(method) {
|
||||
$scope.$location[method] = function() {
|
||||
var result = $location[method]();
|
||||
return angular.isObject(result) ? angular.toJson(result) : result;
|
||||
};
|
||||
});
|
||||
@@ -460,8 +460,8 @@ In these examples we use `<base href="/base/index.html" />`. The inputs represen
|
||||
.directive('ngAddressBar', function($browser, $timeout) {
|
||||
return {
|
||||
template: 'Address: <input id="addressBar" type="text" style="width: 400px" >',
|
||||
link: function(scope, element, attrs){
|
||||
var input = element.children("input"), delay;
|
||||
link: function(scope, element, attrs) {
|
||||
var input = element.children('input'), delay;
|
||||
|
||||
input.on('keypress keyup keydown', function(event) {
|
||||
delay = (!delay ? $timeout(fireUrlChange, 250) : null);
|
||||
@@ -488,7 +488,7 @@ In these examples we use `<base href="/base/index.html" />`. The inputs represen
|
||||
url = 'http://www.example.com/base/path?a=b#h';
|
||||
|
||||
|
||||
it("should show fake browser info on load", function(){
|
||||
it("should show fake browser info on load", function() {
|
||||
expect(addressBar.getAttribute('value')).toBe(url);
|
||||
|
||||
expect(element(by.binding('$location.protocol()')).getText()).toBe('http');
|
||||
@@ -500,7 +500,7 @@ In these examples we use `<base href="/base/index.html" />`. The inputs represen
|
||||
|
||||
});
|
||||
|
||||
it("should change $location accordingly", function(){
|
||||
it("should change $location accordingly", function() {
|
||||
var navigation = element.all(by.css("#navigation a"));
|
||||
|
||||
navigation.get(0).click();
|
||||
@@ -563,11 +563,11 @@ In these examples we use `<base href="/base/index.html" />`. The inputs represen
|
||||
$locationProvider.html5Mode(true).hashPrefix('!');
|
||||
})
|
||||
|
||||
.controller("LocationController", function($scope, $location) {
|
||||
.controller('LocationController', function($scope, $location) {
|
||||
$scope.$location = {};
|
||||
angular.forEach("protocol host port path search hash".split(" "), function(method){
|
||||
$scope.$location[method] = function(){
|
||||
var result = $location[method].call($location);
|
||||
angular.forEach('protocol host port path search hash'.split(' '), function(method) {
|
||||
$scope.$location[method] = function() {
|
||||
var result = $location[method]();
|
||||
return angular.isObject(result) ? angular.toJson(result) : result;
|
||||
};
|
||||
});
|
||||
@@ -614,8 +614,8 @@ In these examples we use `<base href="/base/index.html" />`. The inputs represen
|
||||
.directive('ngAddressBar', function($browser, $timeout) {
|
||||
return {
|
||||
template: 'Address: <input id="addressBar" type="text" style="width: 400px" >',
|
||||
link: function(scope, element, attrs){
|
||||
var input = element.children("input"), delay;
|
||||
link: function(scope, element, attrs) {
|
||||
var input = element.children('input'), delay;
|
||||
|
||||
input.on('keypress keyup keydown', function(event) {
|
||||
delay = (!delay ? $timeout(fireUrlChange, 250) : null);
|
||||
@@ -641,7 +641,7 @@ In these examples we use `<base href="/base/index.html" />`. The inputs represen
|
||||
var addressBar = element(by.css("#addressBar")),
|
||||
url = 'http://www.example.com/base/index.html#!/path?a=b#h';
|
||||
|
||||
it("should show fake browser info on load", function(){
|
||||
it("should show fake browser info on load", function() {
|
||||
expect(addressBar.getAttribute('value')).toBe(url);
|
||||
|
||||
expect(element(by.binding('$location.protocol()')).getText()).toBe('http');
|
||||
@@ -653,7 +653,7 @@ In these examples we use `<base href="/base/index.html" />`. The inputs represen
|
||||
|
||||
});
|
||||
|
||||
it("should change $location accordingly", function(){
|
||||
it("should change $location accordingly", function() {
|
||||
var navigation = element.all(by.css("#navigation a"));
|
||||
|
||||
navigation.get(0).click();
|
||||
@@ -735,7 +735,7 @@ ng.$rootScope.Scope scope} life-cycle. This means it's your responsibility to ca
|
||||
```js
|
||||
describe('serviceUnderTest', function() {
|
||||
beforeEach(module(function($provide) {
|
||||
$provide.factory('serviceUnderTest', function($location){
|
||||
$provide.factory('serviceUnderTest', function($location) {
|
||||
// whatever it does...
|
||||
});
|
||||
});
|
||||
@@ -834,7 +834,7 @@ then uses the information it obtains to compose hashbang URLs (such as
|
||||
Because `$location` uses getters/setters, you can use `ng-model-options="{ getterSetter: true }"`
|
||||
to bind it to `ngModel`:
|
||||
|
||||
<example module="locationExample">
|
||||
<example module="locationExample" name="location-two-way-binding">
|
||||
<file name="index.html">
|
||||
<div ng-controller="LocationController">
|
||||
<input type="text" ng-model="locationPath" ng-model-options="{ getterSetter: true }" />
|
||||
@@ -843,7 +843,7 @@ to bind it to `ngModel`:
|
||||
<file name="script.js">
|
||||
angular.module('locationExample', [])
|
||||
.controller('LocationController', ['$scope', '$location', function($scope, $location) {
|
||||
$scope.locationPath = function (newLocation) {
|
||||
$scope.locationPath = function(newLocation) {
|
||||
return $location.path(newLocation);
|
||||
};
|
||||
}]);
|
||||
|
||||
@@ -62,7 +62,7 @@ attributes (if they have not been explicitly specified by the developer):
|
||||
|
||||
### Example
|
||||
|
||||
<example module="ngAria_ngModelExample" deps="angular-aria.js">
|
||||
<example module="ngAria_ngModelExample" deps="angular-aria.js" name="accessibility-ng-model">
|
||||
<file name="index.html">
|
||||
<form ng-controller="formsController">
|
||||
<some-checkbox role="checkbox" ng-model="checked" ng-class="{active: checked}"
|
||||
@@ -74,20 +74,20 @@ attributes (if they have not been explicitly specified by the developer):
|
||||
</form>
|
||||
</file>
|
||||
<file name="script.js">
|
||||
var app = angular.module('ngAria_ngModelExample', ['ngAria'])
|
||||
.controller('formsController', function($scope){
|
||||
angular.module('ngAria_ngModelExample', ['ngAria'])
|
||||
.controller('formsController', function($scope) {
|
||||
$scope.checked = false;
|
||||
$scope.toggleCheckbox = function(){
|
||||
$scope.toggleCheckbox = function() {
|
||||
$scope.checked = !$scope.checked;
|
||||
};
|
||||
})
|
||||
.directive('someCheckbox', function(){
|
||||
.directive('someCheckbox', function() {
|
||||
return {
|
||||
restrict: 'E',
|
||||
link: function($scope, $el, $attrs) {
|
||||
$el.on('keypress', function(event){
|
||||
$el.on('keypress', function(event) {
|
||||
event.preventDefault();
|
||||
if(event.keyCode === 32 || event.keyCode === 13){
|
||||
if (event.keyCode === 32 || event.keyCode === 13) {
|
||||
$scope.toggleCheckbox();
|
||||
$scope.$apply();
|
||||
}
|
||||
@@ -331,7 +331,7 @@ The attribute magic of ngAria may not work for every scenario. To disable indivi
|
||||
you can use the {@link ngAria.$ariaProvider#config config} method. Just keep in mind this will
|
||||
tell ngAria to ignore the attribute globally.
|
||||
|
||||
<example module="ngAria_ngClickExample" deps="angular-aria.js">
|
||||
<example module="ngAria_ngClickExample" deps="angular-aria.js" name="accessibility-ng-click">
|
||||
<file name="index.html">
|
||||
<div ng-click="someFunction" show-attrs>
|
||||
<div> with ng-click and bindRoleForClick, tabindex set to false
|
||||
|
||||
@@ -23,28 +23,28 @@ Animations are not available unless you include the {@link ngAnimate `ngAnimate`
|
||||
|
||||
Below is a quick example of animations being enabled for `ngShow` and `ngHide`:
|
||||
|
||||
<example module="ngAnimate" deps="angular-animate.js" animations="true">
|
||||
<example module="ngAnimate" deps="angular-animate.js" animations="true" name="animate-ng-show">
|
||||
<file name="index.html">
|
||||
<div ng-init="checked=true">
|
||||
<div ng-init="checked = true">
|
||||
<label>
|
||||
<input type="checkbox" ng-model="checked" style="float:left; margin-right:10px;"> Is Visible...
|
||||
<input type="checkbox" ng-model="checked" />
|
||||
Is visible
|
||||
</label>
|
||||
<div class="check-element sample-show-hide" ng-show="checked" style="clear:both;">
|
||||
Visible...
|
||||
<div class="content-area sample-show-hide" ng-show="checked">
|
||||
Content...
|
||||
</div>
|
||||
</div>
|
||||
</file>
|
||||
<file name="animations.css">
|
||||
.sample-show-hide {
|
||||
padding: 10px;
|
||||
.content-area {
|
||||
border: 1px solid black;
|
||||
background: white;
|
||||
margin-top: 10px;
|
||||
padding: 10px;
|
||||
}
|
||||
|
||||
.sample-show-hide {
|
||||
transition: all linear 0.5s;
|
||||
}
|
||||
|
||||
.sample-show-hide.ng-hide {
|
||||
opacity: 0;
|
||||
}
|
||||
@@ -188,7 +188,7 @@ able to capture class changes if an **expression** or the **ng-class** directive
|
||||
|
||||
The example below shows how to perform animations during class changes:
|
||||
|
||||
<example module="ngAnimate" deps="angular-animate.js" animations="true">
|
||||
<example module="ngAnimate" deps="angular-animate.js" animations="true" name="animate-css-class">
|
||||
<file name="index.html">
|
||||
<p>
|
||||
<input type="button" value="set" ng-click="myCssVar='css-class'">
|
||||
@@ -313,8 +313,8 @@ This function can be used to enable / disable animations in two different ways:
|
||||
With a single `boolean` argument, it enables / disables animations globally: `$animate.enabled(false)`
|
||||
disables all animations in your app.
|
||||
|
||||
When the second argument is a native DOM or jQuery element, the function enables / disables
|
||||
animations on this element *and all its children*: `$animate.enabled(false, myElement)`. This is the
|
||||
When the first argument is a native DOM or jqLite/jQuery element, the function enables / disables
|
||||
animations on this element *and all its children*: `$animate.enabled(myElement, false)`. This is the
|
||||
most flexible way to change the animation state. For example, even if you have used it to disable
|
||||
animations on a parent element, you can still re-enable it for a child element. And compared to the
|
||||
`classNameFilter`, you can change the animation status at runtime instead of during the config phase.
|
||||
@@ -347,6 +347,7 @@ By setting `transition: 0s`, ngAnimate will ignore the existing transition style
|
||||
animations will still execute, though). This can be used to prevent {@link guide/animations#preventing-collisions-with-existing-animations-and-third-party-libraries
|
||||
issues with existing animations interfering with ngAnimate}.
|
||||
|
||||
|
||||
## Preventing flicker before an animation starts
|
||||
|
||||
When nesting elements with structural animations such as `ngIf` into elements that have class-based
|
||||
@@ -421,8 +422,25 @@ than any styles that are independent from ngAnimate.
|
||||
|
||||
You can also use one of the two other {@link guide/animations#how-to-selectively-enable-disable-and-skip-animations strategies to disable animations}.
|
||||
|
||||
|
||||
### Enable animations for elements outside of the Angular application DOM tree: {@link ng.$animate#pin $animate.pin()}
|
||||
|
||||
Before animating, `ngAnimate` checks to see if the element being animated is inside the application DOM tree,
|
||||
and if it is not, no animation is run. Usually, this is not a problem as most apps use the `ngApp`
|
||||
attribute / bootstrap the app on the `html` or `body` element.
|
||||
|
||||
Problems arise when the application is bootstrapped on a different element, and animations are
|
||||
attempted on elements that are outside the application tree, e.g. when libraries append popup and modal
|
||||
elements as the last child in the body tag.
|
||||
|
||||
You can use {@link ng.$animate#pin `$animate.pin(elementToAnimate, parentHost)`} to specify that an
|
||||
element belongs to your application. Simply call it before the element is added to the DOM / before
|
||||
the animation starts, with the element you want to animate, and the element which should be its
|
||||
assumed parent.
|
||||
|
||||
|
||||
## More about animations
|
||||
|
||||
For a full breakdown of each method available on `$animate`, see the {@link ng.$animate API documentation}.
|
||||
|
||||
To see a complete demo, see the {@link tutorial/step_12 animation step within the AngularJS phonecat tutorial}.
|
||||
To see a complete demo, see the {@link tutorial/step_14 animation step within the AngularJS phonecat tutorial}.
|
||||
|
||||
@@ -77,7 +77,7 @@ to write directives.
|
||||
Here is a directive which makes any element draggable. Notice the `draggable` attribute on the
|
||||
`<span>` element.
|
||||
|
||||
<example module="drag">
|
||||
<example module="drag" name="draggable">
|
||||
<file name="script.js">
|
||||
angular.module('drag', []).
|
||||
directive('draggable', function($document) {
|
||||
|
||||
@@ -230,8 +230,8 @@ You can see the complete application running below.
|
||||
|
||||
this.getHero = function(id) {
|
||||
return heroesPromise.then(function(heroes) {
|
||||
for(var i=0; i<heroes.length; i++) {
|
||||
if ( heroes[i].id == id) return heroes[i];
|
||||
for (var i = 0; i < heroes.length; i++) {
|
||||
if (heroes[i].id === id) return heroes[i];
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -250,7 +250,7 @@ You can see the complete application running below.
|
||||
};
|
||||
|
||||
this.isSelected = function(hero) {
|
||||
return (hero.id == selectedId);
|
||||
return (hero.id === selectedId);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -321,8 +321,8 @@ You can see the complete application running below.
|
||||
|
||||
this.getCrisis = function(id) {
|
||||
return crisesPromise.then(function(crises) {
|
||||
for(var i=0; i<crises.length; i++) {
|
||||
if ( crises[i].id == id) return crises[i];
|
||||
for (var i = 0; i < crises.length; i++) {
|
||||
if (crises[i].id === id) return crises[i];
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -342,7 +342,7 @@ You can see the complete application running below.
|
||||
};
|
||||
|
||||
this.isSelected = function(crisis) {
|
||||
return (crisis.id == selectedId);
|
||||
return (crisis.id === selectedId);
|
||||
};
|
||||
|
||||
this.onSelect = function(crisis) {
|
||||
@@ -725,8 +725,8 @@ function HeroService($q) {
|
||||
|
||||
this.getHero = function(id) {
|
||||
return heroesPromise.then(function(heroes) {
|
||||
for(var i=0; i<heroes.length; i++) {
|
||||
if ( heroes[i].id == id) return heroes[i];
|
||||
for (var i = 0; i < heroes.length; i++) {
|
||||
if (heroes[i].id === id) return heroes[i];
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -924,7 +924,7 @@ function HeroListComponent(heroService) {
|
||||
};
|
||||
|
||||
this.isSelected = function(hero) {
|
||||
return (hero.id == selectedId);
|
||||
return (hero.id === selectedId);
|
||||
};
|
||||
}
|
||||
```
|
||||
|
||||
@@ -33,7 +33,7 @@ Components can be registered using the `.component()` method of an Angular modul
|
||||
|
||||
<example name="heroComponentSimple" module="heroApp">
|
||||
<file name="index.js">
|
||||
angular.module('heroApp', []).controller('mainCtrl', function() {
|
||||
angular.module('heroApp', []).controller('MainCtrl', function MainCtrl() {
|
||||
this.hero = {
|
||||
name: 'Spawn'
|
||||
};
|
||||
@@ -55,7 +55,7 @@ Components can be registered using the `.component()` method of an Angular modul
|
||||
</file>
|
||||
<file name="index.html">
|
||||
<!-- components match only elements -->
|
||||
<div ng-controller="mainCtrl as ctrl">
|
||||
<div ng-controller="MainCtrl as ctrl">
|
||||
<b>Hero</b><br>
|
||||
<hero-detail hero="ctrl.hero"></hero-detail>
|
||||
</div>
|
||||
@@ -160,6 +160,12 @@ of the component. The following hook methods can be implemented:
|
||||
are the names of the bound properties that have changed, and the values are an object of the form
|
||||
`{ currentValue, previousValue, isFirstChange() }`. Use this hook to trigger updates within a component such as
|
||||
cloning the bound value to prevent accidental mutation of the outer value.
|
||||
* `$doCheck()` - Called on each turn of the digest cycle. Provides an opportunity to detect and act on
|
||||
changes. Any actions that you wish to take in response to the changes that you detect must be
|
||||
invoked from this hook; implementing this has no effect on when `$onChanges` is called. For example, this hook
|
||||
could be useful if you wish to perform a deep equality check, or to check a Date object, changes to which would not
|
||||
be detected by Angular's change detector and thus not trigger `$onChanges`. This hook is invoked with no arguments;
|
||||
if detecting changes, you must store the previous value(s) for comparison to the current values.
|
||||
* `$onDestroy()` - Called on a controller when its containing scope is destroyed. Use this hook for releasing
|
||||
external resources, watches and event handlers.
|
||||
* `$postLink()` - Called after this controller's element and its children have been linked. Similar to the post-link
|
||||
@@ -194,7 +200,7 @@ it upwards to the heroList component, which updates the original data.
|
||||
|
||||
<example name="heroComponentTree" module="heroApp">
|
||||
<file name="index.js">
|
||||
var mode = angular.module('heroApp', []);
|
||||
angular.module('heroApp', []);
|
||||
</file>
|
||||
|
||||
<file name="heroList.js">
|
||||
@@ -236,6 +242,10 @@ it upwards to the heroList component, which updates the original data.
|
||||
function HeroDetailController() {
|
||||
var ctrl = this;
|
||||
|
||||
ctrl.delete = function() {
|
||||
ctrl.onDelete({hero: ctrl.hero});
|
||||
};
|
||||
|
||||
ctrl.update = function(prop, value) {
|
||||
ctrl.onUpdate({hero: ctrl.hero, prop: prop, value: value});
|
||||
};
|
||||
@@ -303,7 +313,7 @@ it upwards to the heroList component, which updates the original data.
|
||||
<div>
|
||||
Name: {{$ctrl.hero.name}}<br>
|
||||
Location: <editable-field field-value="$ctrl.hero.location" field-type="text" on-update="$ctrl.update('location', value)"></editable-field><br>
|
||||
<button ng-click="$ctrl.onDelete({hero: $ctrl.hero})">Delete</button>
|
||||
<button ng-click="$ctrl.delete()">Delete</button>
|
||||
</div>
|
||||
</file>
|
||||
<file name="editableField.html">
|
||||
@@ -373,12 +383,12 @@ but they are guaranteed to be available just before the `$onInit` method is exec
|
||||
|
||||
Here is a tab pane example built from components:
|
||||
|
||||
<example module="docsTabsExample">
|
||||
<example module="docsTabsExample" name="component-tabs-pane">
|
||||
<file name="script.js">
|
||||
angular.module('docsTabsExample', [])
|
||||
.component('myTabs', {
|
||||
transclude: true,
|
||||
controller: function() {
|
||||
controller: function MyTabsController() {
|
||||
var panes = this.panes = [];
|
||||
this.select = function(pane) {
|
||||
angular.forEach(panes, function(pane) {
|
||||
@@ -443,44 +453,52 @@ angular.module('docsTabsExample', [])
|
||||
|
||||
# Unit-testing Component Controllers
|
||||
|
||||
The easiest way to unit-test a component controller is by using the {@link ngMock.$componentController $componentController}
|
||||
that is included in {@link ngMock}. The advantage of this method is that you do not have
|
||||
to create any DOM elements. The following example shows how to do this for the `heroDetail` component
|
||||
from above.
|
||||
The easiest way to unit-test a component controller is by using the
|
||||
{@link ngMock.$componentController $componentController} that is included in {@link ngMock}. The
|
||||
advantage of this method is that you do not have to create any DOM elements. The following example
|
||||
shows how to do this for the `heroDetail` component from above.
|
||||
|
||||
The examples use the [Jasmine](http://jasmine.github.io/) testing framework.
|
||||
|
||||
**Controller Test:**
|
||||
```js
|
||||
describe('component: heroDetail', function() {
|
||||
var component, scope, hero, $componentController;
|
||||
var $componentController;
|
||||
|
||||
beforeEach(module('heroApp'));
|
||||
|
||||
beforeEach(inject(function($rootScope, _$componentController_) {
|
||||
scope = $rootScope.$new();
|
||||
beforeEach(inject(function(_$componentController_) {
|
||||
$componentController = _$componentController_;
|
||||
hero = {name: 'Wolverine'};
|
||||
}));
|
||||
|
||||
it('should assign the name bindings to the hero object', function() {
|
||||
it('should expose a `hero` object', function() {
|
||||
// Here we are passing actual bindings to the component
|
||||
component = $componentController('heroDetail',
|
||||
null,
|
||||
{hero: hero}
|
||||
);
|
||||
expect(component.hero.name).toBe('Wolverine');
|
||||
var bindings = {hero: {name: 'Wolverine'}};
|
||||
var ctrl = $componentController('heroDetail', null, bindings);
|
||||
|
||||
expect(ctrl.hero).toBeDefined();
|
||||
expect(ctrl.hero.name).toBe('Wolverine');
|
||||
});
|
||||
|
||||
it('should call the onDelete binding when a hero is deleted', function() {
|
||||
var deleteSpy = jasmine.createSpy('deleteSpy');
|
||||
component = $componentController('heroDetail',
|
||||
null,
|
||||
{hero: hero, onDelete: deleteSpy}
|
||||
);
|
||||
it('should call the `onDelete` binding, when deleting the hero', function() {
|
||||
var onDeleteSpy = jasmine.createSpy('onDelete');
|
||||
var bindings = {hero: {}, onDelete: onDeleteSpy};
|
||||
var ctrl = $componentController('heroDetail', null, bindings);
|
||||
|
||||
component.onDelete({hero: component.hero});
|
||||
expect(deleteSpy).toHaveBeenCalledWith({hero: component.hero});
|
||||
ctrl.delete();
|
||||
expect(onDeleteSpy).toHaveBeenCalledWith({hero: ctrl.hero});
|
||||
});
|
||||
|
||||
it('should call the `onUpdate` binding, when updating a property', function() {
|
||||
var onUpdateSpy = jasmine.createSpy('onUpdate');
|
||||
var bindings = {hero: {}, onUpdate: onUpdateSpy};
|
||||
var ctrl = $componentController('heroDetail', null, bindings);
|
||||
|
||||
ctrl.update('foo', 'bar');
|
||||
expect(onUpdateSpy).toHaveBeenCalledWith({
|
||||
hero: ctrl.hero,
|
||||
prop: 'foo',
|
||||
value: 'bar'
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
@@ -103,7 +103,7 @@ different currencies and also pay the invoice.
|
||||
<example name="guide-concepts-2" ng-app-included="true" >
|
||||
<file name="invoice1.js">
|
||||
angular.module('invoice1', [])
|
||||
.controller('InvoiceController', function() {
|
||||
.controller('InvoiceController', function InvoiceController() {
|
||||
this.qty = 1;
|
||||
this.cost = 2;
|
||||
this.inCurr = 'EUR';
|
||||
@@ -121,7 +121,7 @@ different currencies and also pay the invoice.
|
||||
return amount * this.usdToForeignRates[outCurr] / this.usdToForeignRates[inCurr];
|
||||
};
|
||||
this.pay = function pay() {
|
||||
window.alert("Thanks!");
|
||||
window.alert('Thanks!');
|
||||
};
|
||||
});
|
||||
</file>
|
||||
@@ -151,8 +151,9 @@ different currencies and also pay the invoice.
|
||||
What changed?
|
||||
|
||||
First, there is a new JavaScript file that contains a <a name="controller">{@link controller controller}</a>.
|
||||
More exactly, the file contains a constructor function that creates the actual controller instance.
|
||||
The purpose of controllers is to expose variables and functionality to expressions and directives.
|
||||
More accurately, the file specifies a constructor function that will be used to create the actual
|
||||
controller instance. The purpose of controllers is to expose variables and functionality to
|
||||
expressions and directives.
|
||||
|
||||
Besides the new file that contains the controller code we also added an
|
||||
{@link ng.directive:ngController `ng-controller`} directive to the HTML.
|
||||
@@ -199,7 +200,7 @@ Let's refactor our example and move the currency conversion into a service in an
|
||||
EUR: 0.74,
|
||||
CNY: 6.09
|
||||
};
|
||||
var convert = function (amount, inCurr, outCurr) {
|
||||
var convert = function(amount, inCurr, outCurr) {
|
||||
return amount * usdToForeignRates[outCurr] / usdToForeignRates[inCurr];
|
||||
};
|
||||
|
||||
@@ -211,7 +212,7 @@ Let's refactor our example and move the currency conversion into a service in an
|
||||
</file>
|
||||
<file name="invoice2.js">
|
||||
angular.module('invoice2', ['finance2'])
|
||||
.controller('InvoiceController', ['currencyConverter', function(currencyConverter) {
|
||||
.controller('InvoiceController', ['currencyConverter', function InvoiceController(currencyConverter) {
|
||||
this.qty = 1;
|
||||
this.cost = 2;
|
||||
this.inCurr = 'EUR';
|
||||
@@ -221,7 +222,7 @@ Let's refactor our example and move the currency conversion into a service in an
|
||||
return currencyConverter.convert(this.qty * this.cost, this.inCurr, outCurr);
|
||||
};
|
||||
this.pay = function pay() {
|
||||
window.alert("Thanks!");
|
||||
window.alert('Thanks!');
|
||||
};
|
||||
}]);
|
||||
</file>
|
||||
@@ -251,6 +252,7 @@ Let's refactor our example and move the currency conversion into a service in an
|
||||
<img class="pull-right" style="padding-left: 3em; padding-bottom: 1em;" src="img/guide/concepts-module-service.png">
|
||||
|
||||
What changed?
|
||||
|
||||
We moved the `convertCurrency` function and the definition of the existing currencies
|
||||
into the new file `finance2.js`. But how does the controller
|
||||
get a hold of the now separated function?
|
||||
@@ -274,10 +276,11 @@ The code snippet `angular.module('invoice2', ['finance2'])` specifies that the
|
||||
`finance2` module. By this, Angular uses the `InvoiceController` as well as the `currencyConverter` service.
|
||||
|
||||
Now that Angular knows of all the parts of the application, it needs to create them.
|
||||
In the previous section we saw that controllers are created using a factory function.
|
||||
For services there are multiple ways to define their factory
|
||||
In the previous section we saw that controllers are created using a constructor function.
|
||||
For services, there are multiple ways to specify how they are created
|
||||
(see the {@link services service guide}).
|
||||
In the example above, we are using an anonymous function as the factory function for `currencyConverter` service.
|
||||
In the example above, we are using an anonymous function as the factory function for the
|
||||
`currencyConverter` service.
|
||||
This function should return the `currencyConverter` service instance.
|
||||
|
||||
Back to the initial question: How does the `InvoiceController` get a reference to the `currencyConverter` function?
|
||||
@@ -303,7 +306,7 @@ The following example shows how this is done with Angular:
|
||||
<example name="guide-concepts-3" ng-app-included="true">
|
||||
<file name="invoice3.js">
|
||||
angular.module('invoice3', ['finance3'])
|
||||
.controller('InvoiceController', ['currencyConverter', function(currencyConverter) {
|
||||
.controller('InvoiceController', ['currencyConverter', function InvoiceController(currencyConverter) {
|
||||
this.qty = 1;
|
||||
this.cost = 2;
|
||||
this.inCurr = 'EUR';
|
||||
@@ -313,7 +316,7 @@ The following example shows how this is done with Angular:
|
||||
return currencyConverter.convert(this.qty * this.cost, this.inCurr, outCurr);
|
||||
};
|
||||
this.pay = function pay() {
|
||||
window.alert("Thanks!");
|
||||
window.alert('Thanks!');
|
||||
};
|
||||
}]);
|
||||
</file>
|
||||
@@ -321,13 +324,13 @@ The following example shows how this is done with Angular:
|
||||
angular.module('finance3', [])
|
||||
.factory('currencyConverter', ['$http', function($http) {
|
||||
var YAHOO_FINANCE_URL_PATTERN =
|
||||
'//query.yahooapis.com/v1/public/yql?q=select * from '+
|
||||
'yahoo.finance.xchange where pair in ("PAIRS")&format=json&'+
|
||||
'//query.yahooapis.com/v1/public/yql?q=select * from ' +
|
||||
'yahoo.finance.xchange where pair in ("PAIRS")&format=json&' +
|
||||
'env=store://datatables.org/alltableswithkeys&callback=JSON_CALLBACK';
|
||||
var currencies = ['USD', 'EUR', 'CNY'];
|
||||
var usdToForeignRates = {};
|
||||
|
||||
var convert = function (amount, inCurr, outCurr) {
|
||||
var convert = function(amount, inCurr, outCurr) {
|
||||
return amount * usdToForeignRates[outCurr] / usdToForeignRates[inCurr];
|
||||
};
|
||||
|
||||
|
||||
@@ -132,7 +132,7 @@ The message in our template contains a binding to the `spice` model which, by de
|
||||
string "very". Depending on which button is clicked, the `spice` model is set to `chili` or
|
||||
`jalapeño`, and the message is automatically updated by data-binding.
|
||||
|
||||
<example module="spicyApp1">
|
||||
<example module="spicyApp1" name="controller-spicy-1">
|
||||
<file name="index.html">
|
||||
<div ng-controller="SpicyController">
|
||||
<button ng-click="chiliSpicy()">Chili</button>
|
||||
@@ -173,7 +173,7 @@ its children).
|
||||
Controller methods can also take arguments, as demonstrated in the following variation of the
|
||||
previous example.
|
||||
|
||||
<example module="spicyApp2">
|
||||
<example module="spicyApp2" name="controller-spicy-2">
|
||||
<file name="index.html">
|
||||
<div ng-controller="SpicyController">
|
||||
<input ng-model="customSpice">
|
||||
@@ -186,7 +186,7 @@ previous example.
|
||||
var myApp = angular.module('spicyApp2', []);
|
||||
|
||||
myApp.controller('SpicyController', ['$scope', function($scope) {
|
||||
$scope.customSpice = "wasabi";
|
||||
$scope.customSpice = 'wasabi';
|
||||
$scope.spice = 'very';
|
||||
|
||||
$scope.spicy = function(spice) {
|
||||
@@ -210,7 +210,7 @@ have access to properties and methods defined by Controllers higher up the hiera
|
||||
See [Understanding Scopes](https://github.com/angular/angular.js/wiki/Understanding-Scopes) for
|
||||
more information about scope inheritance.
|
||||
|
||||
<example module="scopeInheritance">
|
||||
<example module="scopeInheritance" name="controller-scope-inheritance">
|
||||
<file name="index.html">
|
||||
<div class="spicy">
|
||||
<div ng-controller="MainController">
|
||||
|
||||
@@ -293,7 +293,7 @@ those conditions.
|
||||
<file name="script.js">
|
||||
angular.module('urlDecorator', []).
|
||||
|
||||
controller('Ctrl', ['$scope', function ($scope) {
|
||||
controller('Ctrl', ['$scope', function($scope) {
|
||||
$scope.id = 3;
|
||||
$scope.warnCount = 0; // for testing
|
||||
}]).
|
||||
@@ -336,8 +336,8 @@ those conditions.
|
||||
var exps = matchExpressions(originalExp);
|
||||
|
||||
// create and store the getters using $parse
|
||||
var getters = exps.map(function(el) {
|
||||
if (el) return $parse(el);
|
||||
var getters = exps.map(function(exp) {
|
||||
return exp && $parse(exp);
|
||||
});
|
||||
|
||||
return function newLinkFn(scope, elem, attr) {
|
||||
@@ -388,13 +388,13 @@ those conditions.
|
||||
<file name="index.html">
|
||||
<div ng-controller="Ctrl">
|
||||
<a ng-href="/products/{{ id }}/view" id="id3">View Product {{ id }}</a>
|
||||
- <strong>id == 3</strong>, so no warning<br>
|
||||
- <strong>id === 3</strong>, so no warning<br>
|
||||
<a ng-href="/products/{{ id + 5 }}/view" id="id8">View Product {{ id + 5 }}</a>
|
||||
- <strong>id + 5 == 8</strong>, so no warning<br>
|
||||
- <strong>id + 5 === 8</strong>, so no warning<br>
|
||||
<a ng-href="/products/{{ someOtherId }}/view" id="someOtherId">View Product {{ someOtherId }}</a>
|
||||
- <strong style="background-color: #ffff00;">someOtherId == undefined</strong>, so warn<br>
|
||||
- <strong style="background-color: #ffff00;">someOtherId === undefined</strong>, so warn<br>
|
||||
<a ng-href="/products/{{ someOtherId + 5 }}/view" id="someOtherId5">View Product {{ someOtherId + 5 }}</a>
|
||||
- <strong>someOtherId + 5 == 5</strong>, so no warning<br>
|
||||
- <strong>someOtherId + 5 === 5</strong>, so no warning<br>
|
||||
<div>Warn Count: {{ warnCount }}</div>
|
||||
</div>
|
||||
</file>
|
||||
@@ -432,7 +432,7 @@ changed (that never happens) and we need all of our default dates to be `'shortD
|
||||
<file name="script.js">
|
||||
angular.module('filterDecorator', []).
|
||||
|
||||
controller('Ctrl', ['$scope', function ($scope) {
|
||||
controller('Ctrl', ['$scope', function($scope) {
|
||||
$scope.genesis = new Date(2010, 0, 5);
|
||||
$scope.ngConf = new Date(2016, 4, 4);
|
||||
}]).
|
||||
@@ -480,7 +480,7 @@ changed (that never happens) and we need all of our default dates to be `'shortD
|
||||
|
||||
it('should still allow dates to be formatted', function() {
|
||||
expect(element(by.id('ngConf')).getText())
|
||||
.toMatch(/ng-conf 2016 with full date format\: [A-Za-z]+, [A-Za-z]+ \d{1,2}, \d{4}/);
|
||||
.toMatch(/ng-conf 2016 with full date format: [A-Za-z]+, [A-Za-z]+ \d{1,2}, \d{4}/);
|
||||
});
|
||||
</file>
|
||||
</example>
|
||||
|
||||
@@ -80,7 +80,7 @@ The **normalization** process is as follows:
|
||||
|
||||
For example, the following forms are all equivalent and match the {@link ngBind} directive:
|
||||
|
||||
<example module="docsBindExample">
|
||||
<example module="docsBindExample" name="directive-bind">
|
||||
<file name="index.html">
|
||||
<div ng-controller="Controller">
|
||||
Hello <input ng-model='name'> <hr/>
|
||||
@@ -162,10 +162,6 @@ initialization work here. The function is invoked using
|
||||
{@link auto.$injector#invoke $injector.invoke} which makes it injectable just like a
|
||||
controller.
|
||||
|
||||
<div class="alert alert-success">
|
||||
**Best Practice:** Prefer using the definition object over returning a function.
|
||||
</div>
|
||||
|
||||
|
||||
We'll go over a few common examples of directives, then dive deep into the different options
|
||||
and compilation process.
|
||||
@@ -189,7 +185,7 @@ several others. This is a good opportunity to use a directive to simplify your t
|
||||
|
||||
Let's create a directive that simply replaces its contents with a static template:
|
||||
|
||||
<example module="docsSimpleDirective">
|
||||
<example module="docsSimpleDirective" name="directive-simple">
|
||||
<file name="script.js">
|
||||
angular.module('docsSimpleDirective', [])
|
||||
.controller('Controller', ['$scope', function($scope) {
|
||||
@@ -228,7 +224,7 @@ its own HTML file and load it with the `templateUrl` option.
|
||||
If you are familiar with `ngInclude`, `templateUrl` works just like it. Here's the same example
|
||||
using `templateUrl` instead:
|
||||
|
||||
<example module="docsTemplateUrlDirective">
|
||||
<example module="docsTemplateUrlDirective" name="directive-template-url">
|
||||
<file name="script.js">
|
||||
angular.module('docsTemplateUrlDirective', [])
|
||||
.controller('Controller', ['$scope', function($scope) {
|
||||
@@ -262,7 +258,7 @@ element that the directive was called on, and an `attr` object associated with t
|
||||
function, since the template is requested before the scope is initialized.
|
||||
</div>
|
||||
|
||||
<example module="docsTemplateUrlDirective">
|
||||
<example module="docsTemplateUrlDirective" name="directive-template-url-fn">
|
||||
<file name="script.js">
|
||||
angular.module('docsTemplateUrlDirective', [])
|
||||
.controller('Controller', ['$scope', function($scope) {
|
||||
@@ -273,8 +269,8 @@ function, since the template is requested before the scope is initialized.
|
||||
}])
|
||||
.directive('myCustomer', function() {
|
||||
return {
|
||||
templateUrl: function(elem, attr){
|
||||
return 'customer-'+attr.type+'.html';
|
||||
templateUrl: function(elem, attr) {
|
||||
return 'customer-' + attr.type + '.html';
|
||||
}
|
||||
};
|
||||
});
|
||||
@@ -311,7 +307,7 @@ These restrictions can all be combined as needed:
|
||||
|
||||
Let's change our directive to use `restrict: 'E'`:
|
||||
|
||||
<example module="docsRestrictDirective">
|
||||
<example module="docsRestrictDirective" name="directive-restrict">
|
||||
<file name="script.js">
|
||||
angular.module('docsRestrictDirective', [])
|
||||
.controller('Controller', ['$scope', function($scope) {
|
||||
@@ -367,7 +363,7 @@ given scope.
|
||||
In its current implementation, we'd need to create a different controller each time in order to
|
||||
re-use such a directive:
|
||||
|
||||
<example module="docsScopeProblemExample">
|
||||
<example module="docsScopeProblemExample" name="directive-scope-problem">
|
||||
<file name="script.js">
|
||||
angular.module('docsScopeProblemExample', [])
|
||||
.controller('NaomiController', ['$scope', function($scope) {
|
||||
@@ -409,7 +405,7 @@ What we want to be able to do is separate the scope inside a directive from the
|
||||
outside, and then map the outer scope to a directive's inner scope. We can do this by creating what
|
||||
we call an **isolate scope**. To do this, we can use a {@link $compile#-scope- directive's `scope`} option:
|
||||
|
||||
<example module="docsIsolateScopeDirective">
|
||||
<example module="docsIsolateScopeDirective" name="directive-isolate">
|
||||
<file name="script.js">
|
||||
angular.module('docsIsolateScopeDirective', [])
|
||||
.controller('Controller', ['$scope', function($scope) {
|
||||
@@ -482,7 +478,7 @@ scope has another effect.
|
||||
We can show this by adding another property, `vojta`, to our scope and trying to access it from
|
||||
within our directive's template:
|
||||
|
||||
<example module="docsIsolationExample">
|
||||
<example module="docsIsolationExample" name="directive-isolate-2">
|
||||
<file name="script.js">
|
||||
angular.module('docsIsolationExample', [])
|
||||
.controller('Controller', ['$scope', function($scope) {
|
||||
@@ -561,7 +557,7 @@ to call a handler on a regular basis. This is easier than using `$timeout` but a
|
||||
end-to-end testing, where we want to ensure that all `$timeout`s have completed before completing the test.
|
||||
We also want to remove the `$interval` if the directive is deleted so we don't introduce a memory leak.
|
||||
|
||||
<example module="docsTimeDirective">
|
||||
<example module="docsTimeDirective" name="directive-link">
|
||||
<file name="script.js">
|
||||
angular.module('docsTimeDirective', [])
|
||||
.controller('Controller', ['$scope', function($scope) {
|
||||
@@ -637,7 +633,7 @@ wrap any arbitrary content.
|
||||
|
||||
To do this, we need to use the `transclude` option.
|
||||
|
||||
<example module="docsTransclusionDirective">
|
||||
<example module="docsTransclusionDirective" name="directive-transclude">
|
||||
<file name="script.js">
|
||||
angular.module('docsTransclusionDirective', [])
|
||||
.controller('Controller', ['$scope', function($scope) {
|
||||
@@ -668,7 +664,7 @@ this option have access to the scope **outside** of the directive rather than in
|
||||
To illustrate this, see the example below. Notice that we've added a `link` function in `script.js`
|
||||
that redefines `name` as `Jeff`. What do you think the `{{name}}` binding will resolve to now?
|
||||
|
||||
<example module="docsTransclusionExample">
|
||||
<example module="docsTransclusionExample" name="directive-transclusion">
|
||||
<file name="script.js">
|
||||
angular.module('docsTransclusionExample', [])
|
||||
.controller('Controller', ['$scope', function($scope) {
|
||||
@@ -680,7 +676,7 @@ that redefines `name` as `Jeff`. What do you think the `{{name}}` binding will r
|
||||
transclude: true,
|
||||
scope: {},
|
||||
templateUrl: 'my-dialog.html',
|
||||
link: function (scope) {
|
||||
link: function(scope) {
|
||||
scope.name = 'Jeff';
|
||||
}
|
||||
};
|
||||
@@ -718,16 +714,16 @@ arbitrary content.
|
||||
Next, we want to add buttons to this dialog box, and allow someone using the directive to bind their
|
||||
own behavior to it.
|
||||
|
||||
<example module="docsIsoFnBindExample">
|
||||
<example module="docsIsoFnBindExample" name="directive-transclusion-scope">
|
||||
<file name="script.js">
|
||||
angular.module('docsIsoFnBindExample', [])
|
||||
.controller('Controller', ['$scope', '$timeout', function($scope, $timeout) {
|
||||
$scope.name = 'Tobias';
|
||||
$scope.message = '';
|
||||
$scope.hideDialog = function (message) {
|
||||
$scope.hideDialog = function(message) {
|
||||
$scope.message = message;
|
||||
$scope.dialogIsHidden = true;
|
||||
$timeout(function () {
|
||||
$timeout(function() {
|
||||
$scope.message = '';
|
||||
$scope.dialogIsHidden = false;
|
||||
}, 2000);
|
||||
@@ -795,7 +791,7 @@ its elements.
|
||||
For instance, what if we wanted to create a directive that lets a user drag an
|
||||
element?
|
||||
|
||||
<example module="dragModule">
|
||||
<example module="dragModule" name="directive-drag">
|
||||
<file name="script.js">
|
||||
angular.module('dragModule', [])
|
||||
.directive('myDraggable', ['$document', function($document) {
|
||||
@@ -852,7 +848,7 @@ Sometimes, you want a component that's built from a combination of directives.
|
||||
Imagine you want to have a container with tabs in which the contents of the container correspond
|
||||
to which tab is active.
|
||||
|
||||
<example module="docsTabsExample">
|
||||
<example module="docsTabsExample" name="directive-tabs">
|
||||
<file name="script.js">
|
||||
angular.module('docsTabsExample', [])
|
||||
.directive('myTabs', function() {
|
||||
@@ -860,7 +856,7 @@ to which tab is active.
|
||||
restrict: 'E',
|
||||
transclude: true,
|
||||
scope: {},
|
||||
controller: ['$scope', function($scope) {
|
||||
controller: ['$scope', function MyTabsController($scope) {
|
||||
var panes = $scope.panes = [];
|
||||
|
||||
$scope.select = function(pane) {
|
||||
|
||||
@@ -51,7 +51,7 @@ the method from your view. If you want to `eval()` an Angular expression yoursel
|
||||
{@link ng.$rootScope.Scope#$eval `$eval()`} method.
|
||||
|
||||
## Example
|
||||
<example>
|
||||
<example name="expression-simple">
|
||||
<file name="index.html">
|
||||
<span>
|
||||
1+2={{1+2}}
|
||||
@@ -67,7 +67,7 @@ the method from your view. If you want to `eval()` an Angular expression yoursel
|
||||
|
||||
You can try evaluating different expressions here:
|
||||
|
||||
<example module="expressionExample">
|
||||
<example module="expressionExample" name="expression-eval">
|
||||
<file name="index.html">
|
||||
<div ng-controller="ExampleController" class="expressions">
|
||||
Expression:
|
||||
@@ -122,7 +122,7 @@ provide mockable access to globals.
|
||||
It is possible to access the context object using the identifier `this` and the locals object using the
|
||||
identifier `$locals`.
|
||||
|
||||
<example module="expressionExample">
|
||||
<example module="expressionExample" name="expression-locals">
|
||||
<file name="index.html">
|
||||
<div class="example2" ng-controller="ExampleController">
|
||||
Name: <input ng-model="name" type="text"/>
|
||||
@@ -144,7 +144,7 @@ identifier `$locals`.
|
||||
|
||||
<file name="protractor.js" type="protractor">
|
||||
it('should calculate expression in binding', function() {
|
||||
if (browser.params.browser == 'safari') {
|
||||
if (browser.params.browser === 'safari') {
|
||||
// Safari can't handle dialogs.
|
||||
return;
|
||||
}
|
||||
@@ -197,7 +197,7 @@ expose a `$event` object within the scope of that expression. The object is an i
|
||||
Event Object](http://api.jquery.com/category/events/event-object/) when jQuery is present or a
|
||||
similar jqLite object.
|
||||
|
||||
<example module="eventExampleApp">
|
||||
<example module="eventExampleApp" name="expression-events">
|
||||
<file name="index.html">
|
||||
<div ng-controller="EventController">
|
||||
<button ng-click="clickMe($event)">Event</button>
|
||||
@@ -221,8 +221,8 @@ similar jqLite object.
|
||||
* return a copy of an object with only non-object keys
|
||||
* we need this to avoid circular references
|
||||
*/
|
||||
function simpleKeys (original) {
|
||||
return Object.keys(original).reduce(function (obj, key) {
|
||||
function simpleKeys(original) {
|
||||
return Object.keys(original).reduce(function(obj, key) {
|
||||
obj[key] = typeof original[key] === 'object' ? '{ ... }' : original[key];
|
||||
return obj;
|
||||
}, {});
|
||||
@@ -241,7 +241,7 @@ An expression that starts with `::` is considered a one-time expression. One-tim
|
||||
will stop recalculating once they are stable, which happens after the first digest if the expression
|
||||
result is a non-undefined value (see value stabilization algorithm below).
|
||||
|
||||
<example module="oneTimeBidingExampleApp">
|
||||
<example module="oneTimeBidingExampleApp" name="expression-one-time">
|
||||
<file name="index.html">
|
||||
<div ng-controller="EventController">
|
||||
<button ng-click="clickMe($event)">Click Me</button>
|
||||
|
||||
@@ -0,0 +1,147 @@
|
||||
@ngdoc overview
|
||||
@name External Resources
|
||||
@sortOrder 150
|
||||
@description
|
||||
|
||||
# External Angular 1 Resources
|
||||
|
||||
This is a collection of external, 3rd party resources for learning and developing Angular.
|
||||
|
||||
## Articles, Videos, and Projects
|
||||
|
||||
### Introductory Material
|
||||
|
||||
* [10 Reasons Why You Should Use AngularJS](http://www.sitepoint.com/10-reasons-use-angularjs/)
|
||||
* [10 Reasons Why Developers Should Learn AngularJS](http://wintellect.com/blogs/jlikness/10-reasons-web-developers-should-learn-angularjs)
|
||||
* [Design Principles of AngularJS (video)](https://www.youtube.com/watch?v=HCR7i5F5L8c)
|
||||
* [Fundamentals in 60 Minutes (video)](http://www.youtube.com/watch?v=i9MHigUZKEM)
|
||||
* [For folks with a jQuery background](http://stackoverflow.com/questions/14994391/how-do-i-think-in-angularjs-if-i-have-a-jquery-background)
|
||||
|
||||
### Specific Topics
|
||||
|
||||
#### Application Structure & Style Guides
|
||||
|
||||
* [Angular Styleguide](https://github.com/johnpapa/angular-styleguide/blob/master/a1/README.md)
|
||||
* [Architecture, file structure, components, one-way dataflow and best practices](https://github.com/toddmotto/angular-styleguide)
|
||||
* [When to use directives, controllers or services](http://kirkbushell.me/when-to-use-directives-controllers-or-services-in-angular/)
|
||||
* [Service vs Factory](http://blog.thoughtram.io/angular/2015/07/07/service-vs-factory-once-and-for-all.html)
|
||||
|
||||
#### Testing
|
||||
|
||||
* **Unit testing:** [Using Karma (video)](http://www.youtube.com/watch?v=YG5DEzaQBIc), [Karma in Webstorm](http://blog.jetbrains.com/webstorm/2013/10/running-javascript-tests-with-karma-in-webstorm-7/)
|
||||
|
||||
#### Mobile
|
||||
|
||||
* [Angular on Mobile Guide](http://www.ng-newsletter.com/posts/angular-on-mobile.html)
|
||||
* [Angular and Cordova](http://devgirl.org/2013/06/10/quick-start-guide-phonegap-and-angularjs/)
|
||||
* [Ionic Framework](http://ionicframework.com/)
|
||||
|
||||
#### Deployment
|
||||
|
||||
##### General
|
||||
|
||||
* **Javascript minification: **[Background](http://thegreenpizza.github.io/2013/05/25/building-minification-safe-angular.js-applications/), [ng-annotate automation tool](https://github.com/olov/ng-annotate)
|
||||
* **Analytics and Logging:** [Angularyitcs (Google Analytics)](http://ngmodules.org/modules/angularytics), [Angulartics (Analytics)](https://github.com/luisfarzati/angulartics), [Logging Client-Side Errors](http://www.bennadel.com/blog/2542-Logging-Client-Side-Errors-With-AngularJS-And-Stacktrace-js.htm)
|
||||
* **SEO:** [By hand](http://www.yearofmoo.com/2012/11/angularjs-and-seo.html), [prerender.io](http://prerender.io/), [Brombone](http://www.brombone.com/), [SEO.js](http://getseojs.com/), [SEO4Ajax](http://www.seo4ajax.com/)
|
||||
|
||||
##### Server-Specific
|
||||
|
||||
* **Django:** [Tutorial](http://blog.mourafiq.com/post/55034504632/end-to-end-web-app-with-django-rest-framework), [Integrating AngularJS with Django](http://django-angular.readthedocs.org/en/latest/integration.html), [Getting Started with Django Rest Framework and AngularJS](http://blog.kevinastone.com/getting-started-with-django-rest-framework-and-angularjs.html)
|
||||
* **FireBase:** [AngularFire](http://angularfire.com/), [Firebase Foundations for AngularJS](http://blog.watchandcode.com/firebase-foundations/), [Realtime Apps with AngularJS and FireBase (video)](http://www.youtube.com/watch?v=C7ZI7z7qnHU)
|
||||
* **Google Cloud Platform: **[with Cloud Endpoints](https://cloud.google.com/developers/articles/angularjs-cloud-endpoints-recipe-for-building-modern-web-applications/), [with Go](https://github.com/GoogleCloudPlatform/appengine-angular-gotodos)
|
||||
* **Hood.ie:** [60 Minutes to Awesome](http://www.roberthorvick.com/2013/06/30/todomvc-angularjs-hood-ie-60-minutes-to-awesome/)
|
||||
* **MEAN Stack: **[Blog post](http://blog.mongodb.org/post/49262866911/the-mean-stack-mongodb-expressjs-angularjs-and), [Setup](http://thecodebarbarian.wordpress.com/2013/07/22/introduction-to-the-mean-stack-part-one-setting-up-your-tools/), [GDL Video](https://developers.google.com/live/shows/913996610)
|
||||
* **Rails: **[Tutorial](http://coderberry.me/blog/2013/04/22/angularjs-on-rails-4-part-1/), [AngularJS with Rails4](https://shellycloud.com/blog/2013/10/how-to-integrate-angularjs-with-rails-4), [angularjs-rails](https://github.com/hiravgandhi/angularjs-rails)
|
||||
* **PHP: **[Building a RESTful web service](http://blog.brunoscopelliti.com/building-a-restful-web-service-with-angularjs-and-php-more-power-with-resource), [End to End with Laravel 4 (video)](http://www.youtube.com/watch?v=hqAyiqUs93c)
|
||||
* **Meteor: **[angular-meteor package](https://github.com/Urigo/angular-meteor)
|
||||
|
||||
### Other Languages
|
||||
* [ES6, Webpack, and JSPM Starter Project](https://github.com/AngularClass/NG6-starter)
|
||||
* [ES6/Typescript Best Practices](https://codepen.io/martinmcwhorter/post/angularjs-1-x-with-typescript-or-es6-best-practices)
|
||||
* [Dart](https://github.com/angular/angular.dart.tutorial/wiki)
|
||||
* [CoffeeScript Tutorial](http://www.coffeescriptlove.com/2013/08/angularjs-and-coffeescript-tutorials.html)
|
||||
|
||||
### More Topics
|
||||
|
||||
* **Security:** [video](https://www.youtube.com/watch?v=18ifoT-Id54)
|
||||
* **Internationalization and Localization:** [Creating multilingual support](http://www.novanet.no/blog/hallstein-brotan/dates/2013/10/creating-multilingual-support-using-angularjs/)
|
||||
* **Authentication/Login: **[Google example](https://developers.google.com/+/photohunt/python), [AngularJS Facebook library](https://github.com/pc035860/angular-easyfb), [Facebook example](http://blog.brunoscopelliti.com/facebook-authentication-in-your-angularjs-web-app), [authentication strategy](http://blog.brunoscopelliti.com/deal-with-users-authentication-in-an-angularjs-web-app), [unix-style authorization](http://frederiknakstad.com/authentication-in-single-page-applications-with-angular-js/)
|
||||
* **Visualization:** [SVG](http://gaslight.co/blog/angular-backed-svgs), [D3.js](http://www.ng-newsletter.com/posts/d3-on-angular.html)
|
||||
* **Realtime Communication: **[Socket.io](http://www.creativebloq.com/javascript/angularjs-collaboration-board-socketio-2132885), [OmniBinder](https://github.com/jeffbcross/omnibinder)
|
||||
|
||||
|
||||
## Tools
|
||||
|
||||
* **Getting Started:** [Comparison of the options for starting a new project](http://www.dancancro.com/comparison-of-angularjs-application-starters/)
|
||||
* **Debugging:** [Batarang](https://chrome.google.com/webstore/detail/angularjs-batarang/ighdmehidhipcmcojjgiloacoafjmpfk?hl=en)
|
||||
* **Editor support:** [Webstorm](http://plugins.jetbrains.com/plugin/6971) (and [video](http://www.youtube.com/watch?v=LJOyrSh1kDU)), [Sublime Text](https://github.com/angular-ui/AngularJS-sublime-package), [Visual Studio](http://madskristensen.net/post/angularjs-intellisense-in-visual-studio-2012), [Atom](https://github.com/angular-ui/AngularJS-Atom), [Vim](https://github.com/burnettk/vim-angular)
|
||||
* **Workflow:** [Yeoman.io](https://github.com/yeoman/generator-angular) and [Angular Yeoman Tutorial](http://www.sitepoint.com/kickstart-your-angularjs-development-with-yeoman-grunt-and-bower/)
|
||||
|
||||
## Complementary Libraries
|
||||
|
||||
This is a list of libraries that enhance Angular, add common UI components or integrate with other libraries.
|
||||
You can find a larger list of Angular external libraries at [ngmodules.org](http://ngmodules.org/).
|
||||
|
||||
* **Advanced Routing:** [UI-Router](https://github.com/angular-ui/ui-router)
|
||||
* **Authentication:** [Http Auth Interceptor](https://github.com/witoldsz/angular-http-auth)
|
||||
* **Internationalization:**
|
||||
- [angular-translate](http://angular-translate.github.io)
|
||||
- [angular-gettext](http://angular-gettext.rocketeer.be/)
|
||||
- [angular-localization](http://doshprompt.github.io/angular-localization/)
|
||||
* **RESTful services:** [Restangular](https://github.com/mgonto/restangular)
|
||||
* **SQL and NoSQL backends:**
|
||||
- [BreezeJS](http://www.breezejs.com/)
|
||||
- [AngularFire](http://angularfire.com/)
|
||||
* **Data Handling**
|
||||
- Local Storage and session: [ngStorage](https://github.com/gsklee/ngStorage)
|
||||
- [angular-cache](https://github.com/jmdobry/angular-cache)
|
||||
- Data Modeling [JS-Data-Angular](https://github.com/js-data/js-data-angular)
|
||||
* **Fileupload:**
|
||||
- [ng-file-upload](https://github.com/danialfarid/ng-file-upload)
|
||||
- [blueimp-fileupload for Angular](https://blueimp.github.io/jQuery-File-Upload/angularjs.html)
|
||||
* **General UI Libraries:**
|
||||
- [Angular Material](https://material.angularjs.org/latest/)
|
||||
- [Angular UI Bootstrap](http://angular-ui.github.io/)
|
||||
- [AngularStrap for Bootstrap 3](http://mgcrea.github.io/angular-strap/)
|
||||
- [KendoUI](http://kendo-labs.github.io/angular-kendo/#/)
|
||||
- [Wijmo](http://wijmo.com/tag/angularjs-2/)
|
||||
* **Specific UI Elements:**
|
||||
- [ngInfiniteScroll](https://sroze.github.io/ngInfiniteScroll/)
|
||||
- [ngTable](https://github.com/esvit/ng-table)
|
||||
- [Angular UI Grid](http://angular-ui.github.io/grid)
|
||||
- [Toaster Notifications](https://github.com/jirikavi/AngularJS-Toaster)
|
||||
- [textAngular Rich Text Editor / contenteditable](http://textangular.com/) (Rich Text Editor /
|
||||
binding to contenteditable)
|
||||
- [Angular UI Map (Google Maps)](https://github.com/angular-ui/ui-map)
|
||||
|
||||
## General Learning Resources
|
||||
|
||||
### Books
|
||||
* [AngularJS: Up and Running](http://www.amazon.com/AngularJS-Running-Enhanced-Productivity-Structured/dp/1491901942) by Brad Green and Shyam Seshadri
|
||||
* [Mastering Web App Development](http://www.amazon.com/Mastering-Web-Application-Development-AngularJS/dp/1782161821) by Pawel Kozlowski and Pete Bacon Darwin
|
||||
* [AngularJS Directives](http://www.amazon.com/AngularJS-Directives-Alex-Vanston/dp/1783280336) by Alex Vanston
|
||||
* [Recipes With AngularJS](http://www.amazon.co.uk/Recipes-Angular-js-Frederik-Dietz-ebook/dp/B00DK95V48) by Frederik Dietz
|
||||
* [Developing an AngularJS Edge](http://www.amazon.com/Developing-AngularJS-Edge-Christopher-Hiller-ebook/dp/B00CJLFF8K) by Christopher Hiller
|
||||
* [ng-book: The Complete Book on AngularJS](http://ng-book.com/) by Ari Lerner
|
||||
* [AngularJS : Novice to Ninja](http://www.amazon.in/AngularJS-Novice-Ninja-Sandeep-Panda/dp/0992279453) by Sandeep Panda
|
||||
* [AngularJS UI Development](http://www.amazon.com/AngularJS-UI-Development-Amit-Ghart-ebook/dp/B00OXVAK7A) by Amit Gharat and Matthias Nehlsen
|
||||
* [Responsive Web Design with AngularJS](http://www.amazon.com/Responsive-Design-AngularJS-Sandeep-Kumar/dp/178439842X) by Sandeep Kumar Patel
|
||||
* [Professional AngularJS](http://www.amazon.com/Professional-AngularJS-Valeri-Karpov/dp/1118832078/)
|
||||
|
||||
### Videos:
|
||||
* [egghead.io](http://egghead.io/)
|
||||
|
||||
### Courses
|
||||
* **Free online:**
|
||||
[thinkster.io](http://thinkster.io),
|
||||
[CodeAcademy](http://www.codecademy.com/courses/javascript-advanced-en-2hJ3J/0/1),
|
||||
[CodeSchool](https://www.codeschool.com/courses/shaping-up-with-angular-js)
|
||||
* **Paid online:**
|
||||
[The Angular Course (115 videos that show you how to build a full app)](http://watchandcode.com/courses/angular-course/),
|
||||
[Pluralsite (3 courses)](http://www.pluralsight.com/training/Courses/Find?highlight=true&searchTerm=angularjs),
|
||||
[Tuts+](https://tutsplus.com/course/easier-js-apps-with-angular/),
|
||||
[lynda.com](http://www.lynda.com/AngularJS-tutorials/Up-Running-AngularJS/133318-2.html),
|
||||
[WintellectNOW (4 lessons)](http://www.wintellectnow.com/Course/Detail/mastering-angularjs)
|
||||
* **Paid onsite:**
|
||||
[angularbootcamp.com](http://angularbootcamp.com/)
|
||||
|
||||
@@ -5,10 +5,11 @@
|
||||
|
||||
# Filters
|
||||
|
||||
A filter formats the value of an expression for display to the user. They can be used in view templates,
|
||||
controllers or services and it is easy to define your own filter.
|
||||
Filters format the value of an expression for display to the user. They can be used in view
|
||||
templates, controllers or services. Angular comes with a collection of
|
||||
[built-in filters](api/ng/filter), but it is easy to define your own as well.
|
||||
|
||||
The underlying API is the {@link ng.$filterProvider `filterProvider`}.
|
||||
The underlying API is the {@link ng.$filterProvider}.
|
||||
|
||||
## Using filters in view templates
|
||||
|
||||
@@ -31,6 +32,21 @@ Filters may have arguments. The syntax for this is
|
||||
E.g. the markup `{{ 1234 | number:2 }}` formats the number 1234 with 2 decimal points using the
|
||||
{@link ng.filter:number `number`} filter. The resulting value is `1,234.00`.
|
||||
|
||||
### When filters are executed
|
||||
|
||||
In templates, filters are only executed when their inputs have changed. This is more performant than executing
|
||||
a filter on each {@link ng.$rootScope.Scope#$digest `$digest`} as is the case with {@link guide/expression expressions}.
|
||||
|
||||
There are two exceptions to this rule:
|
||||
|
||||
1. In general, this applies only to filters that take [primitive values](https://developer.mozilla.org/docs/Glossary/Primitive)
|
||||
as inputs. Filters that receive [Objects](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Data_structures#Objects)
|
||||
as input are executed on each `$digest`, as it would be too costly to track if the inputs have changed.
|
||||
|
||||
2. Filters that are marked as `$stateful` are also executed on each $digest.
|
||||
See {@link guide/filter#stateful-filters Stateful filters} for more information. Note that no Angular
|
||||
core filters are $stateful.
|
||||
|
||||
|
||||
## Using filters in controllers, services, and directives
|
||||
|
||||
@@ -53,7 +69,7 @@ The example below therefore calls the filter directly in the controller.
|
||||
By this, the controller is able to call the filter only when needed (e.g. when the data is loaded from the backend
|
||||
or the filter expression is changed).
|
||||
|
||||
<example module="FilterInControllerModule">
|
||||
<example module="FilterInControllerModule" name="filter-in-controller">
|
||||
<file name="index.html">
|
||||
<div ng-controller="FilterController as ctrl">
|
||||
<div>
|
||||
@@ -69,7 +85,7 @@ or the filter expression is changed).
|
||||
|
||||
<file name="script.js">
|
||||
angular.module('FilterInControllerModule', []).
|
||||
controller('FilterController', ['filterFilter', function(filterFilter) {
|
||||
controller('FilterController', ['filterFilter', function FilterController(filterFilter) {
|
||||
this.array = [
|
||||
{name: 'Tobias'},
|
||||
{name: 'Jeff'},
|
||||
@@ -93,8 +109,9 @@ as the first argument. Any filter arguments are passed in as additional argument
|
||||
function.
|
||||
|
||||
The filter function should be a [pure function](http://en.wikipedia.org/wiki/Pure_function), which
|
||||
means that it should be stateless and idempotent. Angular relies on these properties and executes
|
||||
the filter only when the inputs to the function change.
|
||||
means that it should be stateless and idempotent, and not rely for example on other Angular services.
|
||||
Angular relies on this contract and will by default execute a filter only when the inputs to the function change.
|
||||
{@link guide/filter#stateful-filters Stateful filters} are possible, but less performant.
|
||||
|
||||
<div class="alert alert-warning">
|
||||
**Note:** Filter names must be valid angular {@link expression} identifiers, such as `uppercase` or `orderBy`.
|
||||
@@ -106,7 +123,7 @@ your filters, then you can use capitalization (`myappSubsectionFilterx`) or unde
|
||||
The following sample filter reverses a text string. In addition, it conditionally makes the
|
||||
text upper-case.
|
||||
|
||||
<example module="myReverseFilterApp">
|
||||
<example module="myReverseFilterApp" name="filter-reverse">
|
||||
<file name="index.html">
|
||||
<div ng-controller="MyController">
|
||||
<input ng-model="greeting" type="text"><br>
|
||||
@@ -122,7 +139,7 @@ text upper-case.
|
||||
.filter('reverse', function() {
|
||||
return function(input, uppercase) {
|
||||
input = input || '';
|
||||
var out = "";
|
||||
var out = '';
|
||||
for (var i = 0; i < input.length; i++) {
|
||||
out = input.charAt(i) + out;
|
||||
}
|
||||
@@ -141,7 +158,7 @@ text upper-case.
|
||||
</example>
|
||||
|
||||
|
||||
## Stateful filters
|
||||
### Stateful filters
|
||||
|
||||
It is strongly discouraged to write filters that are stateful, because the execution of those can't
|
||||
be optimized by Angular, which often leads to performance issues. Many stateful filters can be
|
||||
@@ -151,7 +168,7 @@ argument for the filter.
|
||||
If you however do need to write a stateful filter, you have to mark the filter as `$stateful`, which
|
||||
means that it will be executed one or more times during the each `$digest` cycle.
|
||||
|
||||
<example module="myStatefulFilterApp">
|
||||
<example module="myStatefulFilterApp" name="filter-stateful">
|
||||
<file name="index.html">
|
||||
<div ng-controller="MyController">
|
||||
Input: <input ng-model="greeting" type="text"><br>
|
||||
@@ -183,4 +200,4 @@ means that it will be executed one or more times during the each `$digest` cycle
|
||||
|
||||
## Testing custom filters
|
||||
|
||||
See the [phonecat tutorial](http://docs.angularjs.org/tutorial/step_09#test) for an example.
|
||||
See the [phonecat tutorial](http://docs.angularjs.org/tutorial/step_11#testing) for an example.
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user