Compare commits
71 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| da984ad187 | |||
| 4015357ce5 | |||
| dc3d11ad19 | |||
| 0e1545eb04 | |||
| ec7cabf5c9 | |||
| 3051beba2f | |||
| 92304323b1 | |||
| c28123a872 | |||
| d798423813 | |||
| 2583e77cc7 | |||
| f66836fee4 | |||
| 0ccc445d53 | |||
| b7d5fa1cbe | |||
| 8bb3942453 | |||
| 51a79cebcb | |||
| 36bcf64008 | |||
| 5c6630605b | |||
| 125827406c | |||
| 62c21422a6 | |||
| 98d489712e | |||
| 2cab2d8ef1 | |||
| 8fa2bb72bc | |||
| d151f94937 | |||
| 5b74b7185b | |||
| 4f0be2ae4e | |||
| bb9badeb2a | |||
| c287c8361d | |||
| ade7127c79 | |||
| d341483f1f | |||
| b36acbc857 | |||
| a4fea38b94 | |||
| 300c5c0c99 | |||
| 152537c4e9 | |||
| 8b46bf6bc9 | |||
| aef861eb41 | |||
| f61d36861d | |||
| 2af0348cea | |||
| 78c5743494 | |||
| 2cb9fbd043 | |||
| e9dad5dbf4 | |||
| 54895fc2a1 | |||
| 60a12b4161 | |||
| cd7e58ba41 | |||
| 9391475dc3 | |||
| 7840803add | |||
| 7d77de2834 | |||
| ab044cada6 | |||
| d010e0cc7d | |||
| 40f728b1aa | |||
| 23abb26405 | |||
| fd55bc8e1d | |||
| 541aaa4e08 | |||
| f22c422547 | |||
| 0e461f0c07 | |||
| 5074448443 | |||
| 8d66af11e6 | |||
| 169948bb47 | |||
| 58d9469574 | |||
| 8d858a2360 | |||
| 5540748890 | |||
| f8a52be817 | |||
| 3b5f1105f6 | |||
| 663ccc5449 | |||
| 263f47819f | |||
| 6b75475ce3 | |||
| 07c354a8c0 | |||
| 1391579599 | |||
| 5d2bd1d84c | |||
| bf77e212af | |||
| eef2f9c31e | |||
| 438627c2c3 |
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<launchConfiguration type="org.eclipse.ui.externaltools.ProgramBuilderLaunchConfigurationType">
|
||||
<booleanAttribute key="org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND" value="false"/>
|
||||
<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_BUILDER_ENABLED" value="true"/>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_BUILD_SCOPE" value="${working_set:<?xml version="1.0" encoding="UTF-8"?> <launchConfigurationWorkingSet editPageId="org.eclipse.ui.resourceWorkingSetPage" factoryID="org.eclipse.ui.internal.WorkingSetFactory" id="1262905463390_2" label="workingSet" name="workingSet"> <item factoryID="org.eclipse.ui.internal.model.ResourceFactory" path="/angular.js/test" type="2"/> <item factoryID="org.eclipse.ui.internal.model.ResourceFactory" path="/angular.js/src" type="2"/> </launchConfigurationWorkingSet>}"/>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:/angular.js}/test.sh"/>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_RUN_BUILD_KINDS" value="full,incremental,auto,"/>
|
||||
<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_TRIGGERS_CONFIGURED" value="true"/>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:/angular.js}"/>
|
||||
</launchConfiguration>
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<launchConfiguration type="org.eclipse.ui.externaltools.ProgramBuilderLaunchConfigurationType">
|
||||
<booleanAttribute key="org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND" value="false"/>
|
||||
<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_BUILDER_ENABLED" value="false"/>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_BUILD_SCOPE" value="${working_set:<?xml version="1.0" encoding="UTF-8"?> <resources> <item path="/angular.js/perf" type="2"/> <item path="/angular.js/src" type="2"/> </resources>}"/>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:/angular.js/perf.sh}"/>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_RUN_BUILD_KINDS" value="full,incremental,auto,"/>
|
||||
<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_TRIGGERS_CONFIGURED" value="true"/>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:/angular.js}"/>
|
||||
</launchConfiguration>
|
||||
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<launchConfiguration type="org.eclipse.ui.externaltools.ProgramBuilderLaunchConfigurationType">
|
||||
<stringAttribute key="org.eclipse.debug.core.ATTR_REFRESH_SCOPE" value="${working_set:<?xml version="1.0" encoding="UTF-8"?> <resources> <item path="/angular.js/build" type="2"/> </resources>}"/>
|
||||
<booleanAttribute key="org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND" value="false"/>
|
||||
<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_BUILDER_ENABLED" value="true"/>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_BUILD_SCOPE" value="${working_set:<?xml version="1.0" encoding="UTF-8"?> <resources> <item path="/angular.js/docs" type="2"/> <item path="/angular.js/src" type="2"/> </resources>}"/>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:/angular.js/gen_docs.sh}"/>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_RUN_BUILD_KINDS" value="full,incremental,auto,"/>
|
||||
<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_TRIGGERS_CONFIGURED" value="true"/>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:/angular.js}"/>
|
||||
</launchConfiguration>
|
||||
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<launchConfiguration type="org.eclipse.ui.externaltools.ProgramLaunchConfigurationType">
|
||||
<stringAttribute key="org.eclipse.debug.core.ATTR_REFRESH_SCOPE" value="${working_set:<?xml version="1.0" encoding="UTF-8"?> <resources> <item path="/angular.js/docs" type="2"/> </resources>}"/>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LAUNCH_CONFIGURATION_BUILD_SCOPE" value="${none}"/>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:/angular.js/gen_docs.sh}"/>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:/angular.js}"/>
|
||||
</launchConfiguration>
|
||||
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<launchConfiguration type="org.eclipse.ui.externaltools.ProgramLaunchConfigurationType">
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:/angular.js/lib/jsl/jsl}"/>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_TOOL_ARGUMENTS" value="-conf lib/jsl/jsl.default.conf"/>
|
||||
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:/angular.js}"/>
|
||||
</launchConfiguration>
|
||||
@@ -0,0 +1,14 @@
|
||||
# Auto detect text files and perform LF normalization
|
||||
* text=auto
|
||||
|
||||
# Standard to msysgit
|
||||
*.doc diff=astextplain
|
||||
*.DOC diff=astextplain
|
||||
*.docx diff=astextplain
|
||||
*.DOCX diff=astextplain
|
||||
*.dot diff=astextplain
|
||||
*.DOT diff=astextplain
|
||||
*.pdf diff=astextplain
|
||||
*.PDF diff=astextplain
|
||||
*.rtf diff=astextplain
|
||||
*.RTF diff=astextplain
|
||||
@@ -10,5 +10,6 @@ performance/temp*.html
|
||||
*~
|
||||
angular.js.tmproj
|
||||
node_modules
|
||||
jsTestDriver*.conf
|
||||
angular.xcodeproj
|
||||
.idea
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>angular.js</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.wst.jsdt.core.javascriptValidator</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.ui.externaltools.ExternalToolBuilder</name>
|
||||
<triggers>auto,full,incremental,</triggers>
|
||||
<arguments>
|
||||
<dictionary>
|
||||
<key>LaunchConfigHandle</key>
|
||||
<value><project>/.externalToolBuilders/docs.launch</value>
|
||||
</dictionary>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.ui.externaltools.ExternalToolBuilder</name>
|
||||
<triggers>auto,full,incremental,</triggers>
|
||||
<arguments>
|
||||
<dictionary>
|
||||
<key>LaunchConfigHandle</key>
|
||||
<value><project>/.externalToolBuilders/JSTD_Tests.launch</value>
|
||||
</dictionary>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.ui.externaltools.ExternalToolBuilder</name>
|
||||
<triggers>auto,full,incremental,</triggers>
|
||||
<arguments>
|
||||
<dictionary>
|
||||
<key>LaunchConfigHandle</key>
|
||||
<value><project>/.externalToolBuilders/JSTD_perf.launch</value>
|
||||
</dictionary>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.wst.jsdt.core.jsNature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry excluding="test/" kind="src" path="src"/>
|
||||
<classpathentry excluding="docs-data.js|docs-scenario.js" kind="src" path="docs"/>
|
||||
<classpathentry excluding="test/" kind="src" path="test"/>
|
||||
<classpathentry kind="src" path="test/test"/>
|
||||
<classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.JRE_CONTAINER"/>
|
||||
<classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.baseBrowserLibrary"/>
|
||||
<classpathentry kind="output" path=""/>
|
||||
</classpath>
|
||||
@@ -0,0 +1,16 @@
|
||||
#Mon Jan 24 10:31:47 PST 2011
|
||||
activeContentFilterList=*.makefile,makefile,*.Makefile,Makefile,Makefile.*,*.mk,MANIFEST.MF
|
||||
addNewLine=true
|
||||
convertActionOnSaave=AnyEdit.CnvrtTabToSpaces
|
||||
eclipse.preferences.version=1
|
||||
inActiveContentFilterList=
|
||||
javaTabWidthForJava=true
|
||||
org.eclipse.jdt.ui.editor.tab.width=2
|
||||
projectPropsEnabled=false
|
||||
removeTrailingSpaces=true
|
||||
replaceAllSpaces=false
|
||||
replaceAllTabs=false
|
||||
saveAndAddLine=true
|
||||
saveAndConvert=true
|
||||
saveAndTrim=true
|
||||
useModulo4Tabs=false
|
||||
@@ -0,0 +1 @@
|
||||
org.eclipse.wst.jsdt.launching.JRE_CONTAINER
|
||||
@@ -0,0 +1 @@
|
||||
Global
|
||||
-13
@@ -1,13 +0,0 @@
|
||||
language: node_js
|
||||
node_js:
|
||||
- 0.8
|
||||
|
||||
before_script:
|
||||
- export DISPLAY=:99.0
|
||||
- sh -e /etc/init.d/xvfb start
|
||||
- npm install -g testacular@canary
|
||||
- rake package
|
||||
- ./nodeserver.sh > /dev/null &
|
||||
|
||||
script:
|
||||
- rake test[Firefox,"--reporters=dots"]
|
||||
+2
-317
@@ -1,326 +1,9 @@
|
||||
<a name="1.1.2"></a>
|
||||
# 1.1.2 tofu-animation (2013-01-22)
|
||||
|
||||
_Note: 1.1.x releases are [considered unstable](http://blog.angularjs.org/2012/07/angularjs-10-12-roadmap.html).
|
||||
They pass all tests but we reserve the right to change new features/apis in between minor releases. Check them
|
||||
out and please give us feedback._
|
||||
|
||||
_Note: This release also contains all bug fixes available in [1.0.4](#1.0.4)._
|
||||
|
||||
## Features
|
||||
|
||||
- **$compile:** support modifying the DOM structure in postlink fn
|
||||
([cdf6fb19](https://github.com/angular/angular.js/commit/cdf6fb19c85560b30607e71dc2b19fde54760faa))
|
||||
- **$log:** add $log.debug()
|
||||
([9e991ddb](https://github.com/angular/angular.js/commit/9e991ddb1de13adf520eda459950be5b90b5b6d9),
|
||||
[#1592](https://github.com/angular/angular.js/issues/1592))
|
||||
- **$parse:** allow strict equality in angular expressions
|
||||
([a179a9a9](https://github.com/angular/angular.js/commit/a179a9a96eda5c566bda8a70ac8a75822c936a68),
|
||||
[#908](https://github.com/angular/angular.js/issues/908))
|
||||
- **$resource:**
|
||||
- allow dynamic default parameters
|
||||
([cc42c99b](https://github.com/angular/angular.js/commit/cc42c99bec6a03d6c41b8e1d29ba2b1f5c16b87d))
|
||||
- support all $http.config actions
|
||||
([af89daf4](https://github.com/angular/angular.js/commit/af89daf4641f57b92be6c1f3635f5a3237f20c71))
|
||||
- **$route:** allow using functions as template params in 'when'
|
||||
([faf02f0c](https://github.com/angular/angular.js/commit/faf02f0c4db7962f863b0da2a82c8cafab2c706f))
|
||||
- **$timeout-mock:** add verifyNoPendingTasks method
|
||||
([f0c6ebc0](https://github.com/angular/angular.js/commit/f0c6ebc07653f6267acec898ccef5677884e3081),
|
||||
[#1245](https://github.com/angular/angular.js/issues/1245))
|
||||
- **directive:**
|
||||
- added ngOpen boolean directive
|
||||
([b8bd4d54](https://github.com/angular/angular.js/commit/b8bd4d5460d9952e9a3bb14992636b17859bd457))
|
||||
- ngKeydown, ngKeyup
|
||||
([e03182f0](https://github.com/angular/angular.js/commit/e03182f018f5069acd5e883ce2e9349b83f2d03f),
|
||||
[#1035](https://github.com/angular/angular.js/issues/1035))
|
||||
- **limitTo filter:** limitTo filter accepts strings
|
||||
([9e96d983](https://github.com/angular/angular.js/commit/9e96d983451899ef0cef3e68395c8f6c1ef83bbe),
|
||||
[#653](https://github.com/angular/angular.js/issues/653))
|
||||
- **scenario:**
|
||||
- add mouseover method to the ngScenario dsl
|
||||
([2f437e89](https://github.com/angular/angular.js/commit/2f437e89781cb2b449abb685e36b26ca1cf0fff5))
|
||||
- fail when an option to select does not exist
|
||||
([15183f3e](https://github.com/angular/angular.js/commit/15183f3e1fbee031c9595206163962788f98b298))
|
||||
|
||||
|
||||
## Breaking Changes
|
||||
|
||||
- **date:** due to [cc821502](https://github.com/angular/angular.js/commit/cc821502bca64d15e1c576bf20a62b28b3d9a88a),
|
||||
string input without timezone info is now parsed as local time/date
|
||||
|
||||
|
||||
|
||||
<a name="1.0.4"></a>
|
||||
# 1.0.4 bewildering-hair (2013-01-22)
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- **$compile:**
|
||||
- do not wrap empty root text nodes in spans
|
||||
([49f9e4ce](https://github.com/angular/angular.js/commit/49f9e4cef13e68ff85b3c160cf8fac6e7cd042a3),
|
||||
[#1059](https://github.com/angular/angular.js/issues/1059))
|
||||
- safely create transclude comment nodes
|
||||
([74dd2f79](https://github.com/angular/angular.js/commit/74dd2f7980ea8ec434a6e0565d857c910653ed9b),
|
||||
[#1740](https://github.com/angular/angular.js/issues/1740))
|
||||
- **$injector:**
|
||||
- remove bogus fn arg
|
||||
([b6b7c5a1](https://github.com/angular/angular.js/commit/b6b7c5a1d66073937709158da8c2d688cb45c9f6),
|
||||
[#1711](https://github.com/angular/angular.js/issues/1711))
|
||||
- provider can now be defined in the array format
|
||||
([2c405f41](https://github.com/angular/angular.js/commit/2c405f417125c80c387a51baece8bf6e1e0c0a81),
|
||||
[#1452](https://github.com/angular/angular.js/issues/1452))
|
||||
- **$resource:**
|
||||
- HTTP method should be case-insensitive
|
||||
([8991680d](https://github.com/angular/angular.js/commit/8991680d8ab632dda60cd70c780868c803c74509),
|
||||
[#1403](https://github.com/angular/angular.js/issues/1403))
|
||||
- **$route:**
|
||||
- support route params not separated with slashes.
|
||||
([c6392616](https://github.com/angular/angular.js/commit/c6392616ea5245bd0d2f77dded0b948d9e2637c8))
|
||||
- correctly extract $routeParams from urls
|
||||
([30a9da5d](https://github.com/angular/angular.js/commit/30a9da5dc159dd1e19b677914356925c7ebdf632))
|
||||
- **Scope:** ensure that a scope is destroyed only once
|
||||
([d6da505f](https://github.com/angular/angular.js/commit/d6da505f4e044f8a487ac27a3ec707c11853ee0a),
|
||||
[#1627](https://github.com/angular/angular.js/issues/1627))
|
||||
- **angular.equals:**
|
||||
- consistently compare undefined object props
|
||||
([5ae63fd3](https://github.com/angular/angular.js/commit/5ae63fd385295d5a7bbdc79466f59727dcab1c85),
|
||||
[3c2e1c5e](https://github.com/angular/angular.js/commit/3c2e1c5e4d12529b1d69a6173c38097527dccc4f),
|
||||
[#1648](https://github.com/angular/angular.js/issues/1648))
|
||||
- **date filter:** parse string input as local time unless TZ is specified
|
||||
([cc821502](https://github.com/angular/angular.js/commit/cc821502bca64d15e1c576bf20a62b28b3d9a88a),
|
||||
[#847](https://github.com/angular/angular.js/issues/847))
|
||||
- **jqLite:**
|
||||
- children() should only return elements
|
||||
([febb4c1c](https://github.com/angular/angular.js/commit/febb4c1c35cf767ae31fc9fef1f4b4f026ac9de0))
|
||||
- make next() ignore non-element nodes
|
||||
([76a6047a](https://github.com/angular/angular.js/commit/76a6047af690781b8238ba7924279470ba76d081))
|
||||
- **scenario:** don't trigger input events on IE9
|
||||
([8b9e6c35](https://github.com/angular/angular.js/commit/8b9e6c3501746edb2c9e2d585e8e0eaeb8ba8327))
|
||||
- **Directives:**
|
||||
- **ngRepeat:** correctly apply $last if repeating over object
|
||||
([7e746015](https://github.com/angular/angular.js/commit/7e746015ea7dec3e9eb81bc4678fa9b6a83bc47c),
|
||||
[#1789](https://github.com/angular/angular.js/issues/1789))
|
||||
- **ngResource:** correct leading slash removal.
|
||||
([b2f46251](https://github.com/angular/angular.js/commit/b2f46251aca76c8568ee7d4bab54edbc9d7a186a))
|
||||
- **ngSwitch:** don't leak when destroyed while not attached
|
||||
([a26234f7](https://github.com/angular/angular.js/commit/a26234f7183013e2fcc9b35377e181ad96dc9917),
|
||||
[#1621](https://github.com/angular/angular.js/issues/1621))
|
||||
- **select:** support optgroup + select[multiple] combo
|
||||
([26adeb11](https://github.com/angular/angular.js/commit/26adeb119bc4fafa6286de484626b8de4170abc9),
|
||||
[#1553](https://github.com/angular/angular.js/issues/1553))
|
||||
|
||||
|
||||
## Features
|
||||
|
||||
- **$compile:** support modifying the DOM structure in postlink fn
|
||||
([cdf6fb19](https://github.com/angular/angular.js/commit/cdf6fb19c85560b30607e71dc2b19fde54760faa))
|
||||
|
||||
|
||||
|
||||
<a name="1.1.1"></a>
|
||||
# 1.1.1 pathological-kerning (2012-11-26)
|
||||
|
||||
_Note: 1.1.x releases are [considered unstable](http://blog.angularjs.org/2012/07/angularjs-10-12-roadmap.html).
|
||||
They pass all tests but we reserve the right to change new features/apis in between minor releases. Check them
|
||||
out and please give us feedback._
|
||||
|
||||
_Note: This release also contains all bug fixes available in [1.0.3](#1.0.3)._
|
||||
|
||||
|
||||
## Features
|
||||
|
||||
- **$cacheFactory:** cache.put now returns the added value
|
||||
([168db339](https://github.com/angular/angular.js/commit/168db33985aa025eb48bc21087717ab70da0bd72))
|
||||
- **$http:** Allow setting withCredentials on defaults
|
||||
([209b67df](https://github.com/angular/angular.js/commit/209b67df6a49fe1646ce63c5e7d11ed26e8abbc1),
|
||||
[#1095](https://github.com/angular/angular.js/issues/1095))
|
||||
- **$resource:** support custom headers per action
|
||||
([fbdab513](https://github.com/angular/angular.js/commit/fbdab513dd48f667ad857030cf4b3481ecdd9097),
|
||||
[#736](https://github.com/angular/angular.js/issues/736))
|
||||
- **$sanitize:** support telephone links
|
||||
([04450c48](https://github.com/angular/angular.js/commit/04450c48dfea065e1c9e4ab8adad94993ed1b037))
|
||||
- **FormController:** add ability to reset a form to pristine state
|
||||
([733a97ad](https://github.com/angular/angular.js/commit/733a97adf87bf8f7ec6be22b37c4676cf7b5fc2b),
|
||||
[#856](https://github.com/angular/angular.js/issues/856))
|
||||
- **jqLite:** add triggerHandler()
|
||||
([650fd933](https://github.com/angular/angular.js/commit/650fd933df614ac733cd43fe31d81d622a2ce2bc))
|
||||
- **linky filter:** allow optional 'target' argument
|
||||
([610927d7](https://github.com/angular/angular.js/commit/610927d77b77700c5c61accd503a2af0fa51cfe6),
|
||||
[#1443](https://github.com/angular/angular.js/issues/1443))
|
||||
- **angular-mocks:** support mocha in angular mocks
|
||||
([92558fe4](https://github.com/angular/angular.js/commit/92558fe4119fb1ee793d781de1888abef181c7f6))
|
||||
- **ngModel:** support ngTrim attribute on input
|
||||
([d519953a](https://github.com/angular/angular.js/commit/d519953a4b219035587e3fcb2e9cc52e02b408ca))
|
||||
- **scenario:** add dblclick method to the ngScenario dsl
|
||||
([8cb9c99e](https://github.com/angular/angular.js/commit/8cb9c99ec064fd95567118d29bfa4a19b8613ab3))
|
||||
- **CSP:** update to the latest CSP api
|
||||
([af7e0bd0](https://github.com/angular/angular.js/commit/af7e0bd0a7c286667c526cb7e0c733d3ee5f17fd),
|
||||
[#1577](https://github.com/angular/angular.js/issues/1577))
|
||||
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- **$http:**
|
||||
- config.param should expand array values properly (see breaking change notes below)
|
||||
([79af2bad](https://github.com/angular/angular.js/commit/79af2badcb087881e3fd600f6ae5bf3f86a2daf8),
|
||||
[#1363](https://github.com/angular/angular.js/issues/1363))
|
||||
- prevent CORS preflight checks by removing `X-Requested-With` from header defaults (see breaking
|
||||
change notes below)
|
||||
([3a75b112](https://github.com/angular/angular.js/commit/3a75b1124d062f64093a90b26630938558909e8d),
|
||||
[#1004](https://github.com/angular/angular.js/issues/1004))
|
||||
- prevent CORS preflight checks by not setting `X-XSFR-TOKEN` header for cross domain requests (see
|
||||
breaking change notes below)
|
||||
([fce100a4](https://github.com/angular/angular.js/commit/fce100a46c5681562253c3a856d67bbd35fbc2f2),
|
||||
[#1096](https://github.com/angular/angular.js/issues/1096))
|
||||
|
||||
|
||||
## Refactorings
|
||||
|
||||
- **$evalAsync:** have only one global async queue
|
||||
([331cd5a8](https://github.com/angular/angular.js/commit/331cd5a8cb5efdafe8ad7eb386aed4033cfc1bb3))
|
||||
|
||||
|
||||
## Breaking Changes
|
||||
|
||||
- Due to fix for [#1363](https://github.com/angular/angular.js/issues/1363) it's possible but unlikely
|
||||
that $http will start generating different URLs for requests. This affects only cases when a request
|
||||
is made with a parameter, value of which is an array. If the server relied on the buggy behavior then
|
||||
either the backend should be fixed or a simple serialization of the array should be done on the client
|
||||
before calling the $http service.
|
||||
|
||||
- Due to fix for [#1004](https://github.com/angular/angular.js/issues/1004) the `X-Requested-With` header
|
||||
is not set by $http service any more. If anyone actually uses this header it's quite easy to add
|
||||
it back via:
|
||||
|
||||
```
|
||||
myAppModule.config(['$httpProvider', function($httpProvider) {
|
||||
$httpProvider.defaults.headers.common["X-Requested-With"] = 'XMLHttpRequest';
|
||||
}]);
|
||||
```
|
||||
|
||||
- Due to fix for [#1096](https://github.com/angular/angular.js/issues/1096) `X-XSFR-TOKEN` header is
|
||||
no longer send for cross domain requests. This shouldn't affect any known production service. If we are
|
||||
wrong, please let us know ;-)
|
||||
|
||||
|
||||
|
||||
<a name="1.0.3"></a>
|
||||
# 1.0.3 bouncy-thunder (2012-11-26)
|
||||
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
- **$cacheFactory:** return undefined when removing non-existent entry
|
||||
([55d15806](https://github.com/angular/angular.js/commit/55d15806fb14b1d98b5ca2770bbbb59e11548c62),
|
||||
[#1497](https://github.com/angular/angular.js/issues/1497))
|
||||
- **$compile:**
|
||||
- prevent double attr interpolation w/ templateUrl
|
||||
([fc115bfd](https://github.com/angular/angular.js/commit/fc115bfd0d18017f4bcef1e39fb22d97a98f8ab1),
|
||||
[#1166](https://github.com/angular/angular.js/issues/1166))
|
||||
- reference local in isolate scope
|
||||
([8db47ca7](https://github.com/angular/angular.js/commit/8db47ca7d4303e3e45a838219a1f6e9be8770ed4),
|
||||
[#1272](https://github.com/angular/angular.js/issues/1272))
|
||||
- don't look for class directives in empty string
|
||||
([54b3875b](https://github.com/angular/angular.js/commit/54b3875ba5cb6ce8ddac61ace33c1b2f600875ff))
|
||||
- compilation should not recurse into empty nodes
|
||||
([008a782b](https://github.com/angular/angular.js/commit/008a782bc8ed8a7ebcb63d563d1420fd1b312452))
|
||||
- **$injector:** more conservative annotation parsing
|
||||
- **$location:** reset $location.$$replace with every watch call
|
||||
([a32bc40f](https://github.com/angular/angular.js/commit/a32bc40fd75ca46e3581ad7a6e3a24a31df6e266),
|
||||
[#1111](https://github.com/angular/angular.js/issues/1111))
|
||||
([d9eff86e](https://github.com/angular/angular.js/commit/d9eff86ef77dd76208cef21e882239d4db0eac1e))
|
||||
- **$parser:** string concatination with undefined model
|
||||
([42c38b29](https://github.com/angular/angular.js/commit/42c38b29f7dcb3327fe58e630b8e2973676989e0),
|
||||
[#988](https://github.com/angular/angular.js/issues/988))
|
||||
- **$resource:**
|
||||
- prevent default params to be shared between actions
|
||||
([94e1c039](https://github.com/angular/angular.js/commit/94e1c0391c351b6f691fad8abed2828fa20548b2))
|
||||
- allow falsy values in URL parameters
|
||||
([4909d1d3](https://github.com/angular/angular.js/commit/4909d1d39d61d6945a0820a5a7276c1e657ba262))
|
||||
- ignore undefined parameters
|
||||
([10e1c759](https://github.com/angular/angular.js/commit/10e1c759f4602d993a76b0eacf6a2d04c8880017),
|
||||
[#875](https://github.com/angular/angular.js/issues/875),
|
||||
[#782](https://github.com/angular/angular.js/issues/782))
|
||||
- **Scope:**
|
||||
- workaround for Chrome's memleak
|
||||
([bd524fc4](https://github.com/angular/angular.js/commit/bd524fc4e5fc0feffe85632a7a6560da6bd9b762),
|
||||
[#1313](https://github.com/angular/angular.js/issues/1313))
|
||||
- allow removing a listener during event
|
||||
([e6966e05](https://github.com/angular/angular.js/commit/e6966e05f508d1d2633b9ff327fea912b12555ac))
|
||||
- **$route:** support inline annotation on .resolve
|
||||
([b0a05a75](https://github.com/angular/angular.js/commit/b0a05a7531ed7235aa6d2c4e3ea11373e1fc73f1))
|
||||
- **FormController:** propagate dirty state to parent forms
|
||||
([04329151](https://github.com/angular/angular.js/commit/04329151d2df833f803629cefa781aa6409fe6a5))
|
||||
- **a:** prevent Opera from incorrectly navigating on link click
|
||||
([c81d8176](https://github.com/angular/angular.js/commit/c81d8176cc55cd15acae05259ead73f90a01f0b7))
|
||||
- **jqLite:**
|
||||
- support append on document fragment
|
||||
([96ed9ff5](https://github.com/angular/angular.js/commit/96ed9ff59a454486c88bdf92ad9d28ab8864b85e))
|
||||
- fire $destroy event via triggerHandler (this makes AngularJS compatible with **jQuery 1.8.x**)
|
||||
([b9a9f91f](https://github.com/angular/angular.js/commit/b9a9f91fbf99b71cfde434b6277f4c7d2533556f),
|
||||
[#1512](https://github.com/angular/angular.js/issues/1512))
|
||||
- **Filters**
|
||||
- **currency:** Handle not-quite-zero values
|
||||
([bca1604c](https://github.com/angular/angular.js/commit/bca1604c12262b66ce3b8004994fb4841fb8b87d),
|
||||
[#1469](https://github.com/angular/angular.js/issues/1469))
|
||||
- **date:**
|
||||
- make timezone optional
|
||||
([9473780e](https://github.com/angular/angular.js/commit/9473780e77a960ba27644ca76c2413924cc8972e))
|
||||
- support sub-second precision on dateFilter
|
||||
([f299fd51](https://github.com/angular/angular.js/commit/f299fd512248321b426a5ab924a329aa1b691280))
|
||||
- **Directives**
|
||||
- **ngClass:** works with class interpolation
|
||||
([cebd015f](https://github.com/angular/angular.js/commit/cebd015f78c5e21bd37d4bc055dbcdc21dac2ef2),
|
||||
[#1016](https://github.com/angular/angular.js/issues/1016))
|
||||
- **ngClassOdd/ngClassEven:** support shrinking/reordering in repeaters
|
||||
([d859dcec](https://github.com/angular/angular.js/commit/d859dcecea654d1d858cd756c6efb8435a453197),
|
||||
[6c67719d](https://github.com/angular/angular.js/commit/6c67719dfa6ff3f2a15a8e1e7660cf2e6e9155b0),
|
||||
[#1076](https://github.com/angular/angular.js/issues/1076))
|
||||
- **ngModel:** sync ngModel state with scope state
|
||||
([e6d9bea4](https://github.com/angular/angular.js/commit/e6d9bea4f3b2eb28851298d3dc3a30d46062d58a),
|
||||
[#933](https://github.com/angular/angular.js/issues/933))
|
||||
- **ngRepeat:** now works better with primitive types
|
||||
([e6d9bea4](https://github.com/angular/angular.js/commit/e6d9bea4f3b2eb28851298d3dc3a30d46062d58a),
|
||||
[#933](https://github.com/angular/angular.js/issues/933))
|
||||
- **ngSrc:** don't set src if value is empty string
|
||||
([b6e4a711](https://github.com/angular/angular.js/commit/b6e4a71166c7f00f4140fd7ea8f0cd81b4487a3f))
|
||||
- **select:** select option with a label of 0 is not shown
|
||||
([b3cae4f4](https://github.com/angular/angular.js/commit/b3cae4f457f1688346bbd0b08cccc9c504f83406),
|
||||
[#1401](https://github.com/angular/angular.js/issues/1401))
|
||||
- **scenario:**
|
||||
- emit RunnerBegin event
|
||||
([95276a7e](https://github.com/angular/angular.js/commit/95276a7e1047c7a3ac6613d8612c62f544388fc9))
|
||||
- NPE when no angular loaded in test page
|
||||
([84c13d96](https://github.com/angular/angular.js/commit/84c13d96ff6e993b2ee9ff6bf49614fc1d514b04))
|
||||
- support data-ng and x-ng based attributes
|
||||
([249a1d84](https://github.com/angular/angular.js/commit/249a1d84e7ac3b8528d317b8b0a80acb5dd9a271),
|
||||
[#1020](https://github.com/angular/angular.js/issues/1020))
|
||||
|
||||
|
||||
## Docs
|
||||
|
||||
- add plunkr support
|
||||
([7c67b2fb](https://github.com/angular/angular.js/commit/7c67b2fb6afbc18f3593c64a5f339f04f9003f3c))
|
||||
- various small documentation fixes and improvements
|
||||
|
||||
|
||||
## Refactorings
|
||||
|
||||
- name all anonymous watch functions in Angular
|
||||
([ca30fce2](https://github.com/angular/angular.js/commit/ca30fce28ca13284bfa1c926e810ed75cdcde499),
|
||||
[#1119](https://github.com/angular/angular.js/issues/1119))
|
||||
|
||||
|
||||
|
||||
|
||||
<a name="1.1.0"></a>
|
||||
# 1.1.0 increase-gravatas (2012-08-31)
|
||||
|
||||
_Note: 1.1.x releases unlike 1.0.x are considered unstable.
|
||||
[More info](http://blog.angularjs.org/2012/07/angularjs-10-12-roadmap.html)_
|
||||
|
||||
This release also contains all bug fixes available in [1.0.2](#1.0.2).
|
||||
|
||||
## Features
|
||||
|
||||
- **$http:** support custom reponseType
|
||||
@@ -334,6 +17,8 @@ This release also contains all bug fixes available in [1.0.2](#1.0.2).
|
||||
- **$sniffer:** auto detect CSP mode (currently requires Chrome on dev channel)
|
||||
([167aa0c2](https://github.com/angular/angular.js/commit/167aa0c29c998be33c49d33302e099b36d1ce0be))
|
||||
|
||||
This release also contains all bug fixes available in [1.0.2](#1.0.2).
|
||||
|
||||
|
||||
|
||||
<a name="1.0.2"></a>
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
## Submitting issues
|
||||
|
||||
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].
|
||||
|
||||
### Guidelines
|
||||
|
||||
* Search the archive first, it's likely that your question was already answered.
|
||||
* A live example demonstrating your problem or question, will get an answer faster.
|
||||
* Create one using this [template][template]
|
||||
* If you get help, help others. Good karma rulez!
|
||||
|
||||
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.
|
||||
|
||||
[stackoverflow]: http://stackoverflow.com/questions/tagged/angularjs
|
||||
[groups]: https://groups.google.com/forum/?fromgroups#!forum/angular
|
||||
[irc]: http://webchat.freenode.net/?channels=angularjs&uio=d4
|
||||
[template]: http://plnkr.co/edit/gist:3510140
|
||||
|
||||
## Contributing to Source Code
|
||||
|
||||
We'd love for you to contribute to our source code and to make AngularJS even
|
||||
better than it is today!
|
||||
|
||||
Please read the [contribution guidelines][contribute] to learn about how to submit code as well as
|
||||
other useful info like how to build and test AngularJS code.
|
||||
|
||||
[list]: https://groups.google.com/forum/?fromgroups#!forum/angular
|
||||
[contribute]: http://docs.angularjs.org/misc/contribute
|
||||
@@ -1,11 +1,11 @@
|
||||
AngularJS
|
||||
=========
|
||||
|
||||
AngularJS lets you write client-side web applications as if you had a smarter browser. It lets you
|
||||
use good old HTML (or HAML, Jade and friends!) as your template language and lets you extend HTML’s
|
||||
AngularJS lets you write client-side web applications as if you had a smarter browser. It lets use
|
||||
good old HTML (or HAML, Jade and friends!) as your template language and lets you extend HTML’s
|
||||
syntax to express your application’s components clearly and succinctly. It automatically
|
||||
synchronizes data from your UI (view) with your JavaScript objects (model) through 2-way data
|
||||
binding. To help you structure your application better and make it easy to test, AngularJS teaches
|
||||
binding. To help you structure your application better and make it easy to test AngularJS teaches
|
||||
the browser how to do dependency injection and inversion of control. Oh yeah and it also helps with
|
||||
server-side communication, taming async callbacks with promises and deferreds; and make client-side
|
||||
navigation and deeplinking with hashbang urls or HTML5 pushState a piece of cake. The best of all:
|
||||
@@ -13,33 +13,17 @@ it makes development fun!
|
||||
|
||||
* Web site: http://angularjs.org
|
||||
* Tutorial: http://docs.angularjs.org/tutorial
|
||||
* API Docs: http://docs.angularjs.org/api
|
||||
* API Docs: http://docs.angularjs.org
|
||||
* Developer Guide: http://docs.angularjs.org/guide
|
||||
* Contribution guidelines: http://docs.angularjs.org/misc/contribute
|
||||
|
||||
Building AngularJS
|
||||
Compiling
|
||||
---------
|
||||
[Once you have your environment setup](http://docs.angularjs.org/misc/contribute) just run:
|
||||
|
||||
rake package
|
||||
|
||||
rake compile
|
||||
|
||||
Running Tests
|
||||
-------------
|
||||
Running tests requires installation of [Testacular](http://vojtajina.github.com/testacular):
|
||||
./server.sh # start the server
|
||||
open http://localhost:9876/capture # capture browser
|
||||
./test.sh # run all unit tests
|
||||
|
||||
sudo npm install -g testacular
|
||||
|
||||
To execute all unit tests, use:
|
||||
|
||||
rake test:unit
|
||||
|
||||
To execute end-to-end (e2e) tests, use:
|
||||
|
||||
rake package
|
||||
rake webserver &
|
||||
rake test:e2e
|
||||
|
||||
To learn more about the rake tasks, run `rake -T` and also read our
|
||||
[contribution guidelines](http://docs.angularjs.org/misc/contribute) and instructions in this
|
||||
[commit message](https://github.com/angular/angular.js/commit/9d168f058f9c6d7eeae0daa7cb72ea4e02a0003a).
|
||||
|
||||
@@ -40,7 +40,6 @@ desc 'Clean Generated Files'
|
||||
task :clean do
|
||||
FileUtils.rm_r(BUILD_DIR, :force => true)
|
||||
FileUtils.mkdir(BUILD_DIR)
|
||||
FileUtils.rm_r('test_out', :force => true)
|
||||
end
|
||||
|
||||
|
||||
@@ -57,6 +56,25 @@ task :concat_scenario => :init do
|
||||
end
|
||||
|
||||
|
||||
desc 'Concat JSTD Scenario Adapter'
|
||||
task :concat_jstd_scenario_adapter => :init do
|
||||
|
||||
concat_file('jstd-scenario-adapter.js', [
|
||||
'src/ngScenario/jstd-scenario-adapter/angular.prefix',
|
||||
'src/ngScenario/jstd-scenario-adapter/Adapter.js',
|
||||
'src/ngScenario/jstd-scenario-adapter/angular.suffix',
|
||||
])
|
||||
|
||||
# TODO(vojta) use jstd configuration when implemented
|
||||
# (instead of including jstd-adapter-config.js)
|
||||
File.open(path_to('jstd-scenario-adapter-config.js'), 'w') do |f|
|
||||
f.write("/**\r\n" +
|
||||
" * Configuration for jstd scenario adapter \n */\n" +
|
||||
"var jstdScenarioAdapter = {\n relativeUrlPrefix: '/build/docs/'\n};\n")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
|
||||
desc 'Concat AngularJS files'
|
||||
task :concat => :init do
|
||||
@@ -96,7 +114,7 @@ end
|
||||
|
||||
|
||||
desc 'Minify JavaScript'
|
||||
task :minify => [:init, :concat, :concat_scenario] do
|
||||
task :minify => [:init, :concat, :concat_scenario, :concat_jstd_scenario_adapter] do
|
||||
[ 'angular.js',
|
||||
'angular-cookies.js',
|
||||
'angular-loader.js',
|
||||
@@ -105,26 +123,8 @@ task :minify => [:init, :concat, :concat_scenario] do
|
||||
'angular-bootstrap.js',
|
||||
'angular-bootstrap-prettify.js'
|
||||
].each do |file|
|
||||
unless ENV['TRAVIS']
|
||||
fork { closure_compile(file) }
|
||||
else
|
||||
closure_compile(file)
|
||||
end
|
||||
closure_compile(file)
|
||||
end
|
||||
|
||||
Process.waitall
|
||||
end
|
||||
|
||||
|
||||
desc 'Generate version.txt and version.json files'
|
||||
task :version => [:init] do
|
||||
`echo #{NG_VERSION.full} > #{path_to('version.txt')}`
|
||||
`echo '{
|
||||
"full": "#{NG_VERSION.full}",
|
||||
"major": "#{NG_VERSION.major}",
|
||||
"minor": "#{NG_VERSION.minor}",
|
||||
"dot": "#{NG_VERSION.dot}",
|
||||
"codename": "#{NG_VERSION.codename}"\n}' > #{path_to('version.json')}`
|
||||
end
|
||||
|
||||
|
||||
@@ -150,7 +150,7 @@ end
|
||||
|
||||
|
||||
desc 'Create angular distribution'
|
||||
task :package => [:clean, :minify, :version, :docs] do
|
||||
task :package => [:clean, :minify, :docs] do
|
||||
zip_dir = "angular-#{NG_VERSION.full}"
|
||||
zip_file = "#{zip_dir}.zip"
|
||||
|
||||
@@ -164,74 +164,37 @@ task :package => [:clean, :minify, :version, :docs] do
|
||||
end
|
||||
|
||||
|
||||
desc 'Start development webserver'
|
||||
task :webserver, :port do |t, args|
|
||||
exec "node lib/nodeserver/server.js #{args[:port]}"
|
||||
namespace :server do
|
||||
|
||||
desc 'Run JsTestDriver Server'
|
||||
task :start do
|
||||
sh %x(java -jar lib/jstestdriver/JsTestDriver.jar --browser open --port 9876)
|
||||
end
|
||||
|
||||
desc 'Run JavaScript tests against the server'
|
||||
task :test do
|
||||
sh %(java -jar lib/jstestdriver/JsTestDriver.jar --tests all)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
desc 'Run all AngularJS tests'
|
||||
task :test, :browsers, :misc_options do |t, args|
|
||||
[ 'test:jqlite',
|
||||
'test:jquery',
|
||||
'test:modules',
|
||||
'test:e2e'
|
||||
].each do |task|
|
||||
Rake::Task[task].invoke(args[:browsers], args[:misc_options])
|
||||
end
|
||||
desc 'Run JavaScript tests'
|
||||
task :test do
|
||||
sh %(java -jar lib/jstestdriver/JsTestDriver.jar --tests all --browser open --port 9876)
|
||||
end
|
||||
|
||||
|
||||
namespace :test do
|
||||
|
||||
desc 'Run all unit tests (single run)'
|
||||
task :unit, :browsers, :misc_options do |t, args|
|
||||
[ 'test:jqlite',
|
||||
'test:jquery',
|
||||
'test:modules'
|
||||
].each do |task|
|
||||
Rake::Task[task].invoke(args[:browsers], args[:misc_options])
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
desc 'Run jqLite-based unit test suite (single run)'
|
||||
task :jqlite, :browsers, :misc_options do |t, args|
|
||||
start_testacular('testacular-jqlite.conf.js', true, args[:browsers], args[:misc_options])
|
||||
end
|
||||
|
||||
|
||||
desc 'Run jQuery-based unit test suite (single run)'
|
||||
task :jquery, :browsers, :misc_options do |t, args|
|
||||
start_testacular('testacular-jquery.conf.js', true, args[:browsers], args[:misc_options])
|
||||
end
|
||||
|
||||
|
||||
desc 'Run bundled modules unit test suite (single run)'
|
||||
task :modules, :browsers, :misc_options do |t, args|
|
||||
start_testacular('testacular-modules.conf.js', true, args[:browsers], args[:misc_options])
|
||||
end
|
||||
|
||||
|
||||
desc 'Run e2e test suite (single run)'
|
||||
task :e2e, :browsers, :misc_options do |t, args|
|
||||
start_testacular('testacular-e2e.conf.js', true, args[:browsers], args[:misc_options])
|
||||
end
|
||||
desc 'Lint'
|
||||
task :lint do
|
||||
out = %x(lib/jsl/jsl -conf lib/jsl/jsl.default.conf)
|
||||
print out
|
||||
end
|
||||
|
||||
|
||||
namespace :autotest do
|
||||
|
||||
desc 'Run jqLite-based unit test suite (autowatch)'
|
||||
task :jqlite, :browsers, :misc_options do |t, args|
|
||||
start_testacular('testacular-jqlite.conf.js', false, args[:browsers], args[:misc_options])
|
||||
end
|
||||
|
||||
|
||||
desc 'Run jQuery-based unit test suite (autowatch)'
|
||||
task :jquery, :browsers, :misc_options do |t, args|
|
||||
start_testacular('testacular-jquery.conf.js', false, args[:browsers], args[:misc_options])
|
||||
end
|
||||
desc 'push_angularjs'
|
||||
task :push_angularjs => :compile do
|
||||
sh %(cat angularjs.ftp | ftp -N angularjs.netrc angularjs.org)
|
||||
end
|
||||
|
||||
|
||||
@@ -277,23 +240,12 @@ def path_to(filename)
|
||||
end
|
||||
|
||||
|
||||
##
|
||||
# returns the 32-bit mode force flags for java compiler if supported, this makes the build much
|
||||
# faster
|
||||
#
|
||||
def java32flags
|
||||
return '-d32 -client' unless Rake::Win32.windows? || `java -version -d32 2>&1`.match(/Error/i)
|
||||
end
|
||||
|
||||
|
||||
def closure_compile(filename)
|
||||
puts "Minifying #{filename} ..."
|
||||
|
||||
min_path = path_to(filename.gsub(/\.js$/, '.min.js'))
|
||||
|
||||
%x(java \
|
||||
#{java32flags()} \
|
||||
-jar lib/closure-compiler/compiler.jar \
|
||||
%x(java -jar lib/closure-compiler/compiler.jar \
|
||||
--compilation_level SIMPLE_OPTIMIZATIONS \
|
||||
--language_in ECMASCRIPT5_STRICT \
|
||||
--js #{path_to(filename)} \
|
||||
@@ -344,12 +296,3 @@ def rewrite_file(filename)
|
||||
f.write content
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
def start_testacular(config, singleRun, browsers, misc_options)
|
||||
sh "./node_modules/testacular/bin/testacular start " +
|
||||
"#{config} " +
|
||||
"#{'--single-run=true' if singleRun} " +
|
||||
"#{'--browsers=' + browsers.gsub('+', ',') if browsers} " +
|
||||
"#{(misc_options || '').gsub('+', ',')}"
|
||||
end
|
||||
|
||||
Vendored
+31
-24
@@ -79,6 +79,7 @@ angularFiles = {
|
||||
'src/ngScenario/Describe.js',
|
||||
'src/ngScenario/Future.js',
|
||||
'src/ngScenario/ObjectModel.js',
|
||||
'src/ngScenario/Describe.js',
|
||||
'src/ngScenario/Runner.js',
|
||||
'src/ngScenario/SpecRunner.js',
|
||||
'src/ngScenario/dsl.js',
|
||||
@@ -195,30 +196,36 @@ angularFiles = {
|
||||
]
|
||||
};
|
||||
|
||||
if (exports) {
|
||||
exports.files = angularFiles
|
||||
exports.mergeFiles = function mergeFiles() {
|
||||
var files = [];
|
||||
|
||||
[].splice.call(arguments, 0).forEach(function(file) {
|
||||
if (file.match(/testacular/)) {
|
||||
files.push(file);
|
||||
} else {
|
||||
angularFiles[file].forEach(function(f) {
|
||||
// replace @ref
|
||||
var match = f.match(/^\@(.*)/);
|
||||
if (match) {
|
||||
var deps = angularFiles[match[1]];
|
||||
files = files.concat(deps);
|
||||
} else {
|
||||
if (!/jstd|jasmine/.test(f)) { //TODO(i): remove once we don't have jstd/jasmine in repo
|
||||
files.push(f);
|
||||
}
|
||||
}
|
||||
});
|
||||
// Execute only in slim-jim
|
||||
if (typeof JASMINE_ADAPTER !== 'undefined') {
|
||||
// Testacular config
|
||||
var mergedFiles = [];
|
||||
angularFiles.jstd.forEach(function(file) {
|
||||
// replace @ref
|
||||
var match = file.match(/^\@(.*)/);
|
||||
if (match) {
|
||||
var deps = angularFiles[match[1]];
|
||||
if (!deps) {
|
||||
console.log('No dependency:' + file)
|
||||
}
|
||||
});
|
||||
mergedFiles = mergedFiles.concat(deps);
|
||||
} else {
|
||||
mergedFiles.push(file);
|
||||
}
|
||||
});
|
||||
|
||||
return files;
|
||||
}
|
||||
files = [JASMINE, JASMINE_ADAPTER];
|
||||
|
||||
mergedFiles.forEach(function(file){
|
||||
if (/jstd|jasmine/.test(file)) return;
|
||||
files.push(file);
|
||||
});
|
||||
|
||||
|
||||
exclude = angularFiles.jstdExclude;
|
||||
|
||||
autoWatch = true;
|
||||
autoWatchInterval = 1;
|
||||
logLevel = LOG_INFO;
|
||||
logColors = true;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
bin
|
||||
cd angularjs.org/ng
|
||||
put angular-debug.js js/angular-debug.js
|
||||
put angular-minified.js js/angular-minified.js
|
||||
put angular-scenario.js js/angular-scenario.js
|
||||
+22
-27
@@ -36,15 +36,16 @@ var parseRawCommit = function(raw) {
|
||||
msg.breaks = [];
|
||||
|
||||
lines.forEach(function(line) {
|
||||
match = line.match(/(?:Closes|Fixes)\s#(\d+)/);
|
||||
match = line.match(/Closes\s#(\d+)/);
|
||||
if (match) msg.closes.push(parseInt(match[1]));
|
||||
});
|
||||
|
||||
|
||||
match = raw.match(/BREAKING CHANGE:([\s\S]*)/);
|
||||
if (match) {
|
||||
msg.breaking = match[1];
|
||||
console.log('found!!!')
|
||||
msg.breaks.push(match[1]);
|
||||
}
|
||||
|
||||
|
||||
|
||||
msg.body = lines.join('\n');
|
||||
match = msg.subject.match(/^(.*)\((.*)\)\:\s(.*)$/);
|
||||
@@ -87,8 +88,7 @@ var currentDate = function() {
|
||||
};
|
||||
|
||||
|
||||
var printSection = function(stream, title, section, printCommitLinks) {
|
||||
printCommitLinks = printCommitLinks === undefined ? true : printCommitLinks;
|
||||
var printSection = function(stream, title, section) {
|
||||
var components = Object.getOwnPropertyNames(section).sort();
|
||||
|
||||
if (!components.length) return;
|
||||
@@ -109,15 +109,11 @@ var printSection = function(stream, title, section, printCommitLinks) {
|
||||
}
|
||||
|
||||
section[name].forEach(function(commit) {
|
||||
if (printCommitLinks) {
|
||||
stream.write(util.format('%s %s\n (%s', prefix, commit.subject, linkToCommit(commit.hash)));
|
||||
if (commit.closes.length) {
|
||||
stream.write(',\n ' + commit.closes.map(linkToIssue).join(', '));
|
||||
}
|
||||
stream.write(')\n');
|
||||
} else {
|
||||
stream.write(util.format('%s %s', prefix, commit.subject));
|
||||
stream.write(util.format('%s %s (%s', prefix, commit.subject, linkToCommit(commit.hash)));
|
||||
if (commit.closes.length) {
|
||||
stream.write(', closes ' + commit.closes.map(linkToIssue).join(', '));
|
||||
}
|
||||
stream.write(')\n');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -126,7 +122,7 @@ var printSection = function(stream, title, section, printCommitLinks) {
|
||||
|
||||
|
||||
var readGitLog = function(grep, from) {
|
||||
var deferred = q.defer();
|
||||
var deffered = q.defer();
|
||||
|
||||
// TODO(vojta): if it's slow, use spawn and stream it instead
|
||||
child.exec(util.format(GIT_LOG_CMD, grep, '%H%n%s%n%b%n==END==', from), function(code, stdout, stderr) {
|
||||
@@ -137,10 +133,10 @@ var readGitLog = function(grep, from) {
|
||||
if (commit) commits.push(commit);
|
||||
});
|
||||
|
||||
deferred.resolve(commits);
|
||||
deffered.resolve(commits);
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
return deffered.promise;
|
||||
};
|
||||
|
||||
|
||||
@@ -162,30 +158,29 @@ var writeChangelog = function(stream, commits, version) {
|
||||
section[component].push(commit);
|
||||
}
|
||||
|
||||
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),
|
||||
commit.breaks.forEach(function(breakMsg) {
|
||||
sections.breaks[EMPTY_COMPONENT].push({
|
||||
subject: breakMsg,
|
||||
hash: commit.hash,
|
||||
closes: []
|
||||
});
|
||||
};
|
||||
});
|
||||
});
|
||||
|
||||
stream.write(util.format(HEADER_TPL, version, version, currentDate()));
|
||||
printSection(stream, 'Bug Fixes', sections.fix);
|
||||
printSection(stream, 'Features', sections.feat);
|
||||
printSection(stream, 'Breaking Changes', sections.breaks, false);
|
||||
printSection(stream, 'Breaking Changes', sections.breaks);
|
||||
}
|
||||
|
||||
|
||||
var getPreviousTag = function() {
|
||||
var deferred = q.defer();
|
||||
var deffered = q.defer();
|
||||
child.exec(GIT_TAG_CMD, function(code, stdout, stderr) {
|
||||
if (code) deferred.reject('Cannot get the previous tag.');
|
||||
else deferred.resolve(stdout.replace('\n', ''));
|
||||
if (code) deffered.reject('Cannot get the previous tag.');
|
||||
else deffered.resolve(stdout.replace('\n', ''));
|
||||
});
|
||||
return deferred.promise;
|
||||
return deffered.promise;
|
||||
};
|
||||
|
||||
|
||||
|
||||
+3
-3
@@ -34,10 +34,10 @@ describe('changelog.js', function() {
|
||||
'13f31602f396bc269076ab4d389cfd8ca94b20ba\n' +
|
||||
'feat(ng-list): Allow custom separator\n' +
|
||||
'bla bla bla\n\n' +
|
||||
'BREAKING CHANGE: first breaking change\nsomething else\n' +
|
||||
'another line with more info\n');
|
||||
'Breaks first breaking change\nsomething else\n' +
|
||||
'Breaks another breaking change\n');
|
||||
|
||||
expect(msg.breaking).toEqual(' first breaking change\nsomething else\nanother line with more info\n');
|
||||
expect(msg.breaks).toEqual(['first breaking change', 'another breaking change']);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
#!/bin/bash
|
||||
|
||||
rake minify
|
||||
rake compile
|
||||
gzip -c < build/angular.min.js > build/angular.min.js.gzip
|
||||
ls -l build/angular.min.*
|
||||
|
||||
@@ -3,5 +3,5 @@
|
||||
@description
|
||||
|
||||
Use the API Reference documentation when you need more information about a specific feature. Check out
|
||||
{@link guide/ Developer Guide} for AngularJS concepts. If you are new to AngularJS we recommend the
|
||||
{@link guide/ Developer Guide} for AngularJS concepts. If you are new to AngularJS we recomend the
|
||||
{@link tutorial/ Tutorial}.
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
@description
|
||||
|
||||
External resources are URLs that provide JSON data, which are then rendered with the help of
|
||||
templates. Angular has a resource factory that can be used to give names to the URLs and then
|
||||
templates. angular has a resource factory that can be used to give names to the URLs and then
|
||||
attach behavior to them. For example you can use the
|
||||
{@link http://code.google.com/apis/buzz/v1/getting_started.html#background-operations| Google Buzz
|
||||
API}
|
||||
@@ -21,12 +21,12 @@ to retrieve Buzz activity and comments.
|
||||
{ get: {method: 'JSONP', params: {visibility: '@self'}},
|
||||
replies: {method: 'JSONP', params: {visibility: '@self', comments: '@comments'}}
|
||||
});
|
||||
|
||||
$scope.fetch = function() {
|
||||
}
|
||||
BuzzController.prototype = {
|
||||
fetch: function() {
|
||||
$scope.activities = $scope.Activity.get({userId:this.userId});
|
||||
}
|
||||
|
||||
$scope.expandReplies = function(activity) {
|
||||
},
|
||||
expandReplies: function(activity) {
|
||||
activity.replies = $scope.Activity.replies({userId: this.userId, activityId: activity.id});
|
||||
}
|
||||
};
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
Deep linking allows you to encode the state of the application in the URL so that it can be
|
||||
bookmarked and the application can be restored from the URL to the same state.
|
||||
|
||||
While Angular does not force you to deal with bookmarks in any particular way, it has services
|
||||
While angular does not force you to deal with bookmarks in any particular way, it has services
|
||||
which make the common case described here very easy to implement.
|
||||
|
||||
# Assumptions
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
@name Cookbook: Form
|
||||
@description
|
||||
|
||||
A web application's main purpose is to present and gather data. For this reason Angular strives
|
||||
A web application's main purpose is to present and gather data. For this reason angular strives
|
||||
to make both of these operations trivial. This example shows off how you can build a simple form to
|
||||
allow a user to enter data.
|
||||
|
||||
|
||||
@@ -28,10 +28,10 @@
|
||||
|
||||
Take a look through the source and note:
|
||||
|
||||
* The script tag that {@link guide/bootstrap bootstraps} the Angular environment.
|
||||
* The script tag that {@link guide/bootstrap bootstraps} the angular environment.
|
||||
* The text {@link api/ng.directive:input input form control} which is
|
||||
bound to the greeting name text.
|
||||
* There is no need for listener registration and event firing on change events.
|
||||
* No need for listener registration and event firing on change events.
|
||||
* The implicit presence of the `name` variable which is in the root {@link api/ng.$rootScope.Scope scope}.
|
||||
* The double curly brace `{{markup}}`, which binds the name variable to the greeting text.
|
||||
* The concept of {@link guide/dev_guide.templates.databinding data binding}, which reflects any
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
@name Cookbook
|
||||
@description
|
||||
|
||||
Welcome to the Angular cookbook. Here we will show you typical uses of Angular by example.
|
||||
Welcome to the angular cookbook. Here we will show you typical uses of angular by example.
|
||||
|
||||
|
||||
# Hello World
|
||||
@@ -45,7 +45,7 @@ allowing you to send links to specific screens in your app.
|
||||
# Services
|
||||
|
||||
{@link api/ng Services}: Services are long lived objects in your applications that are
|
||||
available across controllers. A collection of useful services are pre-bundled with Angular but you
|
||||
available across controllers. A collection of useful services are pre-bundled with angular but you
|
||||
will likely add your own. Services are initialized using dependency injection, which resolves the
|
||||
order of initialization. This safeguards you from the perils of global state (a common way to
|
||||
implement long lived objects).
|
||||
@@ -55,4 +55,4 @@ implement long lived objects).
|
||||
|
||||
{@link buzz Resources}: Web applications must be able to communicate with the external
|
||||
services to get and update data. Resources are the abstractions of external URLs which are
|
||||
specially tailored to Angular data binding.
|
||||
specially tailored to angular data binding.
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
@name Cookbook: MVC
|
||||
@description
|
||||
|
||||
MVC allows for a clean and testable separation between the behavior (controller) and the view
|
||||
MVC allows for a clean an testable separation between the behavior (controller) and the view
|
||||
(HTML template). A Controller is just a JavaScript class which is grafted onto the scope of the
|
||||
view. This makes it very easy for the controller and the view to share the model.
|
||||
|
||||
@@ -115,7 +115,7 @@ view.
|
||||
# Things to notice
|
||||
|
||||
* The controller is defined in JavaScript and has no reference to the rendering logic.
|
||||
* The controller is instantiated by Angular and injected into the view.
|
||||
* The controller is instantiated by <angular/> and injected into the view.
|
||||
* The controller can be instantiated in isolation (without a view) and the code will still execute.
|
||||
This makes it very testable.
|
||||
* The HTML view is a projection of the model. In the above example, the model is stored in the
|
||||
|
||||
@@ -9,7 +9,7 @@ browser new HTML syntax. The compiler allows you to attach behavior to any HTML
|
||||
and even create new HTML element or attributes with custom behavior. Angular calls these behavior
|
||||
extensions {@link api/ng.$compileProvider#directive directives}.
|
||||
|
||||
HTML has a lot of constructs for formatting the HTML for static documents in a declarative fashion.
|
||||
HTML has a lot of constructs for formatting the HTML for static documents in declarative fashion.
|
||||
For example if something needs to be centered, there is no need to provide instructions to the
|
||||
browser how the window size needs to be divided in half so that center is found, and that this
|
||||
center needs to be aligned with the text's center. Simply add `align="center"` attribute to any
|
||||
@@ -37,7 +37,7 @@ process happens into two phases.
|
||||
|
||||
2. **Link:** combine the directives with a scope and produce a live view. Any changes in the
|
||||
scope model are reflected in the view, and any user interactions with the view are reflected
|
||||
in the scope model. This makes the scope model the single source of truth.
|
||||
in the scope model. Making the scope model a single source of truth.
|
||||
|
||||
Some directives such {@link api/ng.directive:ngRepeat
|
||||
`ng-repeat`} clone DOM elements once for each item in collection. Having a compile and link phase
|
||||
@@ -47,9 +47,9 @@ once for each clone instance.
|
||||
|
||||
# Directive
|
||||
|
||||
A directive is a behavior which should be triggered when specific HTML constructs are encountered in
|
||||
the compilation process. The directives can be placed in element names, attributes, class names, as
|
||||
well as comments. Here are some equivalent examples of invoking the {@link
|
||||
Directive is a behavior which should be triggered when specific HTML constructs are encountered in
|
||||
compilation process. The directives can be placed in element names, attributes, class names, as
|
||||
well as comments. Here are some equivalent examples of invoking {@link
|
||||
api/ng.directive:ngBind `ng-bind`} directive.
|
||||
|
||||
<pre>
|
||||
@@ -59,7 +59,7 @@ api/ng.directive:ngBind `ng-bind`} directive.
|
||||
<!-- directive: ng-bind exp -->
|
||||
</pre>
|
||||
|
||||
A directive is just a function which executes when the compiler encounters it in the DOM. See {@link
|
||||
Directive is just a function which executes when the compiler encounters it in the DOM. See {@link
|
||||
api/ng.$compileProvider#directive directive API} for in-depth documentation on how
|
||||
to write directives.
|
||||
|
||||
@@ -107,9 +107,9 @@ Here is a directive which makes any element draggable. Notice the `draggable` at
|
||||
</example>
|
||||
|
||||
|
||||
The presence of the `draggable` attribute on any element gives the element new behavior. The beauty of
|
||||
The presence of `draggable` attribute on any element gives the element new behavior. The beauty of
|
||||
this approach is that we have taught the browser a new trick. We have extended the vocabulary of
|
||||
what the browser understands in a way which is natural to anyone who is familiar with HTML
|
||||
what the browser understands in a way, which is natural to anyone who is familiar with HTML
|
||||
principles.
|
||||
|
||||
|
||||
@@ -122,7 +122,7 @@ an element.
|
||||
<img src="img/One_Way_Data_Binding.png">
|
||||
|
||||
This means that any changes to the data need to be re-merged with the template and then
|
||||
`innerHTML`ed into the DOM. Some of the issues with this approach are: reading user input and merging it with data,
|
||||
`innerHTML`ed into the DOM. Some of the issues are: reading user input and merging it with data,
|
||||
clobbering user input by overwriting it, managing the whole update process, and lack of behavior
|
||||
expressiveness.
|
||||
|
||||
|
||||
@@ -26,20 +26,20 @@ This is how we get the ball rolling (refer to the diagram and example below):
|
||||
|
||||
<img class="pull-right" style="padding-left: 3em;" src="img/guide/concepts-startup.png">
|
||||
|
||||
1. The browser loads the HTML and parses it into a DOM
|
||||
2. The browser loads `angular.js` script
|
||||
1. Browser loads the HTML and parses it into a DOM
|
||||
2. Browser loads `angular.js` script
|
||||
3. Angular waits for `DOMContentLoaded` event
|
||||
4. Angular looks for {@link api/ng.directive:ngApp ng-app}
|
||||
{@link guide/directive directive}, which designates the application boundary
|
||||
5. The {@link guide/module Module} specified in {@link
|
||||
api/ng.directive:ngApp ng-app} (if any) is used to configure
|
||||
{@link guide/directive directive}, which designates application boundary
|
||||
5. {@link guide/module Module} specified in {@link
|
||||
api/ng.directive:ngApp ng-app} (if any) is used to configure
|
||||
the {@link api/AUTO.$injector $injector}
|
||||
6. The {@link api/AUTO.$injector $injector} is used to create the {@link
|
||||
6. {@link api/AUTO.$injector $injector} is used to create the {@link
|
||||
api/ng.$compile $compile} service as well as {@link
|
||||
api/ng.$rootScope $rootScope}
|
||||
7. The {@link api/ng.$compile $compile} service is used to compile the DOM and link
|
||||
7. {@link api/ng.$compile $compile} service is used to compile the DOM and link
|
||||
it with {@link api/ng.$rootScope $rootScope}
|
||||
8. The {@link api/ng.directive:ngInit ng-init} {@link
|
||||
8. {@link api/ng.directive:ngInit ng-init} {@link
|
||||
guide/directive directive} assigns `World` to the `name` property on the {@link guide/scope
|
||||
scope}
|
||||
9. The `{{name}}` {@link api/ng.$interpolate interpolates} the expression to
|
||||
@@ -59,29 +59,29 @@ This is how we get the ball rolling (refer to the diagram and example below):
|
||||
|
||||
<img class="pull-right" style="padding-left: 3em; padding-bottom: 1em;" src="img/guide/concepts-runtime.png">
|
||||
|
||||
The diagram and the example below describe how Angular interacts with the browser's event loop.
|
||||
The diagram and the example below describe how Angular interacts with browser's event loop.
|
||||
|
||||
1. The browser's event-loop waits for an event to arrive. An event is a user interactions, timer event,
|
||||
1. Browsers event-loop waits for an event to arrive. Event is a user interactions, timer event,
|
||||
or network event (response from a server).
|
||||
2. The event's callback gets executed. This enters the JavaScript context. The callback can
|
||||
2. The events callback gets executed. This enters the JavaScript context. The callback can
|
||||
modify the DOM structure.
|
||||
3. Once the callback executes, the browser leaves the JavaScript context and
|
||||
3. Once the callback finishes execution, the browser leaves the JavaScript context and
|
||||
re-renders the view based on DOM changes.
|
||||
|
||||
Angular modifies the normal JavaScript flow by providing its own event processing loop. This
|
||||
Angular modifies the normal JavaScript flow by providing it's own event processing loop. This
|
||||
splits the JavaScript into classical and Angular execution context. Only operations which are
|
||||
applied in Angular execution context will benefit from Angular data-binding, exception handling,
|
||||
property watching, etc... You can also use $apply() to enter Angular execution context from JavaScript. Keep in
|
||||
mind that in most places (controllers, services) $apply has already been called for you by the
|
||||
directive which is handling the event. An explicit call to $apply is needed only when
|
||||
applied in Angular execution context will benefit from angular data-binding, exception handling,
|
||||
property watching, etc... Use $apply() to enter Angular execution context from JavaScript. Keep in
|
||||
mind that in most places (controllers, services) the $apply has already been called for you by the
|
||||
directive which is handling the event. The need to call $apply is reserved only when
|
||||
implementing custom event callbacks, or when working with a third-party library callbacks.
|
||||
|
||||
1. Enter Angular execution context by calling {@link guide/scope scope}`.`{@link
|
||||
api/ng.$rootScope.Scope#$apply $apply}`(stimulusFn)`. Where `stimulusFn` is
|
||||
the work you wish to do in Angular execution context.
|
||||
2. Angular executes the `stimulusFn()`, which typically modifies application state.
|
||||
3. Angular enters the {@link api/ng.$rootScope.Scope#$digest $digest} loop. The
|
||||
loop is made up of two smaller loops which process {@link
|
||||
3. Angular enters the {@link api/ng.$rootScope.Scope#$digest $digest} loop. The
|
||||
loop is made up of two smaller loops which process {@link
|
||||
api/ng.$rootScope.Scope#$evalAsync $evalAsync} queue and the {@link
|
||||
api/ng.$rootScope.Scope#$watch $watch} list. The {@link
|
||||
api/ng.$rootScope.Scope#$digest $digest} loop keeps iterating until the model
|
||||
@@ -89,14 +89,14 @@ implementing custom event callbacks, or when working with a third-party library
|
||||
$evalAsync} queue is empty and the {@link api/ng.$rootScope.Scope#$watch
|
||||
$watch} list does not detect any changes.
|
||||
4. The {@link api/ng.$rootScope.Scope#$evalAsync $evalAsync} queue is used to
|
||||
schedule work which needs to occur outside of current stack frame, but before the browser's
|
||||
schedule work which needs to occur outside of current stack frame, but before the browser
|
||||
view render. This is usually done with `setTimeout(0)`, but the `setTimeout(0)` approach
|
||||
suffers from slowness and may cause view flickering since the browser renders the view after
|
||||
each event.
|
||||
5. The {@link api/ng.$rootScope.Scope#$watch $watch} list is a set of expressions
|
||||
which may have changed since last iteration. If a change is detected then the `$watch`
|
||||
function is called which typically updates the DOM with the new value.
|
||||
6. Once the Angular {@link api/ng.$rootScope.Scope#$digest $digest} loop finishes
|
||||
6. Once Angular {@link api/ng.$rootScope.Scope#$digest $digest} loop finishes
|
||||
the execution leaves the Angular and JavaScript context. This is followed by the browser
|
||||
re-rendering the DOM to reflect any changes.
|
||||
|
||||
@@ -122,7 +122,7 @@ user enters text into the text field.
|
||||
5. The {@link api/ng.$rootScope.Scope#$watch $watch} list detects a change
|
||||
on the `name` property and notifies the {@link api/ng.$interpolate
|
||||
{{name}} } interpolation, which in turn updates the DOM.
|
||||
6. Angular exits the execution context, which in turn exits the `keydown` event and with it
|
||||
6. Angular exits the execution context, which in turn exits the `keydown` event and with it
|
||||
the JavaScript execution context.
|
||||
7. The browser re-renders the view with update text.
|
||||
|
||||
@@ -165,7 +165,7 @@ a diagram depicting the scope boundaries.
|
||||
function GreetCtrl($scope) {
|
||||
$scope.name = 'World';
|
||||
}
|
||||
|
||||
|
||||
function ListCtrl($scope) {
|
||||
$scope.names = ['Igor', 'Misko', 'Vojta'];
|
||||
}
|
||||
@@ -188,7 +188,7 @@ a diagram depicting the scope boundaries.
|
||||
|
||||
<img class="pull-right" style="padding-left: 3em; padding-bottom: 1em;" src="img/guide/concepts-controller.png">
|
||||
|
||||
A controller is the code behind the view. Its job is to construct the model and publish it to the
|
||||
Controller is the code behind the view. Its job is to construct the model and publish it to the
|
||||
view along with callback methods. The view is a projection of the scope onto the template (the
|
||||
HTML). The scope is the glue which marshals the model to the view and forwards the events to the
|
||||
controller.
|
||||
@@ -196,7 +196,7 @@ controller.
|
||||
The separation of the controller and the view is important because:
|
||||
|
||||
* The controller is written in JavaScript. JavaScript is imperative. Imperative is a good fit
|
||||
for specifying application behavior. The controller should not contain any rendering
|
||||
for specifying application behavior. The controller should not contain any rendering
|
||||
information (DOM references or HTML fragments).
|
||||
* The view template is written in HTML. HTML is declarative. Declarative is a good fit for
|
||||
specifying UI. The View should not contain any behavior.
|
||||
@@ -220,7 +220,7 @@ The separation of the controller and the view is important because:
|
||||
$scope.action = function() {
|
||||
$scope.name = 'OK';
|
||||
}
|
||||
|
||||
|
||||
$scope.name = 'World';
|
||||
}
|
||||
</file>
|
||||
@@ -233,7 +233,7 @@ The separation of the controller and the view is important because:
|
||||
<img class="pull-right" style="padding-left: 3em; padding-bottom: 1em;" src="img/guide/concepts-model.png">
|
||||
|
||||
The model is the data which is used merged with the template to produce the view. To be able to
|
||||
render the model into the view, the model has to be able to be referenced from the scope. Unlike many
|
||||
render the model into the view, the model has to be referenceable from the scope. Unlike many
|
||||
other frameworks Angular makes no restrictions or requirements an the model. There are no classes
|
||||
to inherit from or special accessor methods for accessing or changing the model. The model can be
|
||||
primitive, object hash, or a full object Type. In short the model is a plain JavaScript object.
|
||||
@@ -249,8 +249,8 @@ primitive, object hash, or a full object Type. In short the model is a plain Jav
|
||||
<img class="pull-right" style="padding-left: 3em; padding-bottom: 1em;" src="img/guide/concepts-view.png">
|
||||
|
||||
The view is what the users sees. The view begins its life as a template, it is merged with the
|
||||
model and finally rendered into the browser DOM. Angular takes a very different approach to
|
||||
rendering the view, compared to most other templating systems.
|
||||
model and finally rendered into the browser DOM. Angular takes a very different approach to
|
||||
rendering the view, to most other templating systems.
|
||||
|
||||
* **Others** - Most templating systems begin as an HTML string with special templating markup.
|
||||
Often the template markup breaks the HTML syntax which means that the template can not be
|
||||
@@ -260,13 +260,13 @@ rendering the view, compared to most other templating systems.
|
||||
When the model changes the whole process needs to be repeated. The granularity of the template
|
||||
is the granularity of the DOM updates. The key here is that the templating system manipulates
|
||||
strings.
|
||||
* **Angular** - Angular is different, since its templating system works on DOM objects not on
|
||||
strings. The template is still written in an HTML string, but it is HTML (not HTML with
|
||||
template sprinkled in.) The browser parses the HTML into the DOM, and the DOM becomes the input to
|
||||
the template engine known as the {@link api/ng.$compile compiler}. The compiler
|
||||
* **Angular** - Angular is different, since its templating system works on DOM objects not on
|
||||
strings. The template is still written in HTML string, but it is HTML (not HTML with
|
||||
template sprinkled in.) The browser parses the HTML into DOM, and the DOM becomes the input to
|
||||
the template engine know as the {@link api/ng.$compile compiler}. The compiler
|
||||
looks for {@link guide/directive directives} which in turn set up {@link
|
||||
api/ng.$rootScope.Scope#$watch watches} on the model. The result is a
|
||||
continuously updating view which does not need template model re-merging. Your model becomes
|
||||
continuously updating view which does not need template model re-merging. Your model becomes
|
||||
the single source-of-truth for your view.
|
||||
|
||||
<div class="clear">
|
||||
@@ -291,7 +291,7 @@ rendering the view, compared to most other templating systems.
|
||||
<a name="directives"></a>
|
||||
# Directives
|
||||
|
||||
A directive is a behavior or DOM transformation which is triggered by the presence of a custom attribute,
|
||||
A directive is a behavior or DOM transformation which is triggered by a presence of an attribute,
|
||||
element name, or a class name. A directive allows you to extend the HTML vocabulary in a
|
||||
declarative fashion. Following is an example which enables data-binding for the `contenteditable`
|
||||
in HTML.
|
||||
@@ -310,7 +310,7 @@ in HTML.
|
||||
});
|
||||
|
||||
// model -> view
|
||||
ctrl.$render = function(value) {
|
||||
ctrl.render = function(value) {
|
||||
elm.html(value);
|
||||
};
|
||||
|
||||
@@ -337,15 +337,15 @@ in HTML.
|
||||
<a name="filters"></a>
|
||||
# Filters
|
||||
|
||||
{@link api/ng.$filter Filters} perform data transformation. Typically
|
||||
{@link api/ng.$filter Filters} perform data transformation roles. Typically
|
||||
they are used in conjunction with the locale to format the data in locale specific output.
|
||||
They follow the spirit of UNIX filters and use similar syntax `|` (pipe).
|
||||
They are follow the spirit of UNIX filters and follow similar syntax `|` (pipe).
|
||||
|
||||
<example>
|
||||
<file name="index.html">
|
||||
<div ng-init="list = ['Chrome', 'Safari', 'Firefox', 'IE'] ">
|
||||
Number formatting: {{ 1234567890 | number }} <br>
|
||||
array filtering <input ng-model="predicate">
|
||||
array filtering <input ng-model="predicate">
|
||||
{{ list | filter:predicate | json }}
|
||||
</div>
|
||||
</file>
|
||||
@@ -358,11 +358,11 @@ They follow the spirit of UNIX filters and use similar syntax `|` (pipe).
|
||||
|
||||
<img class="pull-right" style="padding-left: 3em; padding-bottom: 1em;" src="img/guide/concepts-module-injector.png">
|
||||
|
||||
The {@link api/AUTO.$injector injector} is a service locator. There is a single
|
||||
An {@link api/AUTO.$injector injector} is a service locator. There is a single
|
||||
{@link api/AUTO.$injector injector} per Angular {@link
|
||||
api/ng.directive:ngApp application}. The {@link
|
||||
api/AUTO.$injector injector} provides a way to look up an object instance by its
|
||||
name. The injector keeps an internal cache of all objects so that repeated calls to get the same
|
||||
name. The injector keeps on internal cache of all objects so that repeated calls to get the same
|
||||
object name result in the same instance. If the object does not exist, then the {@link
|
||||
api/AUTO.$injector injector} asks the instance factory to create a new instance.
|
||||
|
||||
@@ -373,20 +373,20 @@ as a {@link api/AUTO.$provide provider}.
|
||||
<pre>
|
||||
// Create a module
|
||||
var myModule = angular.module('myModule', [])
|
||||
|
||||
|
||||
// Configure the injector
|
||||
myModule.factory('serviceA', function() {
|
||||
return {
|
||||
// instead of {}, put your object creation here
|
||||
};
|
||||
});
|
||||
|
||||
|
||||
// create an injector and configure it from 'myModule'
|
||||
var $injector = angular.injector(['myModule']);
|
||||
|
||||
var $injector = angular.injector('myModule');
|
||||
|
||||
// retrieve an object from the injector by name
|
||||
var serviceA = $injector.get('serviceA');
|
||||
|
||||
|
||||
// always true because of instance cache
|
||||
$injector.get('serviceA') === $injector.get('serviceA');
|
||||
</pre>
|
||||
@@ -395,7 +395,7 @@ as a {@link api/AUTO.$provide provider}.
|
||||
But the real magic of the {@link api/AUTO.$injector injector} is that it can be
|
||||
used to {@link api/AUTO.$injector#invoke call} methods and {@link
|
||||
api/AUTO.$injector#instantiate instantiate} types. This subtle feature is what
|
||||
allows the methods and types to ask for their dependencies instead of having to look for them.
|
||||
allows the methods and types to ask for their dependencies rather then to look for them.
|
||||
|
||||
<pre>
|
||||
// You write functions such as this one.
|
||||
@@ -405,12 +405,12 @@ allows the methods and types to ask for their dependencies instead of having to
|
||||
|
||||
// Angular provides the injector for your application
|
||||
var $injector = ...;
|
||||
|
||||
|
||||
///////////////////////////////////////////////
|
||||
// the old-school way of getting dependencies.
|
||||
var serviceA = $injector.get('serviceA');
|
||||
var serviceB = $injector.get('serviceB');
|
||||
|
||||
|
||||
// now call the function
|
||||
doSomething(serviceA, serviceB);
|
||||
|
||||
@@ -425,7 +425,7 @@ function arguments. When angular calls the function, it will use the {@link
|
||||
api/AUTO.$injector#invoke call} which will automatically fill the function
|
||||
arguments.
|
||||
|
||||
Examine the `ClockCtrl` bellow, and notice how it lists the dependencies in the constructor. When the
|
||||
Examine the `ClockCtrl` bellow, and notice how it list the dependencies in constructor. When the
|
||||
{@link api/ng.directive:ngController ng-controller} instantiates
|
||||
the controller it automatically provides the dependencies. There is no need to create
|
||||
dependencies, look for dependencies, or even get a reference to the injector.
|
||||
@@ -438,19 +438,19 @@ dependencies, look for dependencies, or even get a reference to the injector.
|
||||
</file>
|
||||
<file name="script.js">
|
||||
angular.module('timeExampleModule', []).
|
||||
// Declare new object called time,
|
||||
// Declare new object call time,
|
||||
// which will be available for injection
|
||||
factory('time', function($timeout) {
|
||||
var time = {};
|
||||
|
||||
|
||||
(function tick() {
|
||||
time.now = new Date().toString();
|
||||
$timeout(tick, 1000);
|
||||
})();
|
||||
return time;
|
||||
});
|
||||
|
||||
// Notice that you can simply ask for time
|
||||
|
||||
// Notice that you can simply ask for time
|
||||
// and it will be provided. No need to look for it.
|
||||
function ClockCtrl($scope, time) {
|
||||
$scope.time = time;
|
||||
|
||||
@@ -11,7 +11,7 @@ that will help you verify the health of your Angular application.
|
||||
|
||||
# Overview
|
||||
You will write scenario tests in JavaScript, which describe how your application should behave,
|
||||
given a certain interaction in a specific state. A scenario is comprised of one or more `it` blocks
|
||||
given a certain interaction in a specific state. A scenario is comprised of one or more it blocks
|
||||
(you can think of these as the requirements of your application), which in turn are made of
|
||||
**commands** and **expectations**. Commands tell the Runner to do something with the application
|
||||
(such as navigate to a page or click on a button), and expectations tell the Runner to assert
|
||||
@@ -122,7 +122,7 @@ Returns the current value of an input field with the given `name`.
|
||||
|
||||
## repeater(selector, label).count()
|
||||
Returns the number of rows in the repeater matching the given jQuery `selector`. The `label` is
|
||||
used for test output.
|
||||
used for test ouput.
|
||||
|
||||
## repeater(selector, label).row(index)
|
||||
Returns an array with the bindings in the row at the given `index` in the repeater matching the
|
||||
@@ -175,4 +175,4 @@ Executes the `method` passing in `key` and `value` on the element matching the g
|
||||
JavaScript is a dynamically typed language which comes with great power of expression, but it also
|
||||
come with almost no-help from the compiler. For this reason we feel very strongly that any code
|
||||
written in JavaScript needs to come with a strong set of tests. We have built many features into
|
||||
angular which makes testing your angular applications easy. So there is no excuse for not testing.
|
||||
angular which makes testing your angular applications easy. So there is no excuse for not do it.
|
||||
|
||||
@@ -3,11 +3,11 @@
|
||||
@description
|
||||
|
||||
While Model-View-Controller (MVC) has acquired different shades of meaning over the years since it
|
||||
first appeared, Angular incorporates the basic principles behind the original {@link
|
||||
first appeared, angular incorporates the basic principles behind the original {@link
|
||||
http://en.wikipedia.org/wiki/Model–view–controller MVC} software design pattern into its way of
|
||||
building client-side web applications.
|
||||
|
||||
The MVC pattern summarized:
|
||||
The MVC pattern greatly summarized:
|
||||
|
||||
* Separate applications into distinct presentation, data, and logic components
|
||||
* Encourage loose coupling between these components
|
||||
|
||||
@@ -2,10 +2,10 @@
|
||||
@name Developer Guide: About MVC in Angular: Understanding the Controller Component
|
||||
@description
|
||||
|
||||
In Angular, a controller is a JavaScript function(type/class) that is used to augment instances of
|
||||
angular {@link scope Scope}, excluding the root scope. When you or Angular create a new
|
||||
In angular, a controller is a JavaScript function(type/class) that is used to augment instances of
|
||||
angular {@link scope Scope}, excluding the root scope. When you or angular create a new
|
||||
child scope object via the {@link api/ng.$rootScope.Scope#$new scope.$new} API , there is an
|
||||
option to pass in a controller as a method argument. This will tell Angular to associate the
|
||||
option to pass in a controller as a method argument. This will tell angular to associate the
|
||||
controller with the new scope and to augment its behavior.
|
||||
|
||||
Use controllers to:
|
||||
@@ -15,10 +15,10 @@ Use controllers to:
|
||||
|
||||
# Setting up the initial state of a scope object
|
||||
|
||||
Typically, when you create an application you need to set up an initial state for an Angular scope.
|
||||
Typically, when you create an application you need to set up an initial state for an angular scope.
|
||||
|
||||
Angular applies (in the sense of JavaScript's `Function#apply`) the controller constructor function
|
||||
to a new Angular scope object, which sets up an initial scope state. This means that Angular never
|
||||
to a new angular scope object, which sets up an initial scope state. This means that angular never
|
||||
creates instances of the controller type (by invoking the `new` operator on the controller
|
||||
constructor). Constructors are always applied to an existing scope object.
|
||||
|
||||
@@ -30,23 +30,9 @@ function GreetingCtrl($scope) {
|
||||
|
||||
The `GreetingCtrl` controller creates a `greeting` model which can be referred to in a template.
|
||||
|
||||
**NOTE**: Many of the examples in the documentation show the creation of functions
|
||||
in the global scope. This is only for demonstration purposes - in a real
|
||||
application you should use the `.controller` method of your Angular module for
|
||||
your application as follows:
|
||||
|
||||
var myApp = angular.module('myApp',[]);
|
||||
|
||||
myApp.controller('GreetingCtrl', ['$scope', function(scope) {
|
||||
scope.greeting = 'Hola!';
|
||||
}]);
|
||||
|
||||
Note also that we use the array notation to explicitly specify the dependency
|
||||
of the controller on the `$scope` service provided by Angular.
|
||||
|
||||
# Adding Behavior to a Scope Object
|
||||
|
||||
Behavior on an Angular scope object is in the form of scope method properties available to the
|
||||
Behavior on an angular scope object is in the form of scope method properties available to the
|
||||
template/view. This behavior interacts with and modifies the application model.
|
||||
|
||||
As discussed in the {@link dev_guide.mvc.understanding_model Model} section of this guide, any
|
||||
@@ -69,14 +55,14 @@ Do not use controllers for:
|
||||
- Any kind of DOM manipulation — Controllers should contain only business logic. DOM
|
||||
manipulation—the presentation logic of an application—is well known for being hard to test.
|
||||
Putting any presentation logic into controllers significantly affects testability of the business
|
||||
logic. Angular offers {@link dev_guide.templates.databinding databinding} for automatic DOM manipulation. If
|
||||
logic. Angular offers {@link dev_guide.templates.databinding} for automatic DOM manipulation. If
|
||||
you have to perform your own manual DOM manipulation, encapsulate the presentation logic in
|
||||
{@link guide/directive directives}.
|
||||
- Input formatting — Use {@link forms angular form controls} instead.
|
||||
- Output filtering — Use {@link dev_guide.templates.filters angular filters} instead.
|
||||
- To run stateless or stateful code shared across controllers — Use {@link dev_guide.services angular
|
||||
- Run stateless or stateful code shared across controllers — Use {@link dev_guide.services angular
|
||||
services} instead.
|
||||
- To instantiate or manage the life-cycle of other components (for example, to create service
|
||||
- Instantiate or manage the life-cycle of other components (for example, to create service
|
||||
instances).
|
||||
|
||||
|
||||
@@ -171,7 +157,7 @@ input box) in the second button.
|
||||
|
||||
## Controller Inheritance Example
|
||||
|
||||
Controller inheritance in Angular is based on {@link api/ng.$rootScope.Scope Scope} inheritance. Let's
|
||||
Controller inheritance in angular is based on {@link api/ng.$rootScope.Scope Scope} inheritance. Let's
|
||||
have a look at an example:
|
||||
|
||||
<pre>
|
||||
@@ -211,7 +197,7 @@ Inheritance works between controllers in the same way as it does with models. So
|
||||
examples, all of the models could be replaced with controller methods that return string values.
|
||||
|
||||
Note: Standard prototypical inheritance between two controllers doesn't work as one might expect,
|
||||
because as we mentioned earlier, controllers are not instantiated directly by Angular, but rather
|
||||
because as we mentioned earlier, controllers are not instantiated directly by angular, but rather
|
||||
are applied to the scope object.
|
||||
|
||||
|
||||
@@ -255,8 +241,8 @@ describe('myController function', function() {
|
||||
</pre>
|
||||
|
||||
|
||||
If you need to test a nested controller you need to create the same scope hierarchy
|
||||
in your test that exists in the DOM.
|
||||
If you need to test a nested controller one needs to create the same scope hierarchy
|
||||
in your test as exist in the DOM.
|
||||
|
||||
<pre>
|
||||
describe('state', function() {
|
||||
|
||||
@@ -2,16 +2,16 @@
|
||||
@name Developer Guide: About MVC in Angular: Understanding the Model Component
|
||||
@description
|
||||
|
||||
Depending on the context of the discussion in the Angular documentation, the term _model_ can refer to
|
||||
Depending on the context of the discussion in angular documentation, the term _model_ can refer to
|
||||
either a single object representing one entity (for example, a model called "phones" with its value
|
||||
being an array of phones) or the entire data model for the application (all entities).
|
||||
|
||||
In Angular, a model is any data that is reachable as a property of an angular {@link
|
||||
In angular, a model is any data that is reachable as a property of an angular {@link
|
||||
scope Scope} object. The name of the property is the model identifier and the value is
|
||||
any JavaScript object (including arrays and primitives).
|
||||
|
||||
The only requirement for a JavaScript object to be a model in Angular is that the object must be
|
||||
referenced by an Angular scope as a property of that scope object. This property reference can be
|
||||
The only requirement for a JavaScript object to be a model in angular is that the object must be
|
||||
referenced by an angular scope as a property of that scope object. This property reference can be
|
||||
created explicitly or implicitly.
|
||||
|
||||
You can create models by explicitly creating scope properties referencing JavaScript objects in the
|
||||
@@ -52,11 +52,11 @@ cloud".
|
||||
The code above creates one child scope for each item in the "phones" array and creates a "phone"
|
||||
object (model) on each of these scopes with its value set to the value of "phone" in the array.
|
||||
|
||||
In Angular, a JavaScript object stops being a model when:
|
||||
In angular, a JavaScript object stops being a model when:
|
||||
|
||||
* No Angular scope contains a property that references the object.
|
||||
* No angular scope contains a property that references the object.
|
||||
|
||||
* All Angular scopes that contain a property referencing the object become stale and eligible for
|
||||
* All angular scopes that contain a property referencing the object become stale and eligible for
|
||||
garbage collection.
|
||||
|
||||
The following illustration shows a simple data model created implicitly from a simple template:
|
||||
|
||||
@@ -2,14 +2,14 @@
|
||||
@name Developer Guide: About MVC in Angular: Understanding the View Component
|
||||
@description
|
||||
|
||||
In Angular, the view is the DOM loaded and rendered in the browser, after Angular has transformed
|
||||
In angular, the view is the DOM loaded and rendered in the browser, after angular has transformed
|
||||
the DOM based on information in the template, controller and model.
|
||||
|
||||
<img src="img/guide/about_view_final.png">
|
||||
|
||||
In the Angular implementation of MVC, the view has knowledge of both the model and the controller.
|
||||
In the angular implementation of MVC, the view has knowledge of both the model and the controller.
|
||||
The view knows about the model where two-way data-binding occurs. The view has knowledge of the
|
||||
controller through Angular directives, such as {@link api/ng.directive:ngController
|
||||
controller through angular directives, such as {@link api/ng.directive:ngController
|
||||
ngController} and {@link api/ng.directive:ngView ngView}, and through bindings of this form:
|
||||
`{{someControllerFunction()}}`. In these ways, the view can call functions in an associated
|
||||
controller function.
|
||||
|
||||
@@ -23,13 +23,13 @@ changes to $location are reflected into the browser address bar.
|
||||
|
||||
## Comparing $location to window.location
|
||||
|
||||
<table class="table">
|
||||
<table>
|
||||
<thead>
|
||||
|
||||
<tr>
|
||||
<th class="empty-corner-lt"></th>
|
||||
<th>window.location</th>
|
||||
<th>$location service</th>
|
||||
<td class="empty-corner-lt"></td>
|
||||
<td>window.location</td>
|
||||
<td>$location service</td>
|
||||
</tr>
|
||||
|
||||
</thead>
|
||||
@@ -73,9 +73,10 @@ Any time your application needs to react to a change in the current URL or if yo
|
||||
the current URL in the browser.
|
||||
|
||||
## What does it not do?
|
||||
It does not cause a full page reload when the browser URL is changed. To reload the page after
|
||||
Does not cause a full page reload when the browser URL is changed. To reload the page after
|
||||
changing the URL, use the lower-level API, `$window.location.href`.
|
||||
|
||||
|
||||
# General overview of the API
|
||||
|
||||
The `$location` service can behave differently, depending on the configuration that was provided to
|
||||
@@ -132,12 +133,12 @@ current URL without creating a new browser history record you can call:
|
||||
// or you can chain these as: $location.path('/someNewPath').replace();
|
||||
</pre>
|
||||
|
||||
Note that the setters don't update `window.location` immediately. Instead, the `$location` service is
|
||||
Note that the setters don't update `window.location` immediately. Instead, `$location` service is
|
||||
aware of the {@link api/ng.$rootScope.Scope scope} life-cycle and coalesces multiple `$location`
|
||||
mutations into one "commit" to the `window.location` object during the scope `$digest` phase. Since
|
||||
multiple changes to the $location's state will be pushed to the browser as a single change, it's
|
||||
enough to call the `replace()` method just once to make the entire "commit" a replace operation
|
||||
rather than an addition to the browser history. Once the browser is updated, the $location service
|
||||
rather than addition to the browser history. Once the browser is updated, the $location service
|
||||
resets the flag set by `replace()` method and future mutations will create new history records,
|
||||
unless `replace()` is called again.
|
||||
|
||||
@@ -164,13 +165,13 @@ facilitate the browser URL change and history management.
|
||||
|
||||
<img src="img/guide/hashbang_vs_regular_url.jpg">
|
||||
|
||||
<table class="table">
|
||||
<table>
|
||||
<thead>
|
||||
|
||||
<tr>
|
||||
<th class="empty-corner-lt"></th>
|
||||
<th>Hashbang mode</th>
|
||||
<th>HTML5 mode</th>
|
||||
<td class="empty-corner-lt"></td>
|
||||
<td>Hashbang mode</td>
|
||||
<td>HTML5 mode</td>
|
||||
</tr>
|
||||
|
||||
</thead>
|
||||
@@ -211,7 +212,7 @@ In this mode, `$location` uses Hashbang URLs in all browsers.
|
||||
<pre>
|
||||
it('should show example', inject(
|
||||
function($locationProvider) {
|
||||
$locationProvider.html5Mode(false);
|
||||
$locationProvider.html5mode = false;
|
||||
$locationProvider.hashPrefix = '!';
|
||||
},
|
||||
function($location) {
|
||||
@@ -260,7 +261,7 @@ having to worry about whether the browser displaying your app supports the histo
|
||||
<pre>
|
||||
it('should show example', inject(
|
||||
function($locationProvider) {
|
||||
$locationProvider.html5Mode(true);
|
||||
$locationProvider.html5mode = true;
|
||||
$locationProvider.hashPrefix = '!';
|
||||
},
|
||||
function($location) {
|
||||
@@ -303,7 +304,7 @@ history API or not; the `$location` service makes this transparent to you.
|
||||
|
||||
### Html link rewriting
|
||||
|
||||
When you use HTML5 history API mode, you will need different links in different browsers, but all you
|
||||
When you use the history API mode, you will need different links in different browser, but all you
|
||||
have to do is specify regular URL links, such as: `<a href="/some?foo=bar">link</a>`
|
||||
|
||||
When a user clicks on this link,
|
||||
@@ -542,73 +543,69 @@ then uses the information it obtains to compose hashbang URLs (such as
|
||||
|
||||
## Changes to your code
|
||||
|
||||
<table class="table">
|
||||
<thead>
|
||||
<tr class="head">
|
||||
<th>Navigation inside the app</th>
|
||||
<th>Change to</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<table>
|
||||
<tr class="head">
|
||||
<td>Navigation inside the app</td>
|
||||
<td>Change to</td>
|
||||
</tr>
|
||||
|
||||
<tbody>
|
||||
<tr>
|
||||
<td>$location.href = value<br />$location.hash = value<br />$location.update(value)<br
|
||||
<tr>
|
||||
<td>$location.href = value<br />$location.hash = value<br />$location.update(value)<br
|
||||
/>$location.updateHash(value)</td>
|
||||
<td>$location.path(path).search(search)</td>
|
||||
</tr>
|
||||
<td>$location.path(path).search(search)</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>$location.hashPath = path</td>
|
||||
<td>$location.path(path)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>$location.hashPath = path</td>
|
||||
<td>$location.path(path)</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>$location.hashSearch = search</td>
|
||||
<td>$location.search(search)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>$location.hashSearch = search</td>
|
||||
<td>$location.search(search)</td>
|
||||
</tr>
|
||||
|
||||
<tr class="head">
|
||||
<td>Navigation outside the app</td>
|
||||
<td>Use lower level API</td>
|
||||
</tr>
|
||||
<tr class="head">
|
||||
<td>Navigation outside the app</td>
|
||||
<td>Use lower level API</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>$location.href = value<br />$location.update(value)</td>
|
||||
<td>$window.location.href = value</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>$location.href = value<br />$location.update(value)</td>
|
||||
<td>$window.location.href = value</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>$location[protocol | host | port | path | search]</td>
|
||||
<td>$window.location[protocol | host | port | path | search]</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>$location[protocol | host | port | path | search]</td>
|
||||
<td>$window.location[protocol | host | port | path | search]</td>
|
||||
</tr>
|
||||
|
||||
<tr class="head">
|
||||
<td>Read access</td>
|
||||
<td>Change to</td>
|
||||
</tr>
|
||||
<tr class="head">
|
||||
<td>Read access</td>
|
||||
<td>Change to</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>$location.hashPath</td>
|
||||
<td>$location.path()</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>$location.hashPath</td>
|
||||
<td>$location.path()</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>$location.hashSearch</td>
|
||||
<td>$location.search()</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td>$location.hashSearch</td>
|
||||
<td>$location.search()</td>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>$location.href<br />$location.protocol<br />$location.host<br />$location.port<br
|
||||
<tr>
|
||||
<td>$location.href<br />$location.protocol<br />$location.host<br />$location.port<br
|
||||
/>$location.hash</td>
|
||||
<td>$location.absUrl()<br />$location.protocol()<br />$location.host()<br />$location.port()<br
|
||||
<td>$location.absUrl()<br />$location.protocol()<br />$location.host()<br />$location.port()<br
|
||||
/>$location.path() + $location.search()</td>
|
||||
</tr>
|
||||
</tr>
|
||||
|
||||
<tr>
|
||||
<td>$location.path<br />$location.search</td>
|
||||
<td>$window.location.path<br />$window.location.search</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
<tr>
|
||||
<td>$location.path<br />$location.search</td>
|
||||
<td>$window.location.path<br />$window.location.search</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
## Two-way binding to $location
|
||||
|
||||
@@ -48,9 +48,9 @@ create this instance when called.
|
||||
|
||||
# Dependencies
|
||||
|
||||
Services can not only be depended upon, but can also have their own dependencies. These can be specified
|
||||
as arguments of the factory function. {@link di Read more} about dependency injection (DI)
|
||||
in Angular and the use of array notation and the $inject property to make DI annotation
|
||||
Services can not only be depended upon, but also have its own dependencies. These can be specified
|
||||
as arguments of the factory function. {@link di Read more} about the DI
|
||||
in Angular and the use of array notation and $inject property to make DI annotation
|
||||
minification-proof.
|
||||
|
||||
Following is an example of a very simple service. This service depends on the `$window` service
|
||||
@@ -78,7 +78,7 @@ angular.module('myModule', [], function($provide) {
|
||||
|
||||
All services in Angular are instantiated lazily. This means that a service will be created
|
||||
only when it is needed for instantiation of a service or an application component that depends on it.
|
||||
In other words, Angular won't instantiate services unless they are requested directly or
|
||||
In other words, Angular won't instantiate lazy services unless they are requested directly or
|
||||
indirectly by the application.
|
||||
|
||||
|
||||
|
||||
@@ -39,8 +39,8 @@ function myModuleCfgFn($provide) {
|
||||
</pre>
|
||||
|
||||
|
||||
Here is an example of two services, one of which depends on the other and both
|
||||
of which depend on other services that are provided by the Angular framework:
|
||||
Here is an example of two services that depend on each other, as well as on other services that are
|
||||
provided by Angular's web framework:
|
||||
|
||||
<pre>
|
||||
/**
|
||||
|
||||
@@ -2,9 +2,10 @@
|
||||
@name Developer Guide: Angular Services
|
||||
@description
|
||||
|
||||
Services are a feature that Angular brings to client-side web apps from the server side, where
|
||||
services have been commonly used for a long time. Services in Angular apps are substitutable
|
||||
objects that are wired together using {@link di dependency injection (DI)}.
|
||||
Services are a feature that angular brings to client-side web apps from the server side, where
|
||||
services have been commonly used for a long time. Services in angular apps are substitutable
|
||||
objects that are wired together using {@link di dependency injection (DI)}. Services are
|
||||
most often used with {@link di dependency injection}, also a key feature of angular apps.
|
||||
|
||||
|
||||
## Related Topics
|
||||
|
||||
@@ -6,9 +6,9 @@ Angular services are singletons that carry out specific tasks common to web apps
|
||||
{@link api/ng.$http $http service} that provides low level access to the browser's
|
||||
`XMLHttpRequest` object.
|
||||
|
||||
To use an Angular service, you identify it as a dependency for the dependent (a controller, or
|
||||
To use an angular service, you identify it as a dependency for the dependent (a controller, or
|
||||
another service) that depends on the service. Angular's dependency injection subsystem takes care
|
||||
of the rest. The Angular injector subsystem is in charge of service instantiation, resolution of
|
||||
of the rest. The angular injector subsystem is in charge of service instantiation, resolution of
|
||||
dependencies, and provision of dependencies to factory functions as requested.
|
||||
|
||||
Angular injects dependencies using "constructor" injection (the service is passed in via a factory
|
||||
@@ -18,7 +18,7 @@ must explicitly define its dependencies by using the `$inject` property. For ex
|
||||
|
||||
myController.$inject = ['$location'];
|
||||
|
||||
The Angular web framework provides a set of services for common operations. Like other core Angular
|
||||
The angular web framework provides a set of services for common operations. Like other core angular
|
||||
variables and identifiers, the built-in services always start with `$` (such as `$http` mentioned
|
||||
above). You can also create your own custom services.
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
@name Developer Guide: Templates: Data Binding in Angular
|
||||
@description
|
||||
|
||||
Data-binding in Angular web apps is the automatic syncronization of data between the model and view
|
||||
components. The way that Angular implements data-binding lets you treat the model as the
|
||||
Data-binding in angular web apps is the automatic syncing of data between the model and view
|
||||
components. The way that angular implements data-binding lets you treat the model as the
|
||||
single-source-of-truth in your application. The view is a projection of the model at all times.
|
||||
When the model changes, the view reflects the change, and vice versa.
|
||||
|
||||
@@ -19,7 +19,7 @@ to write code that constantly syncs the view with the model and the model with t
|
||||
## Data Binding in Angular Templates
|
||||
|
||||
<img class="right" src="img/Two_Way_Data_Binding.png"/>
|
||||
The way Angular templates works is different, as illustrated in the diagram. They are different
|
||||
The way angular templates works is different, as illustrated in the diagram. They are different
|
||||
because first the template (which is the uncompiled HTML along with any additional markup or
|
||||
directives) is compiled on the browser, and second, the compilation step produces a live view. We
|
||||
say live because any changes to the view are immediately reflected in the model, and any changes in
|
||||
|
||||
@@ -2,13 +2,13 @@
|
||||
@name Developer Guide: Understanding Angular Templates
|
||||
@description
|
||||
|
||||
An Angular template is the declarative specification that, along with information from the model
|
||||
An angular template is the declarative specification that, along with information from the model
|
||||
and controller, becomes the rendered view that a user sees in the browser. It is the static DOM,
|
||||
containing HTML, CSS, and angular-specific elements and angular-specific element attributes. The
|
||||
Angular elements and attributes direct angular to add behavior and transform the template DOM into
|
||||
angular elements and attributes direct angular to add behavior and transform the template DOM into
|
||||
the dynamic view DOM.
|
||||
|
||||
These are the types of Angular elements and element attributes you can use in a template:
|
||||
These are the types of angular elements and element attributes you can use in a template:
|
||||
|
||||
* {@link guide/directive Directive} — An attribute or element that
|
||||
augments an existing DOM element or represents a reusable DOM component - a widget.
|
||||
@@ -20,8 +20,8 @@ curly brace notation `{{ }}` to bind expressions to elements is built-in angular
|
||||
Note: In addition to declaring the elements above in templates, you can also access these elements
|
||||
in JavaScript code.
|
||||
|
||||
The following code snippet shows a simple Angular template made up of standard HTML tags along with
|
||||
Angular {@link guide/directive directives} and curly-brace bindings
|
||||
The following code snippet shows a simple angular template made up of standard HTML tags along with
|
||||
angular {@link guide/directive directives} and curly-brace bindings
|
||||
with {@link expression expressions}:
|
||||
|
||||
<pre>
|
||||
|
||||
@@ -5,47 +5,35 @@
|
||||
JavaScript is a dynamically typed language which comes with great power of expression, but it also
|
||||
come with almost no-help from the compiler. For this reason we feel very strongly that any code
|
||||
written in JavaScript needs to come with a strong set of tests. We have built many features into
|
||||
Angular which makes testing your Angular applications easy. So there is no excuse for not testing.
|
||||
|
||||
angular which makes testing your angular applications easy. So there is no excuse for not do it.
|
||||
# It is all about NOT mixing concerns
|
||||
|
||||
Unit testing as the name implies is about testing individual units of code. Unit tests try to
|
||||
answer questions such as "Did I think about the logic correctly?" or "Does the sort function order the list
|
||||
in the right order?"
|
||||
|
||||
In order to answer such question it is very important that we can isolate the unit of code under test.
|
||||
That is because when we are testing the sort function we don't want to be forced into creating
|
||||
related pieces such as the DOM elements, or making any XHR calls in getting the data to sort.
|
||||
|
||||
While
|
||||
answer the question: Did I think about the logic correctly. Does the sort function order the list
|
||||
in the right order. In order to answer such question it is very important that we can isolate it.
|
||||
That is because when we are testing the sort function we don't want to be forced into crating
|
||||
related pieces such as the DOM elements, or making any XHR calls in getting the data to sort. While
|
||||
this may seem obvious it usually is very difficult to be able to call an individual function on a
|
||||
typical project. The reason is that the developers often mix concerns, and they end up with a
|
||||
typical project. The reason is that the developers often time mix concerns, and they end up with a
|
||||
piece of code which does everything. It reads the data from XHR, it sorts it and then it
|
||||
manipulates the DOM.
|
||||
|
||||
With Angular we try to make it easy for you to do the right thing, and so we
|
||||
manipulates the DOM. With angular we try to make it easy for you to do the right thing, and so we
|
||||
provide dependency injection for your XHR (which you can mock out) and we created abstraction which
|
||||
allow you to sort your model without having to resort to manipulating the DOM. So that in the end,
|
||||
it is easy to write a sort function which sorts some data, so that your test can create a data set,
|
||||
apply the function, and assert that the resulting model is in the correct order. The test does not
|
||||
have to wait for XHR, or create the right kind of DOM, or assert that your function has mutated the
|
||||
DOM in the right way.
|
||||
DOM in the right way. Angular is written with testability in mind, but it still requires that you
|
||||
do the right thing. We tried to make the right thing easy, but angular is not magic, which means if
|
||||
you don't follow these, you may very well end up with an untestable application.
|
||||
|
||||
## With great power comes great responsibility
|
||||
|
||||
Angular is written with testability in mind, but it still requires that you
|
||||
do the right thing. We tried to make the right thing easy, but Angular is not magic, which means if
|
||||
you don't follow these guidelines you may very well end up with an untestable application.
|
||||
|
||||
## Dependency Injection
|
||||
## Dependency Inject
|
||||
There are several ways in which you can get a hold of a dependency:
|
||||
1. You could create it using the `new` operator.
|
||||
2. You could look for it in a well known place, also known as global singleton.
|
||||
2. You could look for it in a well know place, also known as global singleton.
|
||||
3. You could ask a registry (also known as service registry) for it. (But how do you get a hold of
|
||||
the registry? Most likely by looking it up in a well known place. See #2)
|
||||
4. You could expect that it be handed to you.
|
||||
the registry? Must likely by looking it up in a well know place. See #2)
|
||||
4. You could expect that the it be handed to you.
|
||||
|
||||
Out of the four options in the list above, only the last one is testable. Let's look at why:
|
||||
Out of the list above only the last of is testable. Lets look at why:
|
||||
|
||||
### Using the `new` operator
|
||||
|
||||
@@ -64,10 +52,10 @@ function MyClass() {
|
||||
}
|
||||
</pre>
|
||||
|
||||
The issue becomes that in tests, we would very much like to instantiate a `MockXHR` which would
|
||||
The issue becomes, that in tests, we would very much like to instantiate a `MockXHR` which would
|
||||
allow us to return fake data and simulate network failures. By calling `new XHR()` we are
|
||||
permanently bound to the actual XHR, and there is no good way to replace it. Yes there is monkey
|
||||
patching. That is a bad idea for many reasons which are outside the scope of this document.
|
||||
permanently bound to the actual one, and there is no good way to replace it. Yes there is monkey
|
||||
patching, that is a bad idea for many reasons, which is outside the scope of this document.
|
||||
|
||||
The class above is hard to test since we have to resort to monkey patching:
|
||||
<pre>
|
||||
@@ -81,7 +69,7 @@ XHR = oldXHR; // if you forget this bad things will happen
|
||||
|
||||
|
||||
### Global look-up:
|
||||
Another way to approach the problem is to look for the service in a well known location.
|
||||
Another way to approach the problem is look for the service in a well known location.
|
||||
|
||||
<pre>
|
||||
function MyClass() {
|
||||
@@ -95,7 +83,7 @@ function MyClass() {
|
||||
}
|
||||
</pre>
|
||||
|
||||
While no new instance of the dependency is being created, it is fundamentally the same as `new`, in
|
||||
While no new instance of dependency is being created, it is fundamentally the same as `new`, in
|
||||
that there is no good way to intercept the call to `global.xhr` for testing purposes, other then
|
||||
through monkey patching. The basic issue for testing is that global variable needs to be mutated in
|
||||
order to replace it with call to a mock method. For further explanation why this is bad see: {@link
|
||||
@@ -131,7 +119,7 @@ function MyClass() {
|
||||
}
|
||||
</pre>
|
||||
|
||||
However, where does the serviceRegistry come from? if it is:
|
||||
However, where dose the serviceRegistry come from? if it is:
|
||||
* `new`-ed up, the the test has no chance to reset the services for testing
|
||||
* global look-up, then the service returned is global as well (but resetting is easier, since
|
||||
there is only one global variable to be reset).
|
||||
@@ -176,7 +164,7 @@ myClass.doWork();
|
||||
|
||||
Notice that no global variables were harmed in the writing of this test.
|
||||
|
||||
Angular comes with {@link di dependency injection} built in which makes the right thing
|
||||
Angular comes with {@link di dependency-injection} built in which makes the right thing
|
||||
easy to do, but you still need to do it if you wish to take advantage of the testability story.
|
||||
|
||||
## Controllers
|
||||
@@ -185,7 +173,7 @@ for your application is mixed in with DOM manipulation, it will be hard to test
|
||||
below:
|
||||
|
||||
<pre>
|
||||
function PasswordCtrl() {
|
||||
function PasswordController() {
|
||||
// get references to DOM elements
|
||||
var msg = $('.ex1 span');
|
||||
var input = $('.ex1 input');
|
||||
@@ -209,7 +197,7 @@ function PasswordCtrl() {
|
||||
}
|
||||
</pre>
|
||||
|
||||
The code above is problematic from a testability point of view, since it requires your test to have the right kind
|
||||
The code above is problematic from testability, since it requires your test to have the right kind
|
||||
of DOM present when the code executes. The test would look like this:
|
||||
|
||||
<pre>
|
||||
@@ -219,7 +207,7 @@ $('body').html('<div class="ex1">')
|
||||
.find('div')
|
||||
.append(input)
|
||||
.append(span);
|
||||
var pc = new PasswordCtrl();
|
||||
var pc = new PasswordController();
|
||||
input.val('abc');
|
||||
pc.grade();
|
||||
expect(span.text()).toEqual('weak');
|
||||
@@ -230,7 +218,7 @@ In angular the controllers are strictly separated from the DOM manipulation logi
|
||||
a much easier testability story as can be seen in this example:
|
||||
|
||||
<pre>
|
||||
function PasswordCtrl($scope) {
|
||||
function PasswordCntrl($scope) {
|
||||
$scope.password = '';
|
||||
$scope.grade = function() {
|
||||
var size = $scope.password.length;
|
||||
@@ -245,18 +233,19 @@ function PasswordCtrl($scope) {
|
||||
}
|
||||
</pre>
|
||||
|
||||
and the test is straight forward
|
||||
and the tests is straight forward
|
||||
|
||||
<pre>
|
||||
var pc = new PasswordCtrl();
|
||||
var pc = new PasswordController();
|
||||
pc.password('abc');
|
||||
pc.grade();
|
||||
expect(pc.strength).toEqual('weak');
|
||||
expect(span.strength).toEqual('weak');
|
||||
</pre>
|
||||
|
||||
Notice that the test is not only much shorter but it is easier to follow what is going on. We say
|
||||
that such a test tells a story, rather then asserting random bits which don't seem to be related.
|
||||
|
||||
|
||||
## Filters
|
||||
{@link api/ng.$filter Filters} are functions which transform the data into user readable
|
||||
format. They are important because they remove the formatting responsibility from the application
|
||||
@@ -277,20 +266,16 @@ expect(length('abc')).toEqual(3);
|
||||
## Directives
|
||||
Directives in angular are responsible for updating the DOM when the state of the model changes.
|
||||
|
||||
|
||||
## Mocks
|
||||
oue
|
||||
|
||||
## Global State Isolation
|
||||
oue
|
||||
|
||||
# Preferred way of Testing
|
||||
uo
|
||||
|
||||
## JavaScriptTestDriver
|
||||
ou
|
||||
|
||||
## Jasmine
|
||||
ou
|
||||
|
||||
## Sample project
|
||||
uoe
|
||||
|
||||
+16
-14
@@ -47,7 +47,7 @@ is simply handed the `greeter` at runtime.
|
||||
This is desirable, but it puts the responsibility of getting hold of the dependency onto the
|
||||
code responsible for the construction of `SomeClass`.
|
||||
|
||||
To manage the responsibility of dependency creation, each Angular application has an {@link
|
||||
To manage the responsibility of dependency creation, each angular application has an {@link
|
||||
api/angular.injector injector}. The injector is a service locator that is responsible for
|
||||
construction and lookup of dependencies.
|
||||
|
||||
@@ -67,11 +67,11 @@ Here is an example of using the injector service.
|
||||
$window.alert(text);
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
}).
|
||||
|
||||
// New injector is created from the module.
|
||||
// (This is usually done automatically by angular bootstrap)
|
||||
var injector = angular.injector(['myModule', 'ng']);
|
||||
var injector = angular.injector('myModule');
|
||||
|
||||
// Request any dependency from the injector
|
||||
var greeter = injector.get('greeter');
|
||||
@@ -92,7 +92,7 @@ dependency lookup responsibility to the injector by declaring the dependencies a
|
||||
// And this controller definition
|
||||
function MyController($scope, greeter) {
|
||||
$scope.sayHello = function() {
|
||||
greeter.greet('Hello World');
|
||||
greeter('Hello World');
|
||||
};
|
||||
}
|
||||
|
||||
@@ -109,7 +109,7 @@ deal with the injector. This setup does not break the Law of Demeter.
|
||||
|
||||
How does the injector know what service needs to be injected?
|
||||
|
||||
The application developer needs to provide annotation information that the injector uses in order
|
||||
The application developer needs to provide annotation information, that the injector uses in order
|
||||
to resolve the dependencies. Throughout Angular certain API functions are invoked using the
|
||||
injector, as per the API documentation. The injector needs to know what services to inject into
|
||||
the function. Below are three equivalent ways of annotating your code with service name
|
||||
@@ -186,30 +186,32 @@ For this reason the third annotation style is provided as well.
|
||||
Keep in mind that all of the annotation styles are equivalent and can be used anywhere in Angular
|
||||
where injection is supported.
|
||||
|
||||
|
||||
# Where can I use DI?
|
||||
|
||||
DI is pervasive throughout Angular. It is typically used in controllers and factory methods.
|
||||
|
||||
## DI in controllers
|
||||
|
||||
Controllers are classes which are responsible for application behavior. The recommended way of
|
||||
Controllers are classes which are responsible for application behavior. Recommended way of
|
||||
declaring controllers is:
|
||||
|
||||
<pre>
|
||||
var MyController = function($scope, dep1, dep2) {
|
||||
var MyController = function(dep1, dep2) {
|
||||
...
|
||||
}
|
||||
MyController.$inject = ['dep1', 'dep2'];
|
||||
|
||||
MyController.prototype.aMethod = function() {
|
||||
...
|
||||
$scope.aMethod = function() {
|
||||
...
|
||||
}
|
||||
}
|
||||
MyController.$inject = ['$scope', 'dep1', 'dep2'];
|
||||
</pre>
|
||||
|
||||
|
||||
## Factory methods
|
||||
|
||||
Factory methods are responsible for creating most objects in Angular. Examples are directives,
|
||||
services, and filters. The factory methods are registered with the module, and the recommended way
|
||||
services, and filters. The factory methods are register with the module, and the recommended way
|
||||
of declaring factories is:
|
||||
|
||||
<pre>
|
||||
@@ -229,4 +231,4 @@ of declaring factories is:
|
||||
run(['depService', function(depService) {
|
||||
...
|
||||
}]);
|
||||
</pre>
|
||||
</pre>
|
||||
@@ -63,7 +63,7 @@ api/ng.$rootScope.Scope#$digest digest} cycle. An example of interpolation is sh
|
||||
here:
|
||||
|
||||
<pre>
|
||||
<a href="img/{{username}}.jpg">Hello {{username}}!</a>
|
||||
<img src="img/{{username}}.jpg">Hello {{username}}!</img>
|
||||
</pre>
|
||||
|
||||
# Compilation process, and directive matching
|
||||
@@ -110,7 +110,7 @@ Compilation of HTML happens in three phases:
|
||||
## Reasons behind the compile/link separation
|
||||
|
||||
At this point you may wonder why the compile process is broken down to a compile and link phase.
|
||||
To understand this, let's look at a real world example with a repeater:
|
||||
To understand this, let's look at a real world example with repeater:
|
||||
|
||||
<pre>
|
||||
Hello {{user}}, you have these actions:
|
||||
@@ -144,9 +144,9 @@ links a specific instance of the {@link api/ng.$rootScope.Scope scope} and the s
|
||||
instance of an `li` is performed.
|
||||
|
||||
{@link api/ng.directive:ngRepeat ngRepeat} works by preventing the
|
||||
compilation process from descending into the `li` element. Instead the {@link
|
||||
compilation process form descending into the `li` element. Instead the {@link
|
||||
api/ng.directive:ngRepeat ngRepeat} directive compiles `li`
|
||||
separately. The result of the `li` element compilation is a linking function which contains all
|
||||
separately. The result of of the `li` element compilation is a linking function which contains all
|
||||
of the directives contained in the `li` element, ready to be attached to a specific clone of the `li`
|
||||
element. At runtime the {@link api/ng.directive:ngRepeat ngRepeat}
|
||||
watches the expression and as items are added to the array it clones the `li` element, creates a
|
||||
@@ -253,7 +253,7 @@ An example skeleton of the directive is shown here, for the complete list see be
|
||||
|
||||
In most cases you will not need such fine control and so the above can be simplified. All of the
|
||||
different parts of this skeleton are explained in following sections. In this section we are
|
||||
interested only in some of this skeleton.
|
||||
interested only isomers of this skeleton.
|
||||
|
||||
The first step in simplyfing the code is to rely on the default values. Therefore the above can be
|
||||
simplified as:
|
||||
@@ -296,7 +296,7 @@ makes it injectable following all of the rules of injection annotation.
|
||||
The directive definition object provides instructions to the {@link api/ng.$compile
|
||||
compiler}. The attributes are:
|
||||
|
||||
* `name` - Name of the current scope. Optional and defaults to the name at registration.
|
||||
* `name` - Name of the current scope. Optional defaults to the name at registration.
|
||||
|
||||
* `priority` - When there are multiple directives defined on a single DOM element, sometimes it
|
||||
is necessary to specify the order in which the directives are applied. The `priority` is used
|
||||
@@ -310,7 +310,7 @@ compiler}. The attributes are:
|
||||
* `scope` - If set to:
|
||||
|
||||
* `true` - then a new scope will be created for this directive. If multiple directives on the
|
||||
same element request a new scope, only one new scope is created. The new scope rule does not
|
||||
same element request new scope, only one new scope is created. The new scope rule does not
|
||||
apply for the root of the template since the root of the template always gets a new scope.
|
||||
|
||||
* `{}` (object hash) - then a new 'isolate' scope is created. The 'isolate' scope differs from
|
||||
@@ -321,37 +321,35 @@ compiler}. The attributes are:
|
||||
derived from the parent scope. These local properties are useful for aliasing values for
|
||||
templates. Locals definition is a hash of local scope property to its source:
|
||||
|
||||
* `@` or `@attr` - bind a local scope property to the value of DOM attribute. The result is
|
||||
always a string since DOM attributes are strings. If no `attr` name is specified then the
|
||||
attribute name is assumed to be the same as the local name.
|
||||
Given `<widget my-attr="hello {{name}}">` and widget definition
|
||||
* `@` or `@attr` - bind a local scope property to the DOM attribute. The result is always a
|
||||
string since DOM attributes are strings. If no `attr` name is specified then the local name
|
||||
and attribute name are same. Given `<widget my-attr="hello {{name}}">` and widget definition
|
||||
of `scope: { localName:'@myAttr' }`, then widget scope property `localName` will reflect
|
||||
the interpolated value of `hello {{name}}`. As the `name` attribute changes so will the
|
||||
`localName` property on the widget scope. The `name` is read from the parent scope (not
|
||||
component scope).
|
||||
|
||||
* `=` or `=attr` - set up bi-directional binding between a local scope property and the
|
||||
parent scope property of name defined via the value of the `attr` attribute. If no `attr`
|
||||
name is specified then the attribute name is assumed to be the same as the local name.
|
||||
Given `<widget my-attr="parentModel">` and widget definition of
|
||||
`scope: { localModel:'=myAttr' }`, then widget scope property `localModel` will reflect the
|
||||
* `=` or `=expression` - set up bi-directional binding between a local scope property and the
|
||||
parent scope property. If no `attr` name is specified then the local name and attribute
|
||||
name are same. Given `<widget my-attr="parentModel">` and widget definition of
|
||||
`scope: { localModel:'=myAttr' }`, then widget scope property `localName` will reflect the
|
||||
value of `parentModel` on the parent scope. Any changes to `parentModel` will be reflected
|
||||
in `localModel` and any changes in `localModel` will reflect in `parentModel`.
|
||||
|
||||
* `&` or `&attr` - provides a way to execute an expression in the context of the parent scope.
|
||||
If no `attr` name is specified then the attribute name is assumed to be the same as the
|
||||
local name. Given `<widget my-attr="count = count + value">` and widget definition of
|
||||
`scope: { localFn:'&myAttr' }`, then isolate scope property `localFn` will point to
|
||||
a function wrapper for the `count = count + value` expression. Often it's desirable to
|
||||
pass data from the isolated scope via an expression and to the parent scope, this can be
|
||||
done by passing a map of local variable names and values into the expression wrapper fn.
|
||||
For example, if the expression is `increment(amount)` then we can specify the amount value
|
||||
by calling the `localFn` as `localFn({amount: 22})`.
|
||||
If no `attr` name is specified then the local name and attribute name are same.
|
||||
Given `<widget my-attr="count = count + value">` and widget definition of
|
||||
`scope: { localFn:'increment()' }`, then isolate scope property `localFn` will point to
|
||||
a function wrapper for the `increment()` expression. Often it's desirable to pass data from
|
||||
the isolate scope via an expression and to the parent scope, this can be done by passing a
|
||||
map of local variable names and values into the expression wrapper fn. For example, if the
|
||||
expression is `increment(amount)` then we can specify the amount value by calling the
|
||||
`localFn` as `localFn({amount: 22})`.
|
||||
|
||||
* `controller` - Controller constructor function. The controller is instantiated before the
|
||||
pre-linking phase and it is shared with other directives if they request it by name (see
|
||||
`require` attribute). This allows the directives to communicate with each other and augment
|
||||
each other's behavior. The controller is injectable with the following locals:
|
||||
each other behavior. The controller is injectable with the following locals:
|
||||
|
||||
* `$scope` - Current scope associated with the element
|
||||
* `$element` - Current element
|
||||
@@ -474,7 +472,7 @@ compiler linking function will fail to locate the correct elements for linking.
|
||||
|
||||
### Post-linking function
|
||||
|
||||
Executed after the child elements are linked. It is safe to do DOM transformation in the post-linking function.
|
||||
Executed after the child elements are linked. Safe to do DOM transformation in here.
|
||||
|
||||
<a name="Attributes"></a>
|
||||
## Attributes
|
||||
@@ -528,7 +526,6 @@ dialog component may work.
|
||||
on-ok="show = false; doSomething()">
|
||||
Body goes here: {{username}} is {{title}}.
|
||||
</dialog>
|
||||
</div>
|
||||
</pre>
|
||||
|
||||
Clicking on the "show" button will open the dialog. The dialog will have a title, which is
|
||||
@@ -538,7 +535,7 @@ into the dialog.
|
||||
Here is an example of what the template definition for the `dialog` widget may look like.
|
||||
|
||||
<pre>
|
||||
<div ng-show="visible">
|
||||
<div ng-show="show()">
|
||||
<h3>{{title}}</h3>
|
||||
<div class="body" ng-transclude></div>
|
||||
<div class="footer">
|
||||
@@ -550,18 +547,18 @@ Here is an example of what the template definition for the `dialog` widget may l
|
||||
|
||||
This will not render properly, unless we do some scope magic.
|
||||
|
||||
The first issue we have to solve is that the dialog box template expects `title` to be defined, but
|
||||
the place of instantiation would like to bind to `username`. Furthermore the buttons expect the
|
||||
`onOk` and `onCancel` functions to be present in the scope. This limits the usefulness of the
|
||||
The first issue we have to solve is that the dialog box template expect `title` to be defined, but
|
||||
the place of instantiation would like to bind to `username`. Furthermore the buttons expect `onOk`
|
||||
as well as `onCancel` functions to be present in the scope. This limits the usefulness of the
|
||||
widget. To solve the mapping issue we use the `locals` to create local variables which the template
|
||||
expects as follows:
|
||||
|
||||
<pre>
|
||||
scope: {
|
||||
title: '@', // the title uses the data-binding from the parent scope
|
||||
onOk: '&', // create a delegate onOk function
|
||||
onCancel: '&', // create a delegate onCancel function
|
||||
visible: '=' // set up visible to accept data-binding
|
||||
title: 'bind', // set up title to accept data-binding
|
||||
onOk: 'expression', // create a delegate onOk function
|
||||
onCancel: 'expression', // create a delegate onCancel function
|
||||
show: 'accessor' // create a getter/setter function for visibility.
|
||||
}
|
||||
</pre>
|
||||
|
||||
@@ -584,7 +581,7 @@ isolated scope then it will not be able to bind to anything. For this reason the
|
||||
is a child of the original scope, before the widget created an isolated scope for its local
|
||||
variables. This makes the transcluded and widget isolated scope siblings.
|
||||
|
||||
This may seem to be unexpected complexity, but it gives the widget user and developer the least
|
||||
This may seem as unexpected complexity, but it gives the widget user and developer the least
|
||||
surprise.
|
||||
|
||||
Therefore the final directive definition looks something like this:
|
||||
@@ -592,13 +589,11 @@ Therefore the final directive definition looks something like this:
|
||||
<pre>
|
||||
transclude: true,
|
||||
scope: {
|
||||
title: '@', // the title uses the data-binding from the parent scope
|
||||
onOk: '&', // create a delegate onOk function
|
||||
onCancel: '&', // create a delegate onCancel function
|
||||
visible: '=' // set up visible to accept data-binding
|
||||
},
|
||||
restrict: 'E',
|
||||
replace: true
|
||||
title: 'bind', // set up title to accept data-binding
|
||||
onOk: 'expression', // create a delegate onOk function
|
||||
onCancel: 'expression', // create a delegate onCancel function
|
||||
show: 'accessor' // create a getter/setter function for visibility.
|
||||
}
|
||||
</pre>
|
||||
|
||||
# Creating Components
|
||||
@@ -609,6 +604,7 @@ can be built.
|
||||
|
||||
Following is an example of building a reusable widget.
|
||||
|
||||
|
||||
<doc:example module="zippyModule">
|
||||
<doc:source>
|
||||
<script>
|
||||
|
||||
@@ -15,9 +15,10 @@ For example, these are all valid expressions in angular:
|
||||
|
||||
## Angular Expressions vs. JS Expressions
|
||||
|
||||
It might be tempting to think of Angular view expressions as JavaScript expressions, but that is
|
||||
not entirely correct, since Angular does not use a JavaScript `eval()` to evaluate expressions.
|
||||
You can think of Angular expressions as JavaScript expressions with following differences:
|
||||
It might be tempting to think of angular view expressions as JavaScript expressions, but that is
|
||||
not entirely correct, since angular does not use a JavaScript `eval()` to evaluate expressions.
|
||||
You can think of angular expressions as JavaScript expressions with following differences
|
||||
differences:
|
||||
|
||||
* **Attribute Evaluation:** evaluation of all properties are against the scope, doing the
|
||||
evaluation, unlike in JavaScript where the expressions are evaluated against the global
|
||||
@@ -91,9 +92,9 @@ You can try evaluating different expressions here:
|
||||
# Property Evaluation
|
||||
|
||||
Evaluation of all properties takes place against a scope. Unlike JavaScript, where names default
|
||||
to global window properties, Angular expressions have to use {@link api/ng.$window
|
||||
to global window properties, angular expressions have to use {@link api/ng.$window
|
||||
`$window`} to refer to the global `window` object. For example, if you want to call `alert()`, which is
|
||||
defined on `window`, in an expression you must use `$window.alert()`. This is done intentionally to
|
||||
defined on `window`, in an expression must use `$window.alert()`. This is done intentionally to
|
||||
prevent accidental access to the global state (a common source of subtle bugs).
|
||||
|
||||
<doc:example>
|
||||
@@ -147,7 +148,7 @@ Similarly, invoking a function `a.b.c()` on undefined or null simply returns und
|
||||
## No Control Flow Statements
|
||||
|
||||
You cannot write a control flow statement in an expression. The reason behind this is core to the
|
||||
Angular philosophy that application logic should be in controllers, not in the view. If you need a
|
||||
angular philosophy that application logic should be in controllers, not in the view. If you need a
|
||||
conditional, loop, or to throw from a view expression, delegate to a JavaScript method instead.
|
||||
|
||||
|
||||
@@ -178,9 +179,9 @@ You might be wondering, what is the significance of the $ prefix? It is simply a
|
||||
angular uses, to differentiate its API names from others. If angular didn't use $, then evaluating
|
||||
`a.length()` would return undefined because neither a nor angular define such a property.
|
||||
|
||||
Consider that in a future version of Angular we might choose to add a length method, in which case
|
||||
Consider that in a future version of angular we might choose to add a length method, in which case
|
||||
the behavior of the expression would change. Worse yet, you the developer could create a length
|
||||
property and then we would have a collision. This problem exists because Angular augments existing
|
||||
property and then we would have a collision. This problem exists because angular augments existing
|
||||
objects with additional behavior. By prefixing its additions with $ we are reserving our namespace
|
||||
so that angular developers and developers who use Angular can develop in harmony without collisions.
|
||||
so that angular developers and developers who use angular can develop in harmony without collisions.
|
||||
|
||||
|
||||
@@ -12,9 +12,9 @@ Server-side validation is still necessary for a secure application.
|
||||
|
||||
|
||||
# Simple form
|
||||
The key directive in understanding two-way data-binding is {@link api/ng.directive:ngModel ngModel}.
|
||||
The key directive in understanding two-way data-binding is {@link api/ng.directive:ngModel ngModel}.
|
||||
The `ngModel` directive provides the two-way data-binding by synchronizing the model to the view, as well as view to the model.
|
||||
In addition it provides an {@link api/ng.directive:ngModel.NgModelController API} for other directives to augment its behavior.
|
||||
In addition it provides {@link api/ng.directive:ngModel.NgModelController API} for other directives to augment its behavior.
|
||||
|
||||
<doc:example>
|
||||
<doc:source>
|
||||
@@ -63,7 +63,7 @@ To allow styling of form as well as controls, `ngModel` add these CSS classes:
|
||||
- `ng-pristine`
|
||||
- `ng-dirty`
|
||||
|
||||
The following example uses the CSS to display validity of each form control.
|
||||
Following example uses the CSS to display validity of each form control.
|
||||
In the example both `user.name` and `user.email` are required, but are rendered with red background only when they are dirty.
|
||||
This ensures that the user is not distracted with an error until after interacting with the control, and failing to satisfy its validity.
|
||||
|
||||
@@ -190,18 +190,18 @@ The validation can occur in two places:
|
||||
|
||||
* **View to Model update** -
|
||||
In a similar way, whenever a user interacts with a control it calls {@link api/ng.directive:ngModel.NgModelController#$setViewValue NgModelController#$setViewValue}.
|
||||
This in turn pipelines all functions in the {@link api/ng.directive:ngModel.NgModelController#$parsers NgModelController#$parsers} array, so that each of these functions has an opportunity to convert the value and change validity state of the form control through {@link api/ng.directive:ngModel.NgModelController#$setValidity NgModelController#$setValidity}.
|
||||
This in turn pipelines all functions in {@link api/ng.directive:ngModel.NgModelController#$parsers NgModelController#$parsers} array, so that each of these functions has an opportunity to convert the value and change validity state of the form control through {@link api/ng.directive:ngModel.NgModelController#$setValidity NgModelController#$setValidity}.
|
||||
|
||||
In the following example we create two directives.
|
||||
|
||||
* The first one is `integer` and it validates whether the input is a valid integer.
|
||||
For example `1.23` is an invalid value, since it contains a fraction.
|
||||
Note that we unshift the array instead of pushing.
|
||||
Note, that we unshift the array instead of pushing.
|
||||
This is because we want to be first parser and consume the control string value, as we need to execute the validation function before a conversion to number occurs.
|
||||
|
||||
* The second directive is a `smart-float`.
|
||||
It parses both `1.2` and `1,2` into a valid float number `1.2`.
|
||||
Note that we can't use input type `number` here as HTML5 browsers would not allow the user to type what it would consider an invalid number such as `1,2`.
|
||||
Note that, we can't use input type `number` here as HTML5 browsers would not allow the user to type what it would consider an invalid number such as `1,2`.
|
||||
|
||||
|
||||
<doc:example module="form-example1">
|
||||
@@ -272,7 +272,7 @@ In the following example we create two directives.
|
||||
</doc:example>
|
||||
|
||||
|
||||
# Implementing custom form controls (using `ngModel`)
|
||||
# Implementing custom form control (using `ngModel`)
|
||||
Angular implements all of the basic HTML form controls ({@link api/ng.directive:input input}, {@link api/ng.directive:select select}, {@link api/ng.directive:textarea textarea}), which should be sufficient for most cases.
|
||||
However, if you need more flexibility, you can write your own form control as a directive.
|
||||
|
||||
@@ -300,8 +300,8 @@ The following example shows how to add two-way data-binding to contentEditable e
|
||||
});
|
||||
|
||||
// model -> view
|
||||
ctrl.$render = function() {
|
||||
elm.html(ctrl.$viewValue);
|
||||
ctrl.$render = function(value) {
|
||||
elm.html(value);
|
||||
};
|
||||
|
||||
// load init value from DOM
|
||||
|
||||
@@ -5,12 +5,12 @@
|
||||
# Overview
|
||||
|
||||
This document describes the Internet Explorer (IE) idiosyncrasies when dealing with custom HTML
|
||||
attributes and tags. Read this document if you are planning on deploying your Angular application
|
||||
attributes and tags. Read this document if you are planning on deploying your angular application
|
||||
on IE v8.0 or earlier.
|
||||
|
||||
# Short Version
|
||||
|
||||
To make your Angular application work on IE please make sure that:
|
||||
To make your angular application work on IE please make sure that:
|
||||
|
||||
1. You polyfill JSON.stringify if necessary (IE7 will need this). You can use
|
||||
[JSON2](https://github.com/douglascrockford/JSON-js) or
|
||||
|
||||
@@ -6,7 +6,7 @@ Angular is pure client-side technology, written entirely in JavaScript. It works
|
||||
long-established technologies of the web (HTML, CSS, and JavaScript) to make the development of
|
||||
web apps easier and faster than ever before.
|
||||
|
||||
One important way that Angular simplifies web development is by increasing the level of abstraction
|
||||
One important way that angular simplifies web development is by increasing the level of abstraction
|
||||
between the developer and most low-level web app development tasks. Angular automatically takes
|
||||
care of many of these tasks, including:
|
||||
|
||||
@@ -14,10 +14,10 @@ care of many of these tasks, including:
|
||||
* Setting Up Listeners and Notifiers
|
||||
* Input Validation
|
||||
|
||||
Because Angular handles much of the work involved in these tasks, developers can concentrate more
|
||||
Because angular handles much of the work involved in these tasks, developers can concentrate more
|
||||
on application logic and less on repetitive, error-prone, lower-level coding.
|
||||
|
||||
At the same time that Angular simplifies the development of web apps, it brings relatively
|
||||
At the same time that angular simplifies the development of web apps, it brings relatively
|
||||
sophisticated techniques to the client-side, including:
|
||||
|
||||
* Separation of data, application logic, and presentation components
|
||||
@@ -31,12 +31,12 @@ These techniques have been for the most part absent from the client-side for far
|
||||
|
||||
## Single-page / Round-trip Applications
|
||||
|
||||
You can use Angular to develop both single-page and round-trip apps, but Angular is designed
|
||||
You can use angular to develop both single-page and round-trip apps, but angular is designed
|
||||
primarily for developing single-page apps. Angular supports browser history, forward and back
|
||||
buttons, and bookmarking in single-page apps.
|
||||
|
||||
You normally wouldn't want to load Angular with every page change, as would be the case with using
|
||||
Angular in a round-trip app. However, it would make sense to do so if you were adding a subset of
|
||||
Angular's features (for example, templates to leverage angular's data-binding feature) to an
|
||||
You normally wouldn't want to load angular with every page change, as would be the case with using
|
||||
angular in a round-trip app. However, it would make sense to do so if you were adding a subset of
|
||||
angular's features (for example, templates to leverage angular's data-binding feature) to an
|
||||
existing round-trip app. You might follow this course of action if you were migrating an older app
|
||||
to a single-page Angular app.
|
||||
to a single-page angular app.
|
||||
|
||||
@@ -5,8 +5,9 @@
|
||||
# What is a Module?
|
||||
|
||||
Most applications have a main method which instantiates, wires, and bootstraps the application.
|
||||
Angular apps don't have a main method. Instead modules declaratively specify how an application
|
||||
should be bootstrapped. There are several advantages to this approach:
|
||||
Angular apps don't have a main method, instead modules serve the purpose of declaratively
|
||||
specifying how an application should be bootstrapped. There are several advantages to this
|
||||
approach:
|
||||
|
||||
* The process is more declarative which is easier to understand
|
||||
* In unit-testing there is no need to load all modules, which may aid in writing unit-tests.
|
||||
@@ -30,7 +31,7 @@ Important things to notice:
|
||||
<doc:source>
|
||||
<script>
|
||||
// declare a module
|
||||
var myAppModule = angular.module('myApp', []);
|
||||
var simpleAppModule = angular.module('myApp', []);
|
||||
|
||||
// configure the module.
|
||||
// in this example we will create a greeting filter
|
||||
@@ -194,7 +195,7 @@ and thus script loaders can take advantage of this property and parallelize the
|
||||
|
||||
# Unit Testing
|
||||
|
||||
In its simplest form a unit test is a way of instantiating a subset of the application in test and
|
||||
In its simplest form a unit-test is a way of instantiating a subset of the application in test and
|
||||
then applying a stimulus to it. It is important to realize that each module can only be loaded
|
||||
once per injector. Typically an app has only one injector. But in tests, each test has its own
|
||||
injector, which means that the modules are loaded multiple times per VM. Properly structured
|
||||
@@ -222,8 +223,8 @@ In all of these examples we are going to assume this module definition:
|
||||
Let's write some tests:
|
||||
<pre>
|
||||
describe('myApp', function() {
|
||||
// load the relevant application modules then load a special
|
||||
// test module which overrides the $window with a mock version,
|
||||
// load the application relevant modules then load a special
|
||||
// test module which overrides the $window with mock version,
|
||||
// so that calling window.alert() will not block the test
|
||||
// runner with a real alert box. This is an example of overriding
|
||||
// configuration information in tests.
|
||||
|
||||
@@ -16,7 +16,7 @@ declarative language for static documents. It does not contain much in the way o
|
||||
applications, and as a result building web applications is an exercise in *what do I have to do, so
|
||||
that I trick the browser in to doing what I want.*
|
||||
|
||||
The impedance mismatch between dynamic applications and static documents is often solved as:
|
||||
Impedance mismatch between dynamic applications and static documents are often solved as:
|
||||
|
||||
* **library** - a collection of functions which are useful when writing web apps. Your code is
|
||||
in charge and it calls into the library when it sees fit. E.g., `jQuery`.
|
||||
@@ -111,7 +111,7 @@ concepts which the application developer may face:
|
||||
Try out the Live Preview above, and then let's walk through the example and describe what's going
|
||||
on.
|
||||
|
||||
In the `<html>` tag, we specify that it is an Angular
|
||||
In the `<html>` tag, we specify that it is an angular
|
||||
application with the `ng-app` directive. The `ng-app` will cause Angular to {@link
|
||||
bootstrap auto initialize} your application.
|
||||
|
||||
@@ -121,7 +121,7 @@ We load Angular using the `<script>` tag:
|
||||
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/?.?.?/angular.min.js"></script>
|
||||
|
||||
From the `ng-model` attribute of the `<input>` tags, Angular automatically sets up two-way data
|
||||
From the `ng-model` attribute of the `<input>` tags, angular automatically sets up two-way data
|
||||
binding, and we also demonstrate some easy input validation:
|
||||
|
||||
Quantity: <input type="integer" min="0" ng-model="qty" required >
|
||||
@@ -129,7 +129,7 @@ binding, and we also demonstrate some easy input validation:
|
||||
|
||||
These input widgets look normal enough, but consider these points:
|
||||
|
||||
* When this page loaded, Angular bound the names of the input widgets (`qty` and `cost`) to
|
||||
* When this page loaded, angular bound the names of the input widgets (`qty` and `cost`) to
|
||||
variables of the same name. Think of those variables as the "Model" component of the
|
||||
Model-View-Controller design pattern.
|
||||
* Note that the HTML widget {@link api/ng.directive:input input}
|
||||
@@ -193,7 +193,7 @@ Angular frees you from the following pain:
|
||||
code. Angular eliminates almost all of this boilerplate, leaving code that describes the
|
||||
overall flow of the application rather than all of the implementation details.
|
||||
* **Writing tons of initialization code just to get started:** Typically you need to write a lot
|
||||
of plumbing just to get a basic "Hello World" AJAX app working. With Angular you can bootstrap
|
||||
of plumbing just to get a basic "Hello World" AJAX app working. With angular you can bootstrap
|
||||
your app easily using services, which are auto-injected into your application in a {@link
|
||||
http://code.google.com/p/google-guice/ Guice}-like dependency-injection style. This allows you
|
||||
to get started developing features quickly. As a bonus, you get full control over the
|
||||
|
||||
@@ -81,7 +81,7 @@ Logically the rendering of `{{greeting}}` involves:
|
||||
You can think of the scope and its properties as the data which is used to render the view. The
|
||||
scope is the single source-of-truth for all things view related.
|
||||
|
||||
From a testability point of view, the separation of the controller and the view is desirable, because it allows us
|
||||
From testability, the separation of the controller and the view is desirable, because it allows us
|
||||
to test the behavior without being distracted by the rendering details.
|
||||
|
||||
<pre>
|
||||
@@ -151,7 +151,7 @@ This example illustrates scopes in application, and prototypical inheritance of
|
||||
</file>
|
||||
</example>
|
||||
|
||||
Notice that Angular automatically places `ng-scope` class on elements where scopes are
|
||||
Notice that the Angular automatically places `ng-scope` class on elements where scopes are
|
||||
attached. The `<style>` definition in this example highlights in red the new scope locations. The
|
||||
child scopes are necessary because the repeater evaluates `{{employee.name}}` expression, but
|
||||
depending on which scope the expression is evaluated it produces different result. Similarly the
|
||||
@@ -166,7 +166,7 @@ purposes. (It is unlikely that one would need to retrieve scopes in this way ins
|
||||
application.) The location where the root scope is attached to the DOM is defined by the location
|
||||
of {@link api/ng.directive:ngApp `ng-app`} directive. Typically
|
||||
`ng-app` is placed an the `<html>` element, but it can be placed on other elements as well, if,
|
||||
for example, only a portion of the view needs to be controlled by Angular.
|
||||
for example, only a portion of the view needs to be controlled by angular.
|
||||
|
||||
To examine the scope in the debugger:
|
||||
|
||||
@@ -218,7 +218,7 @@ api/ng.$rootScope.Scope#$emit emitted} to scope parents.
|
||||
|
||||
## Scope Life Cycle
|
||||
|
||||
The normal flow of a browser receiving an event is that it executes a corresponding JavaScript
|
||||
The normal flow of browser receiving an event is that it executes a corresponding JavaScript
|
||||
callback. Once the callback completes the browser re-renders the DOM and returns to waiting for
|
||||
more events.
|
||||
|
||||
|
||||
@@ -13,19 +13,19 @@
|
||||
<a name="H1_1"></a>
|
||||
# License
|
||||
|
||||
AngularJS is an open source project licensed under the {@link
|
||||
`Angular` is an open source project licensed under the {@link
|
||||
http://github.com/angular/angular.js/blob/master/LICENSE MIT license}. Your contributions are
|
||||
always welcome. When working with AngularJS code base, please follow the guidelines provided on
|
||||
always welcome. When working with `angular` source base, please follow the guidelines provided on
|
||||
this page.
|
||||
|
||||
|
||||
<a name="H1_2"></a>
|
||||
# Contributing to Source Code
|
||||
|
||||
We'd love for you to contribute to our source code and to make AngularJS even better than it is
|
||||
today! Here are the guidelines we'd like you to follow:
|
||||
We'd love for you to contribute to our source code and to make `angular` even better than it is
|
||||
today! Here are the guidelines we'd like you to use:
|
||||
|
||||
* Major changes that you intend to contribute to the project should be discussed first on our {@link
|
||||
* Major changes that you intend to contribute to the project must be discussed first on our {@link
|
||||
https://groups.google.com/forum/?hl=en#!forum/angular mailing list} 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 upstream.
|
||||
@@ -64,39 +64,45 @@ inheritance only when absolutely necessary.
|
||||
external API. See our existing code to see what we mean.
|
||||
|
||||
* We don't go crazy with type annotations for private internal APIs unless it's an internal API
|
||||
that is used throughout AngularJS. The best guidance is to do what makes the most sense.
|
||||
that is used throughout `angular`. The best guidance is to do what makes the most sense.
|
||||
|
||||
|
||||
<a name="H1_4"></a>
|
||||
# Checking Out and Building Angular
|
||||
|
||||
The AngularJS source code is hosted at {@link http://github.com Github}, which we also use to
|
||||
accept code contributions. The AngularJS repository can be found at **<https://github.com/angular/angular.js>**.
|
||||
|
||||
Several steps are needed to check out and build AngularJS:
|
||||
The `angular` source code is hosted at {@link http://github.com Github}, which we also use to
|
||||
accept code contributions. Several steps are needed to check out and build `angular`:
|
||||
|
||||
|
||||
## Installation Dependencies
|
||||
|
||||
Before you can build AngularJS, you must install or configure the following dependencies on your
|
||||
Before you can build `angular`, you must install or configure the following dependencies on your
|
||||
machine:
|
||||
|
||||
* {@link http://rake.rubyforge.org Rake}: We use Rake as our build system, which is pre-installed
|
||||
on most Macintosh and Linux machines. If that is not true in your case, you can grab it from the
|
||||
Rake website.
|
||||
|
||||
* Git: The {@link http://help.github.com/mac-git-installation Github Guide to Installing Git} is
|
||||
quite a good source for information on Git.
|
||||
|
||||
* {@link http://nodejs.org Node.js}: We use Node to generate the documentation and to run a
|
||||
development web server. Depending on your system, you can install Node either from source or as a
|
||||
pre-packaged bundle.
|
||||
|
||||
Once installed, you'll also need several npms (node packages), which you can install once you checked out a local copy
|
||||
of the Angular repository (see below) with:
|
||||
You'll also need npm and the following npm modules:
|
||||
|
||||
* `cd angular.js`
|
||||
* `npm install`
|
||||
* install npm: `curl http://npmjs.org/install.sh | sh`
|
||||
* install q: `npm install q`
|
||||
* install qq: `npm install qq`
|
||||
* install q-fs: `npm install q-fs`
|
||||
* install jasmine-node: `npm install jasmine`
|
||||
|
||||
|
||||
|
||||
* Java: The Java runtime is used to run {@link http://code.google.com/p/js-test-driver
|
||||
JsTestDriver} (JSTD), which we use to run our unit test suite. JSTD binaries are part of the
|
||||
`angular` source base, which means there is no need to install or configure it separately.
|
||||
|
||||
* Git: The {@link http://help.github.com/mac-git-installation Github Guide to Installing Git} is
|
||||
quite a good source for information on Git.
|
||||
|
||||
|
||||
## Creating a Github Account and Forking Angular
|
||||
@@ -106,35 +112,31 @@ Afterwards, go ahead and {@link http://help.github.com/forking fork} the {@link
|
||||
https://github.com/angular/angular.js main angular repository}.
|
||||
|
||||
|
||||
## Building AngularJS
|
||||
## Building `Angular`
|
||||
|
||||
To build AngularJS, you check out the source code and use Rake to generate the non-minified and
|
||||
minified AngularJS files:
|
||||
To build `angular`, you check out the source code and use Rake to generate the non-minified and
|
||||
minified `angular` files:
|
||||
|
||||
1. To clone your Github repository, run:
|
||||
|
||||
git clone git@github.com:<github username>/angular.js.git
|
||||
|
||||
2. To go to the AngularJS directory, run:
|
||||
2. To go to the `angular` directory, run:
|
||||
|
||||
cd angular.js
|
||||
|
||||
3. To add the main AngularJS repository as an upstream remote to your repository, run:
|
||||
3. To add the main `angular` repository as an upstream remote to your repository, run:
|
||||
|
||||
git remote add upstream https://github.com/angular/angular.js.git
|
||||
|
||||
4. To add node.js dependencies
|
||||
|
||||
npm install
|
||||
|
||||
5. To build AngularJS, run:
|
||||
4. To build `angular`, run:
|
||||
|
||||
rake package
|
||||
|
||||
The build output can be located under the `build` directory. It consists of the following files and
|
||||
directories:
|
||||
|
||||
* `angular-<version>.zip` — This is the complete zip file, which contains all of the release build
|
||||
* `angular-<version>.tgz` — This is the complete tarball, which contains all of the release build
|
||||
artifacts.
|
||||
|
||||
* `angular.js` — The non-minified `angular` script.
|
||||
@@ -143,6 +145,8 @@ artifacts.
|
||||
|
||||
* `angular-scenario.js` — The `angular` End2End test runner.
|
||||
|
||||
* `angular-ie-compat.js` — The Internet Explorer compatibility patch file.
|
||||
|
||||
* `docs/` — A directory that contains all of the files needed to run `docs.angularjs.org`.
|
||||
|
||||
* `docs/index.html` — The main page for the documentation.
|
||||
@@ -150,70 +154,60 @@ artifacts.
|
||||
* `docs/docs-scenario.html` — The End2End test runner for the documentation application.
|
||||
|
||||
|
||||
<a name="webserver"></a>
|
||||
## Running a Local Development Web Server
|
||||
|
||||
To debug code and run end-to-end tests, it is often useful to have a local HTTP server. For this purpose, we have
|
||||
To debug or test code, it is often useful to have a local HTTP server. For this purpose, we have
|
||||
made available a local web server based on Node.js.
|
||||
|
||||
1. To start the web server, run:
|
||||
|
||||
rake webserver
|
||||
./nodeserver.sh
|
||||
|
||||
2. To access the local server, go to this website:
|
||||
|
||||
http://localhost:8000/
|
||||
|
||||
By default, it serves the contents of the AngularJS project directory.
|
||||
By default, it serves the contents of the `angular` project directory.
|
||||
|
||||
|
||||
<a name="unit-tests"></a>
|
||||
## Running the Unit Test Suite
|
||||
|
||||
Our unit and integration tests are written with Jasmine and executed with Testacular. To run all of the
|
||||
tests once on Chrome run:
|
||||
Our unit and integration tests are written with Jasmine and executed with JsTestDriver. To run the
|
||||
tests:
|
||||
|
||||
rake test:unit
|
||||
1. To start the JSTD server, run:
|
||||
|
||||
To run the tests on other browsers (Chrome, ChromeCanary, Firefox, Opera and Safari are pre-configured) use:
|
||||
./server.sh
|
||||
|
||||
rake test:unit[Opera+Firefox]
|
||||
|
||||
During development it's however more productive to continuously run unit tests every time the source or test files
|
||||
change. To execute tests in this mode run:
|
||||
|
||||
1. To start the Testacular server, capture Chrome browser and run unit tests, run:
|
||||
|
||||
rake autotest:jqlite
|
||||
|
||||
2. To capture more browsers, open this url in the desired browser (url might be different if you have multiple instance
|
||||
of Testacular running, read Testacular's console output for the correct url):
|
||||
2. To capture one or more browsers, go to this website:
|
||||
|
||||
http://localhost:9876/
|
||||
|
||||
3. To re-run tests just change any source or test file.
|
||||
3. To trigger a test execution, run:
|
||||
|
||||
./test.sh
|
||||
|
||||
4. To automatically run the test suite each time one or more of the files in the project directory
|
||||
is changed, you can install `watchr` and then run:
|
||||
|
||||
watchr watchr.rb
|
||||
|
||||
5. To view the output of each test run, you can tail this log file:
|
||||
|
||||
./logs/jstd.log
|
||||
|
||||
|
||||
To learn more about all of the preconfigured Rake tasks run:
|
||||
## Running the End2End Test Suite
|
||||
|
||||
rake -T
|
||||
|
||||
|
||||
## Running the end-to-end Test Suite
|
||||
|
||||
To run the E2E test suite:
|
||||
|
||||
1. Start the local web server if it's not running already.
|
||||
|
||||
rake webserver
|
||||
To run the End2End test suite:
|
||||
|
||||
1. Start the local web server.
|
||||
2. In a browser, go to:
|
||||
|
||||
http://localhost:8000/build/docs/docs-scenario.html
|
||||
|
||||
or in terminal run:
|
||||
|
||||
rake test:e2e
|
||||
The tests are executed automatically.
|
||||
|
||||
|
||||
|
||||
@@ -222,38 +216,30 @@ To run the E2E test suite:
|
||||
|
||||
To create and submit a change:
|
||||
|
||||
1. Please sign our Contributor License Agreement (CLA) before sending pull requests. For any code changes to be
|
||||
accepted, the CLA must be signed. It's a quick process, we promise!
|
||||
|
||||
For individuals we have a [simple click-through form](http://code.google.com/legal/individual-cla-v1.0.html). For
|
||||
corporations we'll need you to
|
||||
[print, sign and one of scan+email, fax or mail the form](http://code.google.com/legal/corporate-cla-v1.0.html).
|
||||
|
||||
|
||||
2. Create a new branch off the master for your changes:
|
||||
1. Create a new branch off the master for your changes:
|
||||
|
||||
git branch my-fix-branch
|
||||
|
||||
3. Check out the branch:
|
||||
2. Check out the branch:
|
||||
|
||||
git checkout my-fix-branch
|
||||
|
||||
4. Create your patch, make sure to have plenty of tests (that pass).
|
||||
3. Create your patch, make sure to have plenty of tests (that pass).
|
||||
|
||||
5. Commit your changes and create a descriptive commit message (the commit message is used to generate release notes,
|
||||
please check out our
|
||||
[commit message conventions](https://docs.google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y/edit#)
|
||||
and our commit message presubmit hook `validate-commit-msg.js`):
|
||||
4. Commit your changes:
|
||||
|
||||
git commit -a
|
||||
|
||||
5. Run JavaScript Lint and be sure to address all new warnings and errors:
|
||||
|
||||
rake lint
|
||||
|
||||
6. Push your branch to Github:
|
||||
|
||||
git push origin my-fix-branch
|
||||
|
||||
7. In Github, send a pull request to `angular:master`.
|
||||
|
||||
|
||||
8. When the patch is reviewed and merged, delete your branch and pull yours — and other — changes
|
||||
from the main (upstream) repository:
|
||||
|
||||
|
||||
@@ -2,9 +2,10 @@
|
||||
@name Downloading
|
||||
@description
|
||||
|
||||
# Including angular scripts from the Google CDN
|
||||
The quickest way to get started is to point your html `<script>` tag to a Google CDN URL.
|
||||
This way, you don't have to download anything or maintain a local copy.
|
||||
# Including angular scripts from the angular server
|
||||
The quickest way to get started is to point your html `<script>` tag to a
|
||||
<http://code.angularjs.org/> URL. This way, you don't have to download anything or maintain a
|
||||
local copy.
|
||||
|
||||
There are two types of angular script URLs you can point to, one for development and one for
|
||||
production:
|
||||
@@ -14,25 +15,21 @@ development.
|
||||
* __angular-<version>.min.js__ — This is the minified version, which we strongly suggest you use in
|
||||
production.
|
||||
|
||||
To point your code to an angular script on the Google CDN server, use the following template. This
|
||||
example points to the minified version 1.0.2:
|
||||
To point your code to an angular script on the angular server, use the following template. This
|
||||
example points to (non-minified) version 0.10.6:
|
||||
|
||||
<pre>
|
||||
<!doctype html>
|
||||
<html ng-app>
|
||||
<head>
|
||||
<title>My Angular App</title>
|
||||
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.2/angular.min.js"></script>
|
||||
<script src="http://code.angularjs.org/angular-0.10.6.js"></script>
|
||||
</head>
|
||||
<body>
|
||||
</body>
|
||||
</html>
|
||||
</pre>
|
||||
|
||||
Note that only versions 1.0.1 and above are available on the CDN, if you need an earlier version
|
||||
you can use the <http://code.angularjs.org/> URL which was the previous recommended location for
|
||||
hosted code source. If you're still using the angular server you should switch to the CDN version
|
||||
for even faster loading times.
|
||||
|
||||
# Downloading and hosting angular files locally
|
||||
This option is for those who want to work with angular offline, or those who want to host the
|
||||
@@ -45,31 +42,29 @@ Download the version you want and have fun.
|
||||
|
||||
Each directory under <http://code.angularjs.org/> includes the following set of files:
|
||||
|
||||
* __`angular.js`__ — This file is non-obfuscated, non-minified, and human-readable by
|
||||
* __`angular-<version>.js`__ — This file is non-obfuscated, non-minified, and human-readable by
|
||||
opening it it any editor or browser. In order to get better error messages during development, you
|
||||
should always use this non-minified angular script.
|
||||
|
||||
* __`angular.min.js`__ — This is a minified and obfuscated version of
|
||||
`angular.js` created with the Closure compiler. Use this version for production in order
|
||||
* __`angular-<version>.min.js`__ — This is a minified and obfuscated version of
|
||||
`angular-<version>.js` created with the Closure compiler. Use this version for production in order
|
||||
to minimize the size of the application that is downloaded by your user's browser.
|
||||
|
||||
* __`angular.zip`__ — This is a zip archive that contains all of the files released
|
||||
* __`angular-<version>.tgz`__ — This is a tarball archive that contains all of the files released
|
||||
for this angular version. Use this file to get everything in a single download.
|
||||
|
||||
* __`angular-mocks.js`__ — This file contains an implementation of mocks that makes
|
||||
* __`angular-ie-compat-<version>.js`__ — This is a special file that contains code and data
|
||||
specifically tailored for getting Internet Explorer to work with angular. If you host your own copy
|
||||
of angular files, make sure that this file is available for download, and that it resides under the
|
||||
same parent path as `angular-<version>.js` or `angular-<version>.min.js`.
|
||||
|
||||
* __`angular-mocks-<version>.js`__ — This file contains an implementation of mocks that makes
|
||||
testing angular apps even easier. Your unit/integration test harness should load this file after
|
||||
`angular-<version>.js` is loaded.
|
||||
|
||||
* __`angular-scenario.js`__ — This file is a very nifty JavaScript file that allows you
|
||||
* __`angular-scenario-<version>.js`__ — This file is a very nifty JavaScript file that allows you
|
||||
to write and execute end-to-end tests for angular applications.
|
||||
|
||||
* __`angular-loader.min.js`__ — Module loader for Angular modules. If you are loading multiple script files containing
|
||||
Angular modules, you can load them asynchronosuly and in any order as long as you load this file first. Often the
|
||||
contents of this file are copy&pasted into the `index.html` to avoid even the inial request to `angular-loader.min.js`.
|
||||
See [angular-seed](https://github.com/angular/angular-seed/blob/master/app/index-async.html) for an example of usage.
|
||||
|
||||
* __`angular-resource.js`__, __`angular-cookies.js`__, etc - extra Angular modules with additional functionality.
|
||||
|
||||
* __`docs`__ — this directory contains all the files that compose the
|
||||
* __`docs-<version>`__ — this directory contains all the files that compose the
|
||||
<http://docs.angularjs.org/> documentation app. These files are handy to see the older version of
|
||||
our docs, or even more importantly, view the docs offline.
|
||||
|
||||
+13
-135
@@ -4,8 +4,6 @@
|
||||
|
||||
#FAQ
|
||||
|
||||
## Questions
|
||||
|
||||
### Why is this project called "AngularJS"? Why is the namespace called "ng"?
|
||||
|
||||
Because HTML has Angular brackets and "ng" sounds like "Angular".
|
||||
@@ -23,7 +21,7 @@ So it's definitely not a plugin or some other native browser extension.
|
||||
### Is AngularJS a templating system?
|
||||
|
||||
At the highest level, Angular does look like a just another templating system. But there is one
|
||||
important reason why the Angular templating system is different, that makes it very good fit for
|
||||
important reason why Angular templating system is different and makes it very good fit for
|
||||
application development: bidirectional data binding. The template is compiled in the browser and
|
||||
the compilation step produces a live view. This means you, the developers, don't need to write
|
||||
code to constantly sync the view with the model and the model with the view as in other
|
||||
@@ -32,7 +30,7 @@ templating systems.
|
||||
|
||||
### Do I need to worry about security holes in AngularJS?
|
||||
|
||||
Like any other technology, AngularJS is not impervious to attack. Angular does, however, provide
|
||||
Like with any technology, AngularJS is not impervious to attack. angular does, however, provide
|
||||
built-in protection from basic security holes including cross-site scripting and HTML injection
|
||||
attacks. AngularJS does round-trip escaping on all strings for you and even offers XSRF protection
|
||||
for server-side communication.
|
||||
@@ -48,9 +46,9 @@ Yes. See instructions in {@link downloading}.
|
||||
|
||||
|
||||
|
||||
### What browsers does Angular work with?
|
||||
### What browsers does angular work with?
|
||||
|
||||
We run our extensive test suite against the following browsers: Safari, Chrome, Firefox, Opera,
|
||||
Our we run our extensive test suite against the following browsers: Safari, Chrome, Firefox, Opera,
|
||||
IE8, IE9 and mobile browsers (Android, Chrome Mobile, iOS Safari).
|
||||
|
||||
|
||||
@@ -69,152 +67,32 @@ illustration we typically build snappy apps with hundreds or thousands of active
|
||||
The size of the file is < 29KB compressed and minified.
|
||||
|
||||
|
||||
### Can I use the open-source Closure Library with Angular?
|
||||
### Can I use the open-source Closure Library with angular?
|
||||
|
||||
Yes, you can use widgets from the {@link http://code.google.com/closure/library Closure Library}
|
||||
in Angular.
|
||||
in angular.
|
||||
|
||||
### Does Angular use the jQuery library?
|
||||
### Does angular use the jQuery library?
|
||||
|
||||
Yes, Angular can use {@link http://jquery.com/ jQuery} if it's present in your app when the
|
||||
application is being bootstrapped. If jQuery is not present in your script path, Angular falls back
|
||||
to its own implementation of the subset of jQuery that we call {@link api/angular.element jQLite}.
|
||||
|
||||
|
||||
### What is testability like in Angular?
|
||||
### What is testability like in angular?
|
||||
|
||||
Very testable and designed this way from ground up. It has an integrated dependency injection
|
||||
framework, provides mocks for many heavy dependencies (server-side communication). See
|
||||
{@link api/ng service} for details.
|
||||
|
||||
|
||||
### How can I learn more about Angular?
|
||||
### How can I learn more about angular?
|
||||
|
||||
Watch the July 17, 2012 talk
|
||||
"{@link http://www.youtube.com/watch?v=1CpiB3Wk25U AngularJS Intro + Dependency Injection}".
|
||||
Watch the July 28, 2010 talk
|
||||
"{@link http://www.youtube.com/watch?v=elvcgVSynRg| Angular: A Radically Different Way of Building
|
||||
AJAX Apps}".
|
||||
|
||||
|
||||
### How is Angular licensed?
|
||||
### How is angular licensed?
|
||||
|
||||
The MIT License.
|
||||
|
||||
### Can I download and use the Angular logo artwork?
|
||||
|
||||
Yes! You can find design files in our github repository, under "{@link https://github.com/angular/angular.js/tree/master/images/logo
|
||||
angular.js/images/logo}"
|
||||
The logo design is licensed under a "{@link http://creativecommons.org/licenses/by-sa/3.0/
|
||||
Creative Commons Attribution-ShareAlike 3.0 Unported License}". If you have some other use in mind, contact us.
|
||||
|
||||
### How can I get some AngularJS schwag?
|
||||
|
||||
We often bring a few t-shirts and stickers to events where we're presenting. If you want to order your own, the folks who
|
||||
make our schwag will be happy to do a custom run for you, based on our existing template. By using the design they have on file,
|
||||
they'll waive the setup costs, and you can order any quantity you need.
|
||||
|
||||
**Stickers**
|
||||
Contact Tom Witting (or anyone in sales) via email at tom@stickergiant.com, and tell him you want to order some AngularJS
|
||||
stickers just like the ones in job #42711. You'll have to give them your own info for billing and shipping.
|
||||
|
||||
As long as the design stays exactly the same, {@link http://www.stickergiant.com StickerGiant} will give you a reorder discount.
|
||||
|
||||
**T-shirts**
|
||||
Contact sales at {@link http://www.customink.com www.customink.com} and tell them you want some shirts with design name "angularjs",
|
||||
just like past order #2106371. You'll have to give them your own info for billing and shipping.
|
||||
|
||||
As long as the design stays exactly the same, CustomInk won't charge for any set up fees, and they'll give you a reorder discount.
|
||||
|
||||
## Common Pitfalls
|
||||
|
||||
The Angular support channel (#angularjs on Freenode) sees a number of recurring pitfalls that new users of Angular fall into.
|
||||
This document aims to point them out before you discover them the hard way.
|
||||
|
||||
### DOM Manipulation
|
||||
|
||||
Stop trying to use jQuery to modify the DOM in controllers. Really.
|
||||
That includes adding elements, removing elements, retrieving their contents, showing and hiding them.
|
||||
Use built-in directives, or write your own where necessary, to do your DOM manipulation.
|
||||
See below about duplicating functionality.
|
||||
|
||||
If you're struggling to break the habit, consider removing jQuery from your app.
|
||||
Really. Angular has the $http service and powerful directives that make it almost always unnecessary.
|
||||
Angular's bundled jQLite has a handful of the features most commonly used in writing Angular directives, especially binding to events.
|
||||
|
||||
### Trying to duplicate functionality that already exists
|
||||
|
||||
There's a good chance that your app isn't the first to require certain functionality.
|
||||
There are a few pieces of Angular that are particularly likely to be reimplemented out of old habits.
|
||||
|
||||
**ng-repeat**
|
||||
|
||||
`ng-repeat` gets this a lot.
|
||||
People try to use jQuery (see above) to add more elements to some container as they're fetched from the server.
|
||||
No, bad dog.
|
||||
This is what `ng-repeat` is for, and it does its job very well.
|
||||
Store the data from the server in an array on your `$scope`, and bind it to the DOM with `ng-repeat`.
|
||||
|
||||
**ng-show**
|
||||
|
||||
`ng-show` gets this frequently too.
|
||||
Conditionally showing and hiding things using jQuery is a common pattern in other apps, but Angular has a better way.
|
||||
`ng-show` (and `ng-hide`) conditionally show and hide elements based on boolean expressions.
|
||||
Describe the conditions for showing and hiding an element in terms of `$scope` variables:
|
||||
|
||||
<div ng-show="!loggedIn">Click <a href="#/login">here</a> to log in</div>
|
||||
|
||||
Note also the counterpart `ng-hide` and similar `ng-disabled`.
|
||||
Note especially the powerful `ng-switch` that should be used instead of several mutually exclusive `ng-show`s.
|
||||
|
||||
**ng-class**
|
||||
|
||||
`ng-class` is the last of the big three.
|
||||
Conditionally applying classes to elements is another thing commonly done manually using jQuery.
|
||||
Angular, of course, has a better way.
|
||||
You can give `ng-class` a whitespace-separated set of class names, and then it's identical to ordinary `class`.
|
||||
That's not very exciting, so there's a second syntax:
|
||||
|
||||
<div ng-class="{ errorClass: isError, warningClass: isWarning, okClass: !isError && !isWarning }">...</div>
|
||||
|
||||
Where you give `ng-class` an object, whose keys are CSS class names and whose values are conditional expressions using `$scope` variables.
|
||||
The element will then have all the classes whose conditions are truthy, and none of those whose conditions are falsy.
|
||||
|
||||
Note also the handy `ng-class-even` and `ng-class-odd`, and the related though somewhat different `ng-style`.
|
||||
|
||||
|
||||
### `$watch` and `$apply`
|
||||
|
||||
Angular's two-way data binding is the root of all awesome in Angular.
|
||||
However, it's not magic, and there are some situations where you need to give it a nudge in the right direction.
|
||||
|
||||
When you bind a value to an element in Angular using `ng-model`, `ng-repeat`, etc., Angular creates a `$watch` on that value.
|
||||
Then whenever a value on a scope changes, all `$watch`es observing that element are executed, and everything updates.
|
||||
|
||||
Sometimes, usually when you're writing a custom directive, you will have to define your own `$watch` on a scope value to make the directive react to changes.
|
||||
|
||||
On the flip side, sometimes you change a scope value in some code but the app doesn't react to it.
|
||||
Angular checks for scope variable changes after pieces of your code have finished running; for example, when `ng-click` calls a function on your scope, Angular will check for changes and react.
|
||||
However, some code is outside of Angular and you'll have to call `scope.$apply()` yourself to trigger the update.
|
||||
This is most commonly seen in event handlers in custom directives.
|
||||
|
||||
### Combining `ng-repeat` with other directives
|
||||
|
||||
`ng-repeat` is extremely useful, one of the most powerful directives in Angular.
|
||||
However the transformation it applies to the DOM is substantial.
|
||||
Therefore applying other directives (such as `ng-show`, `ng-controller` and others) to the same element as `ng-repeat` generally leads to problems.
|
||||
|
||||
If you want to apply a directive to the whole repeat, wrap the repeat in a parent element and put it there.
|
||||
If you want to apply a directive to each inner piece of the repeat, put it on a child of the element with `ng-repeat`.
|
||||
|
||||
### `$rootScope` exists, but it can be used for evil
|
||||
|
||||
Scopes in Angular form a hierarchy, prototypically inheriting from a root scope at the top of the tree.
|
||||
Usually this can be ignored, since most views have a controller, and therefore a scope, of their own.
|
||||
|
||||
Occasionally there are pieces of data that you want to make global to the whole app.
|
||||
For these, you can inject `$rootScope` and set values on it like any other scope.
|
||||
Since the scopes inherit from the root scope, these values will be available to the expressions attached to directives like `ng-show` just like values on your local `$scope`.
|
||||
|
||||
Of course, global state sucks and you should use `$rootScope` sparingly, like you would (hopefully) use with global variables in any language.
|
||||
In particular, don't use it for code, only data.
|
||||
If you're tempted to put a function on `$rootScope`, it's almost always better to put it in a service that can be injected where it's needed, and more easily tested.
|
||||
|
||||
Conversely, don't create a service whose only purpose in life is to store and return bits of data.
|
||||
|
||||
@@ -47,23 +47,20 @@ really digging into it. If you're looking for a shorter introduction to AngularJ
|
||||
# Working with the code
|
||||
|
||||
You can follow this tutorial and hack on the code in either the Mac/Linux or the Windows
|
||||
environment. The tutorial relies on the use of Git versioning system for source code management.
|
||||
You don't need to know anything about Git to follow the tutorial. Select one of the tabs below
|
||||
and follow the instructions for setting up your computer.
|
||||
environment. Options for working with the tutorial are to use the Git versioning system for source
|
||||
code management or to use scripts that copy snapshots of project files into your workspace
|
||||
(`sandbox`) directory. Select one of the tabs below and follow the instructions for setting up your
|
||||
computer for your preferred option.
|
||||
|
||||
<div class="tabbable" show="true">
|
||||
<div class="tab-pane well" id="git-mac" title="Git on Mac/Linux">
|
||||
<ol>
|
||||
<li><p>You will need Node.js and Testacular to run unit tests, so please verify that you have
|
||||
<a href="http://nodejs.org/">Node.js</a> v0.8 or better installed
|
||||
and that the <code>node</code> executable is on your <code>PATH</code> by running the following
|
||||
command in a terminal window:</p>
|
||||
<pre>node --version</pre>
|
||||
<p>Additionally install <a href="http://vojtajina.github.com/testacular">Testacular</a> if you
|
||||
don't have it already:</p>
|
||||
<pre>npm install -g testacular</pre>
|
||||
<li><p>You'll also need Git, which you can get from
|
||||
<a href="http://git-scm.com/download">the Git site</a>.</p></li>
|
||||
<li><p>Verify that you have <a href="http://java.com/">Java</a> installed by running the
|
||||
following command in a terminal window:</p>
|
||||
<pre>java -version</pre>
|
||||
<p>You will need Java to run unit tests.</p></li>
|
||||
<li><p>Download Git from the <a href="http://git-scm.com/download">Git</a> site.</p>
|
||||
<p>You can build Git from source or use the pre-compiled package.</p></li>
|
||||
<li><p>Clone the angular-phonecat repository located at <a
|
||||
href="https://github.com/angular/angular-phonecat">Github</a> by running the following command:</p>
|
||||
<pre>git clone git://github.com/angular/angular-phonecat.git</pre>
|
||||
@@ -74,41 +71,77 @@ directory.</p></li>
|
||||
<p>The tutorial instructions assume you are running all commands from the angular-phonecat
|
||||
directory.</p></li>
|
||||
<li><p>You will need an http server running on your system. Mac and Linux machines typically
|
||||
have Apache pre-installed, but If you don't already have one installed, you can use <code>node</code>
|
||||
to run <code>scripts/web-server.js</code>, a simple bundled http server.</p></li>
|
||||
have Apache pre-installed, but If you don't already have one installed, you can <a
|
||||
href="http://nodejs.org/#download">install node.js</a>. Use <code>node</code> to run
|
||||
<code>scripts/web-server.js</code>, a simple bundled http server.</p></li>
|
||||
</ol>
|
||||
</div>
|
||||
|
||||
<div class="tab-pane well" id="git-win" title="Git on Windows">
|
||||
<ol>
|
||||
<li><p>You will need Node.js and Testacular to run unit tests, so please verify that you have
|
||||
<a href="http://nodejs.org/">Node.js</a> v0.8 or better installed
|
||||
and that the <code>node</code> executable is on your <code>PATH</code> by running the following
|
||||
command in a terminal window:</p>
|
||||
<pre>node --version</pre>
|
||||
<p>Additionally install <a href="http://vojtajina.github.com/testacular">Testacular</a> if you
|
||||
don't have it already:</p>
|
||||
<pre>npm install -g testacular</pre>
|
||||
</li>
|
||||
<li><p>You'll also need Git, which you can get from
|
||||
<a href="http://git-scm.com/download">the Git site</a>.</p></li>
|
||||
<li><p>Clone the angular-phonecat repository located at <a
|
||||
href="https://github.com/angular/angular-phonecat">Github</a> by running the following command:</p>
|
||||
<li><p>You will need Java to run unit tests, so run the following command to verify that you
|
||||
have <a href="http://java.com/">Java</a> installed and that the <code>java</code> executable is on
|
||||
your <code>PATH</code>.</p>
|
||||
<pre>java -version</pre>
|
||||
<p></p></li>
|
||||
<li><p>Install msysGit from <a href="http://git-scm.com/download">the Git</a> site.</p></li>
|
||||
<li><p>Open msysGit bash and clone the angular-phonecat repository located at <a
|
||||
href="https://github.com/angular/angular-phonecat">Github</a> by running the following command:</p>
|
||||
<pre>git clone git://github.com/angular/angular-phonecat.git</pre>
|
||||
<p>This command creates the angular-phonecat directory in your current directory.</p></li>
|
||||
<li><p>Change your current directory to angular-phonecat.</p>
|
||||
<pre>cd angular-phonecat</pre>
|
||||
<p>The tutorial instructions assume you are running all commands from the angular-phonecat
|
||||
directory.</p>
|
||||
<p>You should run all <code>git</code> commands from Git bash.</p>
|
||||
<p>Other commands like <code>test.bat</code> or <code>e2e-test.bat</code> should be
|
||||
<p>You should run all <code>git</code> commands from msysGit bash.</p>
|
||||
<p>Other commands like <code>test-server.bat</code> or <code>test.bat</code> should be
|
||||
executed from the Windows command line.</li>
|
||||
<li><p>You need an http server running on your system, but if you don't already have one
|
||||
already installed, you can use <code>node</code> to run <code>scripts\web-server.js</code>, a simple
|
||||
bundled http server.</p></li>
|
||||
already installed, you can install <a href="http://nodejs.org/#download">node.js</a>. Make sure that
|
||||
<code>nodejs\bin</code> was added into your <code>PATH</code>. Use <code>node</code> to run
|
||||
<code>scripts\web-server.js</code>, a simple bundled http server.</p></li>
|
||||
</ol>
|
||||
</div>
|
||||
|
||||
<div class="tab-pane well" id="ss-mac" title="Snapshots on Mac/Linux">
|
||||
<ol>
|
||||
<li><p>You need Java to run unit tests, so verify that you have <a
|
||||
href="http://java.com/">Java</a> installed by running the following command in a terminal
|
||||
window:</p>
|
||||
<pre>java -version</pre>
|
||||
<li><p>Download the <a href="http://code.angularjs.org/angular-phonecat/">zip archive</a>
|
||||
containing all of the files and unzip them into the [tutorial-dir] directory</p>.</li>
|
||||
<li><p>Change your current directory to [tutorial-dir]/sandbox, as follows:</p>
|
||||
<pre>cd [tutorial-dir]/sandbox</pre>
|
||||
<p>The tutorial instructions assume you are running all commands from your
|
||||
<code>sandbox</code> directory.</p></li>
|
||||
<li><p>You need an http server running on your system and Mac and Linux machines typically
|
||||
have Apache pre-installed. If you don't have an http server installed, you can <a
|
||||
href="http://nodejs.org/#download">install node.js</a> and use it to run
|
||||
<code>scripts/web-server.js</code>, a simple bundled http server.</p></li>
|
||||
</ol>
|
||||
</div>
|
||||
|
||||
<div class="tab-pane well" id="ss-win" title="Snapshots on Windows">
|
||||
<ol>
|
||||
<li><p>Verify that you have <a href="http://java.com/">Java</a> installed and that the
|
||||
<code>java</code> executable is on your <code>PATH</code> by running the following command in the
|
||||
Windows command line:</p>
|
||||
<pre>java -version</pre>
|
||||
<p>You need Java to run unit tests, so download the <a
|
||||
href="http://code.angularjs.org/angular-phonecat/">zip archive</a> that contains all of the files
|
||||
and unzip the files into the [tutorial-dir] directory</p></li>
|
||||
<li><p>Change your current directory to [tutorial-dir]/sandbox, as follows:</p>
|
||||
<pre>cd [tutorial-dir]/sandbox</pre>
|
||||
<p>The tutorial instructions assume you are running all commands from this directory.</p></li>
|
||||
<li><p>You need an http server running on your system, but if you don't already have one
|
||||
already installed, you can install <a href="http://nodejs.org/#download">node.js</a>. Make sure that
|
||||
<code>nodejs\bin</code> was added into your <code>PATH</code>. Use <code>node</code> to run
|
||||
<code>scripts\web-server.js</code>, a simple bundled http server.</p></li>
|
||||
</ol>
|
||||
</div>
|
||||
</divs>
|
||||
|
||||
The last thing to do is to make sure your computer has a web browser and a good text editor
|
||||
installed. Now, let's get some cool stuff done!
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ directory.</li>
|
||||
|
||||
<div class="tab-pane well" id="git-win" title="Git on Windows" value="gitWin">
|
||||
<ol>
|
||||
<li><p>Open Git bash and run this command (in angular-phonecat directory):</p>
|
||||
<li><p>Open msysGit bash and run this command (in angular-phonecat directory):</p>
|
||||
<pre>git checkout -f step-0</pre>
|
||||
<p>This resets your workspace to step 0 of the tutorial app.</p>
|
||||
<p>You must repeat this for every future step in the tutorial and change the number to
|
||||
@@ -74,6 +74,70 @@ directory.</li>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="tab-pane well" id="ss-mac" title="Snapshots on Mac/Linux" value="snapshotUnix">
|
||||
<ol>
|
||||
<li><p>In the angular-phonecat directory, run this command:</p>
|
||||
<pre>./goto_step.sh 0</pre>
|
||||
<p>This resets your workspace to step 0 of the tutorial app.</p>
|
||||
<p>You must repeat this for every future step in the tutorial and change the number to
|
||||
the number of the step you are on. This will cause any changes you made within
|
||||
your working directory to be lost.</p></li>
|
||||
<li>To see the app running in a browser, do one of the following:
|
||||
<ul>
|
||||
<li><b>For node.js users:</b>
|
||||
<ol>
|
||||
<li>In a <i>separate</i> terminal tab or window, run
|
||||
<code>./scripts/web-server.js</code> to start the web server.</li>
|
||||
<li>Open a browser window for the app and navigate to <a
|
||||
href="http://localhost:8000/app/index.html">http://localhost:8000/app/index.html</a></li>
|
||||
</ol>
|
||||
</li>
|
||||
<li><b>For other http servers:</b>
|
||||
<ol>
|
||||
<li>Configure the server to serve the files in the angular-phonecat
|
||||
<code>sandbox</code> directory.</li>
|
||||
<li>Navigate in your browser to
|
||||
<code>http://localhost:[port-number]/[context-path]/app/index.html</code>.</li>
|
||||
</ol>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="tab-pane well" id="ss-win" title="Snapshots on Windows" value="snapshotWin">
|
||||
<ol>
|
||||
<li><p>Open windows command line and run this command (in the angular-phonecat directory):</p>
|
||||
<pre>goto_step.bat 0</pre>
|
||||
<p>This resets your workspace to step 0 of the tutorial app.</p>
|
||||
<p>You must repeat this for every future step in the tutorial and change the number to
|
||||
the number of the step you are on. This will cause any changes you made within
|
||||
your working directory to be lost.</p></li>
|
||||
<li>To see the app running in a browser, do one of the following:
|
||||
<ul>
|
||||
<li><b>For node.js users:</b>
|
||||
<ol>
|
||||
<li>In a <i>separate</i> terminal tab or window, run <code>node
|
||||
scripts\web-server.js</code> to start the web server.</li>
|
||||
<li>Open a browser window for the app and navigate to <a
|
||||
href="http://localhost:8000/app/index.html">http://localhost:8000/app/index.html</a></li>
|
||||
</ol>
|
||||
</li>
|
||||
<li><b>For other http servers:</b>
|
||||
<ol>
|
||||
<li>Configure the server to serve the files in the angular-phonecat
|
||||
<code>sandbox</code> directory.</li>
|
||||
<li>Navigate in your browser to
|
||||
<code>http://localhost:[port-number]/[context-path]/app/index.html</code>.</li>
|
||||
</ol>
|
||||
</li>
|
||||
</ul>
|
||||
</li>
|
||||
</ol>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@
|
||||
<ul doc-tutorial-nav="1"></ul>
|
||||
|
||||
|
||||
In order to illustrate how Angular enhances standard HTML, you will create a purely *static* HTML
|
||||
page and then examine how we can turn this HTML code into a template that Angular will use to
|
||||
In order to illustrate how angular enhances standard HTML, you will create a purely *static* HTML
|
||||
page and then examine how we can turn this HTML code into a template that angular will use to
|
||||
dynamically display the same result with any set of data.
|
||||
|
||||
In this step you will add some basic information about two cell phones to an HTML page.
|
||||
|
||||
@@ -61,7 +61,7 @@ repeater tells Angular to create a `<li>` element for each phone in the list usi
|
||||
tag as the template.
|
||||
|
||||
* As we've learned in step 0, the curly braces around `phone.name` and `phone.snippet` denote
|
||||
bindings. As opposed to evaluating constants, these expressions are referring to our application
|
||||
bindings. As opposed to evaluating constants, these expression are refering to our application
|
||||
model, which was set up in our `PhoneListCtrl` controller.
|
||||
|
||||
<img class="diagram" src="img/tutorial/tutorial_02.png">
|
||||
@@ -146,25 +146,31 @@ http://pivotal.github.com/jasmine/ Jasmine home page} and on the {@link
|
||||
https://github.com/pivotal/jasmine/wiki Jasmine wiki}.
|
||||
|
||||
The angular-seed project is pre-configured to run all unit tests using {@link
|
||||
http://vojtajina.github.com/testacular/ Testacular}. To run the test, do the following:
|
||||
http://code.google.com/p/js-test-driver/ JsTestDriver}. To run the test, do the following:
|
||||
|
||||
1. In a _separate_ terminal window or tab, go to the `angular-phonecat` directory and run
|
||||
`./scripts/test.sh` to start the Testacular server.
|
||||
`./scripts/test-server.sh` to start the test web server.
|
||||
|
||||
2. Testacular will start a new instance of Chrome browser automatically. Just ignore it and let it run in
|
||||
the background. Testacular will use this browser for test execution.
|
||||
2. Open a new browser window and navigate to {@link http://localhost:9876}.
|
||||
|
||||
3. You should see the following or similar output in the terminal:
|
||||
3. Choose "Capture this browser in strict mode".
|
||||
|
||||
info: Testacular server started at http://localhost:9876/
|
||||
info (launcher): Starting browser "Chrome"
|
||||
info (Chrome 22.0): Connected on socket id tPUm9DXcLHtZTKbAEO-n
|
||||
Chrome 22.0: Executed 1 of 1 SUCCESS (0.093 secs / 0.004 secs)
|
||||
At this point, you can leave this window open and forget about it. JsTestDriver will use it to
|
||||
execute the tests and report the results in the terminal.
|
||||
|
||||
4. Execute the test by running `./scripts/test.sh`
|
||||
|
||||
You should see the following or similar output:
|
||||
|
||||
Chrome: Runner reset.
|
||||
.
|
||||
Total 1 tests (Passed: 1; Fails: 0; Errors: 0) (2.00 ms)
|
||||
Chrome 19.0.1084.36 Mac OS: Run 1 tests (Passed: 1; Fails: 0; Errors 0) (2.00 ms)
|
||||
|
||||
Yay! The test passed! Or not...
|
||||
|
||||
4. To rerun the tests, just change any of the source or test files. Testacular will notice the change
|
||||
and will rerun the tests for you. Now isn't that sweet?
|
||||
Note: If you see errors after you run the test, close the browser window and go back to the
|
||||
terminal and kill the script, then repeat the procedure above.
|
||||
|
||||
# Experiments
|
||||
|
||||
@@ -192,7 +198,8 @@ http://vojtajina.github.com/testacular/ Testacular}. To run the test, do the fol
|
||||
<tr ng-repeat="i in [0, 1, 2, 3, 4, 5, 6, 7]"><td>{{i+1}}</td></tr>
|
||||
</table>
|
||||
|
||||
* Make the unit test fail by changing the `toBe(3)` statement to `toBe(4)`.
|
||||
* Make the unit test fail by changing the `toBe(3)` statement to `toBe(4)`, and rerun the
|
||||
`./scripts/test.sh` script.
|
||||
|
||||
|
||||
# Summary
|
||||
|
||||
@@ -54,7 +54,7 @@ __`app/index.html`:__
|
||||
</div>
|
||||
</pre>
|
||||
|
||||
We added a standard HTML `<input>` tag and used Angular's
|
||||
We added a standard HTML `<input>` tag and used angular's
|
||||
{@link api/ng.filter:filter $filter} function to process the input for the
|
||||
{@link api/ng.directive:ngRepeat ngRepeat} directive.
|
||||
|
||||
@@ -122,11 +122,6 @@ To run the end-to-end test, open one of the following in a new browser tab:
|
||||
`http://localhost:[port-number]/[context-path]/test/e2e/runner.html`
|
||||
* casual reader: {@link http://angular.github.com/angular-phonecat/step-3/test/e2e/runner.html}
|
||||
|
||||
Previously we've seen how Testacular can be used to execute unit tests. Well, it can also run the
|
||||
end-to-end tests! Use `./scripts/e2e-test.sh` script for that. End-to-end tests are slow, so unlike
|
||||
with unit tests, Testacular will exit after the test run and will not automatically rerun the test
|
||||
suite on every file change. To rerun the test suite, execute the `e2e-test.sh` script again.
|
||||
|
||||
This test verifies that the search box and the repeater are correctly wired together. Notice how
|
||||
easy it is to write end-to-end tests in Angular. Although this example is for a simple test, it
|
||||
really is that easy to set up any functional, readable, end-to-end test.
|
||||
|
||||
@@ -134,9 +134,13 @@ The unit test now verifies that the default ordering property is set.
|
||||
We used Jasmine's API to extract the controller construction into a `beforeEach` block, which is
|
||||
shared by all tests in the parent `describe` block.
|
||||
|
||||
You should now see the following output in the Testacular tab:
|
||||
To run the unit tests, once again execute the `./scripts/test.sh` script and you should see the
|
||||
following output.
|
||||
|
||||
Chrome 22.0: Executed 2 of 2 SUCCESS (0.021 secs / 0.001 secs)
|
||||
Chrome: Runner reset.
|
||||
..
|
||||
Total 2 tests (Passed: 2; Fails: 0; Errors: 0) (3.00 ms)
|
||||
Chrome 19.0.1084.36 Mac OS: Run 2 tests (Passed: 2; Fails: 0; Errors 0) (3.00 ms)
|
||||
|
||||
|
||||
Let's turn our attention to the end-to-end test.
|
||||
@@ -164,8 +168,8 @@ __`test/e2e/scenarios.js`:__
|
||||
|
||||
The end-to-end test verifies that the ordering mechanism of the select box is working correctly.
|
||||
|
||||
You can now rerun `./scripts/e2e-test.sh` or refresh the browser tab with the end-to-end test
|
||||
`runner.html` to see the tests run, or you can see them running on {@link
|
||||
You can now refresh the browser tab with the end-to-end test runner to see the tests run, or you
|
||||
can see them running on {@link
|
||||
http://angular.github.com/angular-phonecat/step-4/test/e2e/runner.html
|
||||
Angular's server}.
|
||||
|
||||
|
||||
@@ -208,10 +208,13 @@ Finally, we verify that the default value of `orderProp` is set correctly:
|
||||
});
|
||||
</pre>
|
||||
|
||||
You should now see the following output in the Testacular tab:
|
||||
|
||||
Chrome 22.0: Executed 2 of 2 SUCCESS (0.028 secs / 0.007 secs)
|
||||
To run the unit tests, execute the `./scripts/test.sh` script and you should see the following
|
||||
output.
|
||||
|
||||
Chrome: Runner reset.
|
||||
..
|
||||
Total 2 tests (Passed: 2; Fails: 0; Errors: 0) (3.00 ms)
|
||||
Chrome 19.0.1084.36 Mac OS: Run 2 tests (Passed: 2; Fails: 0; Errors 0) (3.00 ms)
|
||||
|
||||
|
||||
# Experiments
|
||||
|
||||
@@ -84,8 +84,8 @@ __`test/e2e/scenarios.js`__:
|
||||
We added a new end-to-end test to verify that the app is generating correct links to the phone
|
||||
views that we will implement in the upcoming steps.
|
||||
|
||||
You can now rerun `./scripts/e2e-test.sh` or refresh the browser tab with the end-to-end test
|
||||
runner to see the tests run, or you can see them running on {@link
|
||||
You can now refresh the browser tab with the end-to-end test runner to see the tests run, or you
|
||||
can see them running on {@link
|
||||
http://angular.github.com/angular-phonecat/step-6/test/e2e/runner.html
|
||||
Angular's server}.
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ history (back and forward navigation) and bookmarks.
|
||||
|
||||
### A Note About DI, Injector and Providers
|
||||
|
||||
As you {@link tutorial/step_05 noticed}, {@link guide/di dependency injection} (DI) is the core feature of
|
||||
As you {@link tutorial/step_05 noticed}, {@link guide/di dependency injection} is the core feature of
|
||||
AngularJS, so it's important for you to understand a thing or two about how it works.
|
||||
|
||||
When the application bootstraps, Angular creates an injector that will be used for all DI stuff in
|
||||
@@ -79,7 +79,7 @@ angular.module('phonecat', []).
|
||||
</pre>
|
||||
|
||||
In order to configure our application with routes, we need to create a module for our application.
|
||||
We call this module `phonecat` and using the `config` API we request the `$routeProvider` to be
|
||||
We call this module `phonecatApp` and using the `config` API we request the `$routeProvider` to be
|
||||
injected into our config function and use `$routeProvider.when` API to define our routes.
|
||||
|
||||
Note that during the injector configuration phase, the providers can be injected as well, but they
|
||||
@@ -232,8 +232,8 @@ to various URLs and verify that the correct view was rendered.
|
||||
</pre>
|
||||
|
||||
|
||||
You can now rerun `./scripts/e2e-test.sh` or refresh the browser tab with the end-to-end test
|
||||
runner to see the tests run, or you can see them running on {@link
|
||||
You can now refresh the browser tab with the end-to-end test runner to see the tests run, or you
|
||||
can see them running on {@link
|
||||
http://angular.github.com/angular-phonecat/step-7/test/e2e/runner.html
|
||||
Angular's server}.
|
||||
|
||||
|
||||
@@ -147,9 +147,13 @@ __`test/unit/controllersSpec.js`:__
|
||||
...
|
||||
</pre>
|
||||
|
||||
You should now see the following output in the Testacular tab:
|
||||
To run the unit tests, execute the `./scripts/test.sh` script and you should see the following
|
||||
output.
|
||||
|
||||
Chrome 22.0: Executed 3 of 3 SUCCESS (0.039 secs / 0.012 secs)
|
||||
Chrome: Runner reset.
|
||||
...
|
||||
Total 3 tests (Passed: 3; Fails: 0; Errors: 0) (5.00 ms)
|
||||
Chrome 19.0.1084.36 Mac OS: Run 3 tests (Passed: 3; Fails: 0; Errors 0) (5.00 ms)
|
||||
|
||||
|
||||
We also added a new end-to-end test that navigates to the Nexus S detail page and verifies that the
|
||||
@@ -173,12 +177,11 @@ __`test/e2e/scenarios.js`:__
|
||||
</pre>
|
||||
|
||||
|
||||
You can now rerun `./scripts/e2e-test.sh` or refresh the browser tab with the end-to-end test
|
||||
runner to see the tests run, or you can see them running on {@link
|
||||
You can now refresh the browser tab with the end-to-end test runner to see the tests run, or you
|
||||
can see them running on {@link
|
||||
http://angular.github.com/angular-phonecat/step-8/test/e2e/runner.html
|
||||
Angular's server}.
|
||||
|
||||
|
||||
# Experiments
|
||||
|
||||
* Using the {@link guide/dev_guide.e2e-testing Angular's end-to-end test runner API}, write a test
|
||||
|
||||
@@ -110,9 +110,13 @@ describe('filter', function() {
|
||||
Note that you need to configure our test injector with the `phonecatFilters` module before any of
|
||||
our filter tests execute.
|
||||
|
||||
You should now see the following output in the Testacular tab:
|
||||
To run the unit tests, execute the `./scripts/test.sh` script and you should see the following
|
||||
output.
|
||||
|
||||
Chrome 22.0: Executed 4 of 4 SUCCESS (0.034 secs / 0.012 secs)
|
||||
Chrome: Runner reset.
|
||||
....
|
||||
Total 4 tests (Passed: 4; Fails: 0; Errors: 0) (3.00 ms)
|
||||
Chrome 19.0.1084.36 Mac OS: Run 4 tests (Passed: 4; Fails: 0; Errors 0) (3.00 ms)
|
||||
|
||||
|
||||
# Experiments
|
||||
|
||||
@@ -102,8 +102,8 @@ __`test/e2e/scenarios.js`:__
|
||||
});
|
||||
</pre>
|
||||
|
||||
You can now rerun `./scripts/e2e-test.sh` or refresh the browser tab with the end-to-end test
|
||||
runner to see the tests run, or you can see them running on {@link
|
||||
You can now refresh the browser tab with the end-to-end test runner to see the tests run, or you
|
||||
can see them running on {@link
|
||||
http://angular.github.com/angular-phonecat/step-8/test/e2e/runner.html
|
||||
Angular's server}.
|
||||
|
||||
|
||||
@@ -214,9 +214,13 @@ describe('PhoneCat controllers', function() {
|
||||
});
|
||||
</pre>
|
||||
|
||||
You should now see the following output in the Testacular tab:
|
||||
To run the unit tests, execute the `./scripts/test.sh` script and you should see the following
|
||||
output.
|
||||
|
||||
Chrome 22.0: Executed 4 of 4 SUCCESS (0.038 secs / 0.01 secs)
|
||||
Chrome: Runner reset.
|
||||
....
|
||||
Total 4 tests (Passed: 4; Fails: 0; Errors: 0) (3.00 ms)
|
||||
Chrome 19.0.1084.36 Mac OS: Run 4 tests (Passed: 4; Fails: 0; Errors 0) (3.00 ms)
|
||||
|
||||
|
||||
# Summary
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
@description
|
||||
|
||||
Our application is now complete. Feel free to experiment with the code further, and jump back to
|
||||
previous steps using the `git checkout` command.
|
||||
previous steps using the `git checkout` or `goto_step.sh` commands.
|
||||
|
||||
For more details and examples of the Angular concepts we touched on in this tutorial, see the
|
||||
{@link guide/ Developer Guide}.
|
||||
|
||||
@@ -36,7 +36,7 @@ writer.makeDir('build/docs/', true).then(function() {
|
||||
});
|
||||
}).then(function printStats() {
|
||||
console.log('DONE. Generated ' + docs.length + ' pages in ' + (now()-start) + 'ms.' );
|
||||
}).done();
|
||||
}).end();
|
||||
|
||||
|
||||
function writeTheRest(writesFuture) {
|
||||
@@ -82,7 +82,10 @@ function writeTheRest(writesFuture) {
|
||||
writesFuture.push(writer.output('appcache.manifest',appCache()));
|
||||
writesFuture.push(writer.copyTemplate('.htaccess')); // will be rewritten, don't symlink
|
||||
|
||||
writesFuture.push(writer.symlinkTemplate('app.yaml'));
|
||||
writesFuture.push(writer.symlinkTemplate('index.yaml'));
|
||||
writesFuture.push(writer.symlinkTemplate('favicon.ico'));
|
||||
writesFuture.push(writer.symlinkTemplate('main.py'));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -6,7 +6,6 @@
|
||||
#
|
||||
# This file must be processed by Rake in order to replace %ANGULAR_VERSION% with the actual version.
|
||||
|
||||
Options -Indexes
|
||||
RewriteEngine on
|
||||
RewriteCond %{HTTP_COOKIE} ng-offline="NG_VERSION_FULL"
|
||||
RewriteRule appcache.manifest appcache-offline.manifest
|
||||
|
||||
@@ -0,0 +1,69 @@
|
||||
application: docs-angularjs-org
|
||||
version: 1
|
||||
runtime: python27
|
||||
api_version: 1
|
||||
threadsafe: yes
|
||||
default_expiration: "2h"
|
||||
|
||||
handlers:
|
||||
- url: /
|
||||
script: main.app
|
||||
|
||||
- url: /appcache.manifest
|
||||
static_files: appcache.manifest
|
||||
upload: appcache\.manifest
|
||||
|
||||
- url: /docs-scenario.html
|
||||
static_files: docs-scenario.html
|
||||
upload: docs-scenario\.html
|
||||
|
||||
- url: /docs-scenario.js
|
||||
static_files: docs-scenario.js
|
||||
upload: docs-scenario\.js
|
||||
|
||||
- url: /favicon\.ico
|
||||
static_files: favicon.ico
|
||||
upload: favicon\.ico
|
||||
|
||||
- url: /docs-keywords.js
|
||||
static_files: docs-keywords.js
|
||||
upload: docs-keywords\.js
|
||||
|
||||
- url: /robots.txt
|
||||
static_files: robots.txt
|
||||
upload: robots\.txt
|
||||
|
||||
- url: /sitemap.xml
|
||||
static_files: sitemap.xml
|
||||
upload: sitemap\.xml
|
||||
|
||||
- url: /css
|
||||
static_dir: css
|
||||
|
||||
- url: /font
|
||||
static_dir: font
|
||||
|
||||
- url: /img
|
||||
static_dir: img
|
||||
|
||||
- url: /js
|
||||
static_dir: js
|
||||
|
||||
- url: /partials/(.+):(.+)
|
||||
static_files: partials/\1_\2
|
||||
upload: partials/.*
|
||||
|
||||
- url: /partials
|
||||
static_dir: partials
|
||||
|
||||
- url: /syntaxhighlighter
|
||||
static_dir: syntaxhighlighter
|
||||
|
||||
- url: /.*
|
||||
static_files: index.html
|
||||
upload: index.html
|
||||
|
||||
|
||||
libraries:
|
||||
- name: webapp2
|
||||
version: "2.5.1"
|
||||
@@ -3,7 +3,7 @@
|
||||
<head>
|
||||
<title>AngularJS Docs E2E Test Runner</title>
|
||||
<script>
|
||||
var production = location.hostname === 'docs.angularjs.org',
|
||||
var gae = (location.pathname.split('/').length == 2),
|
||||
headEl = document.head,
|
||||
angularVersion = {
|
||||
current: '"NG_VERSION_FULL"', // rewrite during build
|
||||
@@ -33,8 +33,9 @@
|
||||
|
||||
|
||||
function path(name) {
|
||||
return production
|
||||
? 'http://code.angularjs.org/' + angularVersion.stable + '/' + name
|
||||
return gae
|
||||
? 'http://code.angularjs.org/' + angularVersion.stable + '/' +
|
||||
name.replace(/\.js$/, '-' + angularVersion.stable + '.js')
|
||||
: '../' + name;
|
||||
}
|
||||
</script>
|
||||
|
||||
@@ -22,7 +22,7 @@
|
||||
baseUrl = location.href.replace(rUrl, indexFile),
|
||||
jQuery = /index-jq[^\.]*\.html$/.test(baseUrl),
|
||||
debug = /index[^\.]*-debug\.html$/.test(baseUrl),
|
||||
production = location.hostname === 'docs.angularjs.org',
|
||||
gae = (baseUrl.split('/').length == 4),
|
||||
headEl = document.getElementsByTagName('head')[0],
|
||||
sync = true,
|
||||
angularVersion = {
|
||||
@@ -45,7 +45,7 @@
|
||||
addTag('script', {src: 'docs-keywords.js'}, sync);
|
||||
|
||||
function path(name) {
|
||||
if (production) {
|
||||
if (gae) {
|
||||
if (name.match(/^angular(-\w+)?\.js/) && !name.match(/bootstrap/)) {
|
||||
name = '//ajax.googleapis.com/ajax/libs/angularjs/' +
|
||||
angularVersion.stable +
|
||||
@@ -55,7 +55,7 @@
|
||||
name = 'http://code.angularjs.org/' +
|
||||
angularVersion.stable +
|
||||
'/' +
|
||||
name.replace(/\.js$/, '.min.js');
|
||||
name.replace(/\.js$/, '-' + angularVersion.stable +'.min.js');
|
||||
}
|
||||
return name;
|
||||
}
|
||||
@@ -122,14 +122,14 @@
|
||||
<li><a href="http://angularjs.org"><i class="icon-home icon-white"></i> Home</a></li>
|
||||
<li class="divider-vertical"></li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
|
||||
<a href="" class="dropdown-toggle" data-toggle="dropdown">
|
||||
<i class="icon-eye-open icon-white"></i> Learn <b class="caret"></b>
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li class="disabled"><a href="http://angularjs.org/">Why AngularJS?</a></li>
|
||||
<li class="disabled"><a href="">Why AngularJS?</a></li>
|
||||
<li><a href="http://www.youtube.com/user/angularjs">Watch</a></li>
|
||||
<li><a href="tutorial">Tutorial</a></li>
|
||||
<li><a href="http://builtwith.angularjs.org/">Case Studies</a></li>
|
||||
<li><a href="https://github.com/angular/angular.js/wiki/Projects-using-AngularJS">Case Studies</a></li>
|
||||
<li><a href="misc/faq">FAQ</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
@@ -139,16 +139,16 @@
|
||||
<i class="icon-book icon-white"></i> Develop <b class="caret"></b>
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a href="http://docs.angularjs.org/tutorial">Tutorial</a></li>
|
||||
<li><a href="http://docs.angularjs.org/guide/">Developer Guide</a></li>
|
||||
<li><a href="http://docs.angularjs.org/api/">API Reference</a></li>
|
||||
<li><a href="http://docs.angularjs.org/misc/contribute">Contribute</a></li>
|
||||
<li><a href="tutorial">Tutorial</a></li>
|
||||
<li><a href="guide/">Developer Guide</a></li>
|
||||
<li><a href="api/">API Reference</a></li>
|
||||
<li><a href="misc/contribute">Contribute</a></li>
|
||||
<li><a href="http://code.angularjs.org/">Download</a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="divider-vertical"></li>
|
||||
<li class="dropdown">
|
||||
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
|
||||
<a href="" class="dropdown-toggle" data-toggle="dropdown">
|
||||
<i class="icon-comment icon-white"></i> Discuss <b class="caret"></b>
|
||||
</a>
|
||||
<ul class="dropdown-menu">
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
indexes:
|
||||
|
||||
# AUTOGENERATED
|
||||
|
||||
# This index.yaml is automatically updated whenever the dev_appserver
|
||||
# detects that a new type of query is run. If you want to manage the
|
||||
# index.yaml file manually, remove the above marker line (the line
|
||||
# saying "# AUTOGENERATED"). If you want to manage some indexes
|
||||
# manually, move them above the marker line. The index.yaml file is
|
||||
# automatically uploaded to the admin console when you next deploy
|
||||
# your application using appcfg.py.
|
||||
|
||||
@@ -30,17 +30,9 @@ docsApp.directive.code = function() {
|
||||
|
||||
docsApp.directive.sourceEdit = function(getEmbeddedTemplate) {
|
||||
return {
|
||||
template: '<div class="btn-group pull-right">' +
|
||||
'<a class="btn dropdown-toggle btn-primary" data-toggle="dropdown" href>' +
|
||||
' <i class="icon-pencil icon-white"></i> Edit<span class="caret"></span>' +
|
||||
'</a>' +
|
||||
'<ul class="dropdown-menu">' +
|
||||
' <li><a ng-click="plunkr($event)" href="">In Plunkr</a></li>' +
|
||||
' <li><a ng-click="fiddle($event)" href="">In JsFiddle</a></li>' +
|
||||
'</ul>' +
|
||||
'</div>',
|
||||
template: '<button ng-click="fiddle($event)" class="btn btn-primary pull-right"><i class="icon-pencil icon-white"></i> Edit</button>\n',
|
||||
scope: true,
|
||||
controller: function($scope, $attrs, openJsFiddle, openPlunkr) {
|
||||
controller: function($scope, $attrs, openJsFiddle) {
|
||||
var sources = {
|
||||
module: $attrs.sourceEdit,
|
||||
deps: read($attrs.sourceEditDeps),
|
||||
@@ -53,19 +45,14 @@ docsApp.directive.sourceEdit = function(getEmbeddedTemplate) {
|
||||
$scope.fiddle = function(e) {
|
||||
e.stopPropagation();
|
||||
openJsFiddle(sources);
|
||||
};
|
||||
$scope.plunkr = function(e) {
|
||||
e.stopPropagation();
|
||||
openPlunkr(sources);
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function read(text) {
|
||||
var files = [];
|
||||
angular.forEach(text ? text.split(' ') : [], function(refId) {
|
||||
// refId is index.html-343, so we need to strip the unique ID when exporting the name
|
||||
files.push({name: refId.replace(/-\d+$/, ''), content: getEmbeddedTemplate(refId)});
|
||||
files.push({name: refId.split('-')[0], content: getEmbeddedTemplate(refId)});
|
||||
});
|
||||
return files;
|
||||
}
|
||||
@@ -124,6 +111,8 @@ docsApp.directive.docTutorialReset = function() {
|
||||
'<div class="tabbable" ng-show="show" ng-model="$cookies.platformPreference">\n' +
|
||||
tab('Git on Mac/Linux', 'git checkout -f step-' + step, 'gitUnix', step) +
|
||||
tab('Git on Windows', 'git checkout -f step-' + step, 'gitWin', step) +
|
||||
tab('Snapshots on Mac/Linux', './goto_step.sh ' + step, 'snapshotUnix', step) +
|
||||
tab('Snapshots on on Windows', './goto_step.bat ' + step, 'snapshotWin', step) +
|
||||
'</div>\n');
|
||||
}
|
||||
};
|
||||
@@ -158,49 +147,8 @@ docsApp.serviceFactory.formPostData = function($document) {
|
||||
};
|
||||
};
|
||||
|
||||
docsApp.serviceFactory.openPlunkr = function(templateMerge, formPostData, angularUrls) {
|
||||
return function(content) {
|
||||
var allFiles = [].concat(content.js, content.css, content.html);
|
||||
var indexHtmlContent = '<!doctype html>\n' +
|
||||
'<html ng-app>\n' +
|
||||
' <head>\n' +
|
||||
' <script src="{{angularJSUrl}}"></script>\n' +
|
||||
'{{scriptDeps}}\n' +
|
||||
' </head>\n' +
|
||||
' <body>\n\n' +
|
||||
'{{indexContents}}' +
|
||||
'\n\n </body>\n' +
|
||||
'</html>\n';
|
||||
var scriptDeps = '';
|
||||
angular.forEach(content.deps, function(file) {
|
||||
if (file.name !== 'angular.js') {
|
||||
scriptDeps += ' <script src="' + file.name + '"></script>\n'
|
||||
}
|
||||
});
|
||||
indexProp = {
|
||||
angularJSUrl: angularUrls['angular.js'],
|
||||
scriptDeps: scriptDeps,
|
||||
indexContents: content.html[0].content
|
||||
};
|
||||
var postData = {};
|
||||
angular.forEach(allFiles, function(file, index) {
|
||||
if (file.content && file.name != 'index.html') {
|
||||
postData['files[' + file.name + ']'] = file.content;
|
||||
}
|
||||
});
|
||||
|
||||
postData['files[index.html]'] = templateMerge(indexHtmlContent, indexProp);
|
||||
postData['tags[]'] = "angularjs";
|
||||
|
||||
postData.private = true;
|
||||
postData.description = 'AngularJS Example Plunkr';
|
||||
|
||||
formPostData('http://plnkr.co/edit/?p=preview', postData);
|
||||
};
|
||||
};
|
||||
|
||||
docsApp.serviceFactory.openJsFiddle = function(templateMerge, formPostData, angularUrls) {
|
||||
|
||||
docsApp.serviceFactory.openJsFiddle = function(templateMerge, getEmbeddedTemplate, formPostData, angularUrls) {
|
||||
var HTML = '<div ng-app=\"{{module}}\">\n{{html:2}}</div>',
|
||||
CSS = '</style> <!-- Ugly Hack due to jsFiddle issue: http://goo.gl/BUfGZ --> \n' +
|
||||
'{{head:0}}<style>\n.ng-invalid { border: 1px solid red; }\n{{css}}',
|
||||
@@ -349,7 +297,7 @@ docsApp.controller.DocsController = function($scope, $location, $window, $cookie
|
||||
tutorial: 'Tutorial',
|
||||
cookbook: 'Examples'
|
||||
};
|
||||
$scope.$watch(function docsPathWatch() {return $location.path(); }, function docsPathWatchAction(path) {
|
||||
$scope.$watch(function() {return $location.path(); }, function(path) {
|
||||
// ignore non-doc links which are used in examples
|
||||
if (DOCS_PATH.test(path)) {
|
||||
var parts = path.split('/'),
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
import webapp2
|
||||
from google.appengine.ext.webapp import template
|
||||
|
||||
|
||||
class IndexHandler(webapp2.RequestHandler):
|
||||
def get(self):
|
||||
fragment = self.request.get('_escaped_fragment_')
|
||||
|
||||
if fragment:
|
||||
fragment = '/partials' + fragment + '.html'
|
||||
self.redirect(fragment, permanent=True)
|
||||
else:
|
||||
self.response.headers['Content-Type'] = 'text/html'
|
||||
self.response.out.write(template.render('index-nocache.html', None))
|
||||
|
||||
|
||||
app = webapp2.WSGIApplication([('/', IndexHandler)])
|
||||
|
||||
+3
-2
@@ -1,9 +1,10 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
JASMINE_NODE='jasmine-node'
|
||||
local_jasmine='./node_modules/.bin/jasmine-node'
|
||||
|
||||
if ! type -p "$JASMINE_NODE" >/dev/null 2>&1;then
|
||||
# Locally (npm)-installed jasmine-node
|
||||
local_jasmine='./node_modules/.bin/jasmine-node'
|
||||
|
||||
if [[ -x "$local_jasmine" ]];then
|
||||
JASMINE_NODE="$local_jasmine"
|
||||
else
|
||||
|
||||
Executable
+47
@@ -0,0 +1,47 @@
|
||||
#!/usr/bin/env node
|
||||
/* This file reads in list of files from angularFiles.js and generate various jstd config files */
|
||||
|
||||
var fs = require('fs'),
|
||||
angularSrc,
|
||||
angularScenario;
|
||||
|
||||
fs.readFile('angularFiles.js', function(err, data) {
|
||||
eval(data.toString());
|
||||
var prefix = 'server: http://localhost:9876\n\n',
|
||||
prefixScenario = 'server: http://localhost:9877\n\n';
|
||||
|
||||
angularSrc = angularFiles.angularSrc.join('\n- ');
|
||||
angularScenario = angularFiles.angularScenario.join('\n- ');
|
||||
|
||||
fs.writeFile('./jsTestDriver.conf', prefix + combine(angularFiles.jstd,
|
||||
angularFiles.jstdExclude));
|
||||
|
||||
fs.writeFile('./jsTestDriver-modules.conf', prefix + combine(angularFiles.jstdModules));
|
||||
|
||||
fs.writeFile('./jsTestDriver-scenario.conf', prefixScenario +
|
||||
combine(angularFiles.jstdScenario) +
|
||||
'\n\nproxy:\n- {matcher: "*", server: "http://localhost:8000"}');
|
||||
|
||||
fs.writeFile('./jsTestDriver-perf.conf', prefix + combine(angularFiles.jstdPerf,
|
||||
angularFiles.jstdPerfExclude));
|
||||
|
||||
fs.writeFile('./jsTestDriver-jquery.conf', prefix + combine(angularFiles.jstdJquery,
|
||||
angularFiles.jstdJqueryExclude));
|
||||
|
||||
fs.writeFile('./jsTestDriver-coverage.conf', prefix +
|
||||
combine(angularFiles.jstd, angularFiles.jstdExclude) +
|
||||
'\n\nplugin:\n- name: "coverage"\n' +
|
||||
'jar: "lib/jstestdriver/coverage.jar"\n' +
|
||||
'module: "com.google.jstestdriver.coverage.CoverageModule"');
|
||||
});
|
||||
|
||||
function combine(load, exclude) {
|
||||
var fileList = 'load:\n- ' + load.join('\n- ');
|
||||
if (exclude) fileList += ('\n\nexclude:\n- ' + exclude.join('\n- '));
|
||||
|
||||
//Replace placeholders for src list before returning
|
||||
return fileList.replace(/@(.*)/g, function(all, alias) {
|
||||
return angularFiles[alias].join('\n- ');
|
||||
});
|
||||
}
|
||||
|
||||
@@ -1,32 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
#
|
||||
# Script to initialize angular repo
|
||||
# - install required node packages
|
||||
# - install Testacular
|
||||
# - install git hooks
|
||||
|
||||
|
||||
node=`which node 2>&1`
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Please install NodeJS."
|
||||
echo "http://nodejs.org/"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
npm=`which npm 2>&1`
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Please install NPM."
|
||||
fi
|
||||
|
||||
|
||||
echo "Installing required npm packages..."
|
||||
npm install
|
||||
|
||||
testacular=`which testacular 2>&1`
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "Installing Testacular..."
|
||||
npm install -g testacular
|
||||
fi
|
||||
|
||||
echo "Installing git hooks..."
|
||||
ln -sf ../../validate-commit-msg.js .git/hooks/commit-msg
|
||||
@@ -0,0 +1,2 @@
|
||||
#!/bin/sh
|
||||
/System/Library/Frameworks/JavaVM.framework/Versions/1.6/Commands/java $@
|
||||
@@ -0,0 +1,198 @@
|
||||
/**
|
||||
* @fileoverview Jasmine JsTestDriver Adapter.
|
||||
* @author misko@hevery.com (Misko Hevery)
|
||||
*/
|
||||
(function(window) {
|
||||
var rootDescribes = new Describes(window);
|
||||
var describePath = [];
|
||||
rootDescribes.collectMode();
|
||||
|
||||
var JASMINE_TYPE = 'jasmine test case';
|
||||
TestCase('Jasmine Adapter Tests', null, JASMINE_TYPE);
|
||||
|
||||
var jasminePlugin = {
|
||||
name:'jasmine',
|
||||
|
||||
getTestRunsConfigurationFor: function(testCaseInfos, expressions, testRunsConfiguration) {
|
||||
for (var i = 0; i < testCaseInfos.length; i++) {
|
||||
if (testCaseInfos[i].getType() == JASMINE_TYPE) {
|
||||
testRunsConfiguration.push(new jstestdriver.TestRunConfiguration(testCaseInfos[i], []));
|
||||
}
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
runTestConfiguration: function(testRunConfiguration, onTestDone, onTestRunConfigurationComplete){
|
||||
if (testRunConfiguration.getTestCaseInfo().getType() != JASMINE_TYPE) return false;
|
||||
|
||||
var jasmineEnv = jasmine.currentEnv_ = new jasmine.Env();
|
||||
rootDescribes.playback();
|
||||
var specLog = jstestdriver.console.log_ = [];
|
||||
var start;
|
||||
jasmineEnv.specFilter = function(spec) {
|
||||
return rootDescribes.isExclusive(spec);
|
||||
};
|
||||
jasmineEnv.reporter = {
|
||||
log: function(str){
|
||||
specLog.push(str);
|
||||
},
|
||||
|
||||
reportRunnerStarting: function(runner) { },
|
||||
|
||||
reportSpecStarting: function(spec) {
|
||||
specLog = jstestdriver.console.log_ = [];
|
||||
start = new Date().getTime();
|
||||
},
|
||||
|
||||
reportSpecResults: function(spec) {
|
||||
var suite = spec.suite;
|
||||
var results = spec.results();
|
||||
if (results.skipped) return;
|
||||
var end = new Date().getTime();
|
||||
var messages = [];
|
||||
var resultItems = results.getItems();
|
||||
var state = 'passed';
|
||||
for ( var i = 0; i < resultItems.length; i++) {
|
||||
if (!resultItems[i].passed()) {
|
||||
state = resultItems[i].message.match(/AssertionError:/) ? 'error' : 'failed';
|
||||
messages.push({
|
||||
message: resultItems[i].toString(),
|
||||
name: resultItems[i].trace.name,
|
||||
stack: formatStack(resultItems[i].trace.stack)
|
||||
});
|
||||
}
|
||||
}
|
||||
onTestDone(
|
||||
new jstestdriver.TestResult(
|
||||
suite.getFullName(),
|
||||
spec.description,
|
||||
state,
|
||||
jstestdriver.angular.toJson(messages),
|
||||
specLog.join('\n'),
|
||||
end - start));
|
||||
},
|
||||
|
||||
reportSuiteResults: function(suite) {},
|
||||
|
||||
reportRunnerResults: function(runner) {
|
||||
onTestRunConfigurationComplete();
|
||||
}
|
||||
};
|
||||
jasmineEnv.execute();
|
||||
return true;
|
||||
},
|
||||
|
||||
onTestsFinish: function(){
|
||||
jasmine.currentEnv_ = null;
|
||||
rootDescribes.collectMode();
|
||||
}
|
||||
};
|
||||
jstestdriver.pluginRegistrar.register(jasminePlugin);
|
||||
|
||||
function formatStack(stack) {
|
||||
var lines = (stack||'').split(/\r?\n/);
|
||||
var frames = [];
|
||||
for (i = 0; i < lines.length; i++) {
|
||||
if (!lines[i].match(/\/jasmine[\.-]/)) {
|
||||
frames.push(lines[i].replace(/https?:\/\/\w+(:\d+)?\/test\//, '').replace(/^\s*/, ' '));
|
||||
}
|
||||
}
|
||||
return frames.join('\n');
|
||||
}
|
||||
|
||||
function noop(){}
|
||||
function Describes(window){
|
||||
var describes = {};
|
||||
var beforeEachs = {};
|
||||
var afterEachs = {};
|
||||
// Here we store:
|
||||
// 0: everyone runs
|
||||
// 1: run everything under ddescribe
|
||||
// 2: run only iits (ignore ddescribe)
|
||||
var exclusive = 0;
|
||||
var collectMode = true;
|
||||
intercept('describe', describes);
|
||||
intercept('xdescribe', describes);
|
||||
intercept('beforeEach', beforeEachs);
|
||||
intercept('afterEach', afterEachs);
|
||||
|
||||
function intercept(functionName, collection){
|
||||
window[functionName] = function(desc, fn){
|
||||
if (collectMode) {
|
||||
collection[desc] = function(){
|
||||
jasmine.getEnv()[functionName](desc, fn);
|
||||
};
|
||||
} else {
|
||||
jasmine.getEnv()[functionName](desc, fn);
|
||||
}
|
||||
};
|
||||
}
|
||||
window.ddescribe = function(name, fn){
|
||||
if (exclusive < 1) {
|
||||
exclusive = 1; // run ddescribe only
|
||||
}
|
||||
window.describe(name, function(){
|
||||
var oldIt = window.it;
|
||||
window.it = function(name, fn){
|
||||
if (fn) fn.exclusive = 1; // run anything under ddescribe
|
||||
oldIt(name, fn);
|
||||
};
|
||||
try {
|
||||
fn.call(this);
|
||||
} finally {
|
||||
window.it = oldIt;
|
||||
};
|
||||
});
|
||||
};
|
||||
window.iit = function(name, fn){
|
||||
exclusive = fn.exclusive = 2; // run only iits
|
||||
jasmine.getEnv().it(name, fn);
|
||||
};
|
||||
|
||||
|
||||
this.collectMode = function() {
|
||||
collectMode = true;
|
||||
exclusive = 0; // run everything
|
||||
};
|
||||
this.playback = function(){
|
||||
collectMode = false;
|
||||
playback(beforeEachs);
|
||||
playback(afterEachs);
|
||||
playback(describes);
|
||||
|
||||
function playback(set) {
|
||||
for ( var name in set) {
|
||||
set[name]();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
this.isExclusive = function(spec) {
|
||||
if (exclusive) {
|
||||
var blocks = spec.queue.blocks;
|
||||
for ( var i = 0; i < blocks.length; i++) {
|
||||
if (blocks[i].func.exclusive >= exclusive) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
};
|
||||
}
|
||||
|
||||
})(window);
|
||||
|
||||
// Patch Jasmine for proper stack traces
|
||||
jasmine.Spec.prototype.fail = function (e) {
|
||||
var expectationResult = new jasmine.ExpectationResult({
|
||||
passed: false,
|
||||
message: e ? jasmine.util.formatException(e) : 'Exception'
|
||||
});
|
||||
// PATCH
|
||||
if (e) {
|
||||
expectationResult.trace = e;
|
||||
}
|
||||
this.results_.addResult(expectationResult);
|
||||
};
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
da92db714142b49f9cf61db664e782bb0ccad80b
|
||||
@@ -0,0 +1,20 @@
|
||||
Copyright (c) 2008-2011 Pivotal Labs
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of this software and associated documentation files (the
|
||||
"Software"), to deal in the Software without restriction, including
|
||||
without limitation the rights to use, copy, modify, merge, publish,
|
||||
distribute, sublicense, and/or sell copies of the Software, and to
|
||||
permit persons to whom the Software is furnished to do so, subject to
|
||||
the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be
|
||||
included in all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
@@ -0,0 +1,190 @@
|
||||
jasmine.TrivialReporter = function(doc) {
|
||||
this.document = doc || document;
|
||||
this.suiteDivs = {};
|
||||
this.logRunningSpecs = false;
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.createDom = function(type, attrs, childrenVarArgs) {
|
||||
var el = document.createElement(type);
|
||||
|
||||
for (var i = 2; i < arguments.length; i++) {
|
||||
var child = arguments[i];
|
||||
|
||||
if (typeof child === 'string') {
|
||||
el.appendChild(document.createTextNode(child));
|
||||
} else {
|
||||
if (child) { el.appendChild(child); }
|
||||
}
|
||||
}
|
||||
|
||||
for (var attr in attrs) {
|
||||
if (attr == "className") {
|
||||
el[attr] = attrs[attr];
|
||||
} else {
|
||||
el.setAttribute(attr, attrs[attr]);
|
||||
}
|
||||
}
|
||||
|
||||
return el;
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.reportRunnerStarting = function(runner) {
|
||||
var showPassed, showSkipped;
|
||||
|
||||
this.outerDiv = this.createDom('div', { className: 'jasmine_reporter' },
|
||||
this.createDom('div', { className: 'banner' },
|
||||
this.createDom('div', { className: 'logo' },
|
||||
this.createDom('span', { className: 'title' }, "Jasmine"),
|
||||
this.createDom('span', { className: 'version' }, runner.env.versionString())),
|
||||
this.createDom('div', { className: 'options' },
|
||||
"Show ",
|
||||
showPassed = this.createDom('input', { id: "__jasmine_TrivialReporter_showPassed__", type: 'checkbox' }),
|
||||
this.createDom('label', { "for": "__jasmine_TrivialReporter_showPassed__" }, " passed "),
|
||||
showSkipped = this.createDom('input', { id: "__jasmine_TrivialReporter_showSkipped__", type: 'checkbox' }),
|
||||
this.createDom('label', { "for": "__jasmine_TrivialReporter_showSkipped__" }, " skipped")
|
||||
)
|
||||
),
|
||||
|
||||
this.runnerDiv = this.createDom('div', { className: 'runner running' },
|
||||
this.createDom('a', { className: 'run_spec', href: '?' }, "run all"),
|
||||
this.runnerMessageSpan = this.createDom('span', {}, "Running..."),
|
||||
this.finishedAtSpan = this.createDom('span', { className: 'finished-at' }, ""))
|
||||
);
|
||||
|
||||
this.document.body.appendChild(this.outerDiv);
|
||||
|
||||
var suites = runner.suites();
|
||||
for (var i = 0; i < suites.length; i++) {
|
||||
var suite = suites[i];
|
||||
var suiteDiv = this.createDom('div', { className: 'suite' },
|
||||
this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, "run"),
|
||||
this.createDom('a', { className: 'description', href: '?spec=' + encodeURIComponent(suite.getFullName()) }, suite.description));
|
||||
this.suiteDivs[suite.id] = suiteDiv;
|
||||
var parentDiv = this.outerDiv;
|
||||
if (suite.parentSuite) {
|
||||
parentDiv = this.suiteDivs[suite.parentSuite.id];
|
||||
}
|
||||
parentDiv.appendChild(suiteDiv);
|
||||
}
|
||||
|
||||
this.startedAt = new Date();
|
||||
|
||||
var self = this;
|
||||
showPassed.onclick = function(evt) {
|
||||
if (showPassed.checked) {
|
||||
self.outerDiv.className += ' show-passed';
|
||||
} else {
|
||||
self.outerDiv.className = self.outerDiv.className.replace(/ show-passed/, '');
|
||||
}
|
||||
};
|
||||
|
||||
showSkipped.onclick = function(evt) {
|
||||
if (showSkipped.checked) {
|
||||
self.outerDiv.className += ' show-skipped';
|
||||
} else {
|
||||
self.outerDiv.className = self.outerDiv.className.replace(/ show-skipped/, '');
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.reportRunnerResults = function(runner) {
|
||||
var results = runner.results();
|
||||
var className = (results.failedCount > 0) ? "runner failed" : "runner passed";
|
||||
this.runnerDiv.setAttribute("class", className);
|
||||
//do it twice for IE
|
||||
this.runnerDiv.setAttribute("className", className);
|
||||
var specs = runner.specs();
|
||||
var specCount = 0;
|
||||
for (var i = 0; i < specs.length; i++) {
|
||||
if (this.specFilter(specs[i])) {
|
||||
specCount++;
|
||||
}
|
||||
}
|
||||
var message = "" + specCount + " spec" + (specCount == 1 ? "" : "s" ) + ", " + results.failedCount + " failure" + ((results.failedCount == 1) ? "" : "s");
|
||||
message += " in " + ((new Date().getTime() - this.startedAt.getTime()) / 1000) + "s";
|
||||
this.runnerMessageSpan.replaceChild(this.createDom('a', { className: 'description', href: '?'}, message), this.runnerMessageSpan.firstChild);
|
||||
|
||||
this.finishedAtSpan.appendChild(document.createTextNode("Finished at " + new Date().toString()));
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.reportSuiteResults = function(suite) {
|
||||
var results = suite.results();
|
||||
var status = results.passed() ? 'passed' : 'failed';
|
||||
if (results.totalCount === 0) { // todo: change this to check results.skipped
|
||||
status = 'skipped';
|
||||
}
|
||||
this.suiteDivs[suite.id].className += " " + status;
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.reportSpecStarting = function(spec) {
|
||||
if (this.logRunningSpecs) {
|
||||
this.log('>> Jasmine Running ' + spec.suite.description + ' ' + spec.description + '...');
|
||||
}
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.reportSpecResults = function(spec) {
|
||||
var results = spec.results();
|
||||
var status = results.passed() ? 'passed' : 'failed';
|
||||
if (results.skipped) {
|
||||
status = 'skipped';
|
||||
}
|
||||
var specDiv = this.createDom('div', { className: 'spec ' + status },
|
||||
this.createDom('a', { className: 'run_spec', href: '?spec=' + encodeURIComponent(spec.getFullName()) }, "run"),
|
||||
this.createDom('a', {
|
||||
className: 'description',
|
||||
href: '?spec=' + encodeURIComponent(spec.getFullName()),
|
||||
title: spec.getFullName()
|
||||
}, spec.description));
|
||||
|
||||
|
||||
var resultItems = results.getItems();
|
||||
var messagesDiv = this.createDom('div', { className: 'messages' });
|
||||
for (var i = 0; i < resultItems.length; i++) {
|
||||
var result = resultItems[i];
|
||||
|
||||
if (result.type == 'log') {
|
||||
messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage log'}, result.toString()));
|
||||
} else if (result.type == 'expect' && result.passed && !result.passed()) {
|
||||
messagesDiv.appendChild(this.createDom('div', {className: 'resultMessage fail'}, result.message));
|
||||
|
||||
if (result.trace.stack) {
|
||||
messagesDiv.appendChild(this.createDom('div', {className: 'stackTrace'}, result.trace.stack));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (messagesDiv.childNodes.length > 0) {
|
||||
specDiv.appendChild(messagesDiv);
|
||||
}
|
||||
|
||||
this.suiteDivs[spec.suite.id].appendChild(specDiv);
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.log = function() {
|
||||
var console = jasmine.getGlobal().console;
|
||||
if (console && console.log) {
|
||||
if (console.log.apply) {
|
||||
console.log.apply(console, arguments);
|
||||
} else {
|
||||
console.log(arguments); // ie fix: console.log.apply doesn't exist on ie
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.getLocation = function() {
|
||||
return this.document.location;
|
||||
};
|
||||
|
||||
jasmine.TrivialReporter.prototype.specFilter = function(spec) {
|
||||
var paramMap = {};
|
||||
var params = this.getLocation().search.substring(1).split('&');
|
||||
for (var i = 0; i < params.length; i++) {
|
||||
var p = params[i].split('=');
|
||||
paramMap[decodeURIComponent(p[0])] = decodeURIComponent(p[1]);
|
||||
}
|
||||
|
||||
if (!paramMap.spec) {
|
||||
return true;
|
||||
}
|
||||
return spec.getFullName().indexOf(paramMap.spec) === 0;
|
||||
};
|
||||
@@ -0,0 +1,166 @@
|
||||
body {
|
||||
font-family: "Helvetica Neue Light", "Lucida Grande", "Calibri", "Arial", sans-serif;
|
||||
}
|
||||
|
||||
|
||||
.jasmine_reporter a:visited, .jasmine_reporter a {
|
||||
color: #303;
|
||||
}
|
||||
|
||||
.jasmine_reporter a:hover, .jasmine_reporter a:active {
|
||||
color: blue;
|
||||
}
|
||||
|
||||
.run_spec {
|
||||
float:right;
|
||||
padding-right: 5px;
|
||||
font-size: .8em;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
.jasmine_reporter {
|
||||
margin: 0 5px;
|
||||
}
|
||||
|
||||
.banner {
|
||||
color: #303;
|
||||
background-color: #fef;
|
||||
padding: 5px;
|
||||
}
|
||||
|
||||
.logo {
|
||||
float: left;
|
||||
font-size: 1.1em;
|
||||
padding-left: 5px;
|
||||
}
|
||||
|
||||
.logo .version {
|
||||
font-size: .6em;
|
||||
padding-left: 1em;
|
||||
}
|
||||
|
||||
.runner.running {
|
||||
background-color: yellow;
|
||||
}
|
||||
|
||||
|
||||
.options {
|
||||
text-align: right;
|
||||
font-size: .8em;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
.suite {
|
||||
border: 1px outset gray;
|
||||
margin: 5px 0;
|
||||
padding-left: 1em;
|
||||
}
|
||||
|
||||
.suite .suite {
|
||||
margin: 5px;
|
||||
}
|
||||
|
||||
.suite.passed {
|
||||
background-color: #dfd;
|
||||
}
|
||||
|
||||
.suite.failed {
|
||||
background-color: #fdd;
|
||||
}
|
||||
|
||||
.spec {
|
||||
margin: 5px;
|
||||
padding-left: 1em;
|
||||
clear: both;
|
||||
}
|
||||
|
||||
.spec.failed, .spec.passed, .spec.skipped {
|
||||
padding-bottom: 5px;
|
||||
border: 1px solid gray;
|
||||
}
|
||||
|
||||
.spec.failed {
|
||||
background-color: #fbb;
|
||||
border-color: red;
|
||||
}
|
||||
|
||||
.spec.passed {
|
||||
background-color: #bfb;
|
||||
border-color: green;
|
||||
}
|
||||
|
||||
.spec.skipped {
|
||||
background-color: #bbb;
|
||||
}
|
||||
|
||||
.messages {
|
||||
border-left: 1px dashed gray;
|
||||
padding-left: 1em;
|
||||
padding-right: 1em;
|
||||
}
|
||||
|
||||
.passed {
|
||||
background-color: #cfc;
|
||||
display: none;
|
||||
}
|
||||
|
||||
.failed {
|
||||
background-color: #fbb;
|
||||
}
|
||||
|
||||
.skipped {
|
||||
color: #777;
|
||||
background-color: #eee;
|
||||
display: none;
|
||||
}
|
||||
|
||||
|
||||
/*.resultMessage {*/
|
||||
/*white-space: pre;*/
|
||||
/*}*/
|
||||
|
||||
.resultMessage span.result {
|
||||
display: block;
|
||||
line-height: 2em;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.resultMessage .mismatch {
|
||||
color: black;
|
||||
}
|
||||
|
||||
.stackTrace {
|
||||
white-space: pre;
|
||||
font-size: .8em;
|
||||
margin-left: 10px;
|
||||
max-height: 5em;
|
||||
overflow: auto;
|
||||
border: 1px inset red;
|
||||
padding: 1em;
|
||||
background: #eef;
|
||||
}
|
||||
|
||||
.finished-at {
|
||||
padding-left: 1em;
|
||||
font-size: .6em;
|
||||
}
|
||||
|
||||
.show-passed .passed,
|
||||
.show-skipped .skipped {
|
||||
display: block;
|
||||
}
|
||||
|
||||
|
||||
#jasmine_content {
|
||||
position:fixed;
|
||||
right: 100%;
|
||||
}
|
||||
|
||||
.runner {
|
||||
border: 1px solid gray;
|
||||
display: block;
|
||||
margin: 5px 0;
|
||||
padding: 2px 0 2px 10px;
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
Binary file not shown.
|
After Width: | Height: | Size: 905 B |
@@ -0,0 +1 @@
|
||||
1.1.0
|
||||
Vendored
+3651
-3687
File diff suppressed because it is too large
Load Diff
Vendored
+4
-2
File diff suppressed because one or more lines are too long
@@ -1 +1 @@
|
||||
1.8.2
|
||||
1.7.2
|
||||
|
||||
Executable
BIN
Binary file not shown.
Executable
+130
@@ -0,0 +1,130 @@
|
||||
#
|
||||
# Configuration File for JavaScript Lint 0.3.0
|
||||
# Developed by Matthias Miller (http://www.JavaScriptLint.com)
|
||||
#
|
||||
# This configuration file can be used to lint a collection of scripts, or to enable
|
||||
# or disable warnings for scripts that are linted via the command line.
|
||||
#
|
||||
|
||||
### Warnings
|
||||
# Enable or disable warnings based on requirements.
|
||||
# Use "+WarningName" to display or "-WarningName" to suppress.
|
||||
#
|
||||
-no_return_value # function {0} does not always return a value
|
||||
+duplicate_formal # duplicate formal argument {0}
|
||||
-equal_as_assign # test for equality (==) mistyped as assignment (=)?{0}
|
||||
+var_hides_arg # variable {0} hides argument
|
||||
+redeclared_var # redeclaration of {0} {1}
|
||||
-anon_no_return_value # anonymous function does not always return a value
|
||||
+missing_semicolon # missing semicolon
|
||||
+meaningless_block # meaningless block; curly braces have no impact
|
||||
+comma_separated_stmts # multiple statements separated by commas (use semicolons?)
|
||||
-unreachable_code # unreachable code
|
||||
-missing_break # missing break statement
|
||||
+missing_break_for_last_case # missing break statement for last case in switch
|
||||
+comparison_type_conv # comparisons against null, 0, true, false, or an empty string allowing implicit type conversion (use === or !==)
|
||||
-inc_dec_within_stmt # increment (++) and decrement (--) operators used as part of greater statement
|
||||
+useless_void # use of the void type may be unnecessary (void is always undefined)
|
||||
+multiple_plus_minus # unknown order of operations for successive plus (e.g. x+++y) or minus (e.g. x---y) signs
|
||||
+use_of_label # use of label
|
||||
-block_without_braces # block statement without curly braces
|
||||
+leading_decimal_point # leading decimal point may indicate a number or an object member
|
||||
+trailing_decimal_point # trailing decimal point may indicate a number or an object member
|
||||
+octal_number # leading zeros make an octal number
|
||||
+nested_comment # nested comment
|
||||
-misplaced_regex # regular expressions should be preceded by a left parenthesis, assignment, colon, or comma
|
||||
+ambiguous_newline # unexpected end of line; it is ambiguous whether these lines are part of the same statement
|
||||
+empty_statement # empty statement or extra semicolon
|
||||
-missing_option_explicit # the "option explicit" control comment is missing
|
||||
+partial_option_explicit # the "option explicit" control comment, if used, must be in the first script tag
|
||||
+dup_option_explicit # duplicate "option explicit" control comment
|
||||
+useless_assign # useless assignment
|
||||
+ambiguous_nested_stmt # block statements containing block statements should use curly braces to resolve ambiguity
|
||||
+ambiguous_else_stmt # the else statement could be matched with one of multiple if statements (use curly braces to indicate intent)
|
||||
-missing_default_case # missing default case in switch statement
|
||||
+duplicate_case_in_switch # duplicate case in switch statements
|
||||
+default_not_at_end # the default case is not at the end of the switch statement
|
||||
+legacy_cc_not_understood # couldn't understand control comment using /*@keyword@*/ syntax
|
||||
+jsl_cc_not_understood # couldn't understand control comment using /*jsl:keyword*/ syntax
|
||||
+useless_comparison # useless comparison; comparing identical expressions
|
||||
+with_statement # with statement hides undeclared variables; use temporary variable instead
|
||||
+trailing_comma_in_array # extra comma is not recommended in array initializers
|
||||
+assign_to_function_call # assignment to a function call
|
||||
+parseint_missing_radix # parseInt missing radix parameter
|
||||
|
||||
|
||||
### Output format
|
||||
# Customize the format of the error message.
|
||||
# __FILE__ indicates current file path
|
||||
# __FILENAME__ indicates current file name
|
||||
# __LINE__ indicates current line
|
||||
# __ERROR__ indicates error message
|
||||
#
|
||||
# Visual Studio syntax (default):
|
||||
+output-format __FILE__(__LINE__): __ERROR__
|
||||
# Alternative syntax:
|
||||
#+output-format __FILE__:__LINE__: __ERROR__
|
||||
|
||||
|
||||
### Context
|
||||
# Show the in-line position of the error.
|
||||
# Use "+context" to display or "-context" to suppress.
|
||||
#
|
||||
+context
|
||||
|
||||
|
||||
### Semicolons
|
||||
# By default, assignments of an anonymous function to a variable or
|
||||
# property (such as a function prototype) must be followed by a semicolon.
|
||||
#
|
||||
+lambda_assign_requires_semicolon
|
||||
|
||||
|
||||
### Control Comments
|
||||
# Both JavaScript Lint and the JScript interpreter confuse each other with the syntax for
|
||||
# the /*@keyword@*/ control comments and JScript conditional comments. (The latter is
|
||||
# enabled in JScript with @cc_on@). The /*jsl:keyword*/ syntax is preferred for this reason,
|
||||
# although legacy control comments are enabled by default for backward compatibility.
|
||||
#
|
||||
+legacy_control_comments
|
||||
|
||||
|
||||
### JScript Function Extensions
|
||||
# JScript allows member functions to be defined like this:
|
||||
# function MyObj() { /*constructor*/ }
|
||||
# function MyObj.prototype.go() { /*member function*/ }
|
||||
#
|
||||
# It also allows events to be attached like this:
|
||||
# function window::onload() { /*init page*/ }
|
||||
#
|
||||
# This is a Microsoft-only JavaScript extension. Enable this setting to allow them.
|
||||
#
|
||||
-jscript_function_extensions
|
||||
|
||||
|
||||
### Defining identifiers
|
||||
# By default, "option explicit" is enabled on a per-file basis.
|
||||
# To enable this for all files, use "+always_use_option_explicit"
|
||||
-always_use_option_explicit
|
||||
|
||||
# Define certain identifiers of which the lint is not aware.
|
||||
# (Use this in conjunction with the "undeclared identifier" warning.)
|
||||
#
|
||||
# Common uses for webpages might be:
|
||||
#+define window
|
||||
#+define document
|
||||
|
||||
|
||||
### Files
|
||||
# Specify which files to lint
|
||||
# Use "+recurse" to enable recursion (disabled by default).
|
||||
# To add a set of files, use "+process FileName", "+process Folder\Path\*.js",
|
||||
# or "+process Folder\Path\*.htm".
|
||||
#
|
||||
+process src/*.js
|
||||
+process src/service/*.js
|
||||
+process src/scenario/*.js
|
||||
+process test/*.js
|
||||
+process test/service/*.js
|
||||
+process test/scenario/*.js
|
||||
|
||||
Binary file not shown.
Binary file not shown.
@@ -0,0 +1 @@
|
||||
1.3.3d
|
||||
Executable
+17
@@ -0,0 +1,17 @@
|
||||
#!/bin/sh
|
||||
|
||||
./gen_docs.sh
|
||||
|
||||
rm build/docs/index.html
|
||||
rm -rf build/docs/css
|
||||
rm -rf build/docs/js
|
||||
rm -rf build/docs/img
|
||||
rm -rf build/docs/examples
|
||||
|
||||
cd build/docs
|
||||
|
||||
ln -s ../../docs/src/templates/index.html
|
||||
ln -s ../../docs/src/templates/css
|
||||
ln -s ../../docs/src/templates/js
|
||||
ln -s ../../docs/img
|
||||
ln -s ../../docs/examples
|
||||
@@ -2,7 +2,6 @@
|
||||
"name": "AngularJS",
|
||||
"version": "0.0.0",
|
||||
"dependencies" : {
|
||||
"testacular" : "canary",
|
||||
"jasmine-node" : "*",
|
||||
"q-fs" : "*",
|
||||
"qq" : "*"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user