Compare commits

...

378 Commits

Author SHA1 Message Date
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
rodyhaddad 93b0c2d892 feat($parse): allow for assignments in ternary operator branches
Closes #8512
Closes #8484
CLoses #5434

Conflicts:
	test/ng/parseSpec.js
2014-08-11 17:04:40 +01:00
Peter Bacon Darwin d262378b7c fix(jqLite): allow triggerHandler() to accept custom event
In some scenarios you want to be able to specify properties on the event
that is passed to the event handler. JQuery does this by overloading the
first parameter (`eventName`). If it is an object with a `type` property
then we assume that it must be a custom event.

In this case the custom event must provide the `type` property which is
the name of the event to be triggered.  `triggerHandler` will continue to
provide dummy default functions for `preventDefault()`, `isDefaultPrevented()`
and `stopPropagation()` but you may override these with your own versions
in your custom object if you wish.

In addition the commit provides some performance and memory usage
improvements by only creating objects and doing work that is necessary.

This commit also renames the parameters inline with jQuery.

Closes #8469
Closes #8505
2014-08-11 12:17:55 +01:00
Peter Bacon Darwin 7729c84ec7 test(docsAppE2E): check that param defaults are shown in docs
Closes https://github.com/angular/dgeni-packages/pull/58
2014-08-10 20:19:23 +01:00
Peter Bacon Darwin dffeef29d7 test(docsAppE2E): tighten CSS selector to only find one element 2014-08-10 20:19:23 +01:00
Peter Bacon Darwin 2e22588ccf chore(package.json): update to dgeni-packages 0.9.7 2014-08-10 17:43:23 +01:00
Caitlin Potter 0b0acb0342 fix($compile): make '='-bindings NaN-aware
Update parent and child scopes correctly when a '='-binding changes from a NaN value.

TBR by angular-core

Closes #8553
Closes #8554

Conflicts:
	test/ng/compileSpec.js
2014-08-10 03:32:13 -04:00
Eddie Hedges 18fc43e828 docs(guide): correct links to unit testing guides
Closes #8548
2014-08-09 14:01:54 -04:00
Caitlin Potter ed47d811e2 chore(travis): specify chrome m34 in protractor configuration
Closes #8541
2014-08-08 17:21:00 -04:00
Derrick Mar a84f9f6178 docs(tutorial/step-10): add mock image data to spec
Closes #8468
Closes #8535
2014-08-08 20:37:42 +01:00
Caitlin Potter 4fbbe1152e docs(http): don't use locale-specific uri for MDN link 2014-08-08 15:32:38 -04:00
Joey Yang df3d941c57 docs($http): fix broken markdown link in withCredentials description
Markdown typo in $http config documentation

Closes #7859
2014-08-08 15:29:50 -04:00
Juampy 2bd3214a55 docs(guide/migration): ngSanitize is out ng core at AngularJS 1.2.21
When using ngBindHTML directive, either ngSanitize or $sce must be used
or this will end in a non-trusted value error.

Closes #8519
2014-08-07 21:04:17 -04:00
James Kleeh fc2abef327 docs(guide/directive): explain how to require multiple controllers
Closes #8524
2014-08-07 15:14:39 +01:00
Andrew Silluron 76a0eb89fb docs($compile): fix typo 'default' spelling
Change spelling of 'defualt' to 'default'

