Compare commits

..

156 Commits

Author SHA1 Message Date
Jeff Cross 07d62426f6 docs(CHANGELOG.md): update 1.2.26 release name 2014-10-02 09:46:40 -07:00
Jeff Cross 3a142e79bd docs(changelog.md): update changelog for 1.3.0-rc.4 and 1.2.26 2014-10-01 21:25:57 -07:00
Brian Feister b40130abcf docs(minerr/unpr): note that ctrls cant depend on other ctrls 2014-09-30 14:37:06 -07:00
active-low ee988d40d0 docs(guide/concepts): improve readability 2014-09-30 12:57:32 -07:00
Adam Humphrey ad4d26c525 docs(readme): fix formatting 2014-09-30 12:36:58 -07:00
Justin Walsh f58681564d docs(guide/compiler): change span to block element in draggable example
The draggable example does not work as expected in Chrome (37.0.2062.124 m).
The span disappears when dragged beyond what appears to be a small area.
Changing the span to a block element (with a width of 65px) resolves this issue.
An alternative solution would be to change the span to a div.
2014-09-30 12:30:09 -07:00
thorn0 d23f585f4a docs($compile): add header to example 2014-09-30 11:41:19 -07:00
Jeff Cross 1850f59765 revert: fix(input): always format viewValue as a string inputs with text controls
This reverts commit 1b8b41ad23.

This is a breaking change.
2014-09-30 09:21:53 -07:00
Peter Bacon Darwin 1f182853d4 revert: fix($compile): Resolve leak with asynchronous compilation
This reverts commit 5c9c197305.

This "fix" is not yet ready for 1.2.x as it has lots of issues when JQuery
is loaded.
2014-09-29 22:19:25 +01:00
Caitlin Potter 5036ac905b docs(CHANGELOG.md): put <base> in codeblock
Prevent the tag from being processed (and not rendered). Thanks @davidlehn.

Closes #9331
2014-09-29 17:16:36 -04:00
Brian Ford 11d2242df6 fix(select): make ctrl.hasOption method consistent
Prior to this fix, options added to a select by ngOptions would not cause
`selectCtrl.hasOption` to return `true`

Closes #8761
2014-09-29 13:59:54 -07:00
Peter Bacon Darwin cea23db3de chore(npm-shrinkwrap): update to dgeni-packages 0.10.0 2014-09-29 21:56:43 +01:00
Peter Bacon Darwin 5c9c197305 fix($compile): Resolve leak with asynchronous compilation
Stop an asynchronous compilation when this is performed on an
already destroyed scope

Closes #9199
Closes #9079
Closes #8504
Closes #9197
2014-09-29 21:56:43 +01:00
Peter Bacon Darwin ecb2222ea1 chore(testabilityPatch): add jqLiteCacheSize helper 2014-09-29 21:56:43 +01:00
Julie Ralph 276310e5b5 chore(ci): remove repeated tests running from Travis build
In b2902446eb the doce2e tests were moved
into the 'unit' test job on Travis, but only half of this change ever made
it into v1.2.x. This change fixes up the other half, so that the doce2e
tests are run only once.
2014-09-29 10:55:53 -07:00
Julie Ralph 6afe0dba39 chore(e2e): bump protractor to version 1.3.1 2014-09-29 10:21:05 -07:00
Peter Bacon Darwin 038ca9b9bf chore(docs): fix links to github 2014-09-26 21:22:02 +01:00
Sandeep Panda 44c451e9f5 docs(guide/index): add book AngularJS: Novice to Ninja
I wrote a book on AngularJS (AngularJS: Novice to Ninja).

Closes #9293
2014-09-26 12:29:09 -04:00
Caitlin Potter 1b8b41ad23 fix(input): always format viewValue as a string inputs with text controls
Backported from 1eda18365a

NgModel will format all scope-based values to string when setting the viewValue for
the associated input element. The formatting, however, only applies to input elements
that contain a text, email, url or blank input type. In the event of a null or undefined
scope or model value, the viewValue will be set to null or undefined instead of being
converted to an empty string.

Closes #5936
Closes #9277
2014-09-25 13:49:59 -04:00
Peter Bacon Darwin 37f2265b88 chore(docs): minify javascript 2014-09-25 06:05:17 +01:00
Peter Bacon Darwin 05a2a1d395 chore(docs): remove unused code 2014-09-25 05:50:52 +01:00
Peter Bacon Darwin fc913eea89 chore(docs): improve logo rendering performance 2014-09-25 05:45:33 +01:00
Peter Bacon Darwin f839e4944a chore(protractor): annotate $animate to allow tests to run under strict-di 2014-09-25 05:45:26 +01:00
Peter Bacon Darwin 2aead39486 chore(docs): ensure DI annotations are in place 2014-09-25 05:45:03 +01:00
Jeff Cross 54af406c2e docs(changelog): add release notes for 1.3.0-rc.3 2014-09-23 18:50:20 -07:00
Georgios Kalpakas 930bd40bac docs(ngController): Fix priority value mentioned in the docs
The `@priority 500` part was missing from the ngDoc comment, thus the docs mentioned a priority of 0
(instead of the correct 500).

Closes #9070
2014-09-23 16:25:43 -07:00
Peter Bacon Darwin 4aa4005f5f chore(docs): AngularJS 1.2.x doesn't support '$includeContentError' event 2014-09-23 19:26:04 +01:00
Peter Bacon Darwin d5c04121cb chore(docs): refactor the docs app search for better bootup time
This commit refactors how the search index is built. The docsSearch service
is now defined by a provider, which returns a different implementation of
the service depending upon whether the current browser supports WebWorkers
or now.

* **WebWorker supported**: The index is then built and stored in a new worker.
The service posts and receives messages to and from this worker to make
queries on the search index.

* **WebWorker no supported**: The index is built locally but with a 500ms
delay so that the initial page can render before the browser is blocked as
the index is built.

Also the way that the current app is identified has been modified so we can
slim down the js data files (pages-data.js) to again improve startup time.

Closes #9204
Closes #9203
2014-09-23 19:01:22 +01:00
Andrew Delikat e6996cc457 docs(tutorial/step_05): fix typo 2014-09-22 14:55:24 -07:00
William Chen 33793ec3e1 docs(triaging): fix formatting 2014-09-22 13:15:15 -07:00
Bocharsky Victor c9f8fb2559 docs(guide/$location): fix broken link 2014-09-22 13:12:52 -07:00
Christopher Rains a0229803de docs(tutorial/step_02): fix formatting 2014-09-22 13:09:39 -07:00
James Ferguson 38cb2b348e docs(readme): improve readability 2014-09-22 11:41:00 -07:00
Ariel Mashraki c54287bf8d docs(route): remove irrelevant note
Closes #9196
Closes #9200
2014-09-22 13:30:24 -04:00
Jeff Cross a36515289a chore($http): disable flaky JSONP test
See #9185
2014-09-19 17:20:32 -07:00
Peter Bacon Darwin c59da09d3e docs(limitTo): exclude the e2e test that fails on safari
Safari and doesn't like the minus key to be sent to it via Protractor.
Commenting out rather than using xit so that it passes the build
2014-09-19 22:57:11 +01:00
Peter Bacon Darwin 98ceda2194 docs(limitTo): exclude the e2e test that fails on safari
Safari and doesn't like the minus key to be sent to it via Protractor.
2014-09-19 22:40:30 +01:00
Sekib Omazic fbd620e8ae docs(angular.extend) actually only copies own enumerable properties
Closes #9007
2014-09-19 22:00:51 +01:00
Zahid Mahir 4cfc279d39 docs(tutorial/step-3): correct slight grammar issue
Closes #8996
2014-09-19 21:36:17 +01:00
jimmywarting 6a07009c12 docs(limitTo): fix input type in examples
Closes #8989
2014-09-19 21:33:55 +01:00
Sercan Eraslan f3f65caac2 docs(navigation): side navigation footer overlap problem fix
Closes #8923
2014-09-19 19:26:23 +01:00
Luke Schoen 130fe92cda docs(guide/directive): fix grammar 2014-09-18 16:12:37 -07:00
Matt Kim 3d83973fa4 docs(misc/faq): fix typo 2014-09-18 16:11:09 -07:00
Greg Fedirko 3b171a851d docs(guide/$location): improve readability 2014-09-18 16:08:59 -07:00
Luke Schoen 9782bc2aa2 docs(tutorial): improve readability 2014-09-18 16:01:13 -07:00
Christopher Rains 77be7cc7d9 docs(tutorial): fix formatting
- proper case "jQuery" vs "JQuery"
- wrap ng-view in markdown code `ng-view`
2014-09-18 15:56:23 -07:00
jeffavis 3da5847500 docs(guide/bootstrap): fix missing ngController in example 2014-09-18 15:51:59 -07:00
Rahul Doshi 53e6590e88 docs(guide): add angular-localization module to internationalization section
Closes #9158
2014-09-18 18:00:26 -04:00
Jose Martinez d1c05ad832 docs(error/$controller/noscp): fix example
Fix the "correct" example to have the proper syntax for creating the locals
object and provide a more explicit explanation as to how the scope object
should be provided.
2014-09-17 11:10:03 -07:00
Brian Ford f6f0791867 docs(changelog): release notes for 1.2.25 2014-09-16 15:05:22 -07:00
Brian Ford fb3d158be9 docs(changelog): release notes for 1.3.0-rc.2 2014-09-16 15:05:06 -07:00
Caitlin Potter 06c76694ac fix(ngLocale): Regenerate Locale Files
Fixes number formatting and symbols for many locales.
Adds support for additional locales.
2014-09-16 17:18:52 -04:00
Michael Gallagher b979ee1f03 chore(ngLocale): Include numberformatsymbolext.js in Closure Slurper Script
Adds missing number format and symbol rules to Closure slurper script.

Closes #6179
Closes #9013
2014-09-16 17:18:22 -04:00
Brian Ford d89d59f453 fix(select): update option labels when model changes
Closes #9025
2014-09-16 12:46:53 -07:00
Peter Bacon Darwin e251db9fb3 docs(ngView): remove obsolete comment from code sample
Closes #9086
2014-09-15 20:40:02 +01:00
Peter Bacon Darwin 9cc968689f chore(docs): remove excess indentation from code blocks
dgeni-packages 0.10.0-rc.5 has a fix for this problem, so this commit updates
to that version.
Adds a new e2e test to prove this is fixed.

Closes #8963
2014-09-15 20:39:55 +01:00
Peter Bacon Darwin dea705b2cf test(docs): fix url matching on api e2e tests 2014-09-15 20:39:43 +01:00
Peter Bacon Darwin c4d3e6fd43 chore(docs): ensure all docs e2e tests are run 2014-09-15 20:39:36 +01:00
Peter Bacon Darwin bf24ad144d docs(ngShowHide): use backticks to denote CSS classes and directive names
add backticks around directive names to improve documentation consistency, as it's used in some
parts of the docs already.

Closes #9081
2014-09-15 20:38:50 +01:00
Peter Bacon Darwin b4de7307c3 test(docs): add extra docs e2e tests 2014-09-15 20:35:40 +01:00
Peter Bacon Darwin 9b9a30c7ae test(docs): improve docs e2e tests 2014-09-15 20:35:20 +01:00
Peter Bacon Darwin 8be7b5d125 chore(docs): update to dgeni-0.4.0
* update package with new services and computeId config
* generateIndexPagesProcessor was not using log
* use StringMap not ES6-shim Map in errorNamespaceMap
* remove unused dependencies from generateErrorDocsProcessor
* ensure generatePagesDataProcessor adds its doc to the collection
* debugDumpProcessor was moved to dgeni-packages
2014-09-15 20:33:58 +01:00
Caitlin Potter a3fbf0ff5a test($parse): ensure CSP code paths are used when testing
Previously, the test suite was not actually taking CSP-mode paths when we were expecting it to.

Numerous CSP-mode tests are failing, working on fixing these.
2014-09-12 15:07:37 -04:00
Caitlin Potter f2894c0f1d test($parse): ensure CSP code paths are used when testing
Previously, the test suite was not actually taking CSP-mode paths when we were expecting it to.

Numerous CSP-mode tests are failing, working on fixing these.
2014-09-12 14:51:55 -04:00
Georgii 6d12e8990b refactor(ngEventDirs): remove a useless call
The event names are already lower-case.
2014-09-11 12:57:32 -07:00
Georgios Kalpakas 71d65821c8 docs(CHANGELOG.md): fix typos for ng-switch-changed workaround
Fix the JavaScript errors in the work-around proposed in 0f806d9 in order to emulate the behaviour
of the removed `change` attribute of ngSwitch.

Closes #9034
2014-09-11 15:42:30 -04:00
Justin Walsh ae92658ebf docs(guide/forms): correct grammar 2014-09-11 12:11:28 -07:00
SirTophamHatt 1a53863662 docs(guide/providers): note that services can create functions
The conclusion table incorrectly states that services can not create functions.
New table row added to separate "can create functions" and "can create primitives".
2014-09-10 16:07:53 -07:00
Lucas Galfaso 1b6d74cc9f fix(i18n): fix typo at i18n generation code
Fix typo at i18n generation code. This would remove the
property `macFrac` that has no meaning from all the
generated locales
2014-09-10 15:30:18 -07:00
Peter Bacon Darwin 6fd048a3b7 docs(tutorial/steps-11&12): add warning about bower conflict error
See: https://github.com/angular/angular-phonecat/issues/163#issuecomment-55181854
2014-09-10 22:52:58 +01:00
Michael Silver 50cd3a4210 docs(tutorial): update step 7 to reference angular-phonecat
This changes the example JSON to be the actual bower.json for angular-phonecat,
with name set to angular-phonecat.
2014-09-10 11:45:32 -07:00
standup75 57ac995b8b docs(ngResource): document steps to skip default json serialization/deserialization 2014-09-10 11:42:28 -07:00
Jeff Cross d396f42537 docs(CHANGELOG.md): add upcoming breaking change 2014-09-09 16:21:16 -07:00
Jeff Cross 5ec900a125 docs(CHANGELOG.md): fix wording and remove reverted change 2014-09-09 16:20:20 -07:00
Jeff Cross 66503a6e18 docs(CHANGELOG.md): add changes for 1.3.0-rc.1 and 1.2.24 2014-09-09 15:48:30 -07:00
Jeff Cross 2d8749e8c9 revert: "fix($compile): render nested transclusion at the root of a template"
This reverts commit 9d9cdfb575.

This commit was causing breakages because of its assumption that transcluded
content would be handled predictably, i.e. with ngTransclude, whereas many
use cases involve manipulating transcluded content in linking functions.
2014-09-09 11:08:39 -07:00
Chirayu Krishnappa b39e1d47b9 fix($parse): disallow passing Function to Array.sort
Fix the following exploit:

    hasOwnProperty.constructor.prototype.valueOf = valueOf.call;
    ["a", "alert(1)"].sort(hasOwnProperty.constructor);

The exploit:
• 1. Array.sort takes a comparison function and passes it 2 parameters to compare.
  2. It then calls .valueOf() if the result is not a primitive.
• The Function object conveniently accepts two string arguments so we can use this
  to construct a function.  However, this doesn't do much unless we can execute it.
• We set the valueOf function on Function.prototype to Function.prototype.call.
  This causes the function that we constructed to be executed when sort calls
  .valueOf() on the result of the comparison.

The fix is in two parts.
• Disallow passing unsafe objects to function calls as parameters.
• Do not traverse the Function object when setting a path.
2014-09-09 10:46:36 -07:00
Peter Bacon Darwin 5061d2c97c chore(npm-shrinkwrap): safely update karma to 0.12.23 2014-09-09 10:21:45 +01:00
Peter Bacon Darwin a961291aa2 chore(npm-shrinkwrap): fix karma dependencies
Updating to karma 0.12.13 (in commit 408508ad29)
caused `iit` and `ddescribe` to crash and disconnect the browser stopping the
test run.

It appears that the problem is with one of the dependencies of karma rather
than karma itself. At least one of the karma dependencies updated in line
with karma's dependencies' semver specifications but subtly changed their
behaviour to break karma.  Possibly this is related to chokidar, glob,
minimatch or fsevents.
2014-09-09 10:04:32 +01:00
Peter Bacon Darwin 3068d8e52a docs($filter): remove duplicate documentation of register method 2014-09-08 14:31:47 +01:00
Peter Bacon Darwin d2dd3581a9 docs(form): move param tag outside of main description 2014-09-08 14:31:47 +01:00
Peter Bacon Darwin 53feb272be chore(bower): refactor bower usage
The gulp bower task in the docs app was never actually running since it couldn't
find the bower.json file and was silently failing. Updating to a newer bower
highlighted this issue.

This commit moves the docs app specific bower components into the docs folder.
There are only jquery and closure compiler related components in the project
folder now.

It also improves the gulp bower task to provide better feedback of progress
and errors.
2014-09-08 14:31:47 +01:00
Peter Bacon Darwin 408508ad29 chore(package.json): tidy up dependencies
Sorted dependencies into alphabetic order. If we can keep them like this
it will be much easier to keep track of version changes.

Updated bower and gulp to newer versions.
2014-09-08 14:31:47 +01:00
Peter Bacon Darwin ece7d19115 chore(clean-shrinkwrap): chokidar is fixed since 0.8.2 2014-09-08 12:31:40 +01:00
Pawel Kozlowski 992101da10 refactor($http): simplify buildUrl function
Closes #8955
2014-09-05 20:22:20 -04:00
Peter Bacon Darwin 47f42ecf45 test(orderBy): remove IE8 incompatible test code 2014-09-05 19:46:40 +01:00
Julie Ralph fd995abc9a chore(tests): fix up test for protractor 1.2.0 update
These changes were made to master in 85880a6490
but never made it to the 1.2.x branch.
2014-09-05 11:16:18 -07:00
Julie Ralph 5f9a9747d2 chore(tests): update Protractor to v1.2.0 2014-09-05 10:51:31 -07:00
Vitali Tsevan 94b0f2d35d fix(orderBy): allow arrayLike objects to be ordered
Closes #8944
2014-09-05 11:56:41 +01:00
Jeff Cross c12e8d4665 fix($location): don't call toString on null values 2014-09-04 17:46:51 -07:00
thorn0 c65796d496 fix($location): remove an unused parameter of $location.url 2014-09-04 15:12:04 -07:00
John Reilly 34b43eab5f docs($location): update search description to include number param 2014-09-04 14:55:48 -07:00
Peter Bacon Darwin 9d9cdfb575 fix($compile): render nested transclusion at the root of a template
Closes #8914
Closes #8925
2014-09-04 19:33:03 +01:00
Pawel Kozlowski 68a09ba74d fix($location): allow numeric location setter arguments
Fixes #7054
2014-09-04 10:47:30 -07:00
Peter Bacon Darwin 239d0b1f49 docs(guide): add sortOrder to each page
Finally we can control the order of the guide pages
2014-09-04 17:15:26 +01:00
Peter Bacon Darwin 4e04c73cd3 chore(docs): enable page ordering by @sortOrder tag 2014-09-04 16:49:55 +01:00
Peter Bacon Darwin 6c863e5bba chore(docs): improve searching by member
The keywords processor now also extracts the members (i.e. method, properties
and events) into its own search term property. These are then used in the lunr
search index with higher weighting that normal keywords to push services that
contain the query term as a member higher up the search results.

Closes #7661
2014-09-04 14:23:29 +01:00
Peter Bacon Darwin e0cf7c5bf2 Revert "fix($compile): render nested transclusion at the root of a template"
This reverts commit 466320f691.
2014-09-04 14:15:38 +01:00
Peter Bacon Darwin 466320f691 fix($compile): render nested transclusion at the root of a template
Closes #8914
Closes #8925
2014-09-04 13:45:49 +01:00
Smitha Milli 7e02fa07eb fix(numberFilter): format numbers that round to zero as nonnegative
Previously when a negative number was rounded to 0 by the number filter
it would be formated as a negative number.  This means something like
{{ -0.01 | number: 1 }} would output -0.0.  Now it will ouput 0.0
instead.

Closes #8489
2014-09-03 15:42:07 -07:00
thorn0 9ed9777317 docs(docs.css): improve comma spacing in TOC on mobile 2014-09-03 14:37:43 -07:00
Juampy e661bc9f15 docs($sce:unsafe): fix link to $sce docs
The second link to Strict Contextual Escaping (SCE) points to a 404.

Closes #8514
2014-09-03 16:31:41 -04:00
thorn0 7af210f1de docs(README): fix 'Contribution guidelines' link
The current link leads to a page 'Building and Testing AngularJS'.
This same link is also included in the 'Building AngularJS' section
of the README where it's more relevant.
2014-09-03 13:25:40 -07:00
TLChan b48203f9f2 docs(tutorial/step_05): improve formatting of code identifier
Closes #8557
2014-09-03 16:25:08 -04:00
Zach Pomerantz 789f0f1809 docs(interpolate): fix link text 2014-09-03 13:20:27 -07:00
Vic Metcalfe 8366d545c5 docs(ngBlur): explain blur events 2014-09-03 13:05:07 -07:00
Caitlin Potter 1f5b4c95eb docs(CHANGELOG.md): add breaking change for a9fcb0d0 (v1.2.13)
Closes #8909
2014-09-03 13:14:02 -04:00
Peter Bacon Darwin 910d652ce5 chore(package.json): update to dgeni-packages v0.9.8
Closes #8860
2014-09-03 11:39:35 +01:00
Nicolai Skogheim e5e62a5479 docs(ngRepeat): update step_02.ngdoc with challenge
Add a simple task for the user to better understand ng-repeat.