Closes #8476
2014-08-04 18:48:29 -04:00
Caitlin Potter ee57b4c26b docs(CHANGELOG.md): add missing breaking change from 1.3.0-beta.14 2014-08-04 17:29:33 -04:00
Peter Bacon Darwin 29eaabc000 test(select): relax test for IE8 bug
There is a bug in IE8 (http://support.microsoft.com/kb/829907 and
http://yuilibrary.com/forum-archive/forum/viewtopic.php@p=14826.html):
when you clone an `<option>` element the selected attribute on the options
can become invalid.

This is not relevant to the proper behaviour of the `select` directive
since it uses `prop` not `attr` to store the selected status of each
option.

This test is only interested in there being at least on option with
the `selected` attribute, for conformance to accessibility guidelines.
So we can safely relax the test to check this rather than concerning
ourselves with which option actually has this attribute.

Fixes 79538afd7b
Closes #8465
2014-08-03 22:15:59 +01:00
Joseph Spencer 2a6081057f docs($resource): clarify the meaning of @ in paramDefaults
Closes #8457
2014-08-03 17:15:03 +01:00
Peter Bacon Darwin 79538afd7b fix(select): ensure that at least one option has the selected attribute set
Using `prop` to set selected is correct programmatically but accessibility
guidelines suggest that at least on item should have the `selected` attribute
set.

Closes #8366
Closes #8429

Conflicts:
	test/ng/directive/selectSpec.js
2014-08-03 16:37:32 +01:00
rodyhaddad bcfa64e77c chore(travis): rename fetch_bundle script and make it not abort a travis build if it fails
This is useful when the npm-bundle-deps server isn't running,
when the tar never gets served (there's a default timeout on the request),
or when the served file isn't a valid tar.
2014-08-01 19:14:48 -07:00
Peter Bacon Darwin b7a2deed30 docs(ngSubmit): add link to form docs to discourage double submission
Closes #6017
2014-07-31 21:27:04 +01:00
Ken Sheedlo 98ff901bda docs(error/$injector/unpr): inadvertently redefining a module can cause error
Closes #8421
2014-07-31 20:48:32 +01:00
k-funk 428b81cba9 docs($http): add link to $http.path()
Closes #8424
2014-07-31 13:43:48 +01:00
Danielle 5dae9c230e docs(ngMockE2E): remove repeated word
Closes #8411
2014-07-31 13:41:05 +01:00
winsontam c3fad1157e fix($location) don't rewrite location when clicking on "javascript:" or "mailto:" link
Previously, absent a specified target attribute, when clicking on an anchor tag with an href beginning
with either "javascript:" or "mailto:", the framework would rewrite the URL, when it ought not to.

With this change, the browser is prevented from rewriting if the URL begins with a case-insensitive match
for "javascript:" or "mailto:", optionally preceeded by whitespace.

Closes #8407
Closes #8425
Closes #8426
2014-07-31 07:31:33 -04:00
Peter Bacon Darwin 9242c580a1 refact(select): don't recreate selectedSet on every digest loop
In the case of a "multiple" select, the model value is an array, changes
to which don't get picked up by NgModelController as it only looks for
object identity change.

We were rebuilding the `selectedSet` (a hash map of selected items) from
the modelValue on every turn of the digest. This is not needed as we can
simply use `$watchCollection` directly on the `$modelValue` instead.
2014-07-31 07:14:14 +01:00
Peter Bacon Darwin c2860944c6 fix(select): do not update selected property of an option element on digest with no change event
The `render()` method was being invoked on every turn of the digest cycle,
which was inadvertently updating the DOM even when a `change` event had
not been triggered.

This change only calls the `render()` method when `ctrl.$render()` is called,
as part of the NgModelController` lifecycle and when the `modelValue` has
significantly changed.

Closes #8221
Closes #7715
2014-07-30 23:14:40 +01:00
Peter Bacon Darwin e9a00fbdc3 test(select): add extra expectations and comments for clarity 2014-07-30 23:14:40 +01:00
Erin Altenhof-Long d018ac2a9a test(select): add test of updating the model because of ng-change
A regression #7855 was introduced by
https://github.com/angular/angular.js/commit/dc149de9364c66b988f169f67cad39577ba43434
This test ensures that reverting that commit fixes this regression.
In the regression, changes to a bound model in ng-change were not propagated back to the view.

Test for #7855
2014-07-30 23:14:40 +01:00
Erin Altenhof-Long b770c353bc test(select): add test cases for selects with blank disabled options
An earlier commit dc149de936 caused an error where the first option of
a select would be skipped over if it had a blank disabled value. These tests demonstrate that with
that commit in place, blank disabled options are skipped in a select. When the commit is reverted,
the correct behavior is seen that the blank disabled option is still selected in both selects
marked with required and those that have optional choices.

Relates to #7715
2014-07-30 23:14:40 +01:00
Erin Altenhof-Long 812277c257 test(select): add test against updating selected property on digest with no change event
Commit dc149de936 was reverted to fix regressions #7715 and #7855.
This commit introduced this test case and a corresponding fix for preventing the update of the
selected property of an option element on a digest with no change event. Although the previous fix
introduced regressions, the test covers a valid issue and should be included.
2014-07-30 23:14:39 +01:00
Erin Altenhof-Long 61871da9de revert(select): avoid checking option element selected properties in render
This reverts commit dc149de936. That commit fixes a bug caused by
Firefox updating `select.value` on hover. However, it
causes other bugs with select including the issue described in #7715. This issue details how
selects with a blank disabled option skip to the second option. We filed a bug
with Firefox for the problematic behavior the reverted commit addresses
https://bugzilla.mozilla.org/show_bug.cgi?id=1039047, and alternate Angular fixes are being
investigated.

Closes #7715 #7855
2014-07-30 23:14:39 +01:00
Caitlin Potter 9ee075518f fix(ngSanitize): ensure html is a string in htmlParser()
Previously, $sanitize(nonString) would throw. Now, the type is converted to a string before any work
is done.

Closes #8417
Closes #8416
2014-07-30 13:34:14 -04:00
Misha Moroshko afe93eaff8 docs(dateFilter): fix milliseconds example
Closes #8389
2014-07-29 17:49:28 +01:00
Andrew Pham d8f94d1a3f docs(tutorial/step-2): warn reader not to minimise browser that Karma's running on
Closes #8386
2014-07-29 17:40:46 +01:00
Nathan Wiebe f53b53df22 docs(tutorial): clarify sentence in step 02
Separate two sentences with a period, and clarify the wording by making it less technical: "to the DOM"
vs "to the <body> tag".

Closes #8394
2014-07-29 11:42:15 -04:00
Shahar Talmi eab5731afc feat(http): allow caching for JSONP requests
Closes #1947
Closes #8356
2014-07-29 09:40:36 +01:00
Sergio Sanguanini 986c446aaf style(AngularPublic): add whitespace to jshint block
Closes #8360
2014-07-27 14:10:40 +01:00
rodyhaddad 60366c8d0b fix($parse): correctly assign expressions who's path is undefined and that use brackets notation
Closes #8039
2014-07-26 23:28:20 -07:00
Julie Ralph 494c8aa0b3 chore(ci): update sauce connect from 3 to 4.3 for the 1.2.x branch 2014-07-25 14:50:24 -07:00
Ivan Alvarez cd9459e129 docs(tutorial): update step_03.ngdoc
1) The original document is not clear to a new developer in where to place the code.
2) The query.clear() statement to clear the query before the second test is missing in the original document.
3) Refactored to use the query and phoneList variables in both tests, so its easier to read and understand.

Closes #7815
2014-07-25 14:26:49 -07:00
Mitch Robb 2862883bd8 docs(tutorial): update step7 ngdoc to fix grammar
This line was missing an 'as'

Previous:
We also have to add the modules dependencies of our app. By listing these two modules as dependencies of `phonecatApp`, ...

New:
We also have to add the modules *as* dependencies of our app.

Closes #8345
2014-07-25 14:12:59 -07:00
Jeff Cross bbb673a48a docs(changelog): release notes for 1.3.0-beta.17 and 1.2.21 2014-07-25 10:17:16 -07:00
Jeff Cross cd9afd9961 revert: fix(ngHref): remove attribute when empty value instead of ignoring
This reverts commit 948c86c602.

This commit caused tests to fail in IE8 due to a TypeError '0.childNodes is
null or not an object. The issue should be investigated and fixed. Issue #8340
has been opened to investigate.

See this job for failures: https://travis-ci.org/angular/angular.js/jobs/30792508
2014-07-25 09:01:43 -07:00
Shahar Talmi e25ed0d48d fix(angular.copy): clone regexp flags correctly
Closes #5781
Closes #8337
2014-07-25 16:40:14 +01:00
Peter Bacon Darwin cd6d21e78a docs(tutorial/step-2): note that ng-app now needs a module name
Closes #7655
2014-07-25 16:38:55 +01:00
TheMrSteve 9cf5b35e5c docs(tutorial/step-3): note that the server needs to be running before running Protractor
Closes #7142
2014-07-25 16:38:55 +01:00
Jeff Cross 5d11e02008 fix(docs): change plnkr form to open in same window
Form previously posted to target="_blank", but pop-up blockers were causing this to not work.
If a user chose to bypass pop-up blocker one time and click the link, they would arrive at
a new default plnkr, not a plnkr with the desired template.

This fix removes the _blank target, causing the plnkr to open in the current window/tab.
2014-07-24 14:37:49 -07:00
Chris Chua 209e600070 fix(jqLite): triggerHandler support unbind self
Fixes .one if the event is invoked from triggerHandler.

Closes #5984

Conflicts:
	test/jqLiteSpec.js
2014-07-24 13:50:28 -07:00
Igor Minar ceaca57786 revert: perf($parse): don't use reflective calls in generated functions
This reverts commit cbdf0c2afb.

The commit causes tests failures on IE8. I'm not quite sure why and I can't
investigate now.

Failed build: https://travis-ci.org/angular/angular.js/jobs/30756773
2014-07-24 09:07:57 -07:00
Igor Minar cbdf0c2afb perf($parse): don't use reflective calls in generated functions
Chrome and FF are smart enough to notice that the key is is a string literal, so this change doesn't
make a difference there. Safari gets a boost. I haven't tested IE, but it can't cause harm there. :)

http://jsperf.com/fn-dereferencing
2014-07-24 07:43:00 -07:00
Patrick Hallisey 1111076552 docs($resource): note methods list is non-exhaustive
The existing documentation for custom action methods implies that only a small
list of upper case methods can be used for custom $resource actions.
2014-07-23 15:02:44 -07:00
Shahar Talmi 948c86c602 fix(ngHref): remove attribute when empty value instead of ignoring
Closes #2755
2014-07-23 13:42:27 -07:00
Diego Plentz cd63ff497d docs(guide/concepts): update example
The "A first example: Data binding" section it implies that the `required` directive is
doing something, but it isn't.

I just removed the parts the refer to the required directive to avoid confusion.
2014-07-23 11:34:32 -07:00
Karl Yang 9d6240561b docs(tutorial): remove index.html from app url 2014-07-23 10:32:58 -07:00
Chad Smith 05b5245790 docs(guide): remove redundancy in providers guide
Highlighted the Best Practices section, and took the styling from the Services doc.
Also removed some superfluous wording that was in the "Provider Recipe"
2014-07-23 09:21:36 -07:00
Shahar Talmi e6ebfc87c9 refactor(Angular): add isPromiseLike helper function
This can be used internally to remove the repeating pattern of `obj && obj.then`. For now, I don't see a good reason to expose this in angular's public interface.

Conflicts:
	src/Angular.js
2014-07-22 16:35:02 -07:00
Julie Ralph 7f2bcc3933 chore(e2e): protractor version bump to 1.0 2014-07-22 15:29:00 -07:00
Igor Minar 492b0cdf28 perf(forEach): use native for loop instead of forEach for Arrays
Conflicts:
	src/Angular.js
2014-07-22 11:40:59 -07:00
hanstest 51863f80d7 docs(guide/directive): fix formatting 2014-07-22 10:34:08 -07:00
Peter Bacon Darwin 9d4000d689 docs(guide/$location): fix up example protractor tests
Closes #8255
2014-07-22 17:55:48 +01:00
vdyckn bc036c68ac docs(guide/$location) global cntl deprecated
Closes #8255
2014-07-22 17:55:48 +01:00
Shane Keller 580135a9cb docs(guide/scope): add missing period 2014-07-21 17:21:34 -07:00
Jason Hamm da0c5efa72 docs(guide/bootstrap): fix example 2014-07-21 16:53:43 -07:00
Vikram Soni c280d5ab02 Updated e2e spec to remove warning
on
element(by.css(.phones li a)).click();

selenium will throw a warning message that more then one element found.

element.all(by.css('.phones li a')).first().click(); fixes the issue
2014-07-21 16:10:42 -07:00
Jesse Palmer 28c8199cd6 docs(misc/faq): minor formatting fixes 2014-07-21 15:30:13 -07:00
garetht 0252a9889b docs($http) Clarify how to specify JSONP callback.
Make clear that it is the name of the callback that should be `JSON_CALLBACK`, instead of the current vague description.

Closes #8269
2014-07-21 14:55:15 -07:00
Trey Hunner 1c15cdc2d0 style: fix whitespace issues
Closes #8277

Conflicts:
	docs/content/guide/migration.ngdoc
2014-07-21 14:52:06 -07:00
Nick Van Dyck 0bd329d4fd docs(guide/concepts): use protocol relative URL
When accessing the docs from https, the "Accessing the backend example fails
because it contains a hard coded protocol. By making the URL protocol relative,
the example should work over http and https.
2014-07-21 14:45:16 -07:00
Trey Hunner 8db84a16db chore(.editorconfig): add .editorconfig file
Closes #8278
2014-07-21 14:43:59 -07:00
Igor Minar cffcfc73a0 style($http): fix indentation 2014-07-21 14:43:48 -07:00
Peter Bacon Darwin 25eb9b794f docs(ngMock) add @packageName tag to fix invalid module overview pages
Closes #7284
Closes #8038
2014-07-21 21:03:40 +01:00
Peter Bacon Darwin 6941779543 chore(package): update dgeni-package to v0.9.6
This version supports `@packageName` tag that will allow us to fix the docs
for ngMock and ngMockE2E
2014-07-21 21:03:40 +01:00
xi 65f40d2123 docs(ngBind): fix wording
You can not change the use of `{{}}`/`ngBind` based on the time when it is used.
So this should be "if".

Closes #7786
2014-07-18 15:54:57 -07:00
rodyhaddad e159f9626c chore(travis): get npm dependencies from npm-bundle-deps
npm-bundle-deps has been rewritten to be more robust
2014-07-18 15:37:20 -07:00
Peter Bacon Darwin 685a9d040d docs(indexPage): move latest versions to the top
Closes #7513
2014-07-18 22:04:08 +01:00
Igor Minar 8eede099cd perf(ngBindHtml): move addClass to the compile phase
Closes #8261

Conflicts:
	src/ng/directive/ngBind.js
2014-07-18 13:52:06 -07:00
Brian Ford a17d42d706 docs(changelog): release notes for 1.3.0-beta.16 pizza-transubstantiation 2014-07-18 12:21:28 -07:00
Carlo s A. Guillen 60af504c18 fix($location): handle plus character in query strings
Closes #3042
2014-07-18 08:37:59 -07:00
Peter Bacon Darwin 243d9ac72c docs(guide/module): add protractor tests 2014-07-18 11:12:49 +01:00
Peter Bacon Darwin cc8eb91665 style(guide/module): use dot first style when chaining 2014-07-18 11:12:49 +01:00
Nick Van Dyck 8697c3bf4c docs(guide/module) fixed global controller in example
Global controllers have been disallowed in Angular 1.3

Closes #8248
2014-07-18 11:12:49 +01:00
Jason Bedard 3c46c94342 perf(jqLite): expose the low-level jqLite.data/removeData calls
- updated the internal jqLite helpers to use the low-level jqLite.data/removeData to avoid unnecessary jq wrappers and loops
- updated $compile to use the low-level jqLite.data/removeData to avoid unnecessary jq wrappers at link time
2014-07-17 17:18:35 -07:00
Jason Bedard 71eb1901f6 perf($compile): only create jqLite object when necessary 2014-07-17 17:15:21 -07:00
Brian Ford 4e57e28589 docs(triaging): clarify severity and frequency labels 2014-07-17 12:32:23 -07:00
Peter Bacon Darwin 13289c0903 chore(package): update to latest dgeni-packages
This fixes an issue with HTML encoding HTML entities in code blocks
2014-07-17 13:05:00 +01:00
Julie Ralph afdb4f1b76 chore(ci): update protractor to 1.0.0-rc5 and increase global timeout for loading pages
This should help with occasional safari page load timeouts. In a test of
4500 page loads, the current 10 second limit caused 3 errors while a 30 second limit
caused none.

Closes #8231
2014-07-16 23:10:05 -07:00
Josh Schreuder e7999e7447 docs($interval): fix missing square brackets in example
Closes #8228
2014-07-16 20:42:43 -04:00
Caitlin Potter d175bb0131 fix(ngSanitize): follow HTML parser rules for start tags / allow < in text content
ngSanitize will now permit opening braces in text content, provided they are not followed by either
an unescaped backslash, or by an ASCII letter (u+0041 - u+005A, u+0061 - u+007A), in compliance with
rules of the parsing spec, without taking insertion mode into account.

BREAKING CHANGE

Previously, $sanitize would "fix" invalid markup in which a space preceded alphanumeric characters
in a start-tag. Following this change, any opening angle bracket which is not followed by either a
forward slash, or by an ASCII letter (a-z | A-Z) will not be considered a start tag delimiter, per
the HTML parsing spec (http://www.whatwg.org/specs/web-apps/current-work/multipage/parsing.html).

Closes #8212
Closes #8193
2014-07-16 19:56:39 -04:00
Michał Gołębiowski fe1188daf3 refactor(jshint): reduce duplication & test all JS files
Conflicts:
	src/Angular.js
	src/AngularPublic.js
	src/jqLite.js
	src/ng/directive/input.js
2014-07-16 19:56:14 -04:00
Michał Gołębiowski e1a3a6251f chore(jshint): update grunt-contrib-jshint 2014-07-16 19:19:21 -04:00
Caitlin Potter 25d3d3730d revert: fix(ngSanitize): follow HTML parser rules for start tags / allow < in text content
This reverts commit 36d2658b94.

This commit broke the ci-checks task when ported into v1.2.x --- I will sort this out shortly.
2014-07-16 18:13:17 -04:00
Caitlin Potter af5aacce05 test(jqLite): make iframe contents() test less flaky 2014-07-16 17:47:57 -04:00
Paul Harris 3abd0fb93c test(filter): fix typo in descriptions
Two descriptions contain typo's to the word predicate.

Closes #8004
2014-07-16 17:05:01 -04:00
Caitlin Potter 36d2658b94 fix(ngSanitize): follow HTML parser rules for start tags / allow < in text content
ngSanitize will now permit opening braces in text content, provided they are not followed by either
an unescaped backslash, or by an ASCII letter (u+0041 - u+005A, u+0061 - u+007A), in compliance with
rules of the parsing spec, without taking insertion mode into account.

BREAKING CHANGE

Previously, $sanitize would "fix" invalid markup in which a space preceded alphanumeric characters
in a start-tag. Following this change, any opening angle bracket which is not followed by either a
forward slash, or by an ASCII letter (a-z | A-Z) will not be considered a start tag delimiter, per
the HTML parsing spec (http://www.whatwg.org/specs/web-apps/current-work/multipage/parsing.html).

Closes #8212
Closes #8193
2014-07-16 16:59:04 -04:00
Izhaki 6ce5a04d42 docs($compile): fix template and replace properties' docs
Closes #8062
2014-07-16 13:43:05 -07:00
Caitlin Potter 929064d9e4 test($http): ignore date-toJSON test if running in IE8
IE8 does not implement Date.prototype.toISOString(), which is necessary for this feature. The
feature still works if this method is polyfilled, but these tests are not run with polyfills.
2014-07-16 12:06:48 -04:00
Caitlin Potter d0b873a4b7 revert: chore(travis): get npm dependencies from npm-bundle-deps
This commit was causing some issues with CI testing, so it's being temporarily removed until that's
resolved.

This reverts commit 8881606cd9.
2014-07-16 11:34:43 -04:00
Almar 2e10659472 docs(misc core): fixed broken angular.copy example
The module was not being registered, and this broke the example for who knows how long!

Closes #8218
2014-07-16 11:30:38 -04:00
Max 2a8493f40c docs(guide/forms): fix controller name in example
The "Binding to form and control state" sample had the wrong controller name

Closes #8206
2014-07-16 11:16:38 +01:00
Dan Barua 2f960f1530 fix($http): fix double-quoted date issue when encoding params
This commit special cases date handling rather than calling toJSON as we always need
a string representation of the object.

$http was wrapping dates in double quotes leading to query strings like this:
  ?date=%222014-07-07T23:00:00.000Z%22

Closes #8150
Closes #6128
Closes #8154
2014-07-15 17:18:38 -07:00
rodyhaddad 3f5f20fe77 chore(travis): get npm dependencies from npm-bundle-deps 2014-07-15 17:09:51 -07:00
Christian 01387c0a8f docs(orderBy filter): fix controller name in example
Closes #8133
Closes #8206
2014-07-15 17:57:03 +01:00
rodyhaddad c0afbfaca5 fix(select): force visual update in IE
IE9, IE10 and IE11 would always show the first <option> as
selected when the user moves from a null <option>
to a non-null one in a non-null <select>.
Even though the model was being updated correctly,
visually, the first <option> always appeared selected.

Setting the `selected` property twice in a row
seems to fix it in all the three versions mentioned above.

Closes #7692
Closes #8158
2014-07-15 09:47:22 -07:00
Shahar Talmi bf13d2683d fix($rootScope): $watchCollection should handle NaN in objects
This fixes a potential infinite digest in $watchCollection when one of the values is NaN. This was previously fixed for arrays, but needs to be handled for objects as well.

Closes #7930
2014-07-15 09:45:13 -07:00
Peter Bacon Darwin fe01a85a8e style(orderBySpec): fix indentation 2014-07-15 14:29:25 +01:00
Peter Bacon Darwin 6b9a332959 style($route): convert tab indent to spaces 2014-07-15 14:01:09 +01:00
Sekib Omazic f1b28847c8 fix(orderBy): correctly order by date values
Closes #6675
Closes #6746
2014-07-15 13:41:27 +01:00
Jason Miller 1b779028fd fix(ngRoute): remove unnecessary call to decodeURIComponent
Since `$location.$$path` is already decoded, doing an extra `decodeURIComponent` is both unnecessary
and can cause problems. Specifically, if the path originally includes an encoded `%` (aka `%25`),
then ngRoute will throw "URIError: URI malformed".

Closes #6326
Closes #6327
2014-07-15 13:24:40 +01:00
Wladimir Coka 49b2a1c8cf refactor($parse): improve readability on conditional assignment
Use logical OR operator instead of if statement

Closes #5065
2014-07-15 12:49:00 +01:00
Wladimir Coka 3e82492fc6 refactor($http): improve readability on conditional assignment
Use ternary operator instead of if statement

Closes #5065
2014-07-15 12:48:48 +01:00
Wladimir Coka 856be44628 refactor(dateFilter): improve readability on conditional assignment
Use ternary operator instead of if statement

Closes #5065
2014-07-15 12:48:39 +01:00
Wladimir Coka dbb21b1531 refactor($compile): improve readability on conditional assignment
Use ternary operator instead of if statement

Closes #5065
2014-07-15 12:48:09 +01:00
Peter Bacon Darwin 3ce56b739c docs(guide/unit-testing): add info on testing element transclude directives
Closes #4505
Closes #8197
2014-07-15 12:40:26 +01:00
Bill Neubauer ecbb374826 docs(tutorial/step-9): link to list of filters rather than filterProvider
Closes #8082
2014-07-15 12:40:26 +01:00
Igor Minar 0e5d31908e fix(csp): fix autodetection of CSP + better docs
CSP spec got changed and it is no longer possible to autodetect if a policy is
active without triggering a CSP error:

https://github.com/w3c/webappsec/commit/18882953ce2d8afca25f685557fef0e0471b2c9a

Now we use `new Function('')` to detect if CSP is on. To prevent error from this
detection to show up in console developers have to use the ngCsp directive.

(This problem became more severe after our recent removal of `simpleGetterFn`
 which made us depend on function constructor for all expressions.)

Closes #8162
Closes #8191
2014-07-14 17:20:06 -07:00
standup75 f1b0d21f97 docs(ngAnimate): ensure the CSS breakdown example uses a compound selector 2014-07-14 11:29:35 -04:00
Igor Minar 58e94dcde9 docs($parse:isecdom): add a section about return values and CoffeeScript
Closes #7973
2014-07-12 20:24:20 -07:00
Erin Altenhof-Long eba192b863 docs(CHANGELOG): add v1.3.0-beta.15 and v1.2.20 changes 2014-07-11 11:26:39 -07:00
rodyhaddad 75099e6137 chore($parse): remove simpleGetter optimizations as they're no longer valid
Closes #8101
2014-07-10 15:17:41 -07:00
perek 172a40931b fix($http) - add ability to remove default headers
Fixes #5784
Closes #5785
2014-07-10 14:38:19 -07:00
Igor Minar 23e5109b64 chore(travis): disable our npm registry cache 2014-07-09 06:43:05 -07:00
Michał Gołębiowski cc84ce3bf5 chore(travis): disable npm spinner & enable HTTP logs; run npm install twice
It's good to have HTTP logs on Travis for debugging purposes and the spinner
doesn't integrate with Travis very well & messes the output.
2014-07-09 12:42:57 +02:00
Michał Gołębiowski bee2d1fbb9 chore(travis): declare Node.js version as '0.10', not 0.10 (which is 0.1) 2014-07-09 11:45:17 +02:00
fuqcool 7101a02c93 docs(error/$sce/insecurl): fix links to $sce and $sceDelegateProvider 2014-07-08 22:40:06 -07:00
Julie Ralph 888be00712 chore(tests): fix warning about a non-unique element locator in e2e tests 2014-07-08 16:28:12 -07:00
Julie Ralph 05597c24c7 chore(e2e): update protractor to 1.0.0-rc4
This change contains a stability improvement to use data URLs instead of
about:blank for resetting the URL.
2014-07-08 16:22:52 -07:00
Domenico Matteo bf55f23325 docs(guide/i18n): fix typo 2014-07-08 03:35:04 -07:00
Brian Ford ab051e78ea docs(select): update example to use a module 2014-07-08 02:32:21 -07:00
Brian Ford 87d46a84c3 docs(guide/expression): update examples to use modules 2014-07-08 02:32:21 -07:00
Brian Ford ae764f1844 docs(linky): update example to use a module 2014-07-08 02:32:21 -07:00
Brian Ford ad8092ed80 docs(angular.copy): update example to use a module 2014-07-08 02:32:21 -07:00
Brian Ford 55e1b3e1c8 docs($sanitize): update example to use a module 2014-07-08 02:32:20 -07:00
Brian Ford 6f465a2b26 docs(guide/scope): update examples to use modules 2014-07-08 02:32:20 -07:00
Brian Ford 3ecac62251 docs(guide/forms): update examples to use modules 2014-07-08 02:32:20 -07:00
Brian Ford c64610269d docs($location): update example to use a module 2014-07-08 02:32:20 -07:00
Brian Ford 5c2302949b docs($cookies): update examples to use modules 2014-07-08 02:32:20 -07:00
Brian Ford 7c84e2632f docs(orderBy): update examples to use modules 2014-07-08 02:32:20 -07:00
Brian Ford 18d18f07db docs(limitTo): update example to use a module 2014-07-08 02:32:20 -07:00
Brian Ford 9f5be534fc docs(ngTransclude): update example to use a module 2014-07-08 02:32:20 -07:00
Brian Ford 1cd7912614 docs($log): update example to use a module 2014-07-08 02:32:19 -07:00
Brian Ford 514da451fc docs(ngPluralize): update example to use a module 2014-07-08 02:32:19 -07:00
Brian Ford 2788cc4e12 docs(ngSwitch): update example to use a module 2014-07-08 02:32:19 -07:00
Brian Ford 7f6322df6a docs(ngInit): update example to use a module 2014-07-08 02:32:19 -07:00
Brian Ford 5bd8613168 docs(ngValue): update example to use a module 2014-07-08 02:32:19 -07:00
Brian Ford 32b507890e docs(ngList): update example to use a module 2014-07-08 02:32:19 -07:00
Brian Ford bfedafdede docs(ngInclude): update example to use a module 2014-07-08 02:32:19 -07:00
Brian Ford cdefbe3425 docs($interval): update example to use a module 2014-07-08 02:32:19 -07:00
Brian Ford f75f4bce82 docs(filters): update examples to use modules 2014-07-08 02:32:19 -07:00
Brian Ford 4349de3d41 docs(ngController): update examples to use modules 2014-07-08 02:32:18 -07:00
Brian Ford df545d7eed docs($window): update example to use a module 2014-07-08 02:32:18 -07:00
Brian Ford 3b5f346314 docs(ngSubmit): update example to use a module 2014-07-08 02:32:18 -07:00
Brian Ford 3aab87b381 docs(ngBind): update examples to use modules 2014-07-08 02:32:18 -07:00
Brian Ford 0973175058 docs($http): update example to use a module 2014-07-08 02:32:18 -07:00
Brian Ford 112da45c07 docs($document): update example to use a module 2014-07-08 02:32:18 -07:00
Brian Ford e3dc85841d docs(ngChange): update example to use a module 2014-07-08 02:32:18 -07:00
Brian Ford ef1c352bc9 docs(ngModel): update examples to use modules 2014-07-08 02:32:18 -07:00
Brian Ford a5b6444324 docs(formDirective): update example to use a module 2014-07-08 02:32:17 -07:00
Brian Ford dd18c00b1d docs($compile): update example to use a module 2014-07-08 02:32:17 -07:00
Shahar Talmi a0fad24dc2 chore(jshint): enforce jshint for tests
Closes #8023
Closes #8026
2014-07-08 00:34:50 -07:00
Shahar Talmi da0e3c99f5 fix(input): escape forward slash in email regexp
This messed up with syntax coloring and variable hovering in chrome developer tools and made debugging really difficult.

Closes #8096
2014-07-07 16:26:27 -04:00
Julie Ralph a41c58e285 chore(tests): increase timeout for navigation in ng-href tests to avoid timeouts
Previously, the timeout for ng-href tests waiting for the url change after a link
was clicked was only 1000 ms. This was causing some flaky timeouts, so increasing
the wait to 5000 ms.
2014-07-07 11:21:33 -07:00
Julie Ralph bce5b49133 chore(e2e): update protractor to 1.0.0-rc2 and add more logging
Use the new options from the reporter to add more logging to end to end tests,
and increase the Jasmine test timeout from 30 seconds to 60 seconds to allow for
legitimately long-lasting tests.
2014-07-07 11:07:48 -07:00
Kevin Brogan 816b84230c fix(input): modify email validation regexp to match rfc1035
Previously, domain parts which began with or ended with a dash, would be accepted as valid. This CL matches Angular's email validation with that of Chromium and Firefox.

Closes #6026
2014-07-07 13:51:58 -04:00
Caitlin Potter 873acf8fab fix(parseKeyValue): ignore properties in prototype chain.
Previously, properties (typically functions) in the prototype chain (Object.prototype) would shadow
query parameters, and cause them to be serialized incorrectly.

This CL guards against this by using hasOwnProperty() to ensure that only own properties are a concern.

Closes #8070
Fixes #8068
2014-07-03 21:58:10 -04:00
Matias Niemelä 9063a0c2e7 chore(ngAnimate): fix broken IE8 tests for ngAnimateChildren 2014-07-04 02:14:57 +03:00
Chris Kuehl 03cbc0d6b1 docs(error/$rootScope/inprog): fix $timeout typo
Closes #8071
2014-07-03 17:33:02 -04:00
Matias Niemelä 931789ec14 feat(ngAnimate): conditionally allow child animations to run in parallel with parent animations
By default ngAnimate prevents child animations from running when a parent is performing an animation.
However there are a cases when an application should allow all child animations to run without blocking
each other. By placing the `ng-animate-children` flag in the template, this effect can now be put to
use within the template.

Closes #7946
2014-07-03 19:35:17 +03:00
Peter Bacon Darwin 9bc807783f docs($httpProvider): revert removal of comments
Related to #7782
2014-07-03 13:29:24 +01:00
Cory Boyd 2d6ee651b1 docs($httpProvider): add missing documentation
Add documentation for $httpProvider default values

Closes #6682
2014-07-03 13:24:48 +01:00
Peter Bacon Darwin 7ca24a8264 chore(docs/css): add margin between ul and p elements
Bootstrap CSS was removing the margin after ul elements if they were
descendents of other ul elements. But if the ul was followed by a p
then this looked terrible.

Related to #5953
2014-07-03 12:51:21 +01:00
Peter Bacon Darwin 1d8e42070a docs(tutorial/step-0): remove hyphen and clarify items
Closes #5953
2014-07-03 12:51:21 +01:00
Robert Kielty fe6b2fbfc4 docs(tutorial/step-7): improve injector information
I attempted to tighten up the language around the DI overview so that it was clearer
and more explicit. The sole responsibilities sentence was semantically jarring and
I think looks better as a list.  Some minor grammar improvements.

Closes #7099
2014-07-03 12:24:15 +01:00
Peter Bacon Darwin 5a222244fb docs(guide/controller): tweak initial example 2014-07-03 12:13:49 +01:00
cranesandcaff 4026074aba docs(guide/controller): only show best practice controller creation
If it is not recommended to use a global function to create controllers,
why should it be shown as possible in the documentation?

One of the most common complaints about AngularJS is that it doesn't enforce
any convention. This is intentional and I generally like this.
However if we can avoid outright bad implementations in examples I believe
we should.

Closes #8011
2014-07-03 12:13:49 +01:00
Peter Bacon Darwin d9a596addd docs(guide/di): further clarification of what can be injected 2014-07-03 10:13:58 +01:00
Artiom Neganov 8c0898b21c docs(guide/di): clarify what "services" can be injected into .config() and .run()
Closes #8106
2014-07-03 10:13:58 +01:00
Mike Haas d9b693bb7a docs($compile): fix minor typo
Closes #8048
2014-07-03 09:51:40 +01:00
Peter Bacon Darwin da94ab2e63 docs($logProvider): debugEnabled is a method not a property
Closes #7824
2014-07-03 09:51:40 +01:00
Peter Bacon Darwin 2fd8dc7061 docs($sce): fix code samples and example
The code samples were using `<pre>` tags rather than code fences (```) so they were
not being displayed correctly.

The inline code example (defined by a `<example>` element) had been placed in an
`@example` jsdoc tag, so rather than appearing inline at the declaration point in
the text, they were being appended to the end of the document in the `Example` section.

Closes #8053
2014-07-03 07:05:32 +01:00
Caitlin Potter 01012a4d7a chore(watchr-docs): remove watchr-docs.rb
This file hasn't changed in forever, and doesn't seem to be in use any longer.

Closes #7978
2014-07-02 17:59:58 -04:00
jpsimons ce84429adf docs($location): update $location.search() jsdoc signature
Closes #8050
2014-07-02 13:55:24 -07:00
Sekib Omazic a26acb64fe fix($location): remove query args when passed in object
Query args will be removed from $location search object if they are passed in as null or undefined object properties

Closes #6565
2014-07-01 08:41:15 -07:00
Igor Minar 7088ed1ed3 docs($parse): add missing 'isecobj' error page 2014-07-01 06:36:50 -07:00
Martin Staffa 7027844d42 fix($http): don't remove content-type header if data is set by request transform
Fixes #7910
2014-06-30 16:58:15 -07:00
Carlo s A. Guillen 16c584ed7f docs(CHANGELOG.md): add changes for 1.3.0-beta.14 and 1.2.19 2014-06-30 16:58:15 -07:00
Michał Gołębiowski b586bfdfab fix(testabilityPatch): fix invocations of angular.mock.dump 2014-06-30 16:58:15 -07:00
Igor Minar 1d69015e3d test($parse): skip Function.prototype.bind test on IE8 2014-06-30 11:22:41 -07:00
Igor Minar f13c33bf10 fix($parse): don't check Function.prototype.bind when it doesn't exist
e.g. IE8 doesn't have it
2014-06-30 11:15:39 -07:00
Igor Minar ba62e975f1 fix($parse): make the window check in ensureSafeObject IE8 friendly 2014-06-30 11:06:18 -07:00
rodyhaddad b89d941cdf style(parseSpec): make jshint happy 2014-06-30 10:50:02 -07:00
rodyhaddad 07fa87a8a8 fix($parse): prevent invocation of Function's bind, call and apply
BREAKING CHANGE:
You can no longer invoke .bind, .call or .apply on a function in angular expressions.
This is to disallow changing the behaviour of existing functions
in an unforseen fashion.
2014-06-30 10:43:29 -07:00
rodyhaddad 0af70eb99e refactor($parse): move around previous security changes made to $parse 2014-06-30 10:40:24 -07:00
Jann Horn cb713e6045 fix($parse): forbid __proto__ properties in angular expressions
__proto__ can be used to mess with global prototypes and it's
deprecated. Therefore, blacklisting it seems like a good idea.

BREAKING CHANGE:
The (deprecated) __proto__ propery does not work inside angular expressions
anymore.
2014-06-30 09:32:38 -07:00
Jann Horn 89ca859734 fix($parse): forbid __{define,lookup}{Getter,Setter}__ properties
It was possible to use `{}.__defineGetter__.call(null, 'alert', (0).valueOf.bind(0))` to set
`window.alert` to a false-ish value, thereby breaking the `isWindow` check, which might lead
to arbitrary code execution in browsers that let you obtain the window object using Array methods.
Prevent that by blacklisting the nasty __{define,lookup}{Getter,Setter}__ properties.

BREAKING CHANGE:
This prevents the use of __{define,lookup}{Getter,Setter}__ inside angular
expressions. If you really need them for some reason, please wrap/bind them to make them
less dangerous, then make them available through the scope object.
2014-06-30 09:29:53 -07:00
Jann Horn bc6fb7cc94 fix($parse): forbid referencing Object in angular expressions
It was possible to run arbitrary JS from inside angular expressions using the
`Object.getOwnPropertyDescriptor` method like this since commit 4ab16aaa:
    ''.sub.call.call(
      ({})["constructor"].getOwnPropertyDescriptor(''.sub.__proto__, "constructor").value,
      null,
      "alert(1)"
    )()
Fix that by blocking access to `Object` because `Object` isn't accessible
without tricks anyway and it provides some other nasty functions.

BREAKING CHANGE:
This prevents the use of `Object` inside angular expressions.
If you need Object.keys, make it accessible in the scope.
2014-06-30 09:26:29 -07:00
Kristian Hellang 0c80df21b6 fix($http): should not read statusText on IE<10 when request is aborted
Commit 1d2414c introduced a regression by retrieving the statusText
of an aborted xhr request. This breaks IE9, which throws a c00c023f
error when accessing properties of an aborted xhr request. The fix
is similar to the one in commit 6f1050d.
2014-06-30 08:09:59 -07:00
vaibhav kohli 3141dbf179 style(Angular.js): remove extra whitespace 2014-06-29 09:42:34 -07:00
Archer aad502bad8 docs(guide/$location): fix a typo
Change "window.location.path" to "window.location.pathname".

Closes #8012
2014-06-28 20:05:32 -07:00
Elnur Abdurrakhimov dca8972367 docs(Getting Started): fix typo
Closes #8015
2014-06-28 19:42:02 -07:00
rodyhaddad 284de57435 test($interval): add tests making sure $interval uses the methods from $window 2014-06-28 17:35:14 -07:00
Praveen f780ccfa1c fix($interval): when canceling, use clearInterval from $window instead of global scope.
In $interval.cancel, use clearInterval from the $window service instead of from global scope.
The variable clearInterval declared above isn't visible here.
2014-06-28 17:35:06 -07:00
Efthymis Sarbanis 55f99e0710 chore: use triple equals comparison with typeof operator.
It is common practice for typeof operator to be used with '==='.

Closes #8009
2014-06-27 16:53:32 -07:00
Domenic Denicola 1a99ca9c08 docs($q): remove unnecessary $scope.apply wrapping
As of Angular 1.2, this kind of thing is no longer necessary (thank goodness!)
2014-06-26 12:37:04 -07:00
Laurent Curau 37500fca83 docs(guide/unit-testing): correct spelling 2014-06-26 12:37:04 -07:00
rodyhaddad 4fe4fc5abf chore(ngMock): replace misplaced comma with semicolon 2014-06-26 12:32:51 -07:00
rodyhaddad 74e1cc683b fix(jqLite): change expando property to a more unique name
This was causing issue when element === window
A better strategy can be thought of later on.
2014-06-26 12:32:30 -07:00
Igor Minar a4faa5cde7 perf(jqLite): don't use reflection to access expandoId
Since we allow only one copy of Angular to be loaded at a time it doesn't
make much sense randomly generate the expando property name and then be
forced to use slow reflective calles to retrieve the IDs.
2014-06-26 12:32:30 -07:00
Eddie Hedges 32cb40b86d docs(guide/introduction): use durandal as an example of a framework
To me knockout is a library that does data binding well.
Durandal is a framework that uses knockout as it's data binding component.
2014-06-26 12:19:56 -07:00
m-tretyak d1cd677433 docs(srcset): fix mistake in example 2014-06-26 12:08:55 -07:00
thorn0 43c735a816 docs($location): hashPrefix, html5Mode are methods
Closes #7915
2014-06-25 14:48:19 -07:00
Caitlin Potter ab2e83c8c8 fix(input): improve html5 validation support
This CL improves mocking support for HTML5 validation, fixes the behaviour which invokes validators.

Previously, an input would only be revalidated if either its value changed, or if it was the empty
string but did not suffer from bad input --- now, it will be revalidated if either the value has
changed, or the value is the empty string, there is a ValidityState for the element, and that
ValidityState is being tested by one of the validators in the pipeline.

Closes #7937
Closes #7957
2014-06-24 08:35:47 -04:00
Igor Minar e5f454c8af fix(numberFilter): correctly round fractions despite floating-point arithmetics issues in JS
Closes #7870
Closes #7878
2014-06-24 00:37:50 -07:00
Igor Minar 67c11b9a39 fix($injector): check if a fn is an array explicitly
This change makes the code easier to read and also fixes a compatibility issue
with opal.js which pollutes the global state by setting $inject property on
Array prototype

Closes #7904
Closes #2653
2014-06-23 17:20:09 -07:00
Zacky Ma 5a306b7ba3 docs(guide/compiler): change {{user}} to {{user.name}} in example
If user has an `actions` property, it should be an object,
which means if you {{user}}, it'll print out the object.
2014-06-23 13:36:04 -07:00
ephigabay 8ce61bf178 docs(ngModelController): update setValidity
Needs to be `$error[validationErrorKey]!=isValid` and not
`$error[validationErrorKey]=isValid`.

See https://github.com/angular/angular.js/blob/master/src/ng/directive/input.js#L1627

Closes #7934
2014-06-23 13:21:44 -07:00
Chaker Nakhli 9d452bc845 docs(ngSrc): srcset used instead of src for img attribute
In `ngSrc` documentation `srcset` is used instead of `src` as `img` element attribute in the example.

Closes #7951
2014-06-23 13:15:03 -07:00
Julie 192fecc790 chore(grunt): check files in src for ddescribe/iit
Previously, only files in test/ were checked. This does not capture
end to end tests, which are in comments in src/.
2014-06-23 11:28:21 -07:00
Julie 32be6369e4 chore(tests): remove a lingering iit in end to end tests 2014-06-23 11:22:37 -07:00
Shahar Talmi 2a45cea0ba fix(input): escape forward slash in email regexp
This messed up with syntax coloring and variable hovering in chrome developer tools and made debugging really difficult.

Closes #7938
2014-06-22 21:28:55 -04:00
Peter Bacon Darwin ea653e4cdd docs($provide): it is a service not an object
Closes #7917
2014-06-20 17:01:10 +01:00
Alex Muntada 03777445e8 docs(tutorial/step-4): fix e2e test
After a protractor update the test syntax had to be changed.

Closes #7919
2014-06-20 14:36:13 +01:00
Neil Giarratana 8b25ea129a docs(ngPluralize): spell Mary's name correctly
Update ngPluralize.js

Just a silly change to the name of one of the examples that appears to be a typo. Changing Marry to
Mary as the first would be a verb and the latter would be an extremely common name.

Closes #7884
2014-06-17 17:44:17 -04:00
Shahar Talmi d71f16e745 fix(injector): allow multiple loading of function modules
Change HashMap to give $$hashKey also for functions so it will be possible to load multiple module
function instances. In order to prevent problem in angular's test suite,  added an option to HashMap
to maintain its own id counter and added cleanup of $$hashKey from all module functions after each
test.

Before this CL, functions were added to the HashMap via toString(), which could potentially return
the same value for different actual instances of a function. This corrects this behaviour by
ensuring that functions are mapped with hashKeys, and ensuring that hashKeys are removed from
functions and objects at the end of tests.

In addition to these changes, the injector uses its own set of UIDs in order to prevent confusingly
breaking tests which expect scopes or ng-repeated items to have specific hash keys.

Closes #7255
2014-06-16 20:45:49 -04:00
Jason Bedard ed59370d80 fix($compile): bind ng-attr-* even if unbound attribute follows ng-attr-*
Previously, <element ng-attr-foo="{{binding}}" foo="bar"></element>'s "foo" attribute would always
equal "bar", because the bound version was overwritten. This CL corrects this behaviour and ensures
that the ordering of attributes does not have an effect on whether or not ng-attr-bound attributes
do their work.
2014-06-16 20:35:13 -04:00
Ahmad Moussawi d8e5acfe27 docs($sce): update the parseAs method name 2014-06-16 13:46:02 -07:00
James Harrison Fisher af59f4e69a docs(ngMock): fix typo providers -> provides
Should be a verb, ☆.。.:・゜☆MERCI BEAUCOUP☆.。.:・゜☆
2014-06-16 11:47:45 -04:00
Colin Casey 24aee81634 refact(select): use prop to modify the select property
jQuery suggests using `prop` rather than `attr` to modify the `select` property of an element.
You can see the full list of migration warnings for jQuery:
https://github.com/jquery/jquery-migrate/blob/master/warnings.md

Closes #4107
Closes #4122
2014-06-14 17:28:12 +01:00
rodyhaddad f81d56e66c docs(CHANGELOG.md): add changes for 1.2.18 2014-06-13 14:52:28 -07:00
Caitlin Potter f0904cf12e fix(ngResource): don't convert literal values into Resource objects when isArray is true
Previously non-object literals would be thrown out of Resource responses with isArray===true, or
otherwise converted into Objects (in the case of string literals). The reason for this is because
shallowClearAndCopy iterates over keys, and copies keys into the destination. Iterating over String
keys results in integer keys, with a single-character value.

Not converting non-objects to Resources means that you lose the ability to perform Resource operations
on them. However, they become usable as strings, numbers, or booleans, which is important.

In the future, it would be useful to make these useful as Resources while still retaining their primitive
value usefulness.

Closes #6314
Closes #7741
2014-06-13 13:55:33 -07:00
Igor Minar 81b7e5ab0e perf($compile): move ng-binding class stamping for interpolation into compile phase 2014-06-13 13:23:22 -07:00
Igor Minar 1b1890274e perf(ngBind): set the ng-binding class during compilation instead of linking 2014-06-13 13:23:22 -07:00
Igor Minar 6d418ef5e3 perf(jqLite): cache collection length for all methods that work on a single element
This affects jqLite#html, #text, #attr, #prop, #css and others.
2014-06-13 13:23:22 -07:00
Igor Minar 3fa1606c43 chore: name the event callback used by ngClick and friends
This maskes looking at stack traces easier.

Since we generate the callbacks for each event type at runtime and we can't
set function's name because it's read-only, we have to use a generic name.
2014-06-13 13:23:21 -07:00
XrXr 8661a9e3d4 docs(CONTRIBUTING.md): fix link to unit testing docs
The old link points to a page that doesn't exist

Closes #7830
2014-06-13 13:56:28 -04:00
Caitlin Potter cf63292742 test($compile): make IE8 happy
Closes #7828
2014-06-13 12:09:39 -04:00
Peter Bacon Darwin fd420c4061 fix($compile): ensure transclude works at root of templateUrl
If a "replace" directive has an async template, which contains a transclusion
directive at its root node, then outer transclusions were failing to be
passed to this directive.  An example would be uses of `ngIf` inside and
outside the template.

Collaborated with @caitp

Closes #7183
Closes #7772
2014-06-13 12:09:33 -04:00
Vojta Jina 1382d4e88e fix($compile): bound transclusion to correct scope
Nested isolated transclude directives.

This improves/fixes the fix in d414b78717.

See the changed ng-ifunit test: The template inside ng-if should be bound to the
isolate scope of `iso` directive (resp. its child scope). Not to a child of
the root scope. This shows the issue with ng-if. It’s however problem with
other directives too.

Instead of remembering the scope, we pass around the bound parent transclusion.

Conflicts:
	test/ng/directive/ngIfSpec.js
2014-06-13 12:09:33 -04:00
Peter Bacon Darwin b9ddef2a49 fix($compile): don't pass transcludes to non-transclude templateUrl directives 2014-06-13 12:09:32 -04:00
Peter Bacon Darwin eafba9e2e5 fix($compile): don't pass transclude to template of non-transclude directive
If a directive provides a template but is not explicitly requesting transclusion
then the compiler should not pass a transclusion function to the directives
within the template.
2014-06-13 12:09:32 -04:00
Peter Bacon Darwin 6f1d9f8ca6 refactor($compile): no need to use bind 2014-06-13 12:09:32 -04:00
Peter Bacon Darwin bb9310974b fix($compile): fix nested isolated transclude directives
Closes #1809
Closes #7499
2014-06-13 12:09:32 -04:00
Peter Bacon Darwin 30279d7b9b refactor($compile): change parameter name
The boundTransclusionFn that is passed in is really the one from the
parent node.  The change to parentBoundTranscludeFn clarifies this compared
to the childBoundTranscludeFn.
2014-06-13 12:09:32 -04:00
Peter Bacon Darwin 8df5f3259a fix($compile): pass transcludeFn down to nested transclude directives
If you have two directives that both expect to receive transcluded content
the outer directive works but the inner directive never receives a
transclusion function. This only failed if the first transclude directive
was not the first directive found in compilation.

Handles the regression identified in e994259739

Fixes #7240
Closes #7387
2014-06-13 12:09:32 -04:00
Tero Parviainen 14e797c1a1 fix($injector): report circularity in circular dependency error message
Change the error message for a circular dependency to display the full
circle back to the first service being instantiated, so that the problem
is obvious. The previous message stopped one dependency short of the full
circle.

Changes the content of the cdep error message, which may be considered
a breaking change.

Closes #7500
2014-06-12 17:32:28 -07:00
Brian Ford 82cd6b87f0 docs(TRIAGING.md): clarification for issues that are not reproducable 2014-06-12 14:39:04 -07:00
Andreas Krummsdorf 6d7cc572b5 style(loader.js): correct JSDoc tags of the params of the function module(name, requires, configFn)
This will improve the hints for IDE's which support the Google Closure Compiler (e.g. Webstorm)
2014-06-12 13:49:33 -07:00
rodyhaddad 2ebbe00eb5 revert: style(loader.js): correct JSDoc tags of the params of the function module(name, requires, configFn)
This reverts commit f4c08fee85.
2014-06-12 13:49:33 -07:00
Michal Kawalec 8b86d363aa perf($http): move xsrf cookie check to after cache check in $http
$http was previously checking cookies to find an xsrf-token prior to checking
the cache. This caused a performance penalty of about 2ms, which can be very
significant when loading hundreds of template instances on a page.

Fixes #7717
2014-06-12 11:28:00 -07:00
Aiden N 9b51067516 docs(guide/bootstrap): fix link to angular.js script in example
code.angularjs.org/angular.js is 404, updated it

Updated http://code.angularjs.org/angular.js in the example to http://code.angularjs.org/snapshot/angular.js
It works fine now.
2014-06-12 14:24:34 -04:00
fuqcool a3208bf66e docs(guide/services): fix link to services api 2014-06-12 00:13:10 -04:00
Dave Wells 4e1fb82628 docs(errors/$compile/nonassing): fix reversed attribute and scope property names 2014-06-11 14:55:32 -07:00
Alexander Karpan ad466412c6 docs(guide/services): fix link to wikipedia article containing parentheses
Fix in a mis-parsed link with ')' symbol in it
2014-06-10 16:11:16 -04:00
fvanderwielen 299a32740c docs(loader): improve explanation of modules 2014-06-10 11:48:52 -07:00
Rocky Assad eb799bcb71 chore(jshint): dedupe jshint option 2014-06-10 01:46:46 -07:00
Brian Ford 7314c1b69e docs(tutorial/step_09): fix formatting 2014-06-10 01:42:21 -07:00
Brian Ford fcfe2b3793 docs(tutorial/step_09): fix link to filter guide 2014-06-10 01:34:58 -07:00
Kevin Western 5e140a99c7 docs($animate): $animate.enabled's param is optional
The docs show that param 'element' (of type DOMElement) is required when it is optional.
2014-06-10 01:09:42 -07:00
Amar Patel 4da169d15d docs(api/index): add Oxford comma
Verified grammar at https://owl.english.purdue.edu/owl/resource/607/01/
2014-06-10 00:58:02 -07:00
Dylan Semler f37c6f9f73 docs(error/$compile/tplrt): note that html comments can cause this 2014-06-10 00:52:41 -07:00
Carl Sutherland eae658fd96 docs(directive/input): document ngTrim for textarea 2014-06-10 00:38:14 -07:00
Matt Johansen 286f269753 docs(tutorial/step_09): note about 'Filter' suffix
Reminder that 'Filter' is appended to filter names when injected.
Link to Filter guide where this is mentioned.
2014-06-09 22:01:57 -07:00
Stephen Nancekivell 73640a6b7c docs(error/$sce/unsafe): suggest including ngSanatize 2014-06-09 20:55:53 -07:00
Arjunkumar 2dc55ff5c2 docs(guide/index): add codeschool link 2014-06-09 15:50:54 -07:00
Uri Goldshtein 98a2563ec4 docs(guide): add UI-Map to Complementary Libraries 2014-06-09 14:31:49 -07:00
Uri Goldshtein 8c02122837 docs(guide): add ngTagsInput to UI Widgets 2014-06-09 14:02:34 -07:00
Joseph Orbegoso Pea 1e069532fc docs(ngController): improve wording 2014-06-09 13:42:05 -07:00
Nikita Vasilyev 6f6f7e82a4 docs(guide/databinding): add line breaks after images
This looks much better, thanks a bunch @NV
2014-06-08 22:13:53 -04:00
Peter Bacon Darwin d852122442 docs(error/$rootScope/inprog): improve understanding and diagnosis of the error
See #5549
2014-06-08 19:35:13 +01:00
Caitlin Potter 66cb161221 docs(CHANGELOG.md): remove mention of strict-DI
Strict-DI feature was originally merged into v1.2.x, but was reverted by https://github.com/angular/angular.js/commit/373078a94cf3d525b9ae11a2f2876acb6e26f6a3
2014-06-08 02:05:35 -04:00
Sebastian Müller 6c14fb1eb6 perf(isArray): use native Array.isArray
see benchmark: http://jsperf.com/isarray-performance
2014-06-06 20:07:08 -04:00
Peter Bacon Darwin e906aafb0a docs(tutorial): mention additional Debian install step
Thanks to GSC Leticia (gsc-leticia) for identifying this problem.

Closes #7665
2014-06-06 21:28:13 +01:00
1018 changed files with 93732 additions and 14756 deletions
-4
View File
@@ -1,4 +0,0 @@
{
"directory": "bower_components",
"json": "bower.json"
}
+21
View File
@@ -0,0 +1,21 @@
# http://editorconfig.org
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
[src/ngLocale/**]
insert_final_newline = false
[dropdown-toggle.js]
trim_trailing_whitespace = false
insert_final_newline = false
[htmlparser.js]
insert_final_newline = false
+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
+2
View File
@@ -0,0 +1,2 @@
node_modules/**
lib/htmlparser/**
+5
View File
@@ -0,0 +1,5 @@
{
"extends": ".jshintrc-base",
"node": true,
"globals": {}
}
+19
View File
@@ -0,0 +1,19 @@
{
"bitwise": true,
"immed": true,
"newcap": true,
"noarg": true,
"noempty": true,
"nonew": true,
"trailing": true,
"maxlen": 200,
"boss": true,
"eqnull": true,
"expr": true,
"globalstrict": true,
"laxbreak": true,
"loopfunc": true,
"sub": true,
"undef": true,
"indent": 2
}
+8 -3
View File
@@ -1,6 +1,6 @@
language: node_js
node_js:
- 0.10
- '0.10'
branches:
except:
@@ -19,8 +19,13 @@ env:
- BROWSER_PROVIDER_READY_FILE=/tmp/sauce-connect-ready
install:
- npm config set registry http://23.251.144.68
- npm install
# - npm config set registry http://23.251.144.68
# Disable the spinner, it looks bad on Travis
- npm config set spin false
# Log HTTP requests
- npm config set loglevel http
- time ./scripts/travis/npm-bundle-deps.sh
- time npm install
before_script:
- mkdir -p $LOGS_DIR
+1983 -3
View File
File diff suppressed because it is too large Load Diff
+3 -3
View File
@@ -119,7 +119,7 @@ Before you submit your pull request consider the following guidelines:
```
* In GitHub, send a pull request to `angular:master`.
* If we suggest changes then
* If we suggest changes then
* Make the required updates.
* Re-run the Angular test suite to ensure tests are still passing.
* Rebase your branch and force push to your GitHub repository (this will update your Pull Request):
@@ -237,7 +237,7 @@ reference GitHub issues that this commit **Closes**.
A detailed explanation can be found in this [document][commit-message-format].
## <a name="cla"></a> Signing the CLA
## <a name="cla"></a> Signing the CLA
Please sign our Contributor License Agreement (CLA) before sending pull requests. For any code
changes to be accepted, the CLA must be signed. It's a quick process, we promise!
@@ -269,6 +269,6 @@ You can find out more detailed information about contributing in the
[ngDocs]: https://github.com/angular/angular.js/wiki/Writing-AngularJS-Documentation
[plunker]: http://plnkr.co/edit
[stackoverflow]: http://stackoverflow.com/questions/tagged/angularjs
[unit-testing]: http://docs.angularjs.org/guide/dev_guide.unit-testing
[unit-testing]: https://docs.angularjs.org/guide/unit-testing
[![Analytics](https://ga-beacon.appspot.com/UA-8594346-11/angular.js/CONTRIBUTING.md?pixel)](https://github.com/igrigorik/ga-beacon)
+17 -2
View File
@@ -1,3 +1,5 @@
'use strict';
var files = require('./angularFiles').files;
var util = require('./lib/grunt/utils.js');
var versionInfo = require('./lib/versions/version-info');
@@ -107,6 +109,12 @@ module.exports = function(grunt) {
options: {
jshintrc: true,
},
node: {
files: { src: ['*.js', 'lib/**/*.js'] },
},
tests: {
files: { src: 'test/**/*.js' },
},
ng: {
files: { src: files['angularSrc'] },
},
@@ -220,8 +228,11 @@ module.exports = function(grunt) {
"ddescribe-iit": {
files: [
'src/**/*.js',
'test/**/*.js',
'!test/ngScenario/DescribeSpec.js'
'!test/ngScenario/DescribeSpec.js',
'!src/ng/directive/booleanAttrs.js', // legitimate xit here
'!src/ngScenario/**/*.js'
]
},
@@ -246,7 +257,11 @@ module.exports = function(grunt) {
compress: {
build: {
options: {archive: 'build/' + dist +'.zip', mode: 'zip'},
src: ['**'], cwd: 'build', expand: true, dot: true, dest: dist + '/'
src: ['**'],
cwd: 'build',
expand: true,
dot: true,
dest: dist + '/'
}
},
+2 -2
View File
@@ -15,7 +15,7 @@ it makes development fun!
* 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 +37,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)
+5 -5
View File
@@ -34,7 +34,7 @@ This process based on the idea of minimizing user pain
* Check if there are comments that link to a dupe. If so verify that this is indeed a dupe, [close it][], and go to the last step.
1. Bugs:
* Label `Type: Bug`
* Reproducible? - Steps to reproduce the bug are clear. If they are not,
* 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:
@@ -44,11 +44,11 @@ This process based on the idea of minimizing user pain
* Label `needs: breaking change` - if needed
* Label `needs: public api` - if the issue requires introduction of a new public API
1. Label `browser: *` - if the issue **only** affects a certain browser
1. Label `frequency: *` How often does this issue come up? How many developers does this affect?
1. Label `frequency: *` How often does this issue come up? How many developers does this affect? Chose just one of the following:
* low - obscure issue affecting a handful of developers
* moderate - impacts a common usage pattern
* high - impacts most or all Angular apps
1. Label `severity: *` - How bad is the issue?
1. Label `severity: *` - How bad is the issue? Chose just one of the following:
* security issue
* regression
* memory leak
@@ -61,9 +61,9 @@ This process based on the idea of minimizing user pain
1. Label `origin: google` for issues from Google
1. Assign a milestone:
* Backlog - triaged fixes and features, should be the default choice
* 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. Unassign yourself from the issue
+3 -1
View File
@@ -1,4 +1,6 @@
angularFiles = {
'use strict';
var angularFiles = {
'angularSrc': [
'src/minErr.js',
'src/Angular.js',
+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"
}
}
+4 -2
View File
@@ -3,6 +3,8 @@
// TODO(vojta): pre-commit hook for validating messages
// TODO(vojta): report errors, currently Q silence everything which really sucks
'use strict';
var child = require('child_process');
var fs = require('fs');
var util = require('util');
@@ -164,7 +166,7 @@ var writeChangelog = function(stream, commits, version) {
hash: commit.hash,
closes: []
});
};
}
});
stream.write(util.format(HEADER_TPL, version, version, currentDate()));
@@ -172,7 +174,7 @@ var writeChangelog = function(stream, commits, version) {
printSection(stream, 'Features', sections.feat);
printSection(stream, 'Performance Improvements', sections.perf);
printSection(stream, 'Breaking Changes', sections.breaks, false);
}
};
var getPreviousTag = function() {
+5 -1
View File
@@ -1,3 +1,7 @@
/* global describe: false, it: false, expect: false */
'use strict';
describe('changelog.js', function() {
var ch = require('./changelog');
@@ -13,7 +17,7 @@ describe('changelog.js', function() {
expect(msg.hash).toBe('9b1aff905b638aa274a5fc8f88662df446d374bd');
expect(msg.subject).toBe('broadcast $destroy event on scope destruction');
expect(msg.body).toBe('perf testing shows that in chrome this change adds 5-15% overhead\n' +
'when destroying 10k nested scopes where each scope has a $destroy listener\n')
'when destroying 10k nested scopes where each scope has a $destroy listener\n');
expect(msg.component).toBe('scope');
});
+3 -1
View File
@@ -1,5 +1,7 @@
#!/usr/local/bin/node
'use strict';
var util = require('util');
var cp = require('child_process');
@@ -143,7 +145,7 @@ then(allInSeries(function (branch) {
return sha + (msg.toLowerCase().indexOf('fix') === -1 ? ' ' : ' * ') + msg;
});
branch.log = log.map(function (line) {
return line.substr(41)
return line.substr(41);
});
return branch;
});
+10 -4
View File
@@ -211,6 +211,10 @@ code.highlighted {
color:maroon;
}
ul + p {
margin-top: 10px;
}
.docs-version-jump {
min-width:100%;
max-width:100%;
@@ -631,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 -1
View File
@@ -40,7 +40,7 @@ pre.prettyprint.linenums {
}
ol.linenums {
margin: 0 0 0 33px; /* IE indents via margin-left */
}
}
ol.linenums li {
padding-left: 12px;
font-size:12px;
+3 -3
View File
@@ -11,7 +11,7 @@ directive.runnableExample = ['$templateCache', '$document', function($templateCa
'ng-repeat="tab in tabs track by $index" ' +
'href="" ' +
'class="btn"' +
'ng-click="setTab($index)">' +
'ng-click="setTab($index)">' +
' {{ tab }}' +
' </a>' +
'</nav>';
@@ -103,7 +103,7 @@ directive.syntax = function() {
restrict: 'A',
link: function(scope, element, attrs) {
function makeLink(type, text, link, icon) {
return '<a href="' + link + '" class="btn syntax-' + type + '" target="_blank" rel="nofollow">' +
return '<a href="' + link + '" class="btn syntax-' + type + '" target="_blank" rel="nofollow">' +
'<span class="' + icon + '"></span> ' + text +
'</a>';
};
@@ -307,7 +307,7 @@ var popoverElement = function() {
return this.titleElement.html(value);
},
content : function(value) {
content : function(value) {
if(value && value.length > 0) {
value = marked(value);
}
+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)');
});
});
@@ -1,10 +1,12 @@
'use strict';
describe('docs.angularjs.org', function () {
describe('App', function () {
// it('should filter the module list when searching', function () {
// browser.get();
// browser.waitForAngular();
// var search = element(by.input('q'));
// var search = element(by.model('q'));
// search.clear();
// search.sendKeys('ngBind');
@@ -24,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.input('user.name'));
nameInput.sendKeys('!!!');
var code = element(by.css('tt'));
expect(code.getText()).toContain('guest!!!');
});
it('should be resilient to trailing slashes', function() {
browser.get('index-debug.html#!/api/ng/function/angular.noop/');
@@ -65,5 +52,12 @@ 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");
});
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!');
});
});
});
+1 -1
View File
@@ -20,4 +20,4 @@ angular.module('docsApp', [
.config(function($locationProvider) {
$locationProvider.html5Mode(true).hashPrefix('!');
});
});
+1 -1
View File
@@ -59,4 +59,4 @@ angular.module('errors', ['ngSanitize'])
element.html(errorLinkFilter(interpolate.apply(null, formatArgs), '_blank'));
}
};
}]);
}]);
+7 -2
View File
@@ -2,7 +2,12 @@ angular.module('examples', [])
.factory('formPostData', ['$document', function($document) {
return function(url, fields) {
var form = angular.element('<form style="display: none;" method="post" action="' + url + '" target="_blank"></form>');
/**
* Form previously posted to target="_blank", but pop-up blockers were causing this to not work.
* If a user chose to bypass pop-up blocker one time and click the link, they would arrive at
* a new default plnkr, not a plnkr with the desired template.
*/
var form = angular.element('<form style="display: none;" method="post" action="' + url + '"></form>');
angular.forEach(fields, function(value, name) {
var input = angular.element('<input type="hidden" name="' + name + '">');
input.attr('value', value);
@@ -69,4 +74,4 @@ angular.module('examples', [])
formPostData('http://plnkr.co/edit/?p=preview', postData);
});
};
}]);
}]);
+1 -1
View File
@@ -21,4 +21,4 @@ angular.module('docsApp.navigationService', [])
}
};
});
});
+3 -1
View File
@@ -74,6 +74,7 @@ angular.module('search', [])
var index = lunrSearch(function() {
this.ref('id');
this.field('title', {boost: 50});
this.field('members', { boost: 40});
this.field('keywords', { boost : 20 });
});
@@ -82,7 +83,8 @@ angular.module('search', [])
index.store({
id : key,
title : page.searchTerms.titleWords,
keywords : page.searchTerms.keywords
keywords : page.searchTerms.keywords,
members : page.searchTerms.members
});
};
});
+19 -3
View File
@@ -1,15 +1,31 @@
"use strict";
angular.module('versions', [])
.controller('DocsVersionsCtrl', ['$scope', '$location', '$window', 'NG_VERSIONS', function($scope, $location, $window, NG_VERSIONS) {
$scope.docs_versions = NG_VERSIONS;
$scope.docs_version = NG_VERSIONS[0];
for(var i=0, minor = NaN; i < NG_VERSIONS.length; i++) {
var version = NG_VERSIONS[i];
// NaN will give false here
if (minor <= version.minor) {
continue;
}
version.isLatest = true;
minor = version.minor;
}
$scope.docs_versions = NG_VERSIONS;
$scope.getGroupName = function(v) {
return v.isLatest ? 'Latest' : (v.isStable ? 'Stable' : 'Unstable');
};
$scope.jumpToDocsVersion = function(version) {
var currentPagePath = $location.path();
// TODO: We need to do some munging of the path for different versions of the API...
$window.location = version.docsUrl + currentPagePath;
};
}]);
}]);
+1 -1
View File
@@ -31,4 +31,4 @@ describe("DocsController", function() {
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"
}
}
+142 -32
View File
@@ -1,43 +1,153 @@
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')
]);
config.append('processing.tagDefinitions', [
require('./tag-defs/tutorial-step')
]);
.factory(require('./services/errorNamespaceMap'))
.factory(require('./services/getMinerrInfo'))
.factory(require('./services/getVersion'))
.factory(require('./services/gitData'))
config.append('processing.defaultTagTransforms', [
require('dgeni-packages/jsdoc/tag-defs/transforms/trim-whitespace')
]);
.factory(require('./services/deployments/debug'))
.factory(require('./services/deployments/default'))
.factory(require('./services/deployments/jquery'))
.factory(require('./services/deployments/production'))
config.append('processing.inlineTagDefinitions', [
require('./inline-tag-defs/type')
]);
.factory(require('./inline-tag-defs/type'))
config.set('processing.search.ignoreWordsFile', path.resolve(packagePath, 'ignore.words'));
config.prepend('rendering.templateFolders', [
path.resolve(packagePath, 'templates')
]);
.processor(require('./processors/error-docs'))
.processor(require('./processors/index-page'))
.processor(require('./processors/keywords'))
.processor(require('./processors/pages-data'))
.processor(require('./processors/versions-data'))
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;
},
getOutputPath: function(doc) {
return 'partials/' + doc.path +
( doc.fileInfo.baseName === 'index' ? '/index.html' : '.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'
});
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');
});
}
+42 -49
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);
});
}
};
};
};
+73 -47
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(' ')
};
});
});
}
};
}
};
};
+166 -155
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,192 @@ 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'],
$runBefore: ['rendering-docs'],
$process: function(docs) {
_(docs)
.filter(function(doc) { return doc.area === 'api' && 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);
});
// 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 docs that are in an area and are not landing pages
var navPages = _.filter(docs, function(page) {
return page.area && page.docType != 'componentGroup';
});
var docData = {
docType: 'pages-data',
id: 'pages-data',
template: 'pages-data.template.js',
outputPath: 'js/pages-data.js',
// 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;
areas: areas,
pages: pages
};
docs.push(docData);
var navGroupMapper = navGroupMappers[area.id] || navGroupMappers['pages'];
area.navGroups = navGroupMapper(pages, 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();
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);
}
}
};
@@ -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;
}
}
};
+28 -32
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/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'
]
};
};
@@ -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.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'
]
};
};
+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.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'
]
};
};
@@ -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.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'
]
};
};
+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);
}
};
+1 -1
View File
@@ -14,4 +14,4 @@
{$ doc.description | marked $}
</div>
{% endblock %}
{% endblock %}
@@ -25,4 +25,4 @@
</div>
</div>
{% endblock %}
{% endblock %}
@@ -175,7 +175,7 @@
<div class="container main-grid main-header-grid">
<div class="grid-left">
<div ng-controller="DocsVersionsCtrl" class="picker version-picker">
<select ng-options="v as ('v' + v.version + (v.isSnapshot ? ' (snapshot)' : '')) group by (v.isStable?'Stable':'Unstable') for v in docs_versions"
<select ng-options="v as ('v' + v.version + (v.isSnapshot ? ' (snapshot)' : '')) group by getGroupName(v) for v in docs_versions"
ng-model="docs_version"
ng-change="jumpToDocsVersion(docs_version)"
class="docs-version-jump">
@@ -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,9 +20,9 @@
</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>
{# Be aware that we need these extra new lines here or marked will not realise that the <div>
above is HTML and wrap each line in a <p> - thus breaking the HTML #}
above is HTML and wrap each line in a <p> - thus breaking the HTML #}
+1 -1
View File
@@ -1 +1 @@
{% include 'overview.template.html' %}
{% include 'overview.template.html' %}
+3 -3
View File
@@ -6,7 +6,7 @@
Welcome to the AngularJS API docs page. These pages contain the AngularJS reference materials for version <strong ng-bind="version"></strong>.
The documentation is organized into **{@link guide/module modules}** which contain various components of an AngularJS application.
These components are {@link guide/directive directives}, {@link guide/services services}, {@link guide/filter filters}, {@link guide/providers providers}, {@link guide/templates templates}, global APIs and testing mocks.
These components are {@link guide/directive directives}, {@link guide/services services}, {@link guide/filter filters}, {@link guide/providers providers}, {@link guide/templates templates}, global APIs, and testing mocks.
<div class="alert alert-info">
**Angular Namespaces `$` and `$$`**
@@ -212,7 +212,7 @@ Use ngTouch when developing for mobile browsers/devices.
{@link ngTouch#service Services / Factories}
</td>
<td>
The {@link ngTouch.$swipe $swipe} service is used to register and manage mobile DOM events.
The {@link ngTouch.$swipe $swipe} service is used to register and manage mobile DOM events.
</td>
</tr>
<tr>
@@ -252,7 +252,7 @@ Use ngSanitize to securely parse and manipulate HTML data in your application.
## {@link ngMock ngMock}
Use ngMock to inject and mock modules, factories, services and providers within your unit tests
Use ngMock to inject and mock modules, factories, services and providers within your unit tests
<div class="alert alert-info">Include the **angular-mocks.js** file into your test runner for this to work.</div>
+1 -1
View File
@@ -16,7 +16,7 @@ myModule.directive('myDirective', function factory() {
return {
...
scope: {
'bind': '=localValue'
localValue: '=bind'
}
...
}
+14
View File
@@ -37,3 +37,17 @@ elements. For example:
```
<b>Hello</b> World!
```
Watch out for html comments at the beginning or end of templates, as these can cause this error as
well. Consider the following template:
```
<div class='container'>
<div class='wrapper>
...
</div> <!-- wrapper -->
</div> <!-- container -->
```
The `<!-- container -->` comment is interpreted as a second root element and causes the template to
be invalid.
+1 -1
View File
@@ -23,4 +23,4 @@ When an instance of `MyCtrl` is created, the service `myService` will be created
by the `$injector`. `myService` depends on itself, which causes the `$injector`
to detect a circular dependency and throw the error.
For more information, see the {@link guide/di Dependency Injection Guide}.
For more information, see the {@link guide/di Dependency Injection Guide}.
+1 -1
View File
@@ -23,4 +23,4 @@ To avoid the error, always use string literals for dependency injection annotati
tokens.
For an explanation of what injection annotations are and how to use them, refer
to the {@link guide/di Dependency Injection Guide}.
to the {@link guide/di Dependency Injection Guide}.
+1 -1
View File
@@ -23,4 +23,4 @@ angular.module("myApp", [])
```
For more information, refer to the {@link auto.$provide#provider
$provide.provider} api doc.
$provide.provider} api doc.
+31 -1
View File
@@ -14,7 +14,7 @@ angular.module('myApp', [])
}]);
```
The above code will fail with `$injector:unpr` if `myService` is not defined.
The above code will fail with `$injector:unpr` if `myService` is not defined.
Making sure each dependency is defined will fix the problem, as noted below.
@@ -25,3 +25,33 @@ angular.module('myApp', [])
// Do something with myService
}]);
```
An unknown provider error can also be caused by accidentally redefining a
module using the `angular.module` API, as shown in the following example.
```
angular.module('myModule', [])
.service('myCoolService', function () { /* ... */ });
angular.module('myModule', [])
// myModule has already been created! This is not what you want!
.directive('myDirective', ['myCoolService', function (myCoolService) {
// This directive definition throws unknown provider, because myCoolService
// has been destroyed.
}]);
```
To fix this problem, make sure you only define each module with the
`angular.module(name, [requires])` syntax once across your entire project.
Retrieve it for subsequent use with `angular.module(name)`. The fixed example
is shown below.
```
angular.module('myModule', [])
.service('myCoolService', function () { /* ... */ });
angular.module('myModule')
.directive('myDirective', ['myCoolService', function (myCoolService) {
// This directive definition does not throw unknown provider.
}]);
```
@@ -9,4 +9,4 @@ it hard to reason about whether some combination of concatenated values are
unsafe to use and could easily lead to XSS.
For more information about how AngularJS helps keep your app secure, refer to
the {@link ng.$sce $sce} API doc.
the {@link ng.$sce $sce} API doc.
+31
View File
@@ -14,3 +14,34 @@ perform this check - it's up to the developer to not expose such sensitive and p
directly on the scope chain.
To resolve this error, avoid access to DOM nodes.
# Event Handlers and Return Values
The `$parse:isecdom` error also occurs when an event handler invokes a function that returns a DOM
node.
```html
<button ng-click="iWillReturnDOM()">click me</button>
```
```js
$scope.iWillReturnDOM = function() {
return someDomNode;
}
```
To fix this issue, avoid returning DOM nodes from event handlers.
*Note: This error often means that you are accessing DOM from your controllers, which is usually
a sign of poor coding style that violates separation of concerns.*
# Implicit Returns in CoffeeScript
This error can occur more frequently when using CoffeeScript, which has a feature called implicit
returns. This language feature returns the last dereferenced object in the function when the
function has no explicit return statement.
The solution in this scenario is to add an explicit return statement. For example `return false` to
the function.
+17
View File
@@ -0,0 +1,17 @@
@ngdoc error
@name $parse:isecff
@fullName Referencing 'call', 'apply' and 'bind' Disallowed
@description
Occurs when an expression attempts to invoke Function's 'call', 'apply' or 'bind'.
Angular bans the invocation of 'call', 'apply' and 'bind' from within expressions
since access is a known way to modify the behaviour of existing functions.
To resolve this error, avoid using these methods in expressions.
Example expression that would result in this error:
```
<div>{{user.sendInfo.call({}, true)}}</div>
```
+17 -8
View File
@@ -1,18 +1,27 @@
@ngdoc error
@name $parse:isecfld
@fullName Referencing 'constructor' Field in Expression
@fullName Referencing Disallowed Field in Expression
@description
Occurs when an expression attempts to access an objects constructor field.
Occurs when an expression attempts to access one of the following fields:
AngularJS bans constructor access from within expressions since constructor
access is a known way to execute arbitrary Javascript code.
* __proto__
* __defineGetter__
* __defineSetter__
* __lookupGetter__
* __lookupSetter__
To resolve this error, avoid constructor access. As a last resort, alias
the constructor and access it through the alias instead.
AngularJS bans access to these fields from within expressions since
access is a known way to mess with native objects or
to execute arbitrary Javascript code.
Example expression that would result in this error:
To resolve this error, avoid using these fields in expressions. As a last resort,
alias their value and access them through the alias instead.
Example expressions that would result in this error:
```
<div>{{user.constructor.name}}</div>
<div>{{user.__proto__.hasOwnProperty = $emit}}</div>
<div>{{user.__defineGetter__('name', noop)}}</div>
```
+11
View File
@@ -0,0 +1,11 @@
@ngdoc error
@name $parse:isecobj
@fullName Referencing Object Disallowed
@description
Occurs when an expression attempts to access the 'Object' object (Root object in JavaScript).
Angular bans access to Object from within expressions since access is a known way to modify
the behaviour of existing objects.
To resolve this error, avoid Object access.
+1 -1
View File
@@ -5,4 +5,4 @@
Occurs when you try to use the name `hasOwnProperty` as a name of a parameter.
Generally, a name cannot be `hasOwnProperty` because it is used, internally, on a object
and allowing such a name would break lookups on this object.
and allowing such a name would break lookups on this object.
+280 -42
View File
@@ -3,72 +3,310 @@
@fullName Action Already In Progress
@description
At any point in time there can be only one `$digest` or $apply operation in progress.
The stack trace of this error allows you to trace the origin of the currently executing $apply or $digest call.
At any point in time there can be only one `$digest` or `$apply` operation in progress. This is to
prevent very hard to detect bugs from entering your application. The stack trace of this error
allows you to trace the origin of the currently executing `$apply` or `$digest` call, which caused
the error.
`$digest` or `$apply` are processing operational states of the Scope - data-structure in Angular that provides context for models and enables model mutation observation.
## Background
Trying to reenter a `$digest` or `$apply` while one of them is already in progress is typically a sign of programming error that needs to be fixed.
Angular uses a dirty-checking digest mechanism to monitor and update values of the scope during
the processing of your application. The digest works by checking all the values that are being
watched against their previous value and running any watch handlers that have been defined for those
values that have changed.
This digest mechanism is triggered by calling `$digest` on a scope object. Normally you do not need
to trigger a digest manually, because every external action that can trigger changes in your
application, such as mouse events, timeouts or server responses, wrap the Angular application code
in a block of code that will run `$digest` when the code completes.
You wrap Angular code in a block that will be followed by a `$digest` by calling `$apply` on a scope
object. So, in pseudo-code, the process looks like this:
```
element.on('mouseup', function() {
scope.$apply(function() {
$scope.doStuff();
});
});
```
where `$apply()` looks something like:
```
$apply = function(fn) {
try {
fn();
} finally() {
$digest();
}
}
```
## Digest Phases
Angular keeps track of what phase of processing we are in, the relevant ones being `$apply` and
`$digest`. Trying to reenter a `$digest` or `$apply` while one of them is already in progress is
typically a sign of programming error that needs to be fixed. So Angular will throw this error when
that occurs.
In most situations it should be well defined whether a piece of code will be run inside an `$apply`,
in which case you should not be calling `$apply` or `$digest`, or it will be run outside, in which
case you should wrap any code that will be interacting with Angular scope or services, in a call to
`$apply`.
As an example, all Controller code should expect to be run within Angular, so it should have no need
to call `$apply` or `$digest`. Conversely, code that is being trigger directly as a call back to
some external event, from the DOM or 3rd party library, should expect that it is never called from
within Angular, and so any Angular application code that it calls should first be wrapped in a call
to $apply.
## Common Causes
Apart from simply incorrect calls to `$apply` or `$digest` there are some cases when you may get
this error through no fault of your own.
### Inconsistent API (Sync/Async)
This error is often seen when interacting with an API that is sometimes sync and sometimes async.
For example:
For example, imagine a 3rd party library that has a method which will retrieve data for us. Since it
may be making an asynchronous call to a server, it accepts a callback function, which will be called
when the data arrives.
```
function MyController() {
function MyController($scope, thirdPartyComponent) {
thirdPartyComponent.getData(function(someData) {
scope.$apply(function() {
scope.someData = someData;
$scope.$apply(function() {
$scope.someData = someData;
});
});
}
```
The controller constructor is always instantiated from within an $apply cycle, so if the third-party component called our callback synchronously, we'd be trying to enter the $apply again.
We expect that our callback will be called asynchronously, and so from outside Angular. Therefore, we
correctly wrap our application code that interacts with Angular in a call to `$apply`.
To resolve this type of issue, either fix the api to be always synchronous or asynchronous or wrap the call to the api with setTimeout call to make it always asynchronous.
The problem comes if `getData()` decides to call the callback handler synchronously; perhaps it has
the data already cached in memory and so it immediately calls the callback to return the data,
synchronously.
Since, the `MyController` constructor is always instantiated from within an `$apply` call, our
handler is trying to enter a new `$apply` block from within one.
Other situation that leads to this error is when you are trying to reuse a function to by using it as a callback for code that is called by various apis inside and outside of $apply.
This is not an ideal design choice on the part of the 3rd party library.
For example:
To resolve this type of issue, either fix the api to be always synchronous or asynchronous or force
your callback handler to always run asynchronously by using the `$timeout` service.
```
myApp.directive('myDirective', function() {
function MyController($scope, thirdPartyComponent) {
thirdPartyComponent.getData(function(someData) {
$timeout(function() {
$scope.someData = someData;
}, 0);
});
}
```
Here we have used `$timeout` to schedule the changes to the scope in a future call stack.
By providing a timeout period of 0ms, this will occur as soon as possible and `$timeout` will ensure
that the code will be called in a single `$apply` block.
### Triggering Events Programmatically
The other situation that often leads to this error is when you trigger code (such as a DOM event)
programmatically (from within Angular), which is normally called by an external trigger.
For example, consider a directive that will set focus on an input control when a value in the scope
is true:
```
myApp.directive('setFocusIf', function() {
return {
link: function($scope, $element) {
function doSomeWork() {
$scope.$apply(function() {
// do work here, and update the model
};
}
$element.on('click', doSomeWork);
doSomeWork(); // << this will throw an exception because templates are compiled within $apply
}
}
});
```
The fix for the example above looks like this:
```
myApp.directive('myDirective', function() {
return {
link: function($scope, $element) {
function doSomeWork() {
// do work here, and update the model
}
$element.on('click', function() {
$scope.$apply(doSomeWork); // <<< the $apply call was moved to the callsite that doesn't execute in $apply call already
link: function($scope, $element, $attr) {
$scope.$watch($attr.setFocusIf, function(value) {
if ( value ) { $element[0].focus(); }
});
}
};
});
```
doSomeWork();
If we applied this directive to an input which also used the `ngFocus` directive to trigger some
work when the element receives focus we will have a problem:
```
<input set-focus-if="hasFocus" ng-focus="msg='has focus'">
<button ng-click="hasFocus = true">Focus</button>
```
In this setup, there are two ways to trigger ngFocus. First from a user interaction:
* Click on the input control
* The input control gets focus
* The `ngFocus` directive is triggered, setting `$scope.msg='has focus'` from within a new call to
`$apply()`
Second programmatically:
* Click the button
* The `ngClick` directive sets the value of `$scope.hasFocus` to true inside a call to `$apply`
* The `$digest` runs, which triggers the watch inside the `setFocusIf` directive
* The watch's handle runs, which gives the focus to the input
* The `ngFocus` directive is triggered, setting `$scope.msg='has focus'` from within a new call to
`$apply()`
In this second scenario, we are already inside a `$digest` when the ngFocus directive makes another
call to `$apply()`, causing this error to be thrown.
It is possible to workaround this problem by moving the call to set the focus outside of the digest,
by using `$timeout(fn, 0, false)`, where the `false` value tells Angular not to wrap this `fn` in a
`$apply` block:
```
myApp.directive('setFocusIf', function($timeout) {
return {
link: function($scope, $element, $attr) {
$scope.$watch($attr.setFocusIf, function(value) {
if ( value ) {
$timeout(function() {
// We must reevaluate the value in case it was changed by a subsequent
// watch handler in the digest.
if ( $scope.$eval($attr.setFocusIf) ) {
$element[0].focus();
}
}, 0, false);
}
});
}
}
});
```
To learn more about Angular processing model please check out the {@link guide/concepts concepts doc} as well as the {@link ng.$rootScope.Scope api} doc.
## Diagnosing This Error
When you get this error it can be rather daunting to diagnose the cause of the issue. The best
course of action is to investigate the stack trace from the error. You need to look for places
where `$apply` or `$digest` have been called and find the context in which this occurred.
There should be two calls:
* The first call is the good `$apply`/`$digest` and would normally be triggered by some event near
the top of the call stack.
* The second call is the bad `$apply`/`$digest` and this is the one to investigate.
Once you have identified this call you work your way up the stack to see what the problem is.
* If the second call was made in your application code then you should look at why this code has been
called from within a `$apply`/`$digest`. It may be a simple oversight or maybe it fits with the
sync/async scenario described earlier.
* If the second call was made inside an Angular directive then it is likely that it matches the second
programmatic event trigger scenario described earlier. In this case you may need to look further up
the tree to what triggered the event in the first place.
### Example Problem
Let's look at how to investigate this error using the `setFocusIf` example from above. This example
defines a new `setFocusIf` directive that sets the focus on the element where it is defined when the
value of its attribute becomes true.
<example name="error-$rootScope-inprog" module="app">
<file name="index.html">
<button ng-click="focusInput = true">Focus</button>
<input ng-focus="count = count + 1" set-focus-if="focusInput" />
</file>
<file name="app.js">
angular.module('app', []).directive('setFocusIf', function() {
return function link($scope, $element, $attr) {
$scope.$watch($attr.setFocusIf, function(value) {
if ( value ) { $element[0].focus(); }
});
};
});
</file>
</example>
When you click on the button to cause the focus to occur we get our `$rootScope:inprog` error. The
stacktrace looks like this:
```
Error: [$rootScope:inprog]
at Error (native)
at angular.min.js:6:467
at n (angular.min.js:105:60)
at g.$get.g.$apply (angular.min.js:113:195)
at HTMLInputElement.<anonymous> (angular.min.js:198:401)
at angular.min.js:32:32
at Array.forEach (native)
at q (angular.min.js:7:295)
at HTMLInputElement.c (angular.min.js:32:14)
at Object.fn (app.js:12:38) angular.js:10111
(anonymous function) angular.js:10111
$get angular.js:7412
$get.g.$apply angular.js:12738 <--- $apply
(anonymous function) angular.js:19833 <--- called here
(anonymous function) angular.js:2890
q angular.js:320
c angular.js:2889
(anonymous function) app.js:12
$get.g.$digest angular.js:12469
$get.g.$apply angular.js:12742 <--- $apply
(anonymous function) angular.js:19833 <--- called here
(anonymous function) angular.js:2890
q angular.js:320
```
We can see (even though the Angular code is minified) that there were two calls to `$apply`, first
on line `19833`, then on line `12738` of `angular.js`.
It is this second call that caused the error. If we look at the angular.js code, we can see that
this call is made by an Angular directive.
```
var ngEventDirectives = {};
forEach(
'click dblclick mousedown mouseup mouseover mouseout mousemove mouseenter mouseleave keydown keyup keypress submit focus blur copy cut paste'.split(' '),
function(name) {
var directiveName = directiveNormalize('ng-' + name);
ngEventDirectives[directiveName] = ['$parse', function($parse) {
return {
compile: function($element, attr) {
var fn = $parse(attr[directiveName]);
return function(scope, element, attr) {
element.on(lowercase(name), function(event) {
scope.$apply(function() {
fn(scope, {$event:event});
});
});
};
}
};
}];
}
);
```
It is not possible to tell which from the stack trace, but we happen to know in this case that it is
the `ngFocus` directive.
Now look up the stack to see that our application code is only entered once in `app.js` at line `12`.
This is where our problem is:
```
10: link: function($scope, $element, $attr) {
11: $scope.$watch($attr.setFocusIf, function(value) {
12: if ( value ) { $element[0].focus(); } <---- This is the source of the problem
13: });
14: }
```
We can now see that the second `$apply` was caused by us programmatically triggering a DOM event
(i.e. focus) to occur. We must fix this by moving the code outside of the $apply block using
`$timeout` as described above.
## Further Reading
To learn more about Angular processing model please check out the
{@link guide/concepts concepts doc} as well as the {@link ng.$rootScope.Scope api} doc.
+3 -3
View File
@@ -15,9 +15,9 @@ By default, only URLs that belong to the same origin are trusted. These are urls
The {@link ng.directive:ngInclude ngInclude} directive and {@link guide/directive directives} that specify a `templateUrl` require a trusted resource URL.
To load templates from other domains and/or protocols, either adjust the {@link
api/ng.$sceDelegateProvider#resourceUrlWhitelist whitelist}/ {@link
api/ng.$sceDelegateProvider#resourceUrlBlacklist blacklist} or wrap the URL with a call to {@link
api/ng.$sce#trustAsResourceUrl $sce.trustAsResourceUrl}.
ng.$sceDelegateProvider#resourceUrlWhitelist whitelist}/ {@link
ng.$sceDelegateProvider#resourceUrlBlacklist blacklist} or wrap the URL with a call to {@link
ng.$sce#trustAsResourceUrl $sce.trustAsResourceUrl}.
**Note**: The browser's [Same Origin
Policy](https://code.google.com/p/browsersec/wiki/Part2#Same-origin_policy_for_XMLHttpRequest) and
+3 -2
View File
@@ -10,6 +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.
+1 -1
View File
@@ -5,4 +5,4 @@
AngularJS often asserts that certain values will be present and truthy using a
helper function. If the assertion fails, this error is thrown. To fix this problem,
make sure that the value the assertion expects is defined and truthy.
make sure that the value the assertion expects is defined and truthy.
+1 -1
View File
@@ -5,4 +5,4 @@
Occurs when you try to use the name `hasOwnProperty` in a context where it is not allow.
Generally, a name cannot be `hasOwnProperty` because it is used, internally, on a object
and allowing such a name would break lookups on this object.
and allowing such a name would break lookups on this object.
+1 -1
View File
@@ -49,4 +49,4 @@ You can also get this error if you accidentally load AngularJS itself more than
<script src="angular.js"></script>
</body>
</html>
```
```
+1 -1
View File
@@ -7,4 +7,4 @@ This error occurs when attempting to copy an object to itself. Calling {@link
api/angular.copy angular.copy} with a `destination` object deletes
all of the elements or properties on `destination` before copying to it. Copying
an object to itself is not supported. Make sure to check your calls to
`angular.copy` and avoid copying objects or arrays to themselves.
`angular.copy` and avoid copying objects or arrays to themselves.
+1 -1
View File
@@ -7,4 +7,4 @@ Copying Window or Scope instances is not supported because of cyclical and self
references. Avoid copying windows and scopes, as well as any other cyclical or
self-referential structures. Note that trying to deep copy an object containing
cyclical references that is neither a window nor a scope will cause infinite
recursion and a stack overflow.
recursion and a stack overflow.
+300 -108
View File
@@ -1,5 +1,6 @@
@ngdoc overview
@name Using $location
@sortOrder 500
@description
# What does it do?
@@ -60,7 +61,7 @@ changes to $location are reflected into the browser address bar.
<tr>
<td class="head">aware of docroot/context from which the application is loaded</td>
<td>no - window.location.path returns "/docroot/actual/path"</td>
<td>no - window.location.pathname returns "/docroot/actual/path"</td>
<td>yes - $location.path() returns "/actual/path"</td>
</tr>
@@ -358,118 +359,308 @@ Note that when you type hashbang url into first browser (or vice versa) it doesn
redirect to regular / hashbang url, as this conversion happens only during parsing the initial URL
= on page reload.
In this examples we use `<base href="/base/index.html" />`
<example>
In these examples we use `<base href="/base/index.html" />`
#### Browser in HTML5 mode
<example module="html5-mode" name="location-html5-mode">
<file name="index.html">
<div id="html5-mode" ng-controller="Html5Cntl">
<h3>Browser with History API</h3>
<div ng-address-bar browser="html5"></div><br><br>
$location.protocol() = {{$location.protocol()}}<br>
$location.host() = {{$location.host()}}<br>
$location.port() = {{$location.port()}}<br>
$location.path() = {{$location.path()}}<br>
$location.search() = {{$location.search()}}<br>
$location.hash() = {{$location.hash()}}<br>
<a href="http://www.example.com/base/first?a=b">/base/first?a=b</a> |
<a href="http://www.example.com/base/sec/ond?flag#hash">sec/ond?flag#hash</a> |
<a href="/other-base/another?search">external</a>
</div>
<div id="hashbang-mode" ng-controller="HashbangCntl">
<h3>Browser without History API</h3>
<div ng-address-bar browser="hashbang"></div><br><br>
$location.protocol() = {{$location.protocol()}}<br>
$location.host() = {{$location.host()}}<br>
$location.port() = {{$location.port()}}<br>
$location.path() = {{$location.path()}}<br>
$location.search() = {{$location.search()}}<br>
$location.hash() = {{$location.hash()}}<br>
<a href="http://www.example.com/base/first?a=b">/base/first?a=b</a> |
<a href="http://www.example.com/base/sec/ond?flag#hash">sec/ond?flag#hash</a> |
<a href="/other-base/another?search">external</a>
<div ng-controller="LocationController">
<div ng-address-bar></div><br><br>
<div>
$location.protocol() = <span ng-bind="$location.protocol()"></span> <br>
$location.host() = <span ng-bind="$location.host()"></span> <br>
$location.port() = <span ng-bind="$location.port()"></span> <br>
$location.path() = <span ng-bind="$location.path()"></span> <br>
$location.search() = <span ng-bind="$location.search()"></span> <br>
$location.hash() = <span ng-bind="$location.hash()"></span> <br>
</div>
<div id="navigation">
<a href="http://www.example.com/base/first?a=b">/base/first?a=b</a> |
<a href="http://www.example.com/base/sec/ond?flag#hash">sec/ond?flag#hash</a> |
<a href="/other-base/another?search">external</a>
</div>
</div>
</file>
<file name="app.js">
angular.module('html5-mode', ['fake-browser', 'address-bar'])
<file name="script.js">
function FakeBrowser(initUrl, baseHref) {
this.onUrlChange = function(fn) {
this.urlChange = fn;
.constant('initUrl', 'http://www.example.com/base/path?a=b#h')
.constant('baseHref', '/base/index.html')
.value('$sniffer', { history: true })
.controller("LocationController", function($scope, $location) {
$scope.$location = {};
angular.forEach("protocol host port path search hash".split(" "), function(method){
$scope.$location[method] = function(){
var result = $location[method].call($location);
return angular.isObject(result) ? angular.toJson(result) : result;
};
});
})
.config(function($locationProvider) {
$locationProvider.html5Mode(true).hashPrefix('!');
})
.run(function($rootElement) {
$rootElement.on('click', function(e) { e.stopPropagation(); });
});
</file>
<file name="fakeBrowser.js">
angular.module('fake-browser', [])
.config(function($provide) {
$provide.decorator('$browser', function($delegate, baseHref, initUrl) {
$delegate.onUrlChange = function(fn) {
this.urlChange = fn;
};
$delegate.url = function() {
return initUrl;
};
this.url = function() {
return initUrl;
};
$delegate.defer = function(fn, delay) {
setTimeout(function() { fn(); }, delay || 0);
};
this.defer = function(fn, delay) {
setTimeout(function() { fn(); }, delay || 0);
};
$delegate.baseHref = function() {
return baseHref;
};
this.baseHref = function() {
return baseHref;
};
return $delegate;
});
});
</file>
this.notifyWhenOutstandingRequests = angular.noop;
}
<file name="addressBar.js">
angular.module('address-bar', [])
.directive('ngAddressBar', function($browser, $timeout) {
return {
template: 'Address: <input id="addressBar" type="text" style="width: 400px" >',
link: function(scope, element, attrs){
var input = element.children("input"), delay;
var browsers = {
html5: new FakeBrowser('http://www.example.com/base/path?a=b#h', '/base/index.html'),
hashbang: new FakeBrowser('http://www.example.com/base/index.html#!/path?a=b#h', '/base/index.html')
};
input.on('keypress keyup keydown', function(event) {
delay = (!delay ? $timeout(fireUrlChange, 250) : null);
event.stopPropagation();
})
.val($browser.url());
function Html5Cntl($scope, $location) {
$scope.$location = $location;
}
function HashbangCntl($scope, $location) {
$scope.$location = $location;
}
function initEnv(name) {
var root = angular.element(document.getElementById(name + '-mode'));
// We must kill a link to the injector for this element otherwise angular will
// complain that it has been bootstrapped already.
root.data('$injector', null);
angular.bootstrap(root, [function($compileProvider, $locationProvider, $provide){
$locationProvider.html5Mode(true).hashPrefix('!');
$provide.value('$browser', browsers[name]);
$provide.value('$sniffer', {history: name == 'html5'});
$compileProvider.directive('ngAddressBar', function() {
return function(scope, elm, attrs) {
var browser = browsers[attrs.browser],
input = angular.element('<input type="text" style="width: 400px">').val(browser.url()),
delay;
input.on('keypress keyup keydown', function() {
if (!delay) {
delay = setTimeout(fireUrlChange, 250);
}
});
browser.url = function(url) {
return input.val(url);
};
elm.append('Address: ').append(input);
function fireUrlChange() {
delay = null;
browser.urlChange(input.val());
}
$browser.url = function(url) {
return url ? input.val(url) : input.val();
};
});
}]);
root.on('click', function(e) {
e.stopPropagation();
});
}
initEnv('html5');
initEnv('hashbang');
function fireUrlChange() {
delay = null;
$browser.urlChange(input.val());
}
}
};
});
</file>
<file name="protractor.js" type="protractor">
var addressBar = element(by.css("#addressBar")),
url = 'http://www.example.com/base/path?a=b#h';
it("should show fake browser info on load", function(){
expect(addressBar.getAttribute('value')).toBe(url);
expect(element(by.binding('$location.protocol')).getText()).toBe('http');
expect(element(by.binding('$location.host')).getText()).toBe('www.example.com');
expect(element(by.binding('$location.port')).getText()).toBe('80');
expect(element(by.binding('$location.path')).getText()).toBe('/path');
expect(element(by.binding('$location.search')).getText()).toBe('{"a":"b"}');
expect(element(by.binding('$location.hash')).getText()).toBe('h');
});
it("should change $location accordingly", function(){
var navigation = element.all(by.css("#navigation a"));
navigation.get(0).click();
expect(addressBar.getAttribute('value')).toBe("http://www.example.com/base/first?a=b");
expect(element(by.binding('$location.protocol')).getText()).toBe('http');
expect(element(by.binding('$location.host')).getText()).toBe('www.example.com');
expect(element(by.binding('$location.port')).getText()).toBe('80');
expect(element(by.binding('$location.path')).getText()).toBe('/first');
expect(element(by.binding('$location.search')).getText()).toBe('{"a":"b"}');
expect(element(by.binding('$location.hash')).getText()).toBe('');
navigation.get(1).click();
expect(addressBar.getAttribute('value')).toBe("http://www.example.com/base/sec/ond?flag#hash");
expect(element(by.binding('$location.protocol')).getText()).toBe('http');
expect(element(by.binding('$location.host')).getText()).toBe('www.example.com');
expect(element(by.binding('$location.port')).getText()).toBe('80');
expect(element(by.binding('$location.path')).getText()).toBe('/sec/ond');
expect(element(by.binding('$location.search')).getText()).toBe('{"flag":true}');
expect(element(by.binding('$location.hash')).getText()).toBe('hash');
});
</file>
</example>
####Browser in HTML5 Fallback mode (Hashbang mode)
<example module="hashbang-mode" name="location-hashbang-mode">
<file name="index.html">
<div ng-controller="LocationController">
<div ng-address-bar></div><br><br>
<div>
$location.protocol() = <span ng-bind="$location.protocol()"></span> <br>
$location.host() = <span ng-bind="$location.host()"></span> <br>
$location.port() = <span ng-bind="$location.port()"></span> <br>
$location.path() = <span ng-bind="$location.path()"></span> <br>
$location.search() = <span ng-bind="$location.search()"></span> <br>
$location.hash() = <span ng-bind="$location.hash()"></span> <br>
</div>
<div id="navigation">
<a href="http://www.example.com/base/first?a=b">/base/first?a=b</a> |
<a href="http://www.example.com/base/sec/ond?flag#hash">sec/ond?flag#hash</a> |
<a href="/other-base/another?search">external</a>
</div>
</div>
</file>
<file name="app.js">
angular.module('hashbang-mode', ['fake-browser', 'address-bar'])
.constant('initUrl', 'http://www.example.com/base/index.html#!/path?a=b#h')
.constant('baseHref', '/base/index.html')
.value('$sniffer', { history: false })
.config(function($locationProvider) {
$locationProvider.html5Mode(true).hashPrefix('!');
})
.controller("LocationController", function($scope, $location) {
$scope.$location = {};
angular.forEach("protocol host port path search hash".split(" "), function(method){
$scope.$location[method] = function(){
var result = $location[method].call($location);
return angular.isObject(result) ? angular.toJson(result) : result;
};
});
})
.run(function($rootElement) {
$rootElement.on('click', function(e) {
e.stopPropagation();
});
});
</file>
<file name="fakeBrowser.js">
angular.module('fake-browser', [])
.config(function($provide) {
$provide.decorator('$browser', function($delegate, baseHref, initUrl) {
$delegate.onUrlChange = function(fn) {
this.urlChange = fn;
};
$delegate.url = function() {
return initUrl;
};
$delegate.defer = function(fn, delay) {
setTimeout(function() { fn(); }, delay || 0);
};
$delegate.baseHref = function() {
return baseHref;
};
return $delegate;
});
});
</file>
<file name="addressBar.js">
angular.module('address-bar', [])
.directive('ngAddressBar', function($browser, $timeout) {
return {
template: 'Address: <input id="addressBar" type="text" style="width: 400px" >',
link: function(scope, element, attrs){
var input = element.children("input"), delay;
input.on('keypress keyup keydown', function(event) {
delay = (!delay ? $timeout(fireUrlChange, 250) : null);
event.stopPropagation();
})
.val($browser.url());
$browser.url = function(url) {
return url ? input.val(url) : input.val();
};
function fireUrlChange() {
delay = null;
$browser.urlChange(input.val());
}
}
};
});
</file>
<file name="protractor.js" type="protractor">
var addressBar = element(by.css("#addressBar")),
url = 'http://www.example.com/base/index.html#!/path?a=b#h';
it("should show fake browser info on load", function(){
expect(addressBar.getAttribute('value')).toBe(url);
expect(element(by.binding('$location.protocol')).getText()).toBe('http');
expect(element(by.binding('$location.host')).getText()).toBe('www.example.com');
expect(element(by.binding('$location.port')).getText()).toBe('80');
expect(element(by.binding('$location.path')).getText()).toBe('/path');
expect(element(by.binding('$location.search')).getText()).toBe('{"a":"b"}');
expect(element(by.binding('$location.hash')).getText()).toBe('h');
});
it("should change $location accordingly", function(){
var navigation = element.all(by.css("#navigation a"));
navigation.get(0).click();
expect(addressBar.getAttribute('value')).toBe("http://www.example.com/base/index.html#!/first?a=b");
expect(element(by.binding('$location.protocol')).getText()).toBe('http');
expect(element(by.binding('$location.host')).getText()).toBe('www.example.com');
expect(element(by.binding('$location.port')).getText()).toBe('80');
expect(element(by.binding('$location.path')).getText()).toBe('/first');
expect(element(by.binding('$location.search')).getText()).toBe('{"a":"b"}');
expect(element(by.binding('$location.hash')).getText()).toBe('');
navigation.get(1).click();
expect(addressBar.getAttribute('value')).toBe("http://www.example.com/base/index.html#!/sec/ond?flag#hash");
expect(element(by.binding('$location.protocol')).getText()).toBe('http');
expect(element(by.binding('$location.host')).getText()).toBe('www.example.com');
expect(element(by.binding('$location.port')).getText()).toBe('80');
expect(element(by.binding('$location.path')).getText()).toBe('/sec/ond');
expect(element(by.binding('$location.search')).getText()).toBe('{"flag":true}');
expect(element(by.binding('$location.hash')).getText()).toBe('hash');
});
</file>
</example>
# Caveats
@@ -622,23 +813,24 @@ The Angular's compiler currently does not support two-way binding for methods (s
to the $location object (using {@link input[text] ngModel} directive on an input
field), you will need to specify an extra model property (e.g. `locationPath`) with two {@link ng.$rootScope.Scope#$watch $watchers}
which push $location updates in both directions. For example:
<example>
<example module="locationExample">
<file name="index.html">
<div ng-controller="LocationController">
<input type="text" ng-model="locationPath" />
</div>
</file>
<file name="script.js">
function LocationController($scope, $location) {
$scope.$watch('locationPath', function(path) {
$location.path(path);
});
$scope.$watch(function() {
return $location.path();
}, function(path) {
$scope.locationPath = path;
});
}
angular.module('locationExample', [])
.controller('LocationController', ['$scope', '$location', function ($scope, $location) {
$scope.$watch('locationPath', function(path) {
$location.path(path);
});
$scope.$watch(function() {
return $location.path();
}, function(path) {
$scope.locationPath = path;
});
}]);
</file>
</example>
+1
View File
@@ -1,5 +1,6 @@
@ngdoc overview
@name Animations
@sortOrder 310
@description
+3 -2
View File
@@ -1,5 +1,6 @@
@ngdoc overview
@name Bootstrap
@sortOrder 350
@description
# Bootstrap
@@ -90,8 +91,8 @@ Here is an example of manually initializing Angular:
<!doctype html>
<html>
<body>
Hello {{'World'}}!
<script src="http://code.angularjs.org/angular.js"></script>
Hello {{greetMe}}!
<script src="http://code.angularjs.org/snapshot/angular.js"></script>
<script>
angular.module('myApp', [])
+4 -3
View File
@@ -1,5 +1,6 @@
@ngdoc overview
@name HTML Compiler
@sortOrder 330
@description
<div class="alert alert-warning">
@@ -198,7 +199,7 @@ This should help give you an idea of what Angular does internally.
// Step 3: link the compiled template with the scope.
var element = linkFn(scope);
// Step 4: Append to DOM (optional)
parent.appendChild(element);
```
@@ -226,7 +227,7 @@ moved to the compile function for performance reasons.
To understand, let's look at a real-world example with `ngRepeat`:
```html
Hello {{user}}, you have these actions:
Hello {{user.name}}, you have these actions:
<ul>
<li ng-repeat="action in user.actions">
{{action.description}}
@@ -236,7 +237,7 @@ Hello {{user}}, you have these actions:
When the above example is compiled, the compiler visits every node and looks for directives.
`{{user}}` matches the {@link ng.$interpolate interpolation directive}
`{{user.name}}` matches the {@link ng.$interpolate interpolation directive}
and `ng-repeat` matches the {@link ng.directive:ngRepeat `ngRepeat` directive}.
But {@link ng.directive:ngRepeat ngRepeat} has a dilemma.
+6 -8
View File
@@ -1,5 +1,6 @@
@ngdoc overview
@name Conceptual Overview
@sortOrder 200
@description
# Conceptual Overview
@@ -37,10 +38,10 @@ Let's start with input fields for quantity and cost whose values are multiplied
<div ng-app ng-init="qty=1;cost=2">
<b>Invoice:</b>
<div>
Quantity: <input type="number" ng-model="qty" required >
Quantity: <input type="number" ng-model="qty">
</div>
<div>
Costs: <input type="number" ng-model="cost" required >
Costs: <input type="number" ng-model="cost">
</div>
<div>
<b>Total:</b> {{qty * cost | currency}}
@@ -62,11 +63,8 @@ The first kind of new markup are the so called <a name="directive">"{@link direc
They apply special behavior to attributes or elements in the HTML. In the example above we use the
{@link ng.directive:ngApp `ng-app`} attribute, which is linked to a directive that automatically
initializes our application. Angular also defines a directive for the {@link ng.directive:input `input`}
element that adds extra behavior to the element. E.g. it is able to automatically validate that the entered
text is non empty by evaluating the `required` attribute.
The {@link ng.directive:ngModel `ng-model`} directive stores/updates
the value of the input field into/from a variable and shows the validation state of the input field by
adding css classes. In the example we use these css classes to mark an empty input field with a red border.
element that adds extra behavior to the element. The {@link ng.directive:ngModel `ng-model`} directive
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
@@ -323,7 +321,7 @@ The following example shows how this is done with Angular:
angular.module('finance3', [])
.factory('currencyConverter', ['$http', function($http) {
var YAHOO_FINANCE_URL_PATTERN =
'http://query.yahooapis.com/v1/public/yql?q=select * from '+
'//query.yahooapis.com/v1/public/yql?q=select * from '+
'yahoo.finance.xchange where pair in ("PAIRS")&format=json&'+
'env=store://datatables.org/alltableswithkeys&callback=JSON_CALLBACK';
var currencies = ['USD', 'EUR', 'CNY'];
+19 -25
View File
@@ -1,5 +1,6 @@
@ngdoc overview
@name Controllers
@sortOrder 220
@description
# Understanding Controllers
@@ -37,27 +38,8 @@ The properties contain the **view model** (the model that will be presented by t
`$scope` properties will be available to the template at the point in the DOM where the Controller
is registered.
The following example shows a very simple constructor function for a Controller, `GreetingController`,
which attaches a `greeting` property containing the string `'Hola!'` to the `$scope`:
```js
function GreetingController($scope) {
$scope.greeting = 'Hola!';
}
```
Once the Controller has been attached to the DOM, the `greeting` property can be data-bound to the
template:
```js
<div ng-controller="GreetingController">
{{ greeting }}
</div>
```
**NOTE**: Although Angular allows you to create Controller functions in the global scope, this is
not recommended. In a real application you should use the `.controller` method of your
{@link module Angular Module} for your application as follows:
The following example demonstrates creating a `GreetingController`, which attaches a `greeting`
property containing the string `'Hola!'` to the `$scope`:
```js
var myApp = angular.module('myApp',[]);
@@ -67,9 +49,24 @@ myApp.controller('GreetingController', ['$scope', function($scope) {
}]);
```
We create an {@link module Angular Module}, `myApp`, for our application. Then we add the controller's
constructor function to the module using the `.controller()` method. This keeps the controller's
constructor function out of the global scope.
<div class="alert alert-info">
We have used an **inline injection annotation** to explicitly specify the dependency
of the Controller on the `$scope` service provided by Angular. See the guide on
[Dependency Injection](http://docs.angularjs.org/guide/di) for more information.
{@link guide/di Dependency Injection} for more information.
</div>
We attach our controller to the DOM using the `ng-controller` directive. The `greeting` property can
now be data-bound to the template:
```js
<div ng-controller="GreetingController">
{{ greeting }}
</div>
```
# Adding Behavior to a Scope Object
@@ -333,6 +330,3 @@ describe('state', function() {
});
});
```
+1
View File
@@ -1,5 +1,6 @@
@ngdoc overview
@name Working With CSS
@sortOrder 510
@description
+3 -2
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
@@ -9,7 +10,7 @@ When the model changes, the view reflects the change, and vice versa.
## Data Binding in Classical Template Systems
<img class="right" src="img/One_Way_Data_Binding.png"/>
<img class="right" src="img/One_Way_Data_Binding.png"/><br />
Most templating systems bind data in only one direction: they merge template and model components
together into a view. After the merge occurs, changes to the model
or related sections of the view are NOT automatically reflected in the view. Worse, any changes
@@ -18,7 +19,7 @@ to write code that constantly syncs the view with the model and the model with t
## Data Binding in Angular Templates
<img class="right" src="img/Two_Way_Data_Binding.png"/>
<img class="right" src="img/Two_Way_Data_Binding.png"/><br />
Angular templates work differently. First the template (which is the uncompiled HTML along with
any additional markup or directives) is compiled on the browser. The compilation step produces a
live view. Any changes to the view are immediately reflected in the model, and any changes in
+20 -12
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
@@ -218,15 +219,22 @@ DI is pervasive throughout Angular. You can use it when defining components or w
and `config` blocks for a module.
- Components such as services, directives, filters and animations are defined by an injectable factory
method or constructor function. These components can be injected with "service" components as
dependencies.
- The `run` and `config` methods accept a function, which can also be injected with "service"
method or constructor function. These components can be injected with "service" and "value"
components as dependencies.
- The `run` method accepts a function, which can be injected with "service", "value" and "constant"
components as dependencies. Note that you cannot inject "providers" into `run` blocks.
- The `config` method accepts a function, which can be injected with "provider" and "constant"
components as dependencies. Note that you cannot inject "service" or "value" components into
configuration
- Controllers are defined by a constructor function, which can be injected with any of the "service"
components as dependencies, but they can also be provided with special dependencies. See "DI in
Controllers" below.
and "value" components as dependencies, but they can also be provided with special dependencies. See
{@link di#controllers Controllers} below for a list of these special dependencies.
See {@link module#module-loading-dependencies Modules} for more details about injecting dependencies
into `run` and `config` blocks.
### Factory Methods
+27 -3
View File
@@ -1,5 +1,6 @@
@ngdoc overview
@name Directives
@sortOrder 300
@description
# Creating Custom Directives
@@ -352,7 +353,7 @@ element as a customer component.
Our `myCustomer` directive above is great, but it has a fatal flaw. We can only use it once within a
given scope.
In its current implementation, we'd need to create a different controller each time In order to
In its current implementation, we'd need to create a different controller each time in order to
re-use such a directive:
<example module="docsScopeProblemExample">
@@ -475,7 +476,6 @@ within our directive's template:
angular.module('docsIsolationExample', [])
.controller('Controller', ['$scope', function($scope) {
$scope.naomi = { name: 'Naomi', address: '1600 Amphitheatre' };
$scope.vojta = { name: 'Vojta', address: '3456 Somewhere Else' };
}])
.directive('myCustomer', function() {
@@ -537,7 +537,7 @@ where:
In our `link` function, we want to update the displayed time once a second, or whenever a user
changes the time formatting string that our directive binds to. We will use the `$interval` service
to call a handler on a regular basis. This is easier than using `$timeout` but also works better with
end-to-end testing, where we want to ensure that all $timeouts have completed before completing the test.
end-to-end testing, where we want to ensure that all `$timeout`s have completed before completing the test.
We also want to remove the `$interval` if the directive is deleted so we don't introduce a memory leak.
<example module="docsTimeDirective">
@@ -910,6 +910,30 @@ Looking back at `myPane`'s definition, notice the last argument in its `link` fu
When a directive requires a controller, it receives that controller as the fourth argument of its
`link` function. Taking advantage of this, `myPane` can call the `addPane` function of `myTabs`.
If multiple controllers are required, the `require` option of the directive can take an array argument.
The corresponding parameter being sent to the `link` function will also be an array.
```js
angular.module('docsTabsExample', [])
.directive('myPane', function() {
return {
require: ['^myTabs', '^ngModel'],
restrict: 'E',
transclude: true,
scope: {
title: '@'
},
link: function(scope, element, attrs, controllers) {
var tabsCtrl = controllers[0],
modelCtrl = controllers[1];
tabsCtrl.addPane(scope);
},
templateUrl: 'my-pane.html'
};
});
```
Savvy readers may be wondering what the difference is between `link` and `controller`.
The basic difference is that `controller` can expose an API, and `link` functions can interact with
controllers using `require`.
+1 -1
View File
@@ -1,6 +1,6 @@
@workInProgress
@ngdoc overview
@name E2E Testing
@sortOrder 420
@description
# E2E Testing
+27 -22
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">
@@ -50,9 +53,9 @@ the method from your view. If you want to `eval()` an Angular expression yoursel
You can try evaluating different expressions here:
<example>
<example module="expressionExample">
<file name="index.html">
<div ng-controller="Cntl2" class="expressions">
<div ng-controller="ExampleController" class="expressions">
Expression:
<input type='text' ng-model="expr" size="80"/>
<button ng-click="addExp(expr)">Evaluate</button>
@@ -66,23 +69,24 @@ You can try evaluating different expressions here:
</file>
<file name="script.js">
function Cntl2($scope) {
var exprs = $scope.exprs = [];
$scope.expr = '3*10|currency';
$scope.addExp = function(expr) {
exprs.push(expr);
};
angular.module('expressionExample', [])
.controller('ExampleController', ['$scope', function($scope) {
var exprs = $scope.exprs = [];
$scope.expr = '3*10|currency';
$scope.addExp = function(expr) {
exprs.push(expr);
};
$scope.removeExp = function(index) {
exprs.splice(index, 1);
};
}
$scope.removeExp = function(index) {
exprs.splice(index, 1);
};
}]);
</file>
<file name="protractor.js" type="protractor">
it('should allow user expression testing', function() {
element(by.css('.expressions button')).click();
var lis = element(by.css('.expressions ul')).element.all(by.repeater('expr in exprs'));
var lis = element(by.css('.expressions ul')).all(by.repeater('expr in exprs'));
expect(lis.count()).toBe(1);
expect(lis.get(0).getText()).toEqual('[ X ] 3*10|currency => $30.00');
});
@@ -101,9 +105,9 @@ This restriction is intentional. It prevents accidental access to the global sta
Instead use services like `$window` and `$location` in functions called from expressions. Such services
provide mockable access to globals.
<example>
<example module="expressionExample">
<file name="index.html">
<div class="example2" ng-controller="Cntl1">
<div class="example2" ng-controller="ExampleController">
Name: <input ng-model="name" type="text"/>
<button ng-click="greet()">Greet</button>
<button ng-click="window.alert('Should not see me')">Won't greet</button>
@@ -111,13 +115,14 @@ provide mockable access to globals.
</file>
<file name="script.js">
function Cntl1($window, $scope){
$scope.name = 'World';
angular.module('expressionExample', [])
.controller('ExampleController', ['$window', '$scope', function($window, $scope) {
$scope.name = 'World';
$scope.greet = function() {
$window.alert('Hello ' + $scope.name);
};
}
$scope.greet = function() {
$window.alert('Hello ' + $scope.name);
};
}]);
</file>
<file name="protractor.js" type="protractor">
+2 -1
View File
@@ -1,11 +1,12 @@
@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,
controllers or services and it is easy to define your own filter.
The underlying API is the {@link ng.$filterProvider filterProvider}.
The underlying API is the {@link ng.$filterProvider `filterProvider`}.
## Using filters in view templates
+44 -40
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.
@@ -16,9 +17,9 @@ The key directive in understanding two-way data-binding is {@link ng.directive:n
The `ngModel` directive provides the two-way data-binding by synchronizing the model to the view, as well as view to the model.
In addition it provides an {@link ngModel.NgModelController API} for other directives to augment its behavior.
<example>
<example module="formExample">
<file name="index.html">
<div ng-controller="Controller">
<div ng-controller="ExampleController">
<form novalidate class="simple-form">
Name: <input type="text" ng-model="user.name" /><br />
E-mail: <input type="email" ng-model="user.email" /><br />
@@ -32,19 +33,20 @@ In addition it provides an {@link ngModel.NgModelController API} for other direc
</div>
<script>
function Controller($scope) {
$scope.master = {};
angular.module('formExample', [])
.controller('ExampleController', ['$scope', function($scope) {
$scope.master = {};
$scope.update = function(user) {
$scope.master = angular.copy(user);
};
$scope.update = function(user) {
$scope.master = angular.copy(user);
};
$scope.reset = function() {
$scope.user = angular.copy($scope.master);
};
$scope.reset = function() {
$scope.user = angular.copy($scope.master);
};
$scope.reset();
}
$scope.reset();
}]);
</script>
</file>
</example>
@@ -67,9 +69,9 @@ The following example uses the CSS to display validity of each form control.
In the example both `user.name` and `user.email` are required, but are rendered with red background only when they are dirty.
This ensures that the user is not distracted with an error until after interacting with the control, and failing to satisfy its validity.
<example>
<example module="formExample">
<file name="index.html">
<div ng-controller="Controller">
<div ng-controller="ExampleController">
<form novalidate class="css-form">
Name:
<input type="text" ng-model="user.name" required /><br />
@@ -92,19 +94,20 @@ This ensures that the user is not distracted with an error until after interacti
</style>
<script>
function Controller($scope) {
$scope.master = {};
angular.module('formExample', [])
.controller('ExampleController', ['$scope', function($scope) {
$scope.master = {};
$scope.update = function(user) {
$scope.master = angular.copy(user);
};
$scope.update = function(user) {
$scope.master = angular.copy(user);
};
$scope.reset = function() {
$scope.user = angular.copy($scope.master);
};
$scope.reset = function() {
$scope.user = angular.copy($scope.master);
};
$scope.reset();
}
$scope.reset();
}]);
</script>
</file>
</example>
@@ -130,9 +133,9 @@ This allows us to extend the above example with these features:
- SAVE button is enabled only if form has some changes and is valid
- custom error messages for `user.email` and `user.agree`
<example>
<example module="formExample">
<file name="index.html">
<div ng-controller="Controller">
<div ng-controller="ExampleController">
<form name="form" class="css-form" novalidate>
Name:
<input type="text" ng-model="user.name" name="uName" required /><br />
@@ -159,23 +162,24 @@ This allows us to extend the above example with these features:
</file>
<file name="script.js">
function Controller($scope) {
$scope.master = {};
angular.module('formExample', [])
.controller('ExampleController', ['$scope', function($scope) {
$scope.master = {};
$scope.update = function(user) {
$scope.master = angular.copy(user);
};
$scope.update = function(user) {
$scope.master = angular.copy(user);
};
$scope.reset = function() {
$scope.user = angular.copy($scope.master);
};
$scope.reset = function() {
$scope.user = angular.copy($scope.master);
};
$scope.isUnchanged = function(user) {
return angular.equals(user, $scope.master);
};
$scope.isUnchanged = function(user) {
return angular.equals(user, $scope.master);
};
$scope.reset();
}
$scope.reset();
}]);
</file>
</example>
@@ -202,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`.
+2 -1
View File
@@ -1,5 +1,6 @@
@ngdoc overview
@name i18n and l10n
@sortOrder 520
@description
# i18n and l10n
@@ -114,7 +115,7 @@ You write the following binding using the currency filter:
If your app is currently in the `en-US` locale, the browser will show `$1000.00`. If someone in the
Japanese locale (`ja`) views your app, their browser will show a balance of `¥1000.00` instead.
This is problematinc because $1000 is not the same as ¥1000.
This is problematic because $1000 is not the same as ¥1000.
In this case, you need to override the default currency symbol by providing the
{@link ng.filter:currency} currency filter with a currency symbol as a parameter.
+1
View File
@@ -1,5 +1,6 @@
@ngdoc overview
@name Internet Explorer Compatibility
@sortOrder 530
@description
# Internet Explorer Compatibility
+4 -2
View File
@@ -47,7 +47,7 @@ In Angular applications, you move the job of filling page templates with data fr
### Testing
* **Unit testing:** [Using Karma (video)](http://www.youtube.com/watch?v=YG5DEzaQBIc), {@link guide/dev_guide.unit-testing Unit testing}, {@link guide/dev_guide.services.testing_services Testing services}, [Karma in Webstorm](http://blog.jetbrains.com/webstorm/2013/10/running-javascript-tests-with-karma-in-webstorm-7/)
* **Unit testing:** [Using Karma (video)](http://www.youtube.com/watch?v=YG5DEzaQBIc), {@link guide/unit-testing Unit testing}, {@link guide/services#unit-testing Testing services}, [Karma in Webstorm](http://blog.jetbrains.com/webstorm/2013/10/running-javascript-tests-with-karma-in-webstorm-7/)
* **Scenario testing:** [Protractor](https://github.com/angular/protractor)
## Specific Topics
@@ -73,8 +73,9 @@ This is a short list of libraries with specific support and documentation for wo
* **Internationalization:** [angular-translate](http://angular-translate.github.io), [angular-gettext](http://angular-gettext.rocketeer.be/)
* **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/)
* **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)
* **Advanced Routing:** [UI-Router](https://github.com/angular-ui/ui-router)
* **Maps:** [UI-Map (Google Maps)](https://github.com/angular-ui/ui-map)
## Deployment
@@ -112,6 +113,7 @@ This is a short list of libraries with specific support and documentation for wo
* **Free online:**
[thinkster.io](http://thinkster.io),
[CodeAcademy](http://www.codecademy.com/courses/javascript-advanced-en-2hJ3J/0/1)
[CodeSchool](https://www.codeschool.com/courses/shaping-up-with-angular-js)
* **Paid online:**
[Pluralsite (3 courses)](http://www.pluralsight.com/training/Courses/Find?highlight=true&searchTerm=angularjs),
[Tuts+](https://tutsplus.com/course/easier-js-apps-with-angular/),
+2 -1
View File
@@ -1,5 +1,6 @@
@ngdoc overview
@name Introduction
@sortOrder 100
@description
@@ -22,7 +23,7 @@ The impedance mismatch between dynamic applications and static documents is ofte
in charge and it calls into the library when it sees fit. E.g., `jQuery`.
* **frameworks** - a particular implementation of a web application, where your code fills in
the details. The framework is in charge and it calls into your code when it needs something
app specific. E.g., `knockout`, `ember`, etc.
app specific. E.g., `durandal`, `ember`, etc.
Angular takes another approach. It attempts to minimize the impedance mismatch between document
+5 -2
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
@@ -382,8 +383,6 @@ See [80739409](https://github.com/angular/angular.js/commit/807394095b991357225a
## ngBindHtmlUnsafe has been removed and replaced by ngBindHtml
`ngBindHtml` which has been moved from `ngSanitize` module to the core `ng` module.
`ngBindHtml` provides `ngBindHtmlUnsafe` like
behavior (evaluate an expression and innerHTML the result into the DOM) when bound to the result
of `$sce.trustAsHtml(string)`. When bound to a plain string, the string is sanitized via
@@ -391,6 +390,10 @@ of `$sce.trustAsHtml(string)`. When bound to a plain string, the string is sanit
module is not loaded) and the bound expression evaluates to a value that is not trusted an
exception is thrown.
When using this directive you can either include `ngSanitize` in your module's dependencis (See the
example at the {@link ngBindHtml} reference) or use the {@link $sce} service to set the value as
trusted.
See [dae69473](https://github.com/angular/angular.js/commit/dae694739b9581bea5dbc53522ec00d87b26ae55).
+34 -16
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>
@@ -45,12 +48,18 @@ I'm in a hurry. How do I get a Hello World module working?
};
});
</file>
<file name="protractor.js" type="protractor">
it('should add Hello to the name', function() {
expect(element(by.binding("{{ 'World' | greet }}")).getText()).toEqual('Hello, World!');
});
</file>
</example>
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.
@@ -75,13 +84,14 @@ The above is a suggestion. Tailor it to your needs.
<example module='xmpl'>
<file name="index.html">
<div ng-controller="XmplController">
{{ greeting }}!
{{ greeting }}
</div>
</file>
<file name="script.js">
angular.module('xmpl.service', []).
value('greeter', {
angular.module('xmpl.service', [])
.value('greeter', {
salutation: 'Hello',
localize: function(localization) {
this.salutation = localization.salutation;
@@ -89,8 +99,9 @@ The above is a suggestion. Tailor it to your needs.
greet: function(name) {
return this.salutation + ' ' + name + '!';
}
}).
value('user', {
})
.value('user', {
load: function(name) {
this.name = name;
}
@@ -100,21 +111,28 @@ The above is a suggestion. Tailor it to your needs.
angular.module('xmpl.filter', []);
angular.module('xmpl', ['xmpl.service', 'xmpl.directive', 'xmpl.filter']).
run(function(greeter, user) {
angular.module('xmpl', ['xmpl.service', 'xmpl.directive', 'xmpl.filter'])
.run(function(greeter, user) {
// This is effectively part of the main method initialization code
greeter.localize({
salutation: 'Bonjour'
});
user.load('World');
})
.controller('XmplController', function($scope, greeter, user){
$scope.greeting = greeter.greet(user.name);
});
// A Controller for your app
var XmplController = function($scope, greeter, user) {
$scope.greeting = greeter.greet(user.name);
};
</file>
<file name="protractor.js" type="protractor">
it('should add Hello to the name', function() {
expect(element(by.binding("{{ greeting }}")).getText()).toEqual('Bonjour World!');
});
</file>
</example>

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