Close #8757
2014-09-02 16:46:20 -04:00
Shahar Talmi 8f14b726b0 docs($rootScope): document scope properties 2014-09-02 13:35:41 -07:00
Tiago Ribeiro 88b6a9a288 docs(changelog): fix inline formatting 2014-09-02 13:05:07 -07:00
Matias Niemelä d4fc40c282 docs(changelog): release notes for 1.3.0-RC.0 sonic-boltification 2014-09-02 13:04:45 -07:00
Nima Mehanian 653700df5b docs(guide/providers): fix grammar and punctuation 2014-09-02 12:48:57 -07:00
Shahar Talmi 2712c2f197 fix(ngEventDirs): check scope.$$phase only on $rootScope
Closes #8891, #8849
2014-09-02 10:48:12 -07:00
Shahar Talmi 36e6de1d91 fix(input): check scope.$$phase only on $rootScope 2014-09-02 10:48:12 -07:00
Brian Ford 9bf964f1f3 style(ngRepeatSpec): make jshint happy 2014-08-29 15:51:02 -07:00
Tobias Bosch 54f0bc0fe0 fix(ngEventDirs): execute blur and focus expression using scope.$evalAsync
BREAKING CHANGE:
The `blur` and `focus` event fire synchronously, also during DOM operations
that remove elements. This lead to errors as the Angular model was not
in a consistent state. See this [fiddle](http://jsfiddle.net/fq1dq5yb/) for a demo.

This change executes the expression of those events using
`scope.$evalAsync` if an `$apply` is in progress, otherwise
keeps the old behavior.

Fixes #4979
Fixes #5945
Closes #8803
Closes #6910
Closes #5402
2014-08-29 15:31:27 -07:00
Tobias Bosch 2ece4d0347 fix($browser): detect changes to the browser url that happened in sync
Closes #6976.
2014-08-29 15:31:13 -07:00
Smitha Milli 1812af58c2 fix(ngRepeat): improve errors for duplicate items
-Log the value that had the duplicate key, as well as the key
The error that is thrown when items have duplicate track by keys can be
confusing because only the duplicate key is logged.  If the user didn't
provide that key themselves, they may not know what it is or what item
it corresponds to.
2014-08-29 13:54:57 -07:00
Michael Barton 19cb2e3d12 docs($rootScope): remove duplicate $digest()
Closes #8840
2014-08-29 14:38:31 -04:00
Guilbert c92ce4511b docs(filterFilter): add note on negation 2014-08-28 14:57:30 -07:00
Matias Niemelä d7548fdf1c fix(form): ensure concurrent animations use setClass
When addClass and removeClass are called in parallel it may
cause follow-up animations to get blocked. This fix ensures
that the validity state CSS classes are applied at the same
time via $animate.setClass.

Closes #8166
2014-08-27 23:29:44 -04:00
dennishall1 7e239f9485 docs(dateFilter): add example of string literals in format string
Also changes the wording to include the word "escaped" and "escape", which may help users find the
information they're looking for via searching. (ノ◕ヮ◕)ノ*:・゚✧

Closes #8770
2014-08-25 23:18:53 -04:00
Smith fa5daa7693 docs(guide/di): correct spelling behinds > behind
Closes #8749
2014-08-23 16:38:27 -04:00
Brian Ford 00456a8f93 docs(changelog): release notes for 1.2.23 superficial-malady 2014-08-22 15:56:49 -07:00
Brian Ford 0b3022e8e0 docs(changelog): release notes for 1.3.0-beta.19 rafter-ascension 2014-08-22 15:56:33 -07:00
Jeff Cross 456026eff1 fix(input): use lowercase method to account for undefined type 2014-08-22 00:41:02 -07:00
danrbergman 8ec3efd967 docs(guide/module): update tag in description
the reference to 'myApp' module changed in the example from <html> to a <div>. Updating description
to reflect the new <div> tag.

Closes #8720
2014-08-21 23:33:59 -04:00
danrbergman 8528781f85 docs(guide/module): make the use of ng-app explicit in example
Helpful for people new to Angular to see the ng-app declaration in context with the expression
example. This will help illustrate the "Important thing to notice" point which follows: "The
reference to myApp module in <html ng-app="myApp">. This is what bootstraps the app using your
module."

Closes #8673
2014-08-21 22:28:48 -04:00
Sekib Omazic 98f603722d fix(Angular): make Date comparison in equals() NaN-aware
Make angular.equals() Date comparison NaN-aware to prevent infinite digest errors when a dealy watched
date has an invalid value.

Closes #8650
Closes #8715
2014-08-21 21:17:46 -04:00
Caitlin Potter ebece0bcb9 fix(input): by default, do not trim input[type=password] values
Do not trim input[type=password] values

BREAKING CHANGE:

Previously, input[type=password] would trim values by default, and would require an explicit ng-trim="false"
to disable the trimming behaviour. After this CL, ng-trim no longer effects input[type=password], and will
never trim the password value.

Closes #8250
Closes #8230

Conflicts:
	src/ng/directive/input.js
2014-08-21 19:14:27 -04:00
Caitlin Potter 4b7398eeca chore(protractor): enable testing ng-app-included examples
/cc @petebacondarwin / @juliemr please review :>

Blocks #8673
Closes #8677
2014-08-21 18:55:12 -04:00
Casey Flynn 4e79decc30 docs($interval): fix typo in example
It's not "nis", it's "is"! 〜( ̄▽ ̄)〜

Closes #8711
2014-08-21 15:30:16 -04:00
Caitlin Potter 888b0f5400 fix(copy): clear array destinations correctly for non-array sources
Closes #8610
Closes #8702
2014-08-20 21:51:32 -04:00
Jeff Cross aaf9c5e598 fix(minErr): encode btstrpd error input to strip angle brackets
The $sanitize service was returning an empty string to the error page
because the input was usually a single html tag (sometimes it could be
`document`). This fix replaces angle brackets with html entities.

Closes #8683
2014-08-20 17:27:48 -07:00
Henrik Nyh 893d2f8000 docs(ngDisabled): clarify "don't do this" example
It's not clear until you read the whole thing that it's an explanation
of what *not* to do and why, so if you scan the page from the top, you
may use this bad solution.
2014-08-20 15:47:37 -07:00
Brian Ford effc98fdc9 fix(linky): handle quotes around email addresses
Closes #8520
2014-08-20 13:40:31 -07:00
mishoo78 64cdbf3ae9 docs(ngMock): note that inject/module helpers only defined for jasmine / mocha
Closes #8694
2014-08-20 13:44:24 -04:00
Ole Weitz 5bba892ffd docs($cacheFactory): prevent example breaking on key update
The example for $cacheFactory breaks when a user tries to update a value for a key.
Setting a new value for an existing key results in duplicate key entries in the key array, thus
breaking the ng-repeat directive. With this fix the key is only added if it isn't contained in the
cache.

Closes #8214
2014-08-20 10:49:14 -04:00
Izhaki ec27deacfd docs($compile): fix documentation for ?^ controller search
Fixed typo: 'parents parents' to 'parents'

Closes #8690
2014-08-20 09:32:20 -04:00
Caitlin Potter c6e4defcb6 fix($location): rewrite relative URI correctly if path==='/' in legacy html5Mode
Currently, legacy browsers get to use a clever scheme for resolving relative URIs in html5Mode,
and resolve the URI relative to $location.path().

Currently, $location.path() can be '/' under certain circumstances, which means that when we
split $location.path() on '/' and later join by '/' after adding another path component,
we end up with '//pathComponent'. $$rewrite fails to deal with this correctly, and effectively
the $location is never changed from the root path.

This CL corrects this by ensuring that the duplicate '/' situation does not occur when resolving
relative URIs.

Closes #8684
2014-08-19 21:31:20 -04:00
Caitlin Potter 74a7afcb31 fix($location): don't call indexOf() of undefined href attribute
Closes #7721
Closes #8681
2014-08-19 19:16:40 -04:00
Brian Ford 08cc6edd38 chore(jshint): add missing scripturl directive 2014-08-19 14:56:06 -07:00
Brian Ford 4f3870500d fix($sanitize): sanitize javascript urls with comments
Closes #8274
2014-08-19 14:16:01 -07:00
Marty Kane cd0507bc3a docs(guide/di): correct a few awkward sentences
Closes #8678
2014-08-19 16:51:45 -04:00
Izhaki 20eef05195 docs($compile): correct documentation for directive controller ^ notation
`^` searches the element and its parents, not exclusively the element's parents. This confuses
a lot of people :(

Closes #8622
2014-08-19 14:31:36 -04:00
Shahar Talmi a6d7b4bdbd docs(*): use @description instead of @returns for properties
Dgeni-packages was not actually rendering the `@returns` text.

Closes #8639
2014-08-19 14:26:06 -04:00
Baptiste Fontaine 5811c5c35b docs(ngBind): irrelevant text removed from ngBindHtml’s example
The ngBindHtml’s example had a copied line from ngBindTemplate’s that’s irrelevant here.

Closes #8668
2014-08-19 12:39:04 -04:00
Pawel Kozlowski e37e30e93f docs(orderBy): clarify expression usage in a predicate
Closes #8592
2014-08-18 13:32:21 -07:00
Tom Kadwill a0b8ab8d7d docs(tutorial/index): improve wording
Removed repetition of 'machine' and 'local machine'.
I think this change makes the sentence more concise
2014-08-18 13:23:56 -07:00
Jeff Sheets 129c53730c docs($http): correct link to "salt (cryptography)" wikipedia article
Closes #8654
2014-08-18 13:35:24 -04:00
Caitlin Potter 8695138aec docs(misc/contribute): fix syntax highlighting of URLS
Closes #8168
Closes #8169
2014-08-17 21:13:57 -04:00
Shahar Talmi ed56872bb2 fix(ngHref): remove attribute when empty value instead of ignoring
Closes #2755
2014-08-13 15:43:10 -07:00
Peter Bacon Darwin cb183433a0 chore(doc-gen): move e2e tests into docs folder
These tests didn't really fit in the test folder as the docs app is mostly
a separate entity from the AngularJS codebase.
2014-08-13 11:24:53 +01:00
Caitlin Potter 631fbda6a9 docs(CHANGELOG.md): fix typo, it's 1.2.22 not 1.2.2!
Whoops!
2014-08-12 16:53:05 -04:00
Caitlin Potter 4c33b56612 docs(CHANGELOG.md): add changelog for v1.3.0-beta.18 and v1.2.22
Closes #8581
2014-08-12 13:17:04 -04:00
879 changed files with 88773 additions and 12873 deletions
-4
View File
@@ -1,4 +0,0 @@
{
"directory": "bower_components",
"json": "bower.json"
}
+1 -2
View File
@@ -9,8 +9,7 @@ performance/temp*.html
*.swp
angular.js.tmproj
/node_modules/
/components/
/bower_components/
bower_components/
angular.xcodeproj
.idea
.agignore
-1
View File
@@ -11,7 +11,6 @@ env:
- JOB=unit
- JOB=e2e TEST_TARGET=jqlite
- JOB=e2e TEST_TARGET=jquery
- JOB=e2e TEST_TARGET=doce2e
global:
- SAUCE_USERNAME=angular-ci
- SAUCE_ACCESS_KEY=9b988f434ff8-fbca-8aa4-4ae3-35442987
+1238
View File
File diff suppressed because it is too large Load Diff
+3 -3
View File
@@ -65,13 +65,13 @@ Help us to maximize the effort we can spend fixing issues and adding new
features, by not reporting duplicate issues. Providing the following information will increase the
chances of your issue being dealt with quickly:
* **Overview of the issue** - if an error is being thrown a non-minified stack trace helps
* **Overview of the Issue** - if an error is being thrown a non-minified stack trace helps
* **Motivation for or Use Case** - explain why this is a bug for you
* **Angular Version(s)** - is it a regression?
* **Browsers and Operating System** - is this a problem with all browsers or only IE8?
* **Reproduce the error** - provide a live example (using [Plunker][plunker] or
* **Reproduce the Error** - provide a live example (using [Plunker][plunker] or
[JSFiddle][jsfiddle]) or a unambiguous set of steps.
* **Related issues** - has a similar issue been reported before?
* **Related Issues** - has a similar issue been reported before?
* **Suggest a Fix** - if you can't fix the bug yourself, perhaps you can point to what might be
causing the problem (line of code or commit)
+7 -6
View File
@@ -6,16 +6,17 @@ use good old HTML (or HAML, Jade and friends!) as your template language and let
syntax to express your applications 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
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 makes client-side
navigation and deeplinking with hashbang urls or HTML5 pushState a piece of cake. The best of all:
it makes development fun!
the browser how to do dependency injection and inversion of control.
Oh yeah and it helps with server-side communication, taming async callbacks with promises and
deferreds. It also makes client-side navigation and deeplinking with hashbang urls or HTML5 pushState a
piece of cake. The best of all: it makes development fun!
* Web site: http://angularjs.org
* Tutorial: http://docs.angularjs.org/tutorial
* API Docs: http://docs.angularjs.org/api
* Developer Guide: http://docs.angularjs.org/guide
* Contribution guidelines: http://docs.angularjs.org/misc/contribute
* Contribution guidelines: [CONTRIBUTING.md](https://github.com/angular/angular.js/blob/master/CONTRIBUTING.md)
* Dashboard: http://dashboard.angularjs.org
Building AngularJS
@@ -37,7 +38,7 @@ To execute end-to-end (e2e) tests, use:
grunt test:e2e
To learn more about the grunt tasks, run `grunt --help` and also read our
[contribution guidelines](http://docs.angularjs.org/misc/contribute).
[contribution guidelines](https://github.com/angular/angular.js/blob/master/CONTRIBUTING.md).
[![Analytics](https://ga-beacon.appspot.com/UA-8594346-11/angular.js/README.md?pixel)](https://github.com/igrigorik/ga-beacon)
-3
View File
@@ -26,7 +26,6 @@ This process based on the idea of minimizing user pain
* You can triage older issues as well
* Triage to your heart's content
1. Assign yourself: Pick an issue that is not assigned to anyone and assign it to you
1. Understandable? - verify if the description of the request is clear.
* If not, [close it][] according to the instructions below and go to the last step.
1. Duplicate?
@@ -36,7 +35,6 @@ This process based on the idea of minimizing user pain
* Label `Type: Bug`
* Reproducible? - Steps to reproduce the bug are clear. If they are not, ask for a clarification. If there's no reply after a week, [close it][].
* Reproducible on master? - <http://code.angularjs.org/snapshot/>
1. Non bugs:
* Label `Type: Feature`, `Type: Chore`, or `Type: Perf`
* Belongs in core? Often new features should be implemented as a third-party module rather than an addition to the core.
@@ -59,7 +57,6 @@ This process based on the idea of minimizing user pain
* In rare cases, it's ok to have multiple components.
1. Label `PRs plz!` - These issues are good targets for PRs from the open source community. Apply to issues where the problem and solution are well defined in the comments, and it's not too complex.
1. Label `origin: google` for issues from Google
1. Assign a milestone:
* Backlog - triaged fixes and features, should be the default choice
* Current 1.x.y milestone (e.g. 1.3.0-beta-2) - regressions and urgent bugs only
+1 -5
View File
@@ -2,11 +2,7 @@
"name": "AngularJS",
"devDependencies": {
"jquery": "1.10.2",
"lunr.js": "0.4.3",
"open-sans-fontface": "1.0.4",
"google-code-prettify": "1.0.1",
"closure-compiler": "https://closure-compiler.googlecode.com/files/compiler-20130603.zip",
"ng-closure-runner": "https://raw.github.com/angular/ng-closure-runner/v0.2.3/assets/ng-closure-runner.zip",
"bootstrap": "3.1.1"
"ng-closure-runner": "https://raw.github.com/angular/ng-closure-runner/v0.2.3/assets/ng-closure-runner.zip"
}
}
+10 -8
View File
@@ -316,10 +316,10 @@ iframe.example {
}
.search-results-group.col-group-api { width:30%; }
.search-results-group.col-group-guide { width:30%; }
.search-results-group.col-group-tutorial { width:25%; }
.search-results-group.col-group-guide,
.search-results-group.col-group-tutorial { width:20%; }
.search-results-group.col-group-misc,
.search-results-group.col-group-error { float:right; clear:both; width:15% }
.search-results-group.col-group-error { width:15%; float: right; }
.search-results-group.col-group-api .search-result {
@@ -391,7 +391,6 @@ iframe.example {
position:fixed;
top:120px;
bottom:0;
padding-bottom:120px;
overflow:auto;
}
@@ -412,6 +411,7 @@ iframe.example {
.main-body-grid .side-navigation {
position:relative;
padding-bottom:120px;
}
.main-body-grid .side-navigation.ng-hide {
@@ -635,12 +635,14 @@ ul.events > li {
display:inline-block;
padding:3px 0;
}
.nav-index-group .nav-index-listing:not(.nav-index-section) + .nav-index-listing:not(.nav-index-section):after {
padding-right:5px;
content:", ";
.nav-index-group .nav-index-listing:not(.nav-index-section):after {
padding-right:5px;
margin-left:-3px;
content:", ";
}
.nav-index-group .nav-index-listing:last-child {
.nav-index-group .nav-index-listing:last-child:after {
content:"";
display:inline-block;
}
.nav-index-group .nav-index-section {
display:block;
+4
View File
@@ -6,6 +6,10 @@
line-height: 1.5;
}
.lang-text * {
color: #333333!important;
}
.pln {
color: #333333;
}
@@ -1,284 +0,0 @@
'use strict';
var directive = {};
var service = { value: {} };
var DEPENDENCIES = {
'angular.js': 'http://code.angularjs.org/' + angular.version.full + '/angular.min.js',
'angular-resource.js': 'http://code.angularjs.org/' + angular.version.full + '/angular-resource.min.js',
'angular-route.js': 'http://code.angularjs.org/' + angular.version.full + '/angular-route.min.js',
'angular-animate.js': 'http://code.angularjs.org/' + angular.version.full + '/angular-animate.min.js',
'angular-sanitize.js': 'http://code.angularjs.org/' + angular.version.full + '/angular-sanitize.min.js',
'angular-cookies.js': 'http://code.angularjs.org/' + angular.version.full + '/angular-cookies.min.js'
};
function escape(text) {
return text.
replace(/\&/g, '&amp;').
replace(/\</g, '&lt;').
replace(/\>/g, '&gt;').
replace(/"/g, '&quot;');
}
/**
* http://stackoverflow.com/questions/451486/pre-tag-loses-line-breaks-when-setting-innerhtml-in-ie
* http://stackoverflow.com/questions/195363/inserting-a-newline-into-a-pre-tag-ie-javascript
*/
function setHtmlIe8SafeWay(element, html) {
var newElement = angular.element('<pre>' + html + '</pre>');
element.empty();
element.append(newElement.contents());
return element;
}
directive.jsFiddle = function(getEmbeddedTemplate, escape, script) {
return {
terminal: true,
link: function(scope, element, attr) {
var name = '',
stylesheet = '<link rel="stylesheet" href="http://twitter.github.com/bootstrap/assets/css/bootstrap.css">\n',
fields = {
html: '',
css: '',
js: ''
};
angular.forEach(attr.jsFiddle.split(' '), function(file, index) {
var fileType = file.split('.')[1];
if (fileType == 'html') {
if (index == 0) {
fields[fileType] +=
'<div ng-app' + (attr.module ? '="' + attr.module + '"' : '') + '>\n' +
getEmbeddedTemplate(file, 2);
} else {
fields[fileType] += '\n\n\n <!-- CACHE FILE: ' + file + ' -->\n' +
' <script type="text/ng-template" id="' + file + '">\n' +
getEmbeddedTemplate(file, 4) +
' </script>\n';
}
} else {
fields[fileType] += getEmbeddedTemplate(file) + '\n';
}
});
fields.html += '</div>\n';
setHtmlIe8SafeWay(element,
'<form class="jsfiddle" method="post" action="http://jsfiddle.net/api/post/library/pure/" target="_blank">' +
hiddenField('title', 'AngularJS Example: ' + name) +
hiddenField('css', '</style> <!-- Ugly Hack due to jsFiddle issue: http://goo.gl/BUfGZ --> \n' +
stylesheet +
script.angular +
(attr.resource ? script.resource : '') +
'<style>\n' +
fields.css) +
hiddenField('html', fields.html) +
hiddenField('js', fields.js) +
'<button class="btn btn-primary"><i class="icon-white icon-pencil"></i> Edit Me</button>' +
'</form>');
function hiddenField(name, value) {
return '<input type="hidden" name="' + name + '" value="' + escape(value) + '">';
}
}
}
};
directive.ngSetText = ['getEmbeddedTemplate', function(getEmbeddedTemplate) {
return {
restrict: 'CA',
priority: 10,
compile: function(element, attr) {
setHtmlIe8SafeWay(element, escape(getEmbeddedTemplate(attr.ngSetText)));
}
}
}]
directive.ngHtmlWrap = ['reindentCode', 'templateMerge', function(reindentCode, templateMerge) {
return {
compile: function(element, attr) {
var properties = {
head: '',
module: '',
body: element.text()
},
html = "<!doctype html>\n<html ng-app{{module}}>\n <head>\n{{head:4}} </head>\n <body>\n{{body:4}} </body>\n</html>";
angular.forEach((attr.ngHtmlWrap || '').split(' '), function(dep) {
if (!dep) return;
dep = DEPENDENCIES[dep] || dep;
var ext = dep.split(/\./).pop();
if (ext == 'css') {
properties.head += '<link rel="stylesheet" href="' + dep + '" type="text/css">\n';
} else if(ext == 'js') {
properties.head += '<script src="' + dep + '"></script>\n';
} else {
properties.module = '="' + dep + '"';
}
});
setHtmlIe8SafeWay(element, escape(templateMerge(html, properties)));
}
}
}];
directive.ngSetHtml = ['getEmbeddedTemplate', function(getEmbeddedTemplate) {
return {
restrict: 'CA',
priority: 10,
compile: function(element, attr) {
setHtmlIe8SafeWay(element, getEmbeddedTemplate(attr.ngSetHtml));
}
}
}];
directive.ngEvalJavascript = ['getEmbeddedTemplate', function(getEmbeddedTemplate) {
return {
compile: function (element, attr) {
var fileNames = attr.ngEvalJavascript.split(' ');
angular.forEach(fileNames, function(fileName) {
var script = getEmbeddedTemplate(fileName);
try {
if (window.execScript) { // IE
window.execScript(script || '""'); // IE complains when evaling empty string
} else {
window.eval(script + '//@ sourceURL=' + fileName);
}
} catch (e) {
if (window.console) {
window.console.log(script, '\n', e);
} else {
window.alert(e);
}
}
});
}
};
}];
directive.ngEmbedApp = ['$templateCache', '$browser', '$rootScope', '$location', '$sniffer', '$animate',
function($templateCache, $browser, docsRootScope, $location, $sniffer, $animate) {
return {
terminal: true,
link: function(scope, element, attrs) {
var modules = ['ngAnimate'],
embedRootScope,
deregisterEmbedRootScope;
modules.push(['$provide', function($provide) {
$provide.value('$templateCache', $templateCache);
$provide.value('$anchorScroll', angular.noop);
$provide.value('$browser', $browser);
$provide.value('$sniffer', $sniffer);
$provide.value('$animate', $animate);
$provide.provider('$location', function() {
this.$get = ['$rootScope', function($rootScope) {
docsRootScope.$on('$locationChangeSuccess', function(event, oldUrl, newUrl) {
$rootScope.$broadcast('$locationChangeSuccess', oldUrl, newUrl);
});
return $location;
}];
this.html5Mode = angular.noop;
});
$provide.decorator('$rootScope', ['$delegate', function($delegate) {
embedRootScope = $delegate;
// Since we are teleporting the $animate service, which relies on the $$postDigestQueue
// we need the embedded scope to use the same $$postDigestQueue as the outer scope
embedRootScope.$$postDigestQueue = docsRootScope.$$postDigestQueue;
deregisterEmbedRootScope = docsRootScope.$watch(function embedRootScopeDigestWatch() {
embedRootScope.$digest();
});
return embedRootScope;
}]);
}]);
if (attrs.ngEmbedApp) modules.push(attrs.ngEmbedApp);
element.on('click', function(event) {
if (event.target.attributes.getNamedItem('ng-click')) {
event.preventDefault();
}
});
element.bind('$destroy', function() {
deregisterEmbedRootScope();
embedRootScope.$destroy();
});
element.data('$injector', null);
angular.bootstrap(element, modules);
}
};
}];
service.reindentCode = function() {
return function (text, spaces) {
if (!text) return text;
var lines = text.split(/\r?\n/);
var prefix = ' '.substr(0, spaces || 0);
var i;
// remove any leading blank lines
while (lines.length && lines[0].match(/^\s*$/)) lines.shift();
// remove any trailing blank lines
while (lines.length && lines[lines.length - 1].match(/^\s*$/)) lines.pop();
var minIndent = 999;
for (i = 0; i < lines.length; i++) {
var line = lines[0];
var reindentCode = line.match(/^\s*/)[0];
if (reindentCode !== line && reindentCode.length < minIndent) {
minIndent = reindentCode.length;
}
}
for (i = 0; i < lines.length; i++) {
lines[i] = prefix + lines[i].substring(minIndent);
}
lines.push('');
return lines.join('\n');
}
};
service.templateMerge = ['reindentCode', function(indentCode) {
return function(template, properties) {
return template.replace(/\{\{(\w+)(?:\:(\d+))?\}\}/g, function(_, key, indent) {
var value = properties[key];
if (indent) {
value = indentCode(value, indent);
}
return value == undefined ? '' : value;
});
};
}];
service.getEmbeddedTemplate = ['reindentCode', function(reindentCode) {
return function (id) {
var element = document.getElementById(id);
if (!element) {
return null;
}
return reindentCode(angular.element(element).html(), 0);
}
}];
angular.module('bootstrapPrettify', []).directive(directive).factory(service);
+44
View File
@@ -0,0 +1,44 @@
"use strict";
/* jshint browser: true */
/* global importScripts, onmessage: true, postMessage, lunr */
// Load up the lunr library
importScripts('../components/lunr.js-0.4.2/lunr.min.js');
// Create the lunr index - the docs should be an array of object, each object containing
// the path and search terms for a page
var index = lunr(function() {
this.ref('path');
this.field('titleWords', {boost: 50});
this.field('members', { boost: 40});
this.field('keywords', { boost : 20 });
});
// Retrieve the searchData which contains the information about each page to be indexed
var searchData = {};
var searchDataRequest = new XMLHttpRequest();
searchDataRequest.onload = function() {
// Store the pages data to be used in mapping query results back to pages
searchData = JSON.parse(this.responseText);
// Add search terms from each page to the search index
searchData.forEach(function(page) {
index.add(page);
});
postMessage({ e: 'index-ready' });
};
searchDataRequest.open('GET', 'search-data.json');
searchDataRequest.send();
// The worker receives a message everytime the web app wants to query the index
onmessage = function(oEvent) {
var q = oEvent.data.q;
var hits = index.search(q);
var results = [];
// Only return the array of paths to pages
hits.forEach(function(hit) {
results.push(hit.ref);
});
// The results of the query are sent back to the web app via a new message
postMessage({ e: 'query-ready', q: q, d: results });
};
+42
View File
@@ -0,0 +1,42 @@
{
"extends": "../../../.jshintrc-base",
"globals": {
/* jasmine / karma */
"it": false,
"iit": false,
"describe": false,
"ddescribe": false,
"beforeEach": false,
"afterEach": false,
"expect": false,
"jasmine": false,
"spyOn": false,
"waits": false,
"waitsFor": false,
"runs": false,
"dump": false,
/* e2e */
"browser": false,
"element": false,
"by": false,
/* testabilityPatch / matchers */
"inject": false,
"module": false,
"dealoc": false,
"_jQuery": false,
"_jqLiteMode": false,
"sortedHtml": false,
"childrenTagsOf": false,
"assertHidden": false,
"assertVisible": false,
"provideLog": false,
"spyOnlyCallsWithArgs": false,
"createMockStyleSheet": false,
"browserTrigger": false,
"jqLiteCacheSize": false
}
}
@@ -0,0 +1,51 @@
'use strict';
describe("doc.angularjs.org", function() {
describe("API pages", function() {
it("should display links to code on GitHub", function() {
browser.get('index-debug.html#!/api/ng/service/$http');
expect(element(by.css('.improve-docs')).getAttribute('href')).toMatch(/https?:\/\/github\.com\/angular\/angular\.js\/edit\/.+\/src\/ng\/http\.js/);
browser.get('index-debug.html#!/api/ng/service/$http');
expect(element(by.css('.view-source')).getAttribute('href')).toMatch(/https?:\/\/github\.com\/angular\/angular\.js\/tree\/.+\/src\/ng\/http\.js#L\d+/);
});
it('should change the page content when clicking a link to a service', function () {
browser.get('');
var ngBindLink = element(by.css('.definition-table td a[href="api/ng/directive/ngClick"]'));
ngBindLink.click();
var pageBody = element(by.css('h1'));
expect(pageBody.getText()).toEqual('ngClick');
});
it('should show the functioning input directive example', function () {
browser.get('index-debug.html#!/api/ng/directive/input');
// Ensure that the page is loaded before trying to switch frames.
browser.waitForAngular();
browser.switchTo().frame('example-input-directive');
var nameInput = element(by.model('user.name'));
nameInput.sendKeys('!!!');
var code = element.all(by.css('tt')).first();
expect(code.getText()).toContain('guest!!!');
});
it("should trim indentation from code blocks", function() {
browser.get('index-debug.html#!/api/ng/type/$rootScope.Scope');
var codeBlocks = element.all(by.css('pre > code.lang-js'));
codeBlocks.each(function(codeBlock) {
var firstSpan = codeBlock.all(by.css('span')).first();
expect(firstSpan.getText()).not.toMatch(/^\W+$/);
});
});
});
});
@@ -0,0 +1,12 @@
'use strict';
describe("provider pages", function() {
it("should show the related service", function() {
browser.get('index-debug.html#!/api/ng/provider/$compileProvider');
var serviceLink = element.all(by.css('ol.api-profile-header-structure li a')).first();
expect(serviceLink.getText()).toEqual('- $compile');
expect(serviceLink.getAttribute('href')).toMatch(/api\/ng\/service\/\$compile/);
});
});
@@ -0,0 +1,22 @@
'use strict';
describe("service pages", function() {
it("should show the related provider if there is one", function() {
browser.get('index-debug.html#!/api/ng/service/$compile');
var providerLink = element.all(by.css('ol.api-profile-header-structure li a')).first();
expect(providerLink.getText()).toEqual('- $compileProvider');
expect(providerLink.getAttribute('href')).toMatch(/api\/ng\/provider\/\$compileProvider/);
browser.get('index-debug.html#!/api/ng/service/$q');
providerLink = element.all(by.css('ol.api-profile-header-structure li a')).first();
expect(providerLink.getText()).not.toEqual('- $qProvider');
expect(providerLink.getAttribute('href')).not.toMatch(/api\/ng\/provider\/\$compileProvider/);
});
it("should show parameter defaults", function() {
browser.get('index-debug.html#!/api/ng/service/$timeout');
expect(element.all(by.css('.input-arguments p em')).first().getText()).toContain('(default: 0)');
});
});
@@ -26,21 +26,6 @@ describe('docs.angularjs.org', function () {
});
it('should show the functioning input directive example', function () {
browser.get('index-debug.html#!/api/ng/directive/input');
// Ensure that the page is loaded before trying to switch frames.
browser.waitForAngular();
browser.switchTo().frame('example-input-directive');
var nameInput = element(by.model('user.name'));
nameInput.sendKeys('!!!');
var code = element.all(by.css('tt')).first();
expect(code.getText()).toContain('guest!!!');
});
it('should be resilient to trailing slashes', function() {
browser.get('index-debug.html#!/api/ng/function/angular.noop/');
@@ -67,12 +52,15 @@ describe('docs.angularjs.org', function () {
browser.get('index-debug.html#!error/ng/areq?p0=Missing&p1=not%20a%20function,%20got%20undefined');
expect(element(by.css('.minerr-errmsg')).getText()).toEqual("Argument 'Missing' is not a function, got undefined");
});
});
describe("templates", function() {
it("should show parameter defaults", function() {
browser.get('index-debug.html#!/api/ng/service/$timeout');
expect(element.all(by.css('.input-arguments p em')).first().getText()).toContain('(default: 0)');
});
});
describe('Error Handling', function() {
it("should display an error if the page does not exist", function() {
browser.get('index-debug.html#!/api/does/not/exist');
expect(element(by.css('h1')).getText()).toBe('Oops!');
});
});
+3 -3
View File
@@ -6,6 +6,7 @@ angular.module('docsApp', [
'DocsController',
'versionsData',
'pagesData',
'navData',
'directives',
'errors',
'examples',
@@ -13,11 +14,10 @@ angular.module('docsApp', [
'tutorials',
'versions',
'bootstrap',
'bootstrapPrettify',
'ui.bootstrap.dropdown'
])
.config(function($locationProvider) {
.config(['$locationProvider', function($locationProvider) {
$locationProvider.html5Mode(true).hashPrefix('!');
});
}]);
+9 -74
View File
@@ -6,31 +6,10 @@ angular.module('DocsController', [])
function($scope, $rootScope, $location, $window, $cookies, openPlunkr,
NG_PAGES, NG_NAVIGATION, NG_VERSION) {
$scope.openPlunkr = openPlunkr;
$scope.docsVersion = NG_VERSION.isSnapshot ? 'snapshot' : NG_VERSION.version;
$scope.fold = function(url) {
if(url) {
$scope.docs_fold = '/notes/' + url;
if(/\/build/.test($window.location.href)) {
$scope.docs_fold = '/build/docs' + $scope.docs_fold;
}
window.scrollTo(0,0);
}
else {
$scope.docs_fold = null;
}
};
var OFFLINE_COOKIE_NAME = 'ng-offline',
INDEX_PATH = /^(\/|\/index[^\.]*.html)$/;
/**********************************
Publish methods
***********************************/
$scope.navClass = function(navItem) {
return {
active: navItem.href && this.currentPage.path,
@@ -38,55 +17,22 @@ angular.module('DocsController', [])
};
};
$scope.afterPartialLoaded = function() {
$scope.$on('$includeContentLoaded', function() {
var pagePath = $scope.currentPage ? $scope.currentPage.path : $location.path();
$window._gaq.push(['_trackPageview', pagePath]);
};
/** stores a cookie that is used by apache to decide which manifest ot send */
$scope.enableOffline = function() {
//The cookie will be good for one year!
var date = new Date();
date.setTime(date.getTime()+(365*24*60*60*1000));
var expires = "; expires="+date.toGMTString();
var value = angular.version.full;
document.cookie = OFFLINE_COOKIE_NAME + "="+value+expires+"; path=" + $location.path;
//force the page to reload so server can serve new manifest file
window.location.reload(true);
};
/**********************************
Watches
***********************************/
});
$scope.$watch(function docsPathWatch() {return $location.path(); }, function docsPathWatchAction(path) {
var currentPage = $scope.currentPage = NG_PAGES[path];
if ( !currentPage && path.charAt(0)==='/' ) {
// Strip off leading slash
path = path.substr(1);
}
currentPage = $scope.currentPage = NG_PAGES[path];
if ( !currentPage && path.charAt(path.length-1) === '/' && path.length > 1 ) {
// Strip off trailing slash
path = path.substr(0, path.length-1);
}
currentPage = $scope.currentPage = NG_PAGES[path];
if ( !currentPage && /\/index$/.test(path) ) {
// Strip off index from the end
path = path.substr(0, path.length - 6);
}
path = path.replace(/^\/?(.+?)(\/index)?\/?$/, '$1');
currentPage = $scope.currentPage = NG_PAGES[path];
if ( currentPage ) {
$scope.currentArea = currentPage && NG_NAVIGATION[currentPage.area];
$scope.partialPath = 'partials/' + path + '.html';
$scope.currentArea = NG_NAVIGATION[currentPage.area];
var pathParts = currentPage.path.split('/');
var breadcrumb = $scope.breadcrumb = [];
var breadcrumbPath = '';
@@ -98,6 +44,7 @@ angular.module('DocsController', [])
} else {
$scope.currentArea = NG_NAVIGATION['api'];
$scope.breadcrumb = [];
$scope.partialPath = 'Error404.html';
}
});
@@ -107,24 +54,12 @@ angular.module('DocsController', [])
$scope.versionNumber = angular.version.full;
$scope.version = angular.version.full + " " + angular.version.codeName;
$scope.subpage = false;
$scope.offlineEnabled = ($cookies[OFFLINE_COOKIE_NAME] == angular.version.full);
$scope.futurePartialTitle = null;
$scope.loading = 0;
$scope.$cookies = $cookies;
$cookies.platformPreference = $cookies.platformPreference || 'gitUnix';
var INDEX_PATH = /^(\/|\/index[^\.]*.html)$/;
if (!$location.path() || INDEX_PATH.test($location.path())) {
$location.path('/api').replace();
}
// bind escape to hash reset callback
angular.element(window).on('keydown', function(e) {
if (e.keyCode === 27) {
$scope.$apply(function() {
$scope.subpage = false;
});
}
});
}]);
-24
View File
@@ -1,24 +0,0 @@
angular.module('docsApp.navigationService', [])
.factory('navigationService', function($window) {
var service = {
currentPage: null,
currentVersion: null,
changePage: function(newPage) {
},
changeVersion: function(newVersion) {
//TODO =========
// var currentPagePath = '';
// // preserve URL path when switching between doc versions
// if (angular.isObject($rootScope.currentPage) && $rootScope.currentPage.section && $rootScope.currentPage.id) {
// currentPagePath = '/' + $rootScope.currentPage.section + '/' + $rootScope.currentPage.id;
// }
// $window.location = version.url + currentPagePath;
}
};
});
+123 -62
View File
@@ -10,22 +10,35 @@ angular.module('search', [])
$scope.search = function(q) {
var MIN_SEARCH_LENGTH = 2;
if(q.length >= MIN_SEARCH_LENGTH) {
var results = docsSearch(q);
var totalAreas = 0;
for(var i in results) {
++totalAreas;
}
if(totalAreas > 0) {
$scope.colClassName = 'cols-' + totalAreas;
}
$scope.hasResults = totalAreas > 0;
$scope.results = results;
docsSearch(q).then(function(hits) {
var results = {};
angular.forEach(hits, function(hit) {
var area = hit.area;
var limit = (area == 'api') ? 40 : 14;
results[area] = results[area] || [];
if(results[area].length < limit) {
results[area].push(hit);
}
});
var totalAreas = 0;
for(var i in results) {
++totalAreas;
}
if(totalAreas > 0) {
$scope.colClassName = 'cols-' + totalAreas;
}
$scope.hasResults = totalAreas > 0;
$scope.results = results;
});
}
else {
clearResults();
}
if(!$scope.$$phase) $scope.$apply();
};
$scope.submit = function() {
var result;
for(var i in $scope.results) {
@@ -39,76 +52,124 @@ angular.module('search', [])
$scope.hideResults();
}
};
$scope.hideResults = function() {
clearResults();
$scope.q = '';
};
}])
.controller('Error404SearchCtrl', ['$scope', '$location', 'docsSearch', function($scope, $location, docsSearch) {
$scope.results = docsSearch($location.path().split(/[\/\.:]/).pop());
.controller('Error404SearchCtrl', ['$scope', '$location', 'docsSearch',
function($scope, $location, docsSearch) {
docsSearch($location.path().split(/[\/\.:]/).pop()).then(function(results) {
$scope.results = {};
angular.forEach(results, function(result) {
var area = $scope.results[result.area] || [];
area.push(result);
$scope.results[result.area] = area;
});
});
}])
.factory('lunrSearch', function() {
return function(properties) {
if (window.RUNNING_IN_NG_TEST_RUNNER) return null;
var engine = lunr(properties);
return {
store : function(values) {
engine.add(values);
},
search : function(q) {
return engine.search(q);
}
};
};
})
.provider('docsSearch', function() {
.factory('docsSearch', ['$rootScope','lunrSearch', 'NG_PAGES',
function($rootScope, lunrSearch, NG_PAGES) {
if (window.RUNNING_IN_NG_TEST_RUNNER) {
return null;
}
// This version of the service builds the index in the current thread,
// which blocks rendering and other browser activities.
// It should only be used where the browser does not support WebWorkers
function localSearchFactory($http, $timeout, NG_PAGES) {
var index = lunrSearch(function() {
this.ref('id');
this.field('title', {boost: 50});
this.field('keywords', { boost : 20 });
});
console.log('Using Local Search Index');
angular.forEach(NG_PAGES, function(page, key) {
if(page.searchTerms) {
index.store({
id : key,
title : page.searchTerms.titleWords,
keywords : page.searchTerms.keywords
// Create the lunr index
var index = lunr(function() {
this.ref('path');
this.field('titleWords', {boost: 50});
this.field('members', { boost: 40});
this.field('keywords', { boost : 20 });
});
// Delay building the index by loading the data asynchronously
var indexReadyPromise = $http.get('js/search-data.json').then(function(response) {
var searchData = response.data;
// Delay building the index for 500ms to allow the page to render
return $timeout(function() {
// load the page data into the index
angular.forEach(searchData, function(page) {
index.add(page);
});
}, 500);
});
// The actual service is a function that takes a query string and
// returns a promise to the search results
// (In this case we just resolve the promise immediately as it is not
// inherently an async process)
return function(q) {
return indexReadyPromise.then(function() {
var hits = index.search(q);
var results = [];
angular.forEach(hits, function(hit) {
results.push(NG_PAGES[hit.ref]);
});
return results;
});
};
});
}
localSearchFactory.$inject = ['$http', '$timeout', 'NG_PAGES'];
return function(q) {
var results = {
api : [],
tutorial : [],
guide : [],
error : [],
misc : []
// This version of the service builds the index in a WebWorker,
// which does not block rendering and other browser activities.
// It should only be used where the browser does support WebWorkers
function webWorkerSearchFactory($q, $rootScope, NG_PAGES) {
console.log('Using WebWorker Search Index')
var searchIndex = $q.defer();
var results;
var worker = new Worker('js/search-worker.js');
// The worker will send us a message in two situations:
// - when the index has been built, ready to run a query
// - when it has completed a search query and the results are available
worker.onmessage = function(oEvent) {
$rootScope.$apply(function() {
switch(oEvent.data.e) {
case 'index-ready':
searchIndex.resolve();
break;
case 'query-ready':
var pages = oEvent.data.d.map(function(path) {
return NG_PAGES[path];
});
results.resolve(pages);
break;
}
});
};
angular.forEach(index.search(q), function(result) {
var key = result.ref;
var item = NG_PAGES[key];
var area = item.area;
item.path = key;
var limit = area == 'api' ? 40 : 14;
if(results[area].length < limit) {
results[area].push(item);
}
});
return results;
// The actual service is a function that takes a query string and
// returns a promise to the search results
return function(q) {
// We only run the query once the index is ready
return searchIndex.promise.then(function() {
results = $q.defer();
worker.postMessage({ q: q });
return results.promise;
});
};
}
webWorkerSearchFactory.$inject = ['$q', '$rootScope', 'NG_PAGES'];
return {
$get: window.Worker ? webWorkerSearchFactory : localSearchFactory
};
}])
})
.directive('focused', function($timeout) {
return function(scope, element, attrs) {
+15 -16
View File
@@ -1,6 +1,6 @@
angular.module('tutorials', [])
.directive('docTutorialNav', function(templateMerge) {
.directive('docTutorialNav', function() {
var pages = [
'',
'step_00', 'step_01', 'step_02', 'step_03', 'step_04',
@@ -8,23 +8,22 @@ angular.module('tutorials', [])
'step_10', 'step_11', 'step_12', 'the_end'
];
return {
compile: function(element, attrs) {
var seq = 1 * attrs.docTutorialNav,
props = {
seq: seq,
prev: pages[seq],
next: pages[2 + seq],
diffLo: seq ? (seq - 1): '0~1',
diffHi: seq
};
scope: {},
template:
'<a ng-href="tutorial/{{prev}}"><li class="btn btn-primary"><i class="glyphicon glyphicon-step-backward"></i> Previous</li></a>\n' +
'<a ng-href="http://angular.github.io/angular-phonecat/step-{{seq}}/app"><li class="btn btn-primary"><i class="glyphicon glyphicon-play"></i> Live Demo</li></a>\n' +
'<a ng-href="https://github.com/angular/angular-phonecat/compare/step-{{diffLo}}...step-{{diffHi}}"><li class="btn btn-primary"><i class="glyphicon glyphicon-search"></i> Code Diff</li></a>\n' +
'<a ng-href="tutorial/{{next}}"><li class="btn btn-primary">Next <i class="glyphicon glyphicon-step-forward"></i></li></a>',
link: function(scope, element, attrs) {
var seq = 1 * attrs.docTutorialNav;
scope.seq = seq;
scope.prev = pages[seq];
scope.next = pages[2 + seq];
scope.diffLo = seq ? (seq - 1): '0~1';
scope.diffHi = seq;
element.addClass('btn-group');
element.addClass('tutorial-nav');
element.append(templateMerge(
'<a href="tutorial/{{prev}}"><li class="btn btn-primary"><i class="glyphicon glyphicon-step-backward"></i> Previous</li></a>\n' +
'<a href="http://angular.github.io/angular-phonecat/step-{{seq}}/app"><li class="btn btn-primary"><i class="glyphicon glyphicon-play"></i> Live Demo</li></a>\n' +
'<a href="https://github.com/angular/angular-phonecat/compare/step-{{diffLo}}...step-{{diffHi}}"><li class="btn btn-primary"><i class="glyphicon glyphicon-search"></i> Code Diff</li></a>\n' +
'<a href="tutorial/{{next}}"><li class="btn btn-primary">Next <i class="glyphicon glyphicon-step-forward"></i></li></a>', props));
}
};
})
@@ -47,4 +46,4 @@ angular.module('tutorials', [])
'<a ng-href="https://github.com/angular/angular-phonecat/compare/step-{{step ? (step - 1): \'0~1\'}}...step-{{step}}">GitHub</a>\n' +
'</p>'
};
});
});
-2
View File
@@ -1,5 +1,3 @@
"use strict";
angular.module('versions', [])
.controller('DocsVersionsCtrl', ['$scope', '$location', '$window', 'NG_VERSIONS', function($scope, $location, $window, NG_VERSIONS) {
+2 -2
View File
@@ -19,7 +19,7 @@ describe("DocsController", function() {
it("should update the Google Analytics with currentPage path if currentPage exists", inject(function($window) {
$window._gaq = [];
$scope.currentPage = { path: 'a/b/c' };
$scope.afterPartialLoaded();
$scope.$broadcast('$includeContentLoaded');
expect($window._gaq.pop()).toEqual(['_trackPageview', 'a/b/c']);
}));
@@ -27,7 +27,7 @@ describe("DocsController", function() {
it("should update the Google Analytics with $location.path if currentPage is missing", inject(function($window, $location) {
$window._gaq = [];
spyOn($location, 'path').andReturn('x/y/z');
$scope.afterPartialLoaded();
$scope.$broadcast('$includeContentLoaded');
expect($window._gaq.pop()).toEqual(['_trackPageview', 'x/y/z']);
}));
});
+10
View File
@@ -0,0 +1,10 @@
{
"name": "AngularJS-docs-app",
"dependencies": {
"jquery": "2.1.1",
"lunr.js": "0.4.3",
"open-sans-fontface": "1.0.4",
"google-code-prettify": "1.0.1",
"bootstrap": "3.1.1"
}
}
+148 -31
View File
@@ -1,43 +1,160 @@
var _ = require('lodash');
"use strict";
var path = require('canonical-path');
var packagePath = __dirname;
var basePackage = require('dgeni-packages/ngdoc');
var examplesPackage = require('dgeni-packages/examples');
var Package = require('dgeni').Package;
module.exports = function(config) {
// Create and export a new Dgeni package called dgeni-example. This package depends upon
// the jsdoc and nunjucks packages defined in the dgeni-packages npm module.
module.exports = new Package('angularjs', [
require('dgeni-packages/ngdoc'),
require('dgeni-packages/nunjucks'),
require('dgeni-packages/examples')
])
config = basePackage(config);
config = examplesPackage(config);
config.append('processing.processors', [
require('./processors/git-data'),
require('./processors/error-docs'),
require('./processors/keywords'),
require('./processors/versions-data'),
require('./processors/pages-data'),
require('./processors/protractor-generate'),
require('./processors/index-page'),
require('./processors/debug-dump')
]);
.factory(require('./services/errorNamespaceMap'))
.factory(require('./services/getMinerrInfo'))
.factory(require('./services/getVersion'))
.factory(require('./services/gitData'))
config.append('processing.tagDefinitions', [
require('./tag-defs/tutorial-step')
]);
.factory(require('./services/deployments/debug'))
.factory(require('./services/deployments/default'))
.factory(require('./services/deployments/jquery'))
.factory(require('./services/deployments/production'))
config.append('processing.defaultTagTransforms', [
require('dgeni-packages/jsdoc/tag-defs/transforms/trim-whitespace')
]);
.factory(require('./inline-tag-defs/type'))
config.append('processing.inlineTagDefinitions', [
require('./inline-tag-defs/type')
]);
config.set('processing.search.ignoreWordsFile', path.resolve(packagePath, 'ignore.words'));
.processor(require('./processors/error-docs'))
.processor(require('./processors/index-page'))
.processor(require('./processors/keywords'))
.processor(require('./processors/pages-data'))
.processor(require('./processors/versions-data'))
config.prepend('rendering.templateFolders', [
path.resolve(packagePath, 'templates')
]);
return config;
};
.config(function(dgeni, log, readFilesProcessor, writeFilesProcessor) {
dgeni.stopOnValidationError = true;
dgeni.stopOnProcessingError = true;
log.level = 'info';
readFilesProcessor.basePath = path.resolve(__dirname,'../..');
readFilesProcessor.sourceFiles = [
{ include: 'src/**/*.js', basePath: 'src' },
{ include: 'docs/content/**/*.ngdoc', basePath: 'docs/content' }
];
writeFilesProcessor.outputFolder = 'build/docs';
})
.config(function(parseTagsProcessor) {
parseTagsProcessor.tagDefinitions.push(require('./tag-defs/tutorial-step'));
parseTagsProcessor.tagDefinitions.push(require('./tag-defs/sortOrder'));
})
.config(function(inlineTagProcessor, typeInlineTagDef) {
inlineTagProcessor.inlineTagDefinitions.push(typeInlineTagDef);
})
.config(function(templateFinder, renderDocsProcessor, gitData) {
templateFinder.templateFolders.unshift(path.resolve(packagePath, 'templates'));
renderDocsProcessor.extraData.git = gitData;
})
.config(function(computePathsProcessor, computeIdsProcessor) {
computePathsProcessor.pathTemplates.push({
docTypes: ['error'],
pathTemplate: 'error/${namespace}/${name}',
outputPathTemplate: 'partials/error/${namespace}/${name}.html'
});
computePathsProcessor.pathTemplates.push({
docTypes: ['errorNamespace'],
pathTemplate: 'error/${name}',
outputPathTemplate: 'partials/error/${name}.html'
});
computePathsProcessor.pathTemplates.push({
docTypes: ['overview', 'tutorial'],
getPath: function(doc) {
var docPath = path.dirname(doc.fileInfo.relativePath);
if ( doc.fileInfo.baseName !== 'index' ) {
docPath = path.join(docPath, doc.fileInfo.baseName);
}
return docPath;
},
outputPathTemplate: 'partials/${path}.html'
});
computePathsProcessor.pathTemplates.push({
docTypes: ['e2e-test'],
getPath: function() {},
outputPathTemplate: 'ptore2e/${example.id}/${deployment.name}_test.js'
});
computePathsProcessor.pathTemplates.push({
docTypes: ['indexPage'],
getPath: function() {},
outputPathTemplate: '${id}.html'
});
computePathsProcessor.pathTemplates.push({
docTypes: ['module' ],
pathTemplate: '${area}/${name}',
outputPathTemplate: 'partials/${area}/${name}.html'
});
computePathsProcessor.pathTemplates.push({
docTypes: ['componentGroup' ],
pathTemplate: '${area}/${moduleName}/${groupType}',
outputPathTemplate: 'partials/${area}/${moduleName}/${groupType}.html'
});
computeIdsProcessor.idTemplates.push({
docTypes: ['overview', 'tutorial', 'e2e-test', 'indexPage'],
getId: function(doc) { return doc.fileInfo.baseName; },
getAliases: function(doc) { return [doc.id]; }
});
computeIdsProcessor.idTemplates.push({
docTypes: ['error', 'errorNamespace'],
getId: function(doc) { return 'error:' + doc.name; },
getAliases: function(doc) { return [doc.id]; }
});
})
.config(function(
generateIndexPagesProcessor,
generateProtractorTestsProcessor,
generateExamplesProcessor,
debugDeployment, defaultDeployment,
jqueryDeployment, productionDeployment) {
generateIndexPagesProcessor.deployments = [
debugDeployment,
defaultDeployment,
jqueryDeployment,
productionDeployment
];
generateProtractorTestsProcessor.deployments = [
defaultDeployment,
jqueryDeployment
];
generateExamplesProcessor.deployments = [
debugDeployment,
defaultDeployment,
jqueryDeployment,
productionDeployment
];
});
+15 -10
View File
@@ -1,12 +1,17 @@
var typeClassFilter = require('dgeni-packages/ngdoc/rendering/filters/type-class');
"use strict";
var encoder = new require('node-html-encoder').Encoder();
module.exports = {
name: 'type',
description: 'Replace with markup that displays a nice type',
handlerFactory: function() {
return function(doc, tagName, tagDescription) {
return '<a href="" class="' + typeClassFilter.process(tagDescription) + '">'+encoder.htmlEncode(tagDescription) + '</a>';
};
}
};
/**
* @dgService typeInlineTagDef
* @description
* Replace with markup that displays a nice type
*/
module.exports = function typeInlineTagDef(getTypeClass) {
return {
name: 'type',
handler: function(doc, tagName, tagDescription) {
return '<a href="" class="' + getTypeClass(tagDescription) + '">'+encoder.htmlEncode(tagDescription) + '</a>';
}
};
};
-33
View File
@@ -1,33 +0,0 @@
var fs = require('q-io/fs');
var log = require('winston');
var util = require("util");
module.exports = {
name: 'debug-dump',
runBefore: ['write-files'],
description: 'This processor dumps docs that match a filter to a file',
process: function(docs, config) {
var filter, outputPath, depth;
filter = config.get('processing.debug-dump.filter');
outputPath = config.get('processing.debug-dump.outputPath');
depth = config.get('processing.debug-dump.depth', 2);
if ( filter && outputPath ) {
log.info('Dumping docs:', filter, outputPath);
var filteredDocs = filter(docs);
var dumpedDocs = util.inspect(filteredDocs, depth);
return writeFile(outputPath, dumpedDocs).then(function() {
return docs;
});
}
}
};
function writeFile(file, content) {
return fs.makeTree(fs.directory(file)).then(function() {
return fs.write(file, content, 'wb');
});
}
+43 -50
View File
@@ -1,59 +1,52 @@
"use strict";
var _ = require('lodash');
var log = require('winston');
var path = require('canonical-path');
module.exports = {
name: 'error-docs',
description: 'Compute the various fields for docs in the Error area',
runAfter: ['tags-extracted', 'compute-path'],
runBefore: ['extra-docs-added'],
exports: {
errorNamespaces: ['factory', function() { return {}; }],
minerrInfo: ['factory', function(config) {
var minerrInfoPath = config.get('processing.errors.minerrInfoPath');
if ( !minerrInfoPath ) {
throw new Error('Error in configuration: Please provide a path to the minerr info file (errors.json) ' +
'in the `config.processing.errors.minerrInfoPath` property');
}
return require(minerrInfoPath);
}]
},
process: function(docs, partialNames, errorNamespaces, minerrInfo) {
/**
* @dgProcessor errorDocsProcessor
* @description
* Process "error" docType docs and generate errorNamespace docs
*/
module.exports = function errorDocsProcessor(errorNamespaceMap, getMinerrInfo) {
return {
$runAfter: ['tags-extracted'],
$runBefore: ['extra-docs-added'],
$process: function(docs) {
// Create error namespace docs and attach error docs to each
_.forEach(docs, function(doc) {
if ( doc.docType === 'error' ) {
// Create error namespace docs and attach error docs to each
docs.forEach(function(doc) {
var parts, namespaceDoc;
// Parse out the error info from the id
parts = doc.name.split(':');
doc.namespace = parts[0];
doc.name = parts[1];
if ( doc.docType === 'error' ) {
// Parse out the error info from the id
parts = doc.name.split(':');
doc.namespace = parts[0];
doc.name = parts[1];
var namespaceDoc = errorNamespaces[doc.namespace];
if ( !namespaceDoc ) {
// First time we came across this namespace, so create a new one
namespaceDoc = errorNamespaces[doc.namespace] = {
area: doc.area,
name: doc.namespace,
errors: [],
path: path.dirname(doc.path),
outputPath: path.dirname(doc.outputPath) + '.html',
docType: 'errorNamespace'
};
// Get or create the relevant errorNamespace doc
namespaceDoc = errorNamespaceMap.get(doc.namespace);
if ( !namespaceDoc ) {
namespaceDoc = {
area: 'error',
name: doc.namespace,
errors: [],
docType: 'errorNamespace'
};
errorNamespaceMap.set(doc.namespace, namespaceDoc);
}
// Link this error doc to its namespace doc
namespaceDoc.errors.push(doc);
doc.namespaceDoc = namespaceDoc;
doc.formattedErrorMessage = getMinerrInfo().errors[doc.namespace][doc.name];
}
});
// Add this error to the namespace
namespaceDoc.errors.push(doc);
doc.namespace = namespaceDoc;
doc.formattedErrorMessage = minerrInfo.errors[doc.namespace.name][doc.name];
}
});
return docs.concat(_.values(errorNamespaces));
}
};
errorNamespaceMap.forEach(function(errorNamespace) {
docs.push(errorNamespace);
});
}
};
};
-20
View File
@@ -1,20 +0,0 @@
var gruntUtils = require('../../../lib/grunt/utils');
var versionInfo = require('../../../lib/versions/version-info');
module.exports = {
name: 'git-data',
runBefore: ['reading-files'],
description: 'This processor adds information from the local git repository to the extraData injectable',
exports: {
gitData: ['factory', function() {
return {
version: versionInfo.currentVersion,
versions: versionInfo.previousVersions,
info: versionInfo.gitRepoInfo
};
}]
},
process: function(extraData, gitData) {
extraData.git = gitData;
}
};
+38 -35
View File
@@ -1,40 +1,43 @@
"use strict";
var _ = require('lodash');
var log = require('winston');
var path = require('canonical-path');
module.exports = {
name: 'index-page',
runAfter: ['adding-extra-docs'],
runBefore: ['extra-docs-added'],
description: 'This processor creates docs that will be rendered as the index page for the app',
process: function(docs, config) {
/**
* @dgProcessor generateIndexPagesProcessor
* @description
* This processor creates docs that will be rendered as the index page for the app
*/
module.exports = function generateIndexPagesProcessor() {
return {
deployments: [],
$validate: {
deployments: { presence: true }
},
$runAfter: ['adding-extra-docs'],
$runBefore: ['extra-docs-added'],
$process: function(docs) {
var deployment = config.deployment;
if ( !deployment || !deployment.environments ) {
throw new Error('No deployment environments found in the config.');
// Collect up all the areas in the docs
var areas = {};
docs.forEach(function(doc) {
if ( doc.area ) {
areas[doc.area] = doc.area;
}
});
areas = _.keys(areas);
this.deployments.forEach(function(deployment) {
var indexDoc = _.defaults({
docType: 'indexPage',
areas: areas
}, deployment);
indexDoc.id = 'index' + (deployment.name === 'default' ? '' : '-' + deployment.name);
docs.push(indexDoc);
});
}
// Collect up all the areas in the docs
var areas = {};
_.forEach(docs, function(doc) {
if ( doc.area ) {
areas[doc.area] = doc.area;
}
});
areas = _.keys(areas);
_.forEach(deployment.environments, function(environment) {
var indexDoc = _.defaults({
docType: 'indexPage',
areas: areas
}, environment);
indexDoc.id = 'index' + (environment.name === 'default' ? '' : '-' + environment.name);
// Use .. to put it at the root of the build
indexDoc.outputPath = indexDoc.id + '.html';
docs.push(indexDoc);
});
}
};
};
};
+72 -46
View File
@@ -1,50 +1,64 @@
"use strict";
var _ = require('lodash');
var log = require('winston');
var fs = require('fs');
var path = require('canonical-path');
module.exports = {
name: 'keywords',
runAfter: ['docs-processed'],
runBefore: ['adding-extra-docs'],
description: 'This processor extracts all the keywords from the document',
process: function(docs, config) {
/**
* @dgProcessor generateKeywordsProcessor
* @description
* This processor extracts all the keywords from each document and creates
* a new document that will be rendered as a JavaScript file containing all
* this data.
*/
module.exports = function generateKeywordsProcessor(log, readFilesProcessor) {
return {
ignoreWordsFile: undefined,
areasToSearch: ['api', 'guide', 'misc', 'error', 'tutorial'],
propertiesToIgnore: [],
$validate: {
ignoreWordsFile: { },
areasToSearch: { presence: true },
propertiesToIgnore: { }
},
$runAfter: ['memberDocsProcessor'],
$runBefore: ['rendering-docs'],
$process: function(docs) {
// Keywords to ignore
var wordsToIgnore = [];
var propertiesToIgnore;
var areasToSearch;
// Keywords to ignore
var wordsToIgnore = [];
var propertiesToIgnore;
var areasToSearch;
// Keywords start with "ng:" or one of $, _ or a letter
var KEYWORD_REGEX = /^((ng:|[\$_a-z])[\w\-_]+)/;
// Keywords start with "ng:" or one of $, _ or a letter
var KEYWORD_REGEX = /^((ng:|[\$_a-z])[\w\-_]+)/;
// Load up the keywords to ignore, if specified in the config
if ( config.processing.search && config.processing.search.ignoreWordsFile ) {
// Load up the keywords to ignore, if specified in the config
if ( this.ignoreWordsFile ) {
var ignoreWordsPath = path.resolve(config.basePath, config.processing.search.ignoreWordsFile);
wordsToIgnore = fs.readFileSync(ignoreWordsPath, 'utf8').toString().split(/[,\s\n\r]+/gm);
var ignoreWordsPath = path.resolve(readFilesProcessor.basePath, this.ignoreWordsFile);
wordsToIgnore = fs.readFileSync(ignoreWordsPath, 'utf8').toString().split(/[,\s\n\r]+/gm);
log.debug('Loaded ignore words from "' + ignoreWordsPath + '"');
log.silly(wordsToIgnore);
log.debug('Loaded ignore words from "' + ignoreWordsPath + '"');
log.silly(wordsToIgnore);
}
areasToSearch = _.indexBy(config.get('processing.search.areasToSearch', ['api', 'guide', 'misc', 'error', 'tutorial']));
propertiesToIgnore = _.indexBy(config.get('processing.search.propertiesToIgnore', []));
log.debug('Properties to ignore', propertiesToIgnore);
var ignoreWordsMap = _.indexBy(wordsToIgnore);
// If the title contains a name starting with ng, e.g. "ngController", then add the module name
// without the ng to the title text, e.g. "controller".
function extractTitleWords(title) {
var match = /ng([A-Z]\w*)/.exec(title);
if ( match ) {
title = title + ' ' + match[1].toLowerCase();
}
return title;
}
areasToSearch = _.indexBy(this.areasToSearch);
propertiesToIgnore = _.indexBy(this.propertiesToIgnore);
log.debug('Properties to ignore', propertiesToIgnore);
var ignoreWordsMap = _.indexBy(wordsToIgnore);
// If the title contains a name starting with ng, e.g. "ngController", then add the module name
// without the ng to the title text, e.g. "controller".
function extractTitleWords(title) {
var match = /ng([A-Z]\w*)/.exec(title);
if ( match ) {
title = title + ' ' + match[1].toLowerCase();
}
return title;
}
function extractWords(text, words, keywordMap) {
@@ -52,37 +66,49 @@ module.exports = {
_.forEach(tokens, function(token){
var match = token.match(KEYWORD_REGEX);
if (match){
key = match[1];
var key = match[1];
if ( !keywordMap[key]) {
keywordMap[key] = true;
words.push(key);
}
}
});
}
}
});
}
// We are only interested in docs that live in the right area
docs = _.filter(docs, function(doc) { return areasToSearch[doc.area]; });
// We are only interested in docs that live in the right area
docs = _.filter(docs, function(doc) { return areasToSearch[doc.area]; });
_.forEach(docs, function(doc) {
_.forEach(docs, function(doc) {
var words = [];
var keywordMap = _.clone(ignoreWordsMap);
var members = [];
var membersMap = {};
// Search each top level property of the document for search terms
_.forEach(doc, function(value, key) {
if ( _.isString(value) && !propertiesToIgnore[key] ) {
extractWords(value, words, keywordMap);
}
if ( key === 'methods' || key === 'properties' || key === 'events' ) {
_.forEach(value, function(member) {
extractWords(member.name, members, membersMap);
});
}
});
doc.searchTerms = {
titleWords: extractTitleWords(doc.name),
keywords: _.sortBy(words).join(' ')
keywords: _.sortBy(words).join(' '),
members: _.sortBy(members).join(' ')
};
});
});
}
}
};
};
+181 -156
View File
@@ -1,6 +1,7 @@
"use strict";
var _ = require('lodash');
var path = require('canonical-path');
var log = require('winston');
var AREA_NAMES = {
api: 'API',
@@ -33,182 +34,206 @@ function getNavGroup(pages, area, pageSorter, pageMapper) {
}
var navGroupMappers = {
api: function(areaPages, area) {
var navGroups = _(areaPages)
.filter('module') // We are not interested in docs that are not in a module
/**
* @dgProcessor generatePagesDataProcessor
* @description
* This processor will create a new doc that will be rendered as a JavaScript file
* containing meta information about the pages and navigation
*/
module.exports = function generatePagesDataProcessor(log) {
.groupBy('module')
.map(function(modulePages, moduleName) {
log.debug('moduleName: ' + moduleName);
var navItems = [];
var modulePage;
var navGroupMappers = {
api: function(areaPages, area) {
var navGroups = _(areaPages)
.filter('module') // We are not interested in docs that are not in a module
_(modulePages)
.groupBy('module')
.groupBy('docType')
.map(function(modulePages, moduleName) {
log.debug('moduleName: ' + moduleName);
var navItems = [];
var modulePage;
.tap(function(docTypes) {
log.debug(_.keys(docTypes));
// Extract the module page from the collection
modulePage = docTypes.module[0];
delete docTypes.module;
})
_(modulePages)
.tap(function(docTypes) {
if ( docTypes.input ) {
docTypes.directive = docTypes.directive || [];
// Combine input docTypes into directive docTypes
docTypes.directive = docTypes.directive.concat(docTypes.input);
delete docTypes.input;
}
})
.groupBy('docType')
.forEach(function(sectionPages, sectionName) {
.tap(function(docTypes) {
log.debug(moduleName, _.keys(docTypes));
// Extract the module page from the collection
modulePage = docTypes.module[0];
delete docTypes.module;
})
sectionPages = _.sortBy(sectionPages, 'name');
.tap(function(docTypes) {
if ( docTypes.input ) {
docTypes.directive = docTypes.directive || [];
// Combine input docTypes into directive docTypes
docTypes.directive = docTypes.directive.concat(docTypes.input);
delete docTypes.input;
}
})
if ( sectionPages.length > 0 ) {
// Push a navItem for this section
navItems.push({
name: sectionName,
type: 'section',
href: path.dirname(sectionPages[0].path)
});
.forEach(function(sectionPages, sectionName) {
// Push the rest of the sectionPages for this section
_.forEach(sectionPages, function(sectionPage) {
sectionPages = _.sortBy(sectionPages, 'name');
if ( sectionPages.length > 0 ) {
// Push a navItem for this section
navItems.push({
name: sectionPage.name,
href: sectionPage.path,
type: sectionPage.docType
name: sectionName,
type: 'section',
href: path.dirname(sectionPages[0].path)
});
});
}
});
// Push the rest of the sectionPages for this section
_.forEach(sectionPages, function(sectionPage) {
navItems.push({
name: sectionPage.name,
href: sectionPage.path,
type: sectionPage.docType
});
});
}
});
return {
name: moduleName,
href: modulePage.path,
type: 'group',
navItems: navItems
};
})
.value();
return navGroups;
},
tutorial: function(pages, area) {
return [getNavGroup(pages, area, 'step', function(page) {
return {
name: moduleName,
href: modulePage.path,
type: 'group',
navItems: navItems
name: page.name,
step: page.step,
href: page.path,
type: 'tutorial'
};
})
.value();
return navGroups;
},
tutorial: function(pages, area) {
return [getNavGroup(pages, area, 'step', function(page) {
return {
name: page.name,
step: page.step,
href: page.path,
type: 'tutorial'
};
})];
},
error: function(pages, area) {
return [getNavGroup(pages, area, 'path', function(page) {
return {
name: page.name,
href: page.path,
type: page.docType === 'errorNamespace' ? 'section' : 'error'
};
})];
},
pages: function(pages, area) {
return [getNavGroup(pages, area, 'path', function(page) {
return {
name: page.name,
href: page.path,
type: 'page'
};
})];
}
};
module.exports = {
name: 'pages-data',
description: 'This plugin will create a new doc that will be rendered as an angularjs module ' +
'which will contain meta information about the pages and navigation',
runAfter: ['adding-extra-docs', 'component-groups-generate', 'compute-path'],
runBefore: ['extra-docs-added'],
process: function(docs, config) {
var outputFolder = config.rendering.outputFolder;
_(docs)
.filter(function(doc) { return doc.area === 'api'; })
.filter(function(doc) { return doc.docType === 'module'; })
.forEach(function(doc) { if ( !doc.path ) {
log.warn('Missing path property for ', doc.id);
}})
.map(function(doc) { return _.pick(doc, ['id', 'module', 'docType', 'area']); })
.tap(function(docs) {
log.debug(docs);
});
// We are only interested in docs that are in a area and not landing pages
var navPages = _.filter(docs, function(page) {
return page.area &&
page.docType != 'componentGroup';
});
// Generate an object collection of pages that is grouped by area e.g.
// - area "api"
// - group "ng"
// - section "directive"
// - ngApp
// - ngBind
// - section "global"
// - angular.element
// - angular.bootstrap
// - section "service"
// - $compile
// - group "ngRoute"
// - section "directive"
// - ngView
// - section "service"
// - $route
//
var areas = {};
_(navPages)
.groupBy('area')
.forEach(function(pages, areaId) {
var area = {
id: areaId,
name: AREA_NAMES[areaId]
})];
},
error: function(pages, area) {
return [getNavGroup(pages, area, 'path', function(page) {
return {
name: page.name,
href: page.path,
type: page.docType === 'errorNamespace' ? 'section' : 'error'
};
areas[areaId] = area;
})];
},
pages: function(pages, area) {
return [getNavGroup(
pages,
area,
function(page) {
return page.sortOrder || page.path;
},
function(page) {
return {
name: page.name,
href: page.path,
type: 'page'
};
}
)];
}
};
var navGroupMapper = navGroupMappers[area.id] || navGroupMappers['pages'];
area.navGroups = navGroupMapper(pages, area);
return {
$runAfter: ['paths-computed', 'generateKeywordsProcessor'],
$runBefore: ['rendering-docs'],
$process: function(docs) {
// We are only interested in docs that are in an area
var pages = _.filter(docs, function(doc) {
return doc.area;
});
// Extract a list of basic page information for mapping paths to partials and for client side searching
var pages = _(docs)
.map(function(doc) {
var page = _.pick(doc, [
'docType', 'id', 'name', 'area', 'outputPath', 'path', 'searchTerms'
]);
return page;
})
.indexBy('path')
.value();
// We are only interested in pages that are not landing pages
var navPages = _.filter(pages, function(page) {
return page.docType != 'componentGroup';
});
// Generate an object collection of pages that is grouped by area e.g.
// - area "api"
// - group "ng"
// - section "directive"
// - ngApp
// - ngBind
// - section "global"
// - angular.element
// - angular.bootstrap
// - section "service"
// - $compile
// - group "ngRoute"
// - section "directive"
// - ngView
// - section "service"
// - $route
//
var areas = {};
_(navPages)
.groupBy('area')
.forEach(function(pages, areaId) {
var area = {
id: areaId,
name: AREA_NAMES[areaId]
};
areas[areaId] = area;
var navGroupMapper = navGroupMappers[area.id] || navGroupMappers['pages'];
area.navGroups = navGroupMapper(pages, area);
});
docs.push({
docType: 'nav-data',
id: 'nav-data',
template: 'nav-data.template.js',
outputPath: 'js/nav-data.js',
areas: areas
});
var docData = {
docType: 'pages-data',
id: 'pages-data',
template: 'pages-data.template.js',
outputPath: 'js/pages-data.js',
areas: areas,
pages: pages
};
docs.push(docData);
}
var searchData = _(pages)
.filter(function(page) {
return page.searchTerms;
})
.map(function(page) {
return _.extend({ path: page.path }, page.searchTerms);
})
.value();
docs.push({
docType: 'json-doc',
id: 'search-data-json',
template: 'json-doc.template.json',
outputPath: 'js/search-data.json',
data: searchData
});
// Extract a list of basic page information for mapping paths to partials and for client side searching
var pageData = _(docs)
.map(function(doc) {
return _.pick(doc, ['name', 'area', 'path']);
})
.indexBy('path')
.value();
docs.push({
docType: 'pages-data',
id: 'pages-data',
template: 'pages-data.template.js',
outputPath: 'js/pages-data.js',
pages: pageData
});
}
};
};
@@ -1,49 +0,0 @@
var _ = require('lodash');
var path = require('canonical-path');
module.exports = {
name: 'protractor-generate',
description: 'Generate a protractor test file from the e2e tests in the examples',
runAfter: ['adding-extra-docs'],
runBefore: ['extra-docs-added'],
process: function(docs, examples, config) {
var protractorFolder = config.get('rendering.protractor.outputFolder', 'ptore2e');
_.forEach(examples, function(example) {
_.forEach(example.files, function(file) {
// Check if it's a Protractor test.
if (file.type !== 'protractor') {
return;
}
// Create new files for the tests.
docs.push(createProtractorDoc(example, file, 'jquery'));
docs.push(createProtractorDoc(example, file, 'jqlite'));
});
});
function createProtractorDoc(example, file, env) {
var protractorDoc = {
docType: 'e2e-test',
id: 'protractorTest' + '-' + example.id,
template: 'protractorTests.template.js',
outputPath: path.join(protractorFolder, example.id, env + '_test.js'),
innerTest: file.fileContents,
pathPrefix: '.', // Hold for if we test with full jQuery
exampleId: example.id,
description: example.doc.id
};
if (env === 'jquery') {
protractorDoc.examplePath = example.outputFolder + '/index-jquery.html';
} else {
protractorDoc.examplePath = example.outputFolder + '/index.html';
}
return protractorDoc;
}
}
};
+29 -33
View File
@@ -1,38 +1,34 @@
"use strict";
var _ = require('lodash');
module.exports = {
name: 'versions-data',
description: 'This plugin will create a new doc that will be rendered as an angularjs module ' +
'which will contain meta information about the versions of angular',
runAfter: ['adding-extra-docs', 'pages-data'],
runBefore: ['extra-docs-added'],
process: function(docs, gitData) {
/**
* @dgProcessor generateVersionDocProcessor
* @description
* This processor will create a new doc that will be rendered as a JavaScript file
* containing meta information about the current versions of AngularJS
*/
module.exports = function generateVersionDocProcessor(gitData) {
return {
$runAfter: ['generatePagesDataProcessor'],
$runBefore: ['rendering-docs'],
$process: function(docs) {
var version = gitData.version;
var versions = gitData.versions;
var versionDoc = {
docType: 'versions-data',
id: 'versions-data',
template: 'versions-data.template.js',
outputPath: 'js/versions-data.js',
currentVersion: gitData.version
};
if ( !version ) {
throw new Error('Invalid configuration. Please provide a valid `source.currentVersion` property');
versionDoc.versions = _(gitData.versions)
.filter(function(version) { return version.major > 0; })
.push(gitData.version)
.reverse()
.value();
docs.push(versionDoc);
}
if ( !versions ) {
throw new Error('Invalid configuration. Please provide a valid `source.previousVersions` property');
}
var versionDoc = {
docType: 'versions-data',
id: 'versions-data',
template: 'versions-data.template.js',
outputPath: 'js/versions-data.js',
};
versionDoc.currentVersion = version;
versionDoc.versions = _(versions)
.filter(function(version) { return version.major > 0; })
.push(version)
.reverse()
.value();
docs.push(versionDoc);
}
};
};
};
+39
View File
@@ -0,0 +1,39 @@
"use strict";
module.exports = function debugDeployment(getVersion) {
return {
name: 'debug',
examples: {
commonFiles: {
scripts: [ '../../../angular.js' ]
},
dependencyPath: '../../../'
},
scripts: [
'../angular.js',
'../angular-resource.js',
'../angular-route.js',
'../angular-cookies.js',
'../angular-sanitize.js',
'../angular-touch.js',
'../angular-animate.js',
'components/marked-' + getVersion('marked', 'node_modules', 'package.json') + '/lib/marked.js',
'js/angular-bootstrap/bootstrap.js',
'js/angular-bootstrap/dropdown-toggle.js',
'components/lunr.js-' + getVersion('lunr.js') + '/lunr.js',
'components/google-code-prettify-' + getVersion('google-code-prettify') + '/src/prettify.js',
'components/google-code-prettify-' + getVersion('google-code-prettify') + '/src/lang-css.js',
'js/versions-data.js',
'js/pages-data.js',
'js/nav-data.js',
'js/docs.js'
],
stylesheets: [
'components/bootstrap-' + getVersion('bootstrap') + '/css/bootstrap.css',
'components/open-sans-fontface-' + getVersion('open-sans-fontface') + '/open-sans.css',
'css/prettify-theme.css',
'css/docs.css',
'css/animations.css'
]
};
};
@@ -0,0 +1,39 @@
"use strict";
module.exports = function defaultDeployment(getVersion) {
return {
name: 'default',
examples: {
commonFiles: {
scripts: [ '../../../angular.min.js' ]
},
dependencyPath: '../../../'
},
scripts: [
'../angular.min.js',
'../angular-resource.min.js',
'../angular-route.min.js',
'../angular-cookies.min.js',
'../angular-sanitize.min.js',
'../angular-touch.min.js',
'../angular-animate.min.js',
'components/marked-' + getVersion('marked', 'node_modules', 'package.json') + '/lib/marked.js',
'js/angular-bootstrap/bootstrap.min.js',
'js/angular-bootstrap/dropdown-toggle.min.js',
'components/lunr.js-' + getVersion('lunr.js') + '/lunr.min.js',
'components/google-code-prettify-' + getVersion('google-code-prettify') + '/src/prettify.js',
'components/google-code-prettify-' + getVersion('google-code-prettify') + '/src/lang-css.js',
'js/versions-data.js',
'js/pages-data.js',
'js/nav-data.js',
'js/docs.min.js'
],
stylesheets: [
'components/bootstrap-' + getVersion('bootstrap') + '/css/bootstrap.min.css',
'components/open-sans-fontface-' + getVersion('open-sans-fontface') + '/open-sans.css',
'css/prettify-theme.css',
'css/docs.css',
'css/animations.css'
]
};
};
+43
View File
@@ -0,0 +1,43 @@
"use strict";
module.exports = function jqueryDeployment(getVersion) {
return {
name: 'jquery',
examples: {
commonFiles: {
scripts: [
'../../components/jquery-' + getVersion('jquery') + '/jquery.js',
'../../../angular.js'
]
},
dependencyPath: '../../../'
},
scripts: [
'components/jquery-' + getVersion('jquery') + '/jquery.js',
'../angular.min.js',
'../angular-resource.min.js',
'../angular-route.min.js',
'../angular-cookies.min.js',
'../angular-sanitize.min.js',
'../angular-touch.min.js',
'../angular-animate.min.js',
'components/marked-' + getVersion('marked', 'node_modules', 'package.json') + '/lib/marked.js',
'js/angular-bootstrap/bootstrap.min.js',
'js/angular-bootstrap/dropdown-toggle.min.js',
'components/lunr.js-' + getVersion('lunr.js') + '/lunr.min.js',
'components/google-code-prettify-' + getVersion('google-code-prettify') + '/src/prettify.js',
'components/google-code-prettify-' + getVersion('google-code-prettify') + '/src/lang-css.js',
'js/versions-data.js',
'js/pages-data.js',
'js/nav-data.js',
'js/docs.min.js'
],
stylesheets: [
'components/bootstrap-' + getVersion('bootstrap') + '/css/bootstrap.min.css',
'components/open-sans-fontface-' + getVersion('open-sans-fontface') + '/open-sans.css',
'css/prettify-theme.css',
'css/docs.css',
'css/animations.css'
]
};
};
@@ -0,0 +1,42 @@
"use strict";
var versionInfo = require('../../../../lib/versions/version-info');
var cdnUrl = "//ajax.googleapis.com/ajax/libs/angularjs/" + versionInfo.cdnVersion;
module.exports = function productionDeployment(getVersion) {
return {
name: 'production',
examples: {
commonFiles: {
scripts: [ cdnUrl + '/angular.min.js' ]
},
dependencyPath: cdnUrl + '/'
},
scripts: [
cdnUrl + '/angular.min.js',
cdnUrl + '/angular-resource.min.js',
cdnUrl + '/angular-route.min.js',
cdnUrl + '/angular-cookies.min.js',
cdnUrl + '/angular-sanitize.min.js',
cdnUrl + '/angular-touch.min.js',
cdnUrl + '/angular-animate.min.js',
'components/marked-' + getVersion('marked', 'node_modules', 'package.json') + '/lib/marked.js',
'js/angular-bootstrap/bootstrap.min.js',
'js/angular-bootstrap/dropdown-toggle.min.js',
'components/lunr.js-' + getVersion('lunr.js') + '/lunr.min.js',
'components/google-code-prettify-' + getVersion('google-code-prettify') + '/src/prettify.js',
'components/google-code-prettify-' + getVersion('google-code-prettify') + '/src/lang-css.js',
'js/versions-data.js',
'js/pages-data.js',
'js/nav-data.js',
'js/docs.min.js'
],
stylesheets: [
'components/bootstrap-' + getVersion('bootstrap') + '/css/bootstrap.min.css',
'components/open-sans-fontface-' + getVersion('open-sans-fontface') + '/open-sans.css',
'css/prettify-theme.css',
'css/docs.css',
'css/animations.css'
]
};
};
+10
View File
@@ -0,0 +1,10 @@
"use strict";
var StringMap = require('stringmap');
/**
* @dgService errorNamespaceMap
* A map of error namespaces by name.
*/
module.exports = function errorNamespaceMap() {
return new StringMap();
};
+15
View File
@@ -0,0 +1,15 @@
"use strict";
var path = require('canonical-path');
/**
* @dgService minErrInfo
* @description
* Load the error information that was generated during the AngularJS build.
*/
module.exports = function getMinerrInfo(readFilesProcessor) {
return function() {
var minerrInfoPath = path.resolve(readFilesProcessor.basePath, 'build/errors.json');
return require(minerrInfoPath);
};
};
+17
View File
@@ -0,0 +1,17 @@
"use strict";
var path = require('canonical-path');
/**
* dgService getVersion
* @description
* Find the current version of the bower component (or npm module)
*/
module.exports = function getVersion(readFilesProcessor) {
var basePath = readFilesProcessor.basePath;
return function(component, sourceFolder, packageFile) {
sourceFolder = path.resolve(basePath, sourceFolder || 'docs/bower_components');
packageFile = packageFile || 'bower.json';
return require(path.join(sourceFolder,component,packageFile)).version;
};
};
+17
View File
@@ -0,0 +1,17 @@
"use strict";
var gruntUtils = require('../../../lib/grunt/utils');
var versionInfo = require('../../../lib/versions/version-info');
/**
* @dgService gitData
* @description
* Information from the local git repository
*/
module.exports = function gitData() {
return {
version: versionInfo.currentVersion,
versions: versionInfo.previousVersions,
info: versionInfo.gitRepoInfo
};
};
+6
View File
@@ -0,0 +1,6 @@
module.exports = {
name: 'sortOrder',
transforms: function(doc, tag, value) {
return parseInt(value, 10);
}
};
+2 -11
View File
@@ -56,15 +56,6 @@
}
})();
// force page reload when new update is available
window.applicationCache && window.applicationCache.addEventListener('updateready', function(e) {
if (window.applicationCache.status == window.applicationCache.UPDATEREADY) {
window.applicationCache.swapCache();
window.location.reload();
}
}, false);
// GA asynchronous tracker
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-8594346-3']);
@@ -85,7 +76,7 @@
<div class="row">
<div class="col-md-9 header-branding">
<a class="brand navbar-brand" href="http://angularjs.org">
<img class="logo" src="img/angularjs-for-header-only.svg">
<img width="117" height="30" class="logo" ng-src="img/angularjs-for-header-only.svg">
</a>
<ul class="nav navbar-nav">
<li class="divider-vertical"></li>
@@ -219,7 +210,7 @@
</div>
<div class="grid-right">
<div id="loading" ng-show="loading">Loading...</div>
<div ng-hide="loading" ng-include="currentPage.outputPath || 'Error404.html'" onload="afterPartialLoaded()" autoscroll></div>
<div ng-hide="loading" ng-include="partialPath" autoscroll></div>
</div>
</div>
</section>
@@ -0,0 +1 @@
{$ doc.data | json $}
@@ -0,0 +1,3 @@
// Meta data used by the AngularJS docs app
angular.module('navData', [])
.value('NG_NAVIGATION', {$ doc.areas | json $});
+1 -2
View File
@@ -1,4 +1,3 @@
// Meta data used by the AngularJS docs app
angular.module('pagesData', [])
.value('NG_PAGES', {$ doc.pages | json $})
.value('NG_NAVIGATION', {$ doc.areas | json $});
.value('NG_PAGES', {$ doc.pages | json $});
@@ -1,7 +0,0 @@
describe("{$ doc.description $}", function() {
beforeEach(function() {
browser.get("{$ doc.pathPrefix $}/{$ doc.examplePath $}");
});
{$ doc.innerTest $}
});
@@ -2,15 +2,16 @@
is HTML and wrap each line in a <p> - thus breaking the HTML #}
<div>
<a ng-click="openPlunkr('{$ doc.example.outputFolder $}')" class="btn pull-right">
<a ng-click="openPlunkr('{$ doc.path $}')" class="btn pull-right">
<i class="glyphicon glyphicon-edit">&nbsp;</i>
Edit in Plunker</a>
<div class="runnable-example"
path="{$ doc.example.outputFolder $}"
path="{$ doc.example.deployments.default.path $}"
{%- for attrName, attrValue in doc.example.attributes %}
{$ attrName $}="{$ attrValue $}"{% endfor %}>
{% for fileName, file in doc.example.files %}
{% for fileName, file in doc.example.files %}
<div class="runnable-example-file" {% for attrName, attrValue in file.attributes %}
{$ attrName $}="{$ attrValue $}"{% endfor %}>
{% code -%}
@@ -19,7 +20,7 @@
</div>
{% endfor %}
<iframe class="runnable-example-frame" src="{$ doc.example.outputFolder $}/index.html" name="{$ doc.example.id $}"></iframe>
<iframe class="runnable-example-frame" src="{$ doc.example.deployments.default.outputPath $}" name="{$ doc.example.id $}"></iframe>
</div>
</div>
+2 -2
View File
@@ -12,10 +12,10 @@ $controller(MyController);
$controller(MyController, {scope: newScope});
```
To fix the example above please provide a scope to the $controller call:
To fix the example above please provide a scope (using the `$scope` property in the locals object) to the $controller call:
```
$controller(MyController, {$scope, newScope});
$controller(MyController, {$scope: newScope});
```
Please consult the {@link ng.$controller $controller} service api docs to learn more.
+15 -1
View File
@@ -54,4 +54,18 @@ angular.module('myModule')
.directive('myDirective', ['myCoolService', function (myCoolService) {
// This directive definition does not throw unknown provider.
}]);
```
```
Attempting to inject one controller into another will also throw an `Unknown provider` error:
```
angular.module('myModule', [])
.controller('MyFirstController', function() { /* ... */ });
.controller('MySecondController', ['MyFirstController', function(MyFirstController) {
// This controller throws an unknown provider error because
// MyFirstController cannot be injected.
}]);
```
Use the `$controller` service if you want to instantiate controllers yourself.
+2 -2
View File
@@ -10,7 +10,7 @@ Angular's {@link ng.$sce Strict Contextual Escaping (SCE)} mode
contexts to result in a value that is trusted as safe for use in such a context. (e.g. loading an
Angular template from a URL requires that the URL is one considered safe for loading resources.)
This helps prevent XSS and other security issues. Read more at {@link
api/ng.$sce Strict Contextual Escaping (SCE)}
This helps prevent XSS and other security issues. Read more at
{@link ng.$sce Strict Contextual Escaping (SCE)}
You may want to include the ngSanitize module to use the automatic sanitizing.
+3 -2
View File
@@ -1,5 +1,6 @@
@ngdoc overview
@name Using $location
@sortOrder 500
@description
# What does it do?
@@ -163,7 +164,7 @@ encoded.
`$location` service has two configuration modes which control the format of the URL in the browser
address bar: **Hashbang mode** (the default) and the **HTML5 mode** which is based on using the
HTML5 [History API](http://www.w3.org/TR/html5/history.html). Applications use the same API in
HTML5 [History API](http://www.w3.org/TR/html5/introduction.html#history-0). Applications use the same API in
both modes and the `$location` service will work with appropriate URL segments and browser APIs to
facilitate the browser URL change and history management.
@@ -240,7 +241,7 @@ it('should show example', inject(
## HTML5 mode
In HTML5 mode, the `$location` service getters and setters interact with the browser URL address
through the HTML5 history API, which allows for use of regular URL path and search segments,
through the HTML5 history API. This allows for use of regular URL path and search segments,
instead of their hashbang equivalents. If the HTML5 History API is not supported by a browser, the
`$location` service will fall back to using the hashbang URLs automatically. This frees you from
having to worry about whether the browser displaying your app supports the history API or not; the
+1
View File
@@ -1,5 +1,6 @@
@ngdoc overview
@name Animations
@sortOrder 310
@description
+4 -1
View File
@@ -1,5 +1,6 @@
@ngdoc overview
@name Bootstrap
@sortOrder 350
@description
# Bootstrap
@@ -90,7 +91,9 @@ Here is an example of manually initializing Angular:
<!doctype html>
<html>
<body>
Hello {{greetMe}}!
<div ng-controller="MyController">
Hello {{greetMe}}!
</div>
<script src="http://code.angularjs.org/snapshot/angular.js"></script>
<script>
+4 -1
View File
@@ -1,5 +1,6 @@
@ngdoc overview
@name HTML Compiler
@sortOrder 330
@description
<div class="alert alert-warning">
@@ -84,7 +85,9 @@ Here is a directive which makes any element draggable. Notice the `draggable` at
position: 'relative',
border: '1px solid red',
backgroundColor: 'lightgrey',
cursor: 'pointer'
cursor: 'pointer',
display: 'block',
width: '65px'
});
element.on('mousedown', function(event) {
// Prevent default dragging of selected content
+3 -2
View File
@@ -1,5 +1,6 @@
@ngdoc overview
@name Conceptual Overview
@sortOrder 200
@description
# Conceptual Overview
@@ -66,8 +67,8 @@ element that adds extra behavior to the element. The {@link ng.directive:ngModel
stores/updates the value of the input field into/from a variable.
<div class="alert alert-info">
**Custom directives to access the DOM**: In Angular, the only place where an application touches the DOM is
within directives. This is good as artifacts that access the DOM are hard to test.
**Custom directives to access the DOM**: In Angular, the only place where an application should access the DOM is
within directives. This is important because artifacts that access the DOM are hard to test.
If you need to access the DOM directly you should write a custom directive for this. The
{@link directive directives guide} explains how to do this.
</div>
+1
View File
@@ -1,5 +1,6 @@
@ngdoc overview
@name Controllers
@sortOrder 220
@description
# Understanding Controllers
+1
View File
@@ -1,5 +1,6 @@
@ngdoc overview
@name Working With CSS
@sortOrder 510
@description
+1
View File
@@ -1,5 +1,6 @@
@ngdoc overview
@name Data Binding
@sortOrder 210
@description
Data-binding in Angular apps is the automatic synchronization of data between the model and view
+7 -6
View File
@@ -1,5 +1,6 @@
@ngdoc overview
@name Dependency Injection
@sortOrder 250
@description
# Dependency Injection
@@ -109,7 +110,7 @@ asks the injector to create an instance of the controller and its dependencies.
injector.instantiate(MyController);
```
This is all done behinds the scenes. Notice that by having the `ng-controller` ask the injector to
This is all done behind the scenes. Notice that by having the `ng-controller` ask the injector to
instantiate the class, it can satisfy all of the dependencies of `MyController` without the
controller ever knowing about the injector.
@@ -135,7 +136,7 @@ These can be used interchangeably as you see fit and are equivalent.
### Implicit Dependencies
The simplest way to get hold of the dependencies, is to assume that the function parameter names
The simplest way to get hold of the dependencies is to assume that the function parameter names
are the names of the dependencies.
```js
@@ -144,7 +145,7 @@ function MyController($scope, greeter) {
}
```
Given a function the injector can infer the names of the service to inject by examining the
Given a function the injector can infer the names of the services to inject by examining the
function declaration and extracting the parameter names. In the above example `$scope`, and
`greeter` are two services which need to be injected into the function.
@@ -154,7 +155,7 @@ rename the method parameter names. This makes this way of annotating only useful
### `$inject` Property Annotation
To allow the minifiers to rename the function parameters and still be able to inject right services,
To allow the minifiers to rename the function parameters and still be able to inject the right services,
the function needs to be annotated with the `$inject` property. The `$inject` property is an array
of service names to inject.
@@ -166,7 +167,7 @@ MyController['$inject'] = ['$scope', 'greeter'];
```
In this scenario the ordering of the values in the `$inject` array must match the ordering of the
arguments to inject. Using above code snippet as an example, `$scope` will be injected into
arguments to inject. Using the above code snippet as an example, `$scope` will be injected into
`renamed$scope` and `greeter` into `renamedGreeter`. Care must be taken that the `$inject`
annotation is kept in sync with the actual arguments in the function declaration.
@@ -206,7 +207,7 @@ someModule.factory('greeter', ['$window', function(renamed$window) {
}]);
```
Here, instead of simply providing the factory function, we pass an array, whose elements consist of
Here, instead of simply providing the factory function, we pass an array whose elements consist of
a list of strings (the names of the dependencies) followed by the function itself.
Keep in mind that all of the annotation styles are equivalent and can be used anywhere in Angular
+2 -1
View File
@@ -1,5 +1,6 @@
@ngdoc overview
@name Directives
@sortOrder 300
@description
# Creating Custom Directives
@@ -159,7 +160,7 @@ restrictions, you cannot simply write `cx="{{cx}}"`.
With `ng-attr-cx` you can work around this problem.
If an attribute with a binding is prefixed with the `ngAttr` prefix (denormalized as `ng-attr-`)
then during the binding will be applied to the corresponding unprefixed attribute. This allows
then during the binding it will be applied to the corresponding unprefixed attribute. This allows
you to bind to attributes that would otherwise be eagerly processed by browsers
(e.g. an SVG element's `circle[cx]` attributes).
+1 -1
View File
@@ -1,6 +1,6 @@
@workInProgress
@ngdoc overview
@name E2E Testing
@sortOrder 420
@description
# E2E Testing
+4 -1
View File
@@ -1,5 +1,6 @@
@ngdoc overview
@name Expressions
@sortOrder 270
@description
# Angular Expressions
@@ -38,7 +39,9 @@ the method from your view. If you want to `eval()` an Angular expression yoursel
## Example
<example>
<file name="index.html">
1+2={{1+2}}
<span>
1+2={{1+2}}
</span>
</file>
<file name="protractor.js" type="protractor">
+1
View File
@@ -1,5 +1,6 @@
@ngdoc overview
@name Filters
@sortOrder 280
@description
A filter formats the value of an expression for display to the user. They can be used in view templates,
+2 -1
View File
@@ -1,5 +1,6 @@
@ngdoc overview
@name Forms
@sortOrder 290
@description
Controls (`input`, `select`, `textarea`) are ways for a user to enter data.
@@ -205,7 +206,7 @@ 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.
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.
This is because we want it to be the 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`.
+1
View File
@@ -1,5 +1,6 @@
@ngdoc overview
@name i18n and l10n
@sortOrder 520
@description
# i18n and l10n
+1
View File
@@ -1,5 +1,6 @@
@ngdoc overview
@name Internet Explorer Compatibility
@sortOrder 530
@description
# Internet Explorer Compatibility
+2 -1
View File
@@ -70,7 +70,7 @@ In Angular applications, you move the job of filling page templates with data fr
This is a short list of libraries with specific support and documentation for working with Angular. You can find a full list of all known Angular external libraries at [ngmodules.org](http://ngmodules.org/).
* **Internationalization:** [angular-translate](http://angular-translate.github.io), [angular-gettext](http://angular-gettext.rocketeer.be/)
* **Internationalization:** [angular-translate](http://angular-translate.github.io), [angular-gettext](http://angular-gettext.rocketeer.be/), [angular-localization](http://doshprompt.github.io/angular-localization/)
* **RESTful services:** [Restangular](https://github.com/mgonto/restangular)
* **SQL and NoSQL backends:** [BreezeJS](http://www.breezejs.com/), [AngularFire](http://angularfire.com/)
* **UI Widgets: **[KendoUI](http://kendo-labs.github.io/angular-kendo/#/), [UI Bootstrap](http://angular-ui.github.io/bootstrap/), [Wijmo](http://wijmo.com/tag/angularjs-2/), [ngTagsInput](https://github.com/mbenford/ngTagsInput)
@@ -104,6 +104,7 @@ This is a short list of libraries with specific support and documentation for wo
* [Recipes With AngularJS](http://www.amazon.co.uk/Recipes-Angular-js-Frederik-Dietz-ebook/dp/B00DK95V48) by Frederik Dietz
* [Developing an AngularJS Edge](http://www.amazon.com/Developing-AngularJS-Edge-Christopher-Hiller-ebook/dp/B00CJLFF8K) by Christopher Hiller
* [ng-book: The Complete Book on AngularJS](http://ng-book.com/) by Ari Lerner
* [AngularJS : Novice to Ninja](http://www.amazon.in/AngularJS-Novice-Ninja-Sandeep-Panda/dp/0992279453) by Sandeep Panda
###Videos:
* [egghead.io](http://egghead.io/)
+1
View File
@@ -1,5 +1,6 @@
@ngdoc overview
@name Introduction
@sortOrder 100
@description
+1
View File
@@ -1,5 +1,6 @@
@ngdoc overview
@name Migrating from 1.0 to 1.2
@sortOrder 550
@description
# Migrating from 1.0 to 1.2
+7 -4
View File
@@ -1,5 +1,6 @@
@ngdoc overview
@name Modules
@sortOrder 320
@description
# What is a Module?
@@ -26,10 +27,12 @@ should be bootstrapped. There are several advantages to this approach:
I'm in a hurry. How do I get a Hello World module working?
<example module='myApp'>
<example ng-app-included="true">
<file name="index.html">
<div>
{{ 'World' | greet }}
<div ng-app="myApp">
<div>
{{ 'World' | greet }}
</div>
</div>
</file>
@@ -56,7 +59,7 @@ I'm in a hurry. How do I get a Hello World module working?
Important things to notice:
* The {@link angular.Module Module} API
* The reference to `myApp` module in `<html ng-app="myApp">`.
* The reference to `myApp` module in `<div ng-app="myApp">`.
This is what bootstraps the app using your module.
* The empty array in `angular.module('myApp', [])`.
This array is the list of modules `myApp` depends on.
+27 -19
View File
@@ -1,5 +1,6 @@
@ngdoc overview
@name Providers
@sortOrder 340
@description
# Providers
@@ -97,9 +98,8 @@ created by this recipe.
Note: All services in Angular are singletons. That means that the injector uses each recipe at most
once to create the object. The injector then caches the reference for all future needs.
Since Factory is more a powerful version of the Value recipe, you can construct the same service with it.
Using our previous `clientId` Value recipe example, we can rewrite it as a Factory recipe like
this:
Since a Factory is a more powerful version of the Value recipe, the same service can be constructed with it.
Using our previous `clientId` Value recipe example, we can rewrite it as a Factory recipe like this:
```javascript
myApp.factory('clientId', function clientIdFactory() {
@@ -134,11 +134,11 @@ token.
<div class="alert alert-success">
**Best Practice:** name the factory functions as `<serviceId>Factory`
(e.g. apiTokenFactory). While this naming convention is not required, it helps when navigating the code base
(e.g., apiTokenFactory). While this naming convention is not required, it helps when navigating the codebase
or looking at stack traces in the debugger.
</div>
Just like with Value recipe, Factory recipe can create a service of any type, whether it be a
Just like with the Value recipe, the Factory recipe can create a service of any type, whether it be a
primitive, object literal, function, or even an instance of a custom type.
@@ -153,7 +153,7 @@ function UnicornLauncher(apiToken) {
this.launchedCount = 0;
this.launch = function() {
// make a request to the remote api and include the apiToken
// Make a request to the remote API and include the apiToken
...
this.launchedCount++;
}
@@ -170,7 +170,7 @@ myApp.factory('unicornLauncher', ["apiToken", function(apiToken) {
```
This is, however, exactly the use-case that Service recipe is the most suitable for.
This is, however, exactly the use-case that the Service recipe is the most suitable for.
The Service recipe produces a service just like the Value or Factory recipes, but it does so by
*invoking a constructor with the `new` operator*. The constructor can take zero or more arguments,
@@ -189,7 +189,7 @@ myApp.service('unicornLauncher', ["apiToken", UnicornLauncher]);
Much simpler!
Note: Yes, we have called one of our service recipes 'Service'. We regret this and know that we'll
be somehow punished for our mis-deed. It's like we named one of our offspring 'Child'. Boy,
be somehow punished for our misdeed. It's like we named one of our offspring 'Child'. Boy,
that would mess with the teachers.
@@ -199,8 +199,8 @@ As already mentioned in the intro, the Provider recipe is the core recipe type a
all the other recipe types are just syntactic sugar on top of it. It is the most verbose recipe
with the most abilities, but for most services it's overkill.
Provider recipe is syntactically defined as a custom type that implements a `$get` method. This
method is a factory function just like the one we use in Factory recipe. In fact, if you define
The Provider recipe is syntactically defined as a custom type that implements a `$get` method. This
method is a factory function just like the one we use in the Factory recipe. In fact, if you define
a Factory recipe, an empty Provider type with the `$get` method set to your factory function is
automatically created under the hood.
@@ -248,7 +248,7 @@ and wires (injects) all provider instances only.
During application bootstrap, before Angular goes off creating all services, it configures and
instantiates all providers. We call this the configuration phase of the application life-cycle.
During this phase services aren't accessible because they haven't been created yet.
During this phase, services aren't accessible because they haven't been created yet.
Once the configuration phase is over, interaction with providers is disallowed and the process of
creating services starts. We call this part of the application life-cycle the run phase.
@@ -259,9 +259,9 @@ creating services starts. We call this part of the application life-cycle the ru
We've just learned how Angular splits the life-cycle into configuration phase and run phase and how
you can provide configuration to your application via the config function. Since the config
function runs in the configuration phase when no services are available, it doesn't have access
even to simple value objects created via Value recipe.
even to simple value objects created via the Value recipe.
Since simple values, like url prefix, don't have dependencies or configuration, it is often handy
Since simple values, like URL prefixes, don't have dependencies or configuration, it's often handy
to make them available in both the configuration and run phases. This is what the Constant recipe
is for.
@@ -317,7 +317,7 @@ Let's take a look at how we would create a very simple component via the directi
on the `planetName` constant we've just defined and displays the planet name, in our case:
"Planet Name: Greasy Giant".
Since the directives are registered via Factory recipe, we can use the same syntax as with factories.
Since the directives are registered via the Factory recipe, we can use the same syntax as with factories.
```javascript
myApp.directive('myPlanet', ['planetName', function myPlanetDirectiveFactory(planetName) {
@@ -340,7 +340,7 @@ We can then use the component like this:
</html>
```
Using Factory recipes you can also define Angular's filters and animations, but the controllers
Using Factory recipes, you can also define Angular's filters and animations, but the controllers
are a bit special. You create a controller as a custom type that declares its dependencies as
arguments for its constructor function. This constructor is then registered with a module. Let's
take a look at the `DemoController`, created in one of the early examples:
@@ -351,7 +351,7 @@ myApp.controller('DemoController', ['clientId', function DemoController(clientId
}]);
```
The DemoController is instantiated via its constructor every time the app needs an instance of
The DemoController is instantiated via its constructor, every time the app needs an instance of
DemoController (in our simple app it's just once). So unlike services, controllers are not
singletons. The constructor is called with all the requested services, in our case the `clientId`
service.
@@ -365,12 +365,12 @@ To wrap it up, let's summarize the most important points:
- There are five recipe types that define how to create objects: Value, Factory, Service, Provider
and Constant.
- Factory and Service are the most commonly used recipes. The only difference between them is that
Service recipe works better for objects of custom type, while Factory can produce JavaScript
the Service recipe works better for objects of a custom type, while the Factory can produce JavaScript
primitives and functions.
- The Provider recipe is the core recipe type and all the other ones are just syntactic sugar on it.
- Provider is the most complex recipe type. You don't need it unless you are building a reusable
piece of code that needs global configuration.
- All special purpose objects except for Controller are defined via Factory recipes.
- All special purpose objects except for the Controller are defined via Factory recipes.
<table class="table table-bordered code-table">
<thead>
@@ -409,7 +409,15 @@ To wrap it up, let's summarize the most important points:
<td class="success">yes\*\*</td>
</tr>
<tr>
<td>can create functions/primitives</td>
<td>can create functions</td>
<td class="success">yes</td>
<td class="success">yes</td>
<td class="success">yes</td>
<td class="success">yes</td>
<td class="success">yes</td>
</tr>
<tr>
<td>can create primitives</td>
<td class="success">yes</td>
<td class="error">no</td>
<td class="success">yes</td>
+1
View File
@@ -1,5 +1,6 @@
@ngdoc overview
@name Scopes
@sortOrder 240
@description
# What are Scopes?
+1
View File
@@ -1,5 +1,6 @@
@ngdoc overview
@name Services
@sortOrder 230
@description
# Services
+1
View File
@@ -1,5 +1,6 @@
@ngdoc overview
@name Templates
@sortOrder 260
@description
In Angular, templates are written with HTML that contains Angular-specific elements and attributes.
+1
View File
@@ -1,5 +1,6 @@
@ngdoc overview
@name Unit Testing
@sortOrder 410
@description
JavaScript is a dynamically typed language which comes with great power of expression, but it also
+5 -5
View File
@@ -62,13 +62,13 @@ minified AngularJS files:
```shell
# Clone your Github repository:
git clone git@github.com:<github username>/angular.js.git
git clone "git@github.com:<github username>/angular.js.git"
# Go to the AngularJS directory:
cd angular.js
# Add the main AngularJS repository as an upstream remote to your repository:
git remote add upstream https://github.com/angular/angular.js.git
git remote add upstream "https://github.com/angular/angular.js.git"
# Install node.js dependencies:
npm install
@@ -126,13 +126,13 @@ made available a local web server based on Node.js.
```
2. To access the local server, enter the following URL into your web browser:
```
```text
http://localhost:8000/
```
By default, it serves the contents of the AngularJS project directory.
3. To access the locally served docs, visit this URL:
```
```text
http://localhost:8000/build/docs/
```
@@ -165,7 +165,7 @@ change. To execute tests in this mode run:
2. To capture more browsers, open this URL in the desired browser (URL might be different if you have multiple instance
of Karma running, read Karma's console output for the correct URL):
```shell
```text
http://localhost:9876/
```
+1 -1
View File
@@ -204,7 +204,7 @@ If you want to apply a directive to each inner piece of the repeat, put it on a
### `$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.
Scopes in Angular form a hierarchy, prototypally 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.
+2 -2
View File
@@ -44,8 +44,8 @@ really digging into it. If you're looking for a shorter introduction to AngularJ
# Get Started
The rest of this page explains how you can set up your machine to work with the code on your local
machine. If you just want to read the tutorial then you can just go straight to the first step:
The rest of this page explains how you can set up your local machine for development.
If you just want to read the tutorial then you can just go straight to the first step:
[Step 0 - Bootstrapping](tutorial/step_00).
# Working with the code
+3 -1
View File
@@ -233,7 +233,7 @@ browser is limited, which results in your karma tests running extremely slow.
Refresh your browser and verify that it says "Hello, World!".
* Update the unit test for the controller in ./test/unit/controllersSpec.js to reflect the previous change. For example by adding:
* Update the unit test for the controller in `./test/unit/controllersSpec.js` to reflect the previous change. For example by adding:
expect(scope.name).toBe('World');
@@ -250,6 +250,8 @@ browser is limited, which results in your karma tests running extremely slow.
<tr><th>row number</th></tr>
<tr ng-repeat="i in [0, 1, 2, 3, 4, 5, 6, 7]"><td>{{i+1}}</td></tr>
</table>
Extra points: try and make an 8x8 table using an additional `ng-repeat`.
* Make the unit test fail by changing `expect(scope.phones.length).toBe(3)` to instead use `toBe(4)`.
+2 -2
View File
@@ -95,7 +95,7 @@ describe('PhoneCat App', function() {
});
it('should filter the phone list as user types into the search box', function() {
it('should filter the phone list as a user types into the search box', function() {
var phoneList = element.all(by.repeater('phone in phones'));
var query = element(by.model('query'));
@@ -159,7 +159,7 @@ Let's see how we can get the current value of the `query` model to appear in the
var phoneList = element.all(by.repeater('phone in phones'));
var query = element(by.model('query'));
it('should filter the phone list as user types into the search box', function() {
it('should filter the phone list as a user types into the search box', function() {
expect(phoneList.count()).toBe(3);
query.sendKeys('nexus');
+2 -2
View File
@@ -11,7 +11,7 @@ from our server using one of Angular's built-in {@link guide/services services}
ng.$http $http}. We will use Angular's {@link guide/di dependency
injection (DI)} to provide the service to the `PhoneListCtrl` controller.
* There are now a list of 20 phones, loaded from the server.
* There is now a list of 20 phones, loaded from the server.
<div doc-tutorial-reset="5"></div>
@@ -166,7 +166,7 @@ Because we started using dependency injection and our controller has dependencie
controller in our tests is a bit more complicated. We could use the `new` operator and provide the
constructor with some kind of fake `$http` implementation. However, Angular provides a mock `$http`
service that we can use in unit tests. We configure "fake" responses to server requests by calling
methods on a service called $httpBackend:
methods on a service called `$httpBackend`:
```js
describe('PhoneCat controllers', function() {
+3 -2
View File
@@ -26,15 +26,16 @@ We are using [Bower][bower] to install client side dependencies. This step upda
```json
{
"name": "angular-seed",
"name": "angular-phonecat",
"description": "A starter project for AngularJS",
"version": "0.0.0",
"homepage": "https://github.com/angular/angular-seed",
"homepage": "https://github.com/angular/angular-phonecat",
"license": "MIT",
"private": true,
"dependencies": {
"angular": "1.2.x",
"angular-mocks": "~1.2.x",
"jquery": "1.10.2",
"bootstrap": "~3.1.1",
"angular-route": "~1.2.x"
}
+8 -1
View File
@@ -49,8 +49,15 @@ and install this dependency. We can do this by running:
npm install
```
<div class="alert alert-warning">
**Warning:** If a new version of Angular has been released since you last ran `npm install`, then you may have a
problem with the `bower install` due to a conflict between the versions of angular.js that need to
be installed. If you get this then simply delete your `app/bower_components` folder before running
`npm install`.
</div>
<div class="alert alert-info">
If you have bower installed globally then you can run `bower install` but for this project we have
**Note:** If you have bower installed globally then you can run `bower install` but for this project we have
preconfigured `npm install` to run bower for us.
</div>
+15 -8
View File
@@ -21,7 +21,7 @@ animations on top of the template code we created before.
## Dependencies
The animation functionality is provided by Angular in the `ngAnimate` module, which is distributed
separately from the core Angular framework. In addition we will use `JQuery` in this project to do
separately from the core Angular framework. In addition we will use `jQuery` in this project to do
extra JavaScript animations.
We are using [Bower][bower] to install client side dependencies. This step updates the
@@ -49,8 +49,8 @@ We are using [Bower][bower] to install client side dependencies. This step upda
* `"angular-animate": "~1.2.x"` tells bower to install a version of the
angular-animate component that is compatible with version 1.2.x.
* `"jquery": "1.10.2"` tells bower to install the 1.10.2 version of JQuery. Note that this is not an
Angular library, it is the standard JQuery library. We can use bower to install a wide range of 3rd
* `"jquery": "1.10.2"` tells bower to install the 1.10.2 version of jQuery. Note that this is not an
Angular library, it is the standard jQuery library. We can use bower to install a wide range of 3rd
party libraries.
We must ask bower to download and install this dependency. We can do this by running:
@@ -59,8 +59,15 @@ We must ask bower to download and install this dependency. We can do this by run
npm install
```
<div class="alert alert-warning">
**Warning:** If a new version of Angular has been released since you last ran `npm install`, then you may have a
problem with the `bower install` due to a conflict between the versions of angular.js that need to
be installed. If you get this then simply delete your `app/bower_components` folder before running
`npm install`.
</div>
<div class="alert alert-info">
If you have bower installed globally then you can run `bower install` but for this project we have
**Note:** If you have bower installed globally then you can run `bower install` but for this project we have
preconfigured `npm install` to run bower for us.
</div>
@@ -247,7 +254,7 @@ which are described in detail below.
Next let's add an animation for transitions between route changes in {@link api/ngRoute.directive:ngView `ngView`}.
To start, let's add a new CSS class to our HTML like we did in the example above.
This time, instead of the `ng-repeat` element, let's add it to the element containing the ng-view directive.
This time, instead of the `ng-repeat` element, let's add it to the element containing the `ng-view` directive.
In order to do this, we'll have to make some small changes to the HTML code so that we can have more control over our
animations between view changes.
@@ -332,13 +339,13 @@ a cross fade animation in between. So as the previous page is just about to be r
while the new page fades in right on top of it.
Once the leave animation is over then element is removed and once the enter animation is complete
then the `ng-enter` and `ng-enter-active` CSS classes are removed from the element rendering it to
be position itself with its default CSS code (so no more absolute positioning once the animation is
then the `ng-enter` and `ng-enter-active` CSS classes are removed from the element, causing it to rerender and
reposition itself with its default CSS code (so no more absolute positioning once the animation is
over). This works fluidly so that pages flow naturally between route changes without anything
jumping around.
The CSS classes applied (the start and end classes) are much the same as with `ng-repeat`. Each time
a new page is loaded the ng-view directive will create a copy of itself, download the template and
a new page is loaded the `ng-view` directive will create a copy of itself, download the template and
append the contents. This ensures that all views are contained within a single HTML element which
allows for easy animation control.
-185
View File
@@ -1,185 +0,0 @@
var path = require('canonical-path');
var versionInfo = require('../lib/versions/version-info');
var basePath = __dirname;
var basePackage = require('./config');
module.exports = function(config) {
var cdnUrl = "//ajax.googleapis.com/ajax/libs/angularjs/" + versionInfo.cdnVersion;
var getVersion = function(component, sourceFolder, packageFile) {
sourceFolder = sourceFolder || '../bower_components';
packageFile = packageFile || 'bower.json';
return require(path.join(sourceFolder,component,packageFile)).version;
};
config = basePackage(config);
config.set('source.projectPath', path.resolve(basePath, '..'));
config.set('source.files', [
{ pattern: 'src/**/*.js', basePath: path.resolve(basePath,'..') },
{ pattern: '**/*.ngdoc', basePath: path.resolve(basePath, 'content') }
]);
config.set('processing.stopOnError', true);
config.set('processing.errors.minerrInfoPath', path.resolve(basePath, '../build/errors.json'));
config.set('rendering.outputFolder', '../build/docs');
config.set('rendering.contentsFolder', 'partials');
config.set('logging.level', 'info');
config.merge('deployment', {
environments: [{
name: 'debug',
examples: {
commonFiles: {
scripts: [ '../../../angular.js' ]
},
dependencyPath: '../../../'
},
scripts: [
'../angular.js',
'../angular-resource.js',
'../angular-route.js',
'../angular-cookies.js',
'../angular-sanitize.js',
'../angular-touch.js',
'../angular-animate.js',
'components/marked-' + getVersion('marked', '../node_modules', 'package.json') + '/lib/marked.js',
'js/angular-bootstrap/bootstrap.js',
'js/angular-bootstrap/bootstrap-prettify.js',
'js/angular-bootstrap/dropdown-toggle.js',
'components/lunr.js-' + getVersion('lunr.js') + '/lunr.js',
'components/google-code-prettify-' + getVersion('google-code-prettify') + '/src/prettify.js',
'components/google-code-prettify-' + getVersion('google-code-prettify') + '/src/lang-css.js',
'js/versions-data.js',
'js/pages-data.js',
'js/docs.js'
],
stylesheets: [
'components/bootstrap-' + getVersion('bootstrap') + '/css/bootstrap.css',
'components/open-sans-fontface-' + getVersion('open-sans-fontface') + '/open-sans.css',
'css/prettify-theme.css',
'css/docs.css',
'css/animations.css'
]
},
{
name: 'default',
examples: {
commonFiles: {
scripts: [ '../../../angular.min.js' ]
},
dependencyPath: '../../../'
},
scripts: [
'../angular.min.js',
'../angular-resource.min.js',
'../angular-route.min.js',
'../angular-cookies.min.js',
'../angular-sanitize.min.js',
'../angular-touch.min.js',
'../angular-animate.min.js',
'components/marked-' + getVersion('marked', '../node_modules', 'package.json') + '/lib/marked.js',
'js/angular-bootstrap/bootstrap.js',
'js/angular-bootstrap/bootstrap-prettify.js',
'js/angular-bootstrap/dropdown-toggle.js',
'components/lunr.js-' + getVersion('lunr.js') + '/lunr.min.js',
'components/google-code-prettify-' + getVersion('google-code-prettify') + '/src/prettify.js',
'components/google-code-prettify-' + getVersion('google-code-prettify') + '/src/lang-css.js',
'js/versions-data.js',
'js/pages-data.js',
'js/docs.js'
],
stylesheets: [
'components/bootstrap-' + getVersion('bootstrap') + '/css/bootstrap.min.css',
'components/open-sans-fontface-' + getVersion('open-sans-fontface') + '/open-sans.css',
'css/prettify-theme.css',
'css/docs.css',
'css/animations.css'
]
},
{
name: 'jquery',
examples: {
commonFiles: {
scripts: [
'../../components/jquery-' + getVersion('jquery') + '/jquery.js',
'../../../angular.js'
]
},
dependencyPath: '../../../'
},
scripts: [
'components/jquery-' + getVersion('jquery') + '/jquery.js',
'../angular.min.js',
'../angular-resource.min.js',
'../angular-route.min.js',
'../angular-cookies.min.js',
'../angular-sanitize.min.js',
'../angular-touch.min.js',
'../angular-animate.min.js',
'components/marked-' + getVersion('marked', '../node_modules', 'package.json') + '/lib/marked.js',
'js/angular-bootstrap/bootstrap.js',
'js/angular-bootstrap/bootstrap-prettify.js',
'js/angular-bootstrap/dropdown-toggle.js',
'components/lunr.js-' + getVersion('lunr.js') + '/lunr.min.js',
'components/google-code-prettify-' + getVersion('google-code-prettify') + '/src/prettify.js',
'components/google-code-prettify-' + getVersion('google-code-prettify') + '/src/lang-css.js',
'js/versions-data.js',
'js/pages-data.js',
'js/docs.js'
],
stylesheets: [
'components/bootstrap-' + getVersion('bootstrap') + '/css/bootstrap.min.css',
'components/open-sans-fontface-' + getVersion('open-sans-fontface') + '/open-sans.css',
'css/prettify-theme.css',
'css/docs.css',
'css/animations.css'
]
},
{
name: 'production',
examples: {
commonFiles: {
scripts: [ cdnUrl + '/angular.min.js' ]
},
dependencyPath: cdnUrl + '/'
},
scripts: [
cdnUrl + '/angular.min.js',
cdnUrl + '/angular-resource.min.js',
cdnUrl + '/angular-route.min.js',
cdnUrl + '/angular-cookies.min.js',
cdnUrl + '/angular-sanitize.min.js',
cdnUrl + '/angular-touch.min.js',
cdnUrl + '/angular-animate.min.js',
'components/marked-' + getVersion('marked', '../node_modules', 'package.json') + '/lib/marked.js',
'js/angular-bootstrap/bootstrap.js',
'js/angular-bootstrap/bootstrap-prettify.js',
'js/angular-bootstrap/dropdown-toggle.js',
'components/lunr.js-' + getVersion('lunr.js') + '/lunr.min.js',
'components/google-code-prettify-' + getVersion('google-code-prettify') + '/src/prettify.js',
'components/google-code-prettify-' + getVersion('google-code-prettify') + '/src/lang-css.js',
'js/versions-data.js',
'js/pages-data.js',
'js/docs.js'
],
stylesheets: [
'components/bootstrap-' + getVersion('bootstrap') + '/css/bootstrap.min.css',
'components/open-sans-fontface-' + getVersion('open-sans-fontface') + '/open-sans.css',
'css/prettify-theme.css',
'css/docs.css',
'css/animations.css'
]
}
]
});
return config;
};
+55 -14
View File
@@ -1,18 +1,27 @@
"use strict";
var gulp = require('gulp');
var log = require('gulp-util').log;
var concat = require('gulp-concat');
var jshint = require('gulp-jshint');
var bower = require('bower');
var dgeni = require('dgeni');
var Dgeni = require('dgeni');
var merge = require('event-stream').merge;
var path = require('canonical-path');
var foreach = require('gulp-foreach');
var uglify = require('gulp-uglify');
var sourcemaps = require('gulp-sourcemaps');
var rename = require('gulp-rename');
// We indicate to gulp that tasks are async by returning the stream.
// Gulp can then wait for the stream to close before starting dependent tasks.
// See clean and bower for async tasks, and see assets and doc-gen for dependent tasks below
var outputFolder = '../build/docs';
var bowerFolder = '../bower_components';
var bowerFolder = 'bower_components';
var src = 'app/src/**/*.js';
var assets = 'app/assets/**/*';
var copyComponent = function(component, pattern, sourceFolder, packageFile) {
@@ -26,18 +35,48 @@ var copyComponent = function(component, pattern, sourceFolder, packageFile) {
};
gulp.task('bower', function() {
return bower.commands.install();
var bowerTask = bower.commands.install();
bowerTask.on('log', function (result) {
log('bower:', result.id, result.data.endpoint.name);
});
bowerTask.on('error', function(error) {
log(error);
});
return bowerTask;
});
gulp.task('build-app', function() {
gulp.src('app/src/**/*.js')
.pipe(concat('docs.js'))
.pipe(gulp.dest(outputFolder + '/js/'));
var file = 'docs.js';
var minFile = 'docs.min.js';
var folder = outputFolder + '/js/';
return gulp.src(src)
.pipe(sourcemaps.init())
.pipe(concat(file))
.pipe(gulp.dest(folder))
.pipe(rename(minFile))
.pipe(uglify())
.pipe(sourcemaps.write('.'))
.pipe(gulp.dest(folder));
});
gulp.task('assets', ['bower'], function() {
var JS_EXT = /\.js$/;
return merge(
gulp.src(['app/assets/**/*']).pipe(gulp.dest(outputFolder)),
gulp.src([assets])
.pipe(gulp.dest(outputFolder)),
gulp.src([assets])
.pipe(foreach(function(stream, file) {
if (JS_EXT.test(file.relative)) {
var minFile = file.relative.replace(JS_EXT, '.min.js');
return stream
.pipe(sourcemaps.init())
.pipe(concat(minFile))
.pipe(uglify())
.pipe(sourcemaps.write('.'))
.pipe(gulp.dest(outputFolder));
}
})),
copyComponent('bootstrap', '/dist/**/*'),
copyComponent('open-sans-fontface'),
copyComponent('lunr.js','/*.js'),
@@ -48,12 +87,11 @@ gulp.task('assets', ['bower'], function() {
});
gulp.task('doc-gen', function() {
var generateDocs = dgeni.generator('docs.config.js');
return generateDocs()
.catch(function(error) {
process.exit(1);
});
gulp.task('doc-gen', ['bower'], function() {
var dgeni = new Dgeni([require('./config')]);
return dgeni.generate().catch(function(error) {
process.exit(1);
});
});
// JSHint the example and protractor test files
@@ -68,3 +106,6 @@ gulp.task('jshint', ['doc-gen'], function() {
// The default task that will be run if no task is supplied
gulp.task('default', ['assets', 'doc-gen', 'build-app', 'jshint']);
gulp.task('watch', function() {
gulp.watch([src, assets], ['assets', 'build-app']);
});
+13
View File
@@ -0,0 +1,13 @@
'use strict';
var config = require('../protractor-shared-conf').config;
config.specs = [
'app/e2e/**/*.scenario.js'
];
config.capabilities = {
browserName: 'chrome',
};
exports.config = config;
+42 -30
View File
@@ -33,6 +33,8 @@
goog.provide('goog.i18n.currency');
goog.provide('goog.i18n.currency.CurrencyInfo');
goog.provide('goog.i18n.currency.CurrencyInfoTier2');
/**
@@ -46,7 +48,7 @@ goog.i18n.currency.PRECISION_MASK_ = 0x07;
* Whether the currency sign should be positioned after the number.
* @private
*/
goog.i18n.currency.POSITION_FLAG_ = 0x08;
goog.i18n.currency.POSITION_FLAG_ = 0x10;
/**
@@ -56,6 +58,13 @@ goog.i18n.currency.POSITION_FLAG_ = 0x08;
goog.i18n.currency.SPACE_FLAG_ = 0x20;
/**
* Whether tier2 was enabled already by calling addTier2Support().
* @private
*/
goog.i18n.currency.tier2Enabled_ = false;
/**
* This function will add tier2 currency support. Be default, only tier1
* (most popular currencies) are supported. If an application really needs
@@ -63,9 +72,13 @@ goog.i18n.currency.SPACE_FLAG_ = 0x20;
* before any other functions in this namespace.
*/
goog.i18n.currency.addTier2Support = function() {
for (var key in goog.i18n.currency.CurrencyInfoTier2) {
goog.i18n.currency.CurrencyInfo[key] =
goog.i18n.currency.CurrencyInfoTier2[key];
// Protection from executing this these again and again.
if (!goog.i18n.currency.tier2Enabled_) {
for (var key in goog.i18n.currency.CurrencyInfoTier2) {
goog.i18n.currency.CurrencyInfo[key] =
goog.i18n.currency.CurrencyInfoTier2[key];
}
goog.i18n.currency.tier2Enabled_ = true;
}
};
@@ -244,7 +257,7 @@ goog.i18n.currency.adjustPrecision = function(pattern, currencyCode) {
* the currency sign should be positioned after the number. Valid values are 0
* (before the number) or 16 (after the number). The space flag indicates
* whether a space should be inserted between the currency sign and number.
* Valid values are 0 (no space) and 24 (space).
* Valid values are 0 (no space) and 32 (space).
*
* The number in the array is calculated by adding together the mask and flag
* values. For example:
@@ -252,52 +265,67 @@ goog.i18n.currency.adjustPrecision = function(pattern, currencyCode) {
* 0: no precision (0), currency sign first (0), no space (0)
* 2: two decimals precision (2), currency sign first (0), no space (0)
* 18: two decimals precision (2), currency sign last (16), no space (0)
* 42: two decimals precision (2), currency sign last (16), space (24)
* 50: two decimals precision (2), currency sign last (16), space (32)
*
* @type {!Object.<!Array>}
*/
goog.i18n.currency.CurrencyInfo = {
'AED': [2, 'dh', '\u062f.\u0625.', 'DH'],
'ALL': [0, 'Lek', 'Lek'],
'AUD': [2, '$', 'AU$'],
'BDT': [2, '\u09F3', 'Tk'],
'BGN': [2, 'lev', 'lev'],
'BRL': [2, 'R$', 'R$'],
'CAD': [2, '$', 'C$'],
'CDF': [2, 'FrCD', 'CDF'],
'CHF': [2, 'CHF', 'CHF'],
'CLP': [0, '$', 'CL$'],
'CNY': [2, '¥', 'RMB¥'],
'COP': [0, '$', 'COL$'],
'CRC': [0, '\u20a1', 'CR\u20a1'],
'CZK': [2, 'K\u010d', 'K\u010d'],
'CZK': [50, 'K\u010d', 'K\u010d'],
'DKK': [18, 'kr', 'kr'],
'DOP': [2, '$', 'RD$'],
'EGP': [2, '£', 'LE'],
'EUR': [18, '', ''],
'ETB': [2, 'Birr', 'Birr'],
'EUR': [2, '€', '€'],
'GBP': [2, '£', 'GB£'],
'HKD': [2, '$', 'HK$'],
'HRK': [2, 'kn', 'kn'],
'HUF': [0, 'Ft', 'Ft'],
'IDR': [0, 'Rp', 'Rp'],
'ILS': [2, '\u20AA', 'IL\u20AA'],
'INR': [2, '\u20B9', 'Rs'],
'IRR': [0, 'Rial', 'IRR'],
'ISK': [0, 'kr', 'kr'],
'JMD': [2, '$', 'JA$'],
'JPY': [0, '¥', 'JP¥'],
'KRW': [0, '\u20A9', 'KR₩'],
'LKR': [2, 'Rs', 'SLRs'],
'LTL': [2, 'Lt', 'Lt'],
'LVL': [2, 'Ls', 'Ls'],
'MNT': [0, '\u20AE', 'MN₮'],
'MXN': [2, '$', 'Mex$'],
'MYR': [2, 'RM', 'RM'],
'NOK': [18, 'kr', 'NOkr'],
'NOK': [50, 'kr', 'NOkr'],
'PAB': [2, 'B/.', 'B/.'],
'PEN': [2, 'S/.', 'S/.'],
'PHP': [2, '\u20B1', 'Php'],
'PKR': [0, 'Rs', 'PKRs.'],
'RUB': [42, 'руб.', 'руб.'],
'PLN': [50, 'z\u0142', 'z\u0142'],
'RON': [2, 'RON', 'RON'],
'RSD': [0, 'din', 'RSD'],
'RUB': [50, 'руб.', 'руб.'],
'SAR': [2, 'Rial', 'Rial'],
'SEK': [2, 'kr', 'kr'],
'SGD': [2, '$', 'S$'],
'THB': [2, '\u0e3f', 'THB'],
'TRY': [2, 'TL', 'YTL'],
'TWD': [2, 'NT$', 'NT$'],
'TZS': [0, 'TSh', 'TSh'],
'UAH': [2, '\u20B4', 'UAH'],
'USD': [2, '$', 'US$'],
'UYU': [2, '$', 'UY$'],
'UYU': [2, '$', '$U'],
'VND': [0, '\u20AB', 'VN\u20AB'],
'YER': [0, 'Rial', 'Rial'],
'ZAR': [2, 'R', 'ZAR']
@@ -309,16 +337,14 @@ goog.i18n.currency.CurrencyInfo = {
* @type {!Object.<!Array>}
*/
goog.i18n.currency.CurrencyInfoTier2 = {
'AFN': [16, 'Af.', 'AFN'],
'ALL': [0, 'Lek', 'Lek'],
'AFN': [48, 'Af.', 'AFN'],
'AMD': [0, 'Dram', 'dram'],
'AOA': [2, 'Kz', 'Kz'],
'ARS': [2, '$', 'AR$'],
'AWG': [2, 'Afl.', 'Afl.'],
'AZN': [2, 'man.', 'man.'],
'BAM': [18, 'KM', 'KM'],
'BAM': [2, 'KM', 'KM'],
'BBD': [2, '$', 'Bds$'],
'BGN': [2, 'lev', 'lev'],
'BHD': [3, 'din', 'din'],
'BIF': [0, 'FBu', 'FBu'],
'BMD': [2, '$', 'BD$'],
@@ -329,14 +355,12 @@ goog.i18n.currency.CurrencyInfoTier2 = {
'BWP': [2, 'P', 'pula'],
'BYR': [0, 'BYR', 'BYR'],
'BZD': [2, '$', 'BZ$'],
'CDF': [2, 'FrCD', 'CDF'],
'CUC': [1, '$', 'CUC$'],
'CUP': [2, '$', 'CU$'],
'CVE': [2, 'CVE', 'Esc'],
'DJF': [0, 'Fdj', 'Fdj'],
'DZD': [2, 'din', 'din'],
'ERN': [2, 'Nfk', 'Nfk'],
'ETB': [2, 'Birr', 'Birr'],
'FJD': [2, '$', 'FJ$'],
'FKP': [2, '£', 'FK£'],
'GEL': [2, 'GEL', 'GEL'],
@@ -347,12 +371,8 @@ goog.i18n.currency.CurrencyInfoTier2 = {
'GTQ': [2, 'Q', 'GTQ'],
'GYD': [0, '$', 'GY$'],
'HNL': [2, 'L', 'HNL'],
'HRK': [2, 'kn', 'kn'],
'HTG': [2, 'HTG', 'HTG'],
'HUF': [0, 'Ft', 'Ft'],
'IDR': [0, 'Rp', 'Rp'],
'IQD': [0, 'din', 'IQD'],
'IRR': [0, 'Rial', 'IRR'],
'JOD': [3, 'din', 'JOD'],
'KES': [2, 'Ksh', 'Ksh'],
'KGS': [2, 'KGS', 'KGS'],
@@ -366,8 +386,6 @@ goog.i18n.currency.CurrencyInfoTier2 = {
'LBP': [0, 'L£', 'LBP'],
'LRD': [2, '$', 'L$'],
'LSL': [2, 'LSL', 'LSL'],
'LTL': [2, 'Lt', 'Lt'],
'LVL': [2, 'Ls', 'Ls'],
'LYD': [3, 'din', 'LD'],
'MAD': [2, 'dh', 'MAD'],
'MDL': [2, 'MDL', 'MDL'],
@@ -386,11 +404,8 @@ goog.i18n.currency.CurrencyInfoTier2 = {
'NZD': [2, '$', 'NZ$'],
'OMR': [3, 'Rial', 'OMR'],
'PGK': [2, 'PGK', 'PGK'],
'PLN': [2, 'z\u0142', 'z\u0142'],
'PYG': [0, 'Gs', 'PYG'],
'QAR': [2, 'Rial', 'QR'],
'RON': [2, 'RON', 'RON'],
'RSD': [0, 'din', 'RSD'],
'RWF': [0, 'RF', 'RF'],
'SBD': [2, '$', 'SI$'],
'SCR': [2, 'SCR', 'SCR'],
@@ -400,16 +415,13 @@ goog.i18n.currency.CurrencyInfoTier2 = {
'SOS': [0, 'SOS', 'SOS'],
'SRD': [2, '$', 'SR$'],
'STD': [0, 'Db', 'Db'],
'SYP': [16, '£', 'SY£'],
'SYP': [0, '£', 'SY£'],
'SZL': [2, 'SZL', 'SZL'],
'TJS': [2, 'Som', 'TJS'],
'TND': [3, 'din', 'DT'],
'TOP': [2, 'T$', 'T$'],
'TTD': [2, '$', 'TT$'],
'TZS': [0, 'TSh', 'TSh'],
'UAH': [2, '\u20B4', 'UAH'],
'UGX': [0, 'UGX', 'UGX'],
'UYU': [1, '$', '$U'],
'UZS': [0, 'so\u02bcm', 'UZS'],
'VEF': [2, 'Bs', 'Bs'],
'VUV': [0, 'VUV', 'VUV'],
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+6 -1
View File
@@ -22,7 +22,12 @@ function readSymbols() {
.then(function(content) {
var currencySymbols = closureI18nExtractor.extractCurrencySymbols(content);
return qfs.read(__dirname + '/../closure/numberSymbols.js', 'b').then(function(content) {
closureI18nExtractor.extractNumberSymbols(content, localeInfo, currencySymbols);
var numberSymbols = content;
return qfs.read(__dirname + '/../closure/numberSymbolsExt.js', 'b')
.then(function(content) {
numberSymbols += content;
return closureI18nExtractor.extractNumberSymbols(numberSymbols, localeInfo, currencySymbols);
});
});
});
+1 -1
View File
@@ -18,7 +18,7 @@ function parsePattern(pattern) {
var p = {
minInt: 1,
minFrac: 0,
macFrac: 0,
maxFrac: 0,
posPre: '',
posSuf: '',
negPre: '',
+1
View File
@@ -14,4 +14,5 @@ curl "$I18N_BASE/currency.js" > closure/currencySymbols.js
curl "$I18N_BASE/datetimesymbols.js" > closure/datetimeSymbols.js
curl "$I18N_BASE/datetimesymbolsext.js" > closure/datetimeSymbolsExt.js
curl "$I18N_BASE/numberformatsymbols.js" > closure/numberSymbols.js
curl "$I18N_BASE/numberformatsymbolsext.js" > closure/numberSymbolsExt.js
curl "$I18N_BASE/pluralrules.js" > closure/pluralRules.js
+2
View File
@@ -83,6 +83,7 @@ var getTaggedVersion = function() {
if ( version && semver.satisfies(version, currentPackage.branchVersion)) {
version.codeName = getCodeName(tag);
version.full = version.version;
version.branch = 'v' + currentPackage.branchVersion.replace('*', 'x');
return version;
}
}
@@ -197,6 +198,7 @@ var getSnapshotVersion = function() {
version.isSnapshot = true;
version.format();
version.full = version.version + '+' + version.build;
version.branch = 'master';
return version;
};

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