Compare commits

...

277 Commits

Author SHA1 Message Date
Igor Minar 729fb13c9e docs(changelog): release notes for 1.2.14 feisty-cryokinesis 2014-03-01 09:51:19 -08:00
Michele Beltrame 9e16aaf3a9 docs($sce/insecurl): mention port in the same origin policy
Closes #5759

The default trusted origin appears to be the same protocol+domain+port,
non just protocol+domain.
I patched the doc accordingly.
2014-03-01 12:58:20 +01:00
Igor Minar d3fbc25be2 style: enable jscs requireRightStickedOperators rule 2014-02-28 16:47:21 -08:00
Matias Niemelä 0d034a98ec docs(forms): generated CSS classes for forms and inputs must have a ng prefix 2014-02-28 14:59:12 -05:00
Jason Winnebeck 0c8a88ba09 docs(input): update $parsers NgModelController doc
Make it clear that the result of the $parsers pipeline is what goes to the model value.

Closes #5708
2014-02-28 20:09:30 +01:00
Daniel 6b5baaddb0 docs(tutorial/step-05): fix path for 'phones.json'
Closes #5460
2014-02-28 19:10:01 +01:00
nosideeffects 9aab5bfc03 docs(ngAnimate): add missing 'super' to addClass 2014-02-28 11:37:57 -05:00
Matias Niemelä 18c41af065 fix($animate): delegate down to addClass/removeClass if setClass is not found
Closes #6463
2014-02-28 01:34:57 -05:00
Yves Brissaud 33443966c8 feat($animate): animate dirty, pristine, valid, invalid for form/fields
Add css animations when form or field status change to/from dirty,
pristine, valid or invalid. This works like animation system present
with ngClass, ngShow, etc.

Closes #5378
2014-02-28 01:01:34 -05:00
linclark 8794a173f9 docs(core): update fromJson return values
Dates are not returned, so remove Date from list of return values.

Closes #3070
2014-02-27 16:13:52 -08:00
Brian Ford 41e648a47f chore(triaging.md): update triaging guidelines
I removed the complexity metric as suggested by this blog post on triaging:
http://www.lostgarden.com/2008/05/improving-bug-triage-with-user-pain.html
(see The temptation to assign ‘cost’)

Big thanks to @ashleygwilliams and @davidjnelson for their help and feedback!
2014-02-27 15:56:47 -08:00
Pavel Pomerantsev 5d9d6a59d2 docs(guides/providers): fix typo
Closes #5465
2014-02-27 23:29:47 +01:00
Pawel Kozlowski 4e73c80b17 fix(jqLite): properly toggle multiple classes
Fixes #4467
Closes #6448
2014-02-27 19:44:57 +01:00
Lajos Veres 27873acbf0 chore(qSpec): fix typos 2014-02-27 01:54:06 -08:00
Lajos Veres 4f48898728 chore(parseSpec): fix typo 2014-02-27 01:53:35 -08:00
Lajos Veres 0df6e20e6a chore(httpSpec): fix typo 2014-02-27 01:53:13 -08:00
Lajos Veres 074ad03072 chore(filtersSpec): fix typo 2014-02-27 01:52:51 -08:00
Lajos Veres a20e76ea80 chore(ngRepeatSpec): fix typo 2014-02-27 01:52:21 -08:00
Lajos Veres d59678a080 chore(AngularSpec): fix typo 2014-02-27 01:51:45 -08:00
Lajos Veres c34602007c chore(animate): fix typo in a comment 2014-02-27 01:44:25 -08:00
Lajos Veres 8ae296823b docs($sce): fix typo 2014-02-27 01:43:26 -08:00
Lajos Veres 2586e3a2ac docs($compile): fix typo 2014-02-27 01:42:30 -08:00
Lajos Veres 5020d2e8f7 chore(scripts): fix typos in scripts/utils.inc 2014-02-27 01:41:40 -08:00
Lajos Veres 1300c74b32 docs(changelog): fix typos 2014-02-27 01:41:12 -08:00
desertapple 214c65d334 docs($injector): fix typo
Duplicate 'that' words present in the document, just remove one of them.

Closes #6469
2014-02-26 17:14:08 -08:00
Jan Hancic b3750e5201 docs(guide/resource): add links to ngResource and $resource 2014-02-26 19:49:56 -05:00
Mauro 4aac37e7be docs(guide): add a new django tutorial
- add a link to a tutorial on intergrating angular and django
2014-02-26 19:39:55 -05:00
Brad Williams fd09586b08 docs(errors/infdig): add a common example
Mention common cause of error is binding to a new array on every $digest loop.

Closes #6465
2014-02-26 16:33:59 -08:00
pyriand3r 713f9758e2 docs(guide/directive): update directive restrict options
- add missing 'C' restriction for class names
2014-02-26 18:50:43 -05:00
ashley williams 794e5e6098 docs(contribute): add table of contents to contributing doc
- add linked list to top of document
- add anchor elements to secondary headings

closes #6287
2014-02-26 15:36:26 -08:00
Matias Niemelä f4f1f43d51 fix($animate): ensure all comment nodes are removed during a leave animation
Closes #6403
2014-02-26 17:17:41 -05:00
Igor Minar 73daa79e91 chore(travis): add gitter config 2014-02-26 14:12:07 -08:00
Matias Niemelä e71e7b6cae fix($animate): only block keyframes if a stagger is set to occur
Transitions must be blocked so that the initial CSS class can be applied
without triggering an animation. Keyframes do not need to be blocked since
animations are always triggered on the starting CSS class, however, if a
stagger animation is set to occur then all elements for index > 0 should
be blocked. This is to prevent the animation from occuring early on before
the stagger delay for the given element has passed.

With ngAnimate and keyframe animations, IE10 and Safari will render a slight
flicker effect caused by the blocking. This fix resolves this issue.

Closes #4225
2014-02-26 17:08:51 -05:00
Stanislav Sysoev c914cd99b3 fix(ngAnimate): TypeError Cannot call method 'querySelectorAll' in cancelChildAnimations
When an element containing both ng-repeat and ng-if directives attempts to remove any items from
the repeat collection, the following error is thrown: "TypeError Cannot call method 'querySelectorAll'
of undefined".  This happens because the cancelChildAnimations code naively belives that the jqLite
object always has an element node within it. The fix in this commit addresses to securely check to see
if a node was properly extracted before any child elements are inspected.

Closes #6205
2014-02-26 15:39:54 -05:00
Matias Niemelä e9881991ca fix($animate): ensure that animateable directives cancel expired leave animations
If enter -> leave -> enter -> leave occurs then the first leave animation will
animate alongside the second. This causes the very first DOM node (the view in ngView
for example) to animate at the same time as the most recent DOM node which ends
up being an undesired effect. This fix takes care of this issue.

Closes #5886
2014-02-26 14:53:57 -05:00
Matias Niemelä c9245cf759 test($animate): ensure staggering timeout tests are secure 2014-02-26 14:23:56 -05:00
Matias Niemelä 99720fb5ab fix($animate): ensure all animated elements are taken care of during the closing timeout
Closes #6395
2014-02-26 14:23:47 -05:00
Peter Bacon Darwin 332e935048 docs(*): fix jsdoc type expressions
These errors in the docs were preventing some parts of the docs from being
parsed.
2014-02-26 11:47:22 +00:00
Peter Bacon Darwin 30c8207e0f chore(doc-gen): add debug-dump processor 2014-02-26 11:47:22 +00:00
Igor Minar 3d6dff44f3 revert: fix($location): parse query string when path is empty in hashbang mode
This reverts commit cad717b117.

This change causes regressions in existing code and after closer inspection
I realized that it is trying to fix an issue that is should not be considered
a valid issue.

The location service was designed to work against either "hash" part of the
window.location when in the hashbang mode or full url when in the html5 mode.

This change tries to merge the two modes partially, which is not right. One
reason for this is that the search part of window.location can't be modified
while in the hashbang mode (a browser limitation), so with this change part
of the search object should be immutable and read-only which will only cause
more confusion.

Relates to #5964
2014-02-25 22:59:31 -08:00
Michał Gołębiowski 6b049c74cc feat($parse): support trailing commas in object & array literals
Per ECMAScript 5.1 specification trailing commas are allowed in object and
array literals. All modern browsers as well as IE>8 support this syntax.
This commit adds support for such syntax to Angular expressions.
2014-02-26 00:38:37 +01:00
Brian Ford c99dd224a5 chore(docs/contribute): add note about serving the docs 2014-02-25 15:11:45 -08:00
adeelcap15 1b1413a9d4 docs(guide/concepts): reference correct module name.
Fixed a mistake, changed invoice to invoice2.

Closes #6438
2014-02-24 23:18:44 -05:00
Matias Niemelä 4c4537e65e perf($animate): use rAF instead of timeouts to issue animation callbacks 2014-02-24 21:23:18 -05:00
Matias Niemelä 62761428ef chore(core): create a wrapper to manage async callbacks 2014-02-24 21:23:10 -05:00
Matias Niemelä 04d7317cdd chore(core): introduce a wrapper for requestAnimationFrame 2014-02-24 21:23:05 -05:00
Diego Muñoz Escalante 2cd87dbb93 docs($interpolate) fix sample code appearing unformatted
Closes #6418
2014-02-24 18:48:01 +00:00
Leniel Macaferi 348a77145d docs(tutorial): referenced e2e-test.bat for Windows users in step 3
Closes #5755
2014-02-23 21:26:51 +01:00
Alessandro Bahgat 24fe1632b0 docs($routeProvider): correct "slashs" to "slashes"
Closes #6415
2014-02-23 17:49:54 +01:00
George Cox 832be4123d docs(guide): grammar fix
use of the article, both definite and indefinite, is not optional

Closes #5981
2014-02-22 23:23:20 +01:00
Chia-liang Kao ffe5115355 style(tests): remove trailing comma in specs
Closes #6241
2014-02-22 22:41:51 +01:00
Alessandro Bahgat 61b2515c0d docs(ngPluralize): corrected "bounded to" to "bound to"
Closes #6408
2014-02-22 15:29:14 -05:00
Peter Bacon Darwin f296e2ee12 docs($animate): change @param to use valid types
`{jQuery/jqLite element}` is not a valid jsdoc type and breaks when being
parsed causing the documentation to look wrong.  This commit changes all
such param tags to use `DOMElement` instead, which is what is used for
similar params in `$compile` and `angular.element`.
2014-02-22 13:07:19 +00:00
Peter Bacon Darwin f4a121f6c2 chore(protractor-jenkins-config): don't use this inside onPrepare
Closes #6406
2014-02-22 12:19:49 +00:00
Peter Bacon Darwin b72ea59019 chore(docs-app): re-activate docs-app test tasks
Currently there is only a minimal test spec in place. But this will now
be run as part of the test tasks.
2014-02-22 10:07:31 +00:00
Peter Bacon Darwin 3b5480e9fc chore(doc-app): ensure only canonical paths get sent to Google Analytics
Before we were simply sending the current location, but multiple URLs map
to the same document.
Now, we use the canonical path of the current document if available and
fall back to the $location path otherwise.
Includes tests!!

Closes #6402
2014-02-22 10:07:31 +00:00
Sekib Omazic a4078fcae4 perf($cacheFactory): skip LRU bookkeeping for caches with unbound capacity
Fixes #6193
Closes #6226
2014-02-21 22:29:46 -08:00
Julie 39c82f3fb7 chore(travis): reorganize protractor configs to group by spec instead of by browser
Use the multiConfiguration ability of Protractor to start tests on multiple browsers
from the same travis cell. Group tests by type (jquery, jqlite, or docs tests) instead
of by browser. Turn on tests for jQuery.
2014-02-21 16:57:04 -08:00
Caitlin Potter 1293cc88cd chore(examples): remove final traces of examples from the tree
Apparently some example files were referenced in angularFiles.js, and this was missed when
2f45133393 was checked in. This cleans it up.

Closes #6405
2014-02-21 18:37:12 -05:00
Caitlin Potter cad717b117 fix($location): parse query string when path is empty in hashbang mode
Before this fix, search queries in hashbang mode were ignored if the hash was not present in the
url. This patch corrects this by ensuring that the search query is available to be parsed by
urlResolve when the hashbang is not present.

Closes #5964
2014-02-21 18:31:13 -05:00
Caitlin Potter c2d447e378 fix(input): use ValidityState to determine validity
In browsers where HTML5 constraint validation is (partially) implemented, an invalid number
entered into an input[type=number] (for example) input element would be visible to the
script context as the empty string. When the required or ngRequired attributes are not used,
this results in the invalid state of the input being ignored and considered valid.

To address this, a validator which considers the state of the HTML5 ValidityState object is
used when available.

Closes #4293
Closes #2144
Closes #4857
Closes #5120
Closes #4945
Closes #5500
Closes #5944
2014-02-21 18:03:24 -05:00
Caitlin Potter 75515852ea fix(isElement): reduce false-positives in isElement tests
Complimentary change to match changed $parse behaviour.
2014-02-21 17:59:01 -05:00
Caitlin Potter 5fe1f39f02 fix($parse): reduce false-positives in isElement tests
There are always going to be false positives here, unfortunately. But
testing different properties will hopefully reduce the number of false
positives in a meaningful way, without harming performance too much.

Closes #4805
Closes #5675
2014-02-21 17:58:48 -05:00
Caitlin Potter 2bce71e9dc feat(ngHref): bind ng-href to xlink:href for SVGAElement
This change makes the ngHref directive useful for SVGAElements by having it bind
to the xlink:href attribute rather than the href attribute.

Closes #5904
2014-02-21 17:56:48 -05:00
Boris Serdyuk c8e03e34b2 fix($http): do not add trailing question
Closes #6342
2014-02-21 14:51:10 -08:00
Pawel Kozlowski 267b217376 fix($http): send GET requests by default
Fixes #5985
Closes #6401
2014-02-21 14:42:03 -08:00
Caitlin Potter 2f45133393 chore(examples): remove ancient examples from the tree
Let these poor scripts retire, goodness.

Closes #6398
Closes #3310
2014-02-21 14:52:12 -05:00
Peter Bacon Darwin 4a6a3ba7fb docs(*): fix anchors for members in api docs 2014-02-21 19:37:37 +00:00
Peter Bacon Darwin 0c9abc32c0 docs(guide/filter): fix input type in example
Closes #6366
2014-02-21 13:57:18 +00:00
Stéphane Reynaud a9cc6efb3c docs(tutorial/step_11): fix url-based links refs to AUTO module
Closes #6389
2014-02-21 13:52:30 +00:00
Stéphane Reynaud d7d3ef12a6 docs(tutorial/step_06): fix url-based links refs to AUTO module
Closes #6388
2014-02-21 13:52:16 +00:00
Stéphane Reynaud 1a98b4fe02 docs(tutorial/step_05): fix url-based links refs to AUTO module
Closes #6387
2014-02-21 13:52:00 +00:00
Stéphane Reynaud a5859aaf63 docs(guide/di): fix url-based links refs to AUTO module
Closes #6386
2014-02-21 13:49:59 +00:00
Stéphane Reynaud dacdcc6d96 docs(guide/compiler): fix url-based links refs to AUTO module
Closes #6385
2014-02-21 13:49:13 +00:00
Sadaoui Abderrahim 7cd79b6f8f docs(ngMock.$interval): fix return description
Closes #6384
2014-02-21 13:48:01 +00:00
Stéphane Reynaud fa5ca115ac docs(guide/i18n): fix url-based links refs to AUTO module
Closes #6383
2014-02-21 13:32:16 +00:00
Stéphane Reynaud 48b86a4eae docs(guide/scope): fix url-based links refs to AUTO module
Closes #6382
2014-02-21 13:26:08 +00:00
Stéphane Reynaud f827d64c2e docs(guide/location): fix url-based link to AUTO module
Closes #6381
2014-02-21 13:00:26 +00:00
Julie 4d7e1cef37 chore(doc-gen): generate examples for each deployment, e.g. jquery
Update to the latest dgeni-packages, which supports multiple
deployment environments for the examples.

Add a jQuery deployment environment for the examples.

Currently, the target of the runnable example iframe always points
to the default deployment environment, not to the environment under
which the main app is running.

Closes #6361
2014-02-21 09:59:12 +00:00
Jennifer Song 58b01fac1e docs(tutorial/step-05): replace minify wiki link with shortened URL
marked has an existing bug where links ending with a ')' will not be parsed correctly. The workaround
is to use a shortened URL. The original URL that is being replaced by this commit is
http://en.wikipedia.org/wiki/Minification_(programming) .

Closes #6377
2014-02-21 01:19:26 -05:00
Tobias Leugger - Vibes 84ad0a037c docs(guide/ie): correct conditional comment to load JSON polyfill for IE7 and lower
Text specifies "polyfill JSON.stringify for IE7 and below" conditional comment for loading the
polyfill was "lte IE 8".

Closes #6227
2014-02-20 17:16:48 -05:00
James Roome 2a37690f70 docs(ngSubmit): reference correct object ($scope) in example.
Switched from this to $scope. It's confusing using $scope and this interchangeably.

Closes #6375
2014-02-20 17:12:52 -05:00
Brad Williams 45304a9d68 docs(guide/directive): add a more detailed description of isolate scope & bindings
More description of "&" bindings, the fact that they trigger evaluation of expressions in the
original scope's context.

Closes #6255
2014-02-20 15:18:47 -05:00
Richard Collins 0478bb4a60 docs(ie): document IE style attribute interpolation problem
IE has issues with this, it's good to make a note of this.

Closes #6329
2014-02-20 14:55:18 -05:00
cnlevy 3193a3a5af docs(core): add note that isObject returns true for arrays
Closes #6353
2014-02-20 14:52:25 -05:00
Sadaoui Abderrahim 6082e2ad16 docs(ngMock): document method ngMock.$interval#cancel()
I have been looking around and was not able to find any informations on how to clear the $interval
but reading the source code, sharing is caring!

Closes #6367
2014-02-20 10:43:05 -05:00
Matias Niemelä 39bae62f53 chore(docs): fix header wrapping for tablet devices 2014-02-20 10:37:03 -05:00
Peter Bacon Darwin d7a73e41ed chore(doc-gen): add formatted error messages to error pages
This got missed in the doc migration: When there is an error in an
Angular app, extra information is placed in the URL, which can be used
by the docs application to display a more useful message.

This fix adds that back in.  The error message templates are extracted
by the minerr tool during build and put into the errors.json file. The
errors-doc processor will load this up and attach these message templates
to the error docs.

The display of these templates was already in place, via the errorDisplay
directive in docs/app/js/errors.js.

(Also, moved the error.template.html file into the angular.js repository
from the dgeni-packages repository as this is specific to the angular.js
project and all the other error related stuff is in here.

Finally, also, added an e2e test that checks that minerr formatted
messages are displayed correctly.

Closes #6363
2014-02-20 14:41:32 +00:00
Peter Bacon Darwin e6c35e1b6b chore(package.json): update dgeni dependencies 2014-02-20 11:01:51 +00:00
Matias Niemelä 0b6ba9c940 chore(docs): make the layout fully responsive
Closes #6308
2014-02-19 17:22:54 -05:00
Peter Bacon Darwin cc1f7539d4 docs(modules): remove unused {@installModule} tags 2014-02-19 21:22:27 +00:00
Peter Bacon Darwin 9ca685bfbd chore(doc-gen): add path of project to the doc gen config 2014-02-19 18:32:38 +00:00
Aaron Wang 1b74e5ed0a docs(api): remove ngRoute.$routeParams link from ng section
Closes #6219
2014-02-19 18:17:41 +00:00
Peter Bacon Darwin 3fbc25718e chore(doc-gen): improve grouping and sorting of api nav items 2014-02-19 16:21:20 +00:00
Peter Bacon Darwin b488bbf4bf chore(doc-app): remove invalid line of code 2014-02-19 16:07:56 +00:00
Steven Petryk 696928dbc6 docs($routeProvider): fix indentation
Closes #6345

Somebody accidentally padded a list with one-too-many indentations, which caused the actual documentation page to render incorrectly. This should fix it.
2014-02-19 08:03:20 -08:00
Igor Minar cbcfaa2c8d docs(contributing): remove reference to the obsolete chrome extension 2014-02-18 19:52:10 -08:00
Igor Minar cafde93a40 docs(triaging): remove reference to the obsolete chrome extension 2014-02-18 19:50:46 -08:00
Igor Minar 1523fc7e6d docs(guide/providers): fix example snippet
Closes #6331
Closes #6332
2014-02-18 19:39:41 -08:00
Caitlin Potter a3f70172ef chore(travis): don't run Travis-CI builds for G3 branches
Building the G3 commits occupies a lot of time, and these branches have
already been tested.

Closes #6328
2014-02-18 19:15:50 -05:00
Caitlin Potter 868a2c401f style(jqLite): remove trailing whitespace in new test
Oops.
2014-02-18 18:52:09 -05:00
Caitlin Potter 05fbed5710 fix(jqLite): make jqLite('<iframe src="someurl">').contents() return iframe document, as in jQuery
This is a very tiny change to make behaviour consistent with jQuery.

Closes #6320
Closes #6323
2014-02-18 18:43:59 -05:00
Brad Williams 21dac2a3da docs(ngClass): Explain all 3 ways how to use ngClass
Closes #6324.
2014-02-18 15:08:30 -08:00
Igor Minar 481508d0e7 style: remove ws and enfore no-trailing-ws jscs rule 2014-02-18 10:44:48 -08:00
Caitlin Potter 12e4d3ac4d docs($q): fixup dgeni ngdoc annotations for $q methods
Just a tiny fixup, that's all.

Closes #6317
2014-02-18 12:25:08 -05:00
Peter Bacon Darwin 4f937bda18 test(docs): add check for resilience to trailing slashes, etc. 2014-02-18 06:36:34 +00:00
Shai Reznik b6f3d4007a docs(guide/compiler): remove innacurate statement
The $compile service accepts string as a value and wraps it if
needed, so this statement isn't correct, at least by the source
code.

Closes #6301
2014-02-18 06:36:34 +00:00
Paul Dijou 774b2adb89 docs($interpolate): correct small typo 2014-02-18 06:26:24 +00:00
Peter Bacon Darwin ad6767949c chore(docs): cope with trailing slash and "index" in URLs
Closes #6295
2014-02-18 06:26:24 +00:00
ahliddin 2407891ddf docs(tutorial/step-11): add controller to correct object 2014-02-18 05:47:04 +00:00
Matias Niemelä 666137d635 chore(docs): fix broken example tabs 2014-02-17 16:36:22 -05:00
plmetz 846ebb4073 docs(guide/concepts): clarify wording 2014-02-17 14:15:25 +00:00
Stéphane Reynaud e23a6a320e docs(bike-shed-migration): convert doctype and names
To keep the same logic as the commit https://github.com/angular/angular.js/commit/2e641ac49f121a6e2cc70bd3879930b44a8a7710
2014-02-17 14:05:51 +00:00
Stéphane Reynaud f8b11f3584 docs(tutorial): add missing @step tags
Since steps 9 and 11 were missing @step tags they were out of order

Closes #6292
Closes #6291
2014-02-17 14:04:26 +00:00
Peter Bacon Darwin 4c02d0bea5 chore(docs-assets): add versions to paths for imported assets
This should prevent stale caches in browsers if we upgrade any of these
assets.
2014-02-17 14:01:30 +00:00
Peter Bacon Darwin 47ec6f5d7f chore(doc-gen): add production deployment environment 2014-02-17 07:43:58 +00:00
Matias Niemelä 1fb47e08a0 chore(docs): use fixed versions with all registered bower components 2014-02-16 20:27:13 -05:00
Matias Niemelä f8b50cd410 chore(docs): replace local bootstrap build with one from bower 2014-02-16 20:25:27 -05:00
Matias Niemelä 1de7411c8b chore(ngPluralize): remove useless docs heading 2014-02-16 20:04:22 -05:00
Matias Niemelä 7c8a1bfbac docs(design): footer and spacing fixes added to the layout 2014-02-16 19:44:44 -05:00
Matias Niemelä 713c8e629d docs(design): ui-fixes for examples, layout and API components 2014-02-17 00:20:26 +00:00
Peter Bacon Darwin 33e1bdc543 chore(errors): rename folders to match namespaces 2014-02-16 22:02:41 +00:00
Peter Bacon Darwin 49f90e559e chore(travis): disable Safari and JQuery e2e tests on Travis
There are no real JQuery tests at this point anyway and the Safari that we
are getting from SauceLabs seems to be a flakey Windows 2000 version that
is not necessarily providing accurate results.
2014-02-16 19:03:45 +00:00
Peter Bacon Darwin a48a99377c docs(indexPage.template): fix top-nav links to work on localhost 2014-02-16 19:03:45 +00:00
Caitlin Potter f7fad29fd9 docs(bike-shed-migration): convert guide <doc:...> examples to <example>...
This CL also contains style fixes as the converted scripts caused jshint to complain.
2014-02-16 19:03:45 +00:00
Peter Bacon Darwin 896e34689d docs(NgModelController): don't run contenteditable example on FF 2014-02-16 19:03:45 +00:00
Peter Bacon Darwin 0b28de1e55 chore(doc-gen): improve error page navigation 2014-02-16 19:03:45 +00:00
Peter Bacon Darwin 84d9a57416 chore(doc-gen): remove trailing whitespace in ptor template 2014-02-16 19:03:45 +00:00
Peter Bacon Darwin ecdb9a5688 docs(*): fix jshint issues in examples 2014-02-16 19:03:45 +00:00
Peter Bacon Darwin c6f406f03b chore(doc-gen): add jshint checking to examples and tests 2014-02-16 19:03:44 +00:00
Julie c663b39826 chore(e2etests): fix a browser check which was actually assigning the parameter 2014-02-16 19:03:44 +00:00
Peter Bacon Darwin af9e897ecd docs(guide): remove unnecessary "Developer Guide: " from @names 2014-02-16 19:03:44 +00:00
Peter Bacon Darwin a8f21d4c48 chore(doc-gen): only output info (and more severe) log messages 2014-02-16 19:03:44 +00:00
Peter Bacon Darwin 6fcf544528 chore(doc-gen): fix navGroup hrefs 2014-02-16 19:03:44 +00:00
Julie 4ee35287f0 chore(grunt): grunt should error when doc generation grunt errors 2014-02-16 19:03:44 +00:00
Caitlin Potter 3655d3ffbe chore(travis): remove test:docgen task from build
The task was removed by an earlier commit, and executing it breaks TravisCI builds. It may be
replaced at a later date.
2014-02-16 19:03:44 +00:00
Peter Bacon Darwin ec3ba47c4c chore(package.json): move to published npm version of dgeni-packages 2014-02-16 19:03:44 +00:00
Peter Bacon Darwin 2123772a65 docs(api): escape params that have <object> in their type
Really the doc-gen process should escape there but for now this should
stop the layout from breaking.
2014-02-16 19:03:44 +00:00
Peter Bacon Darwin cb1efd818b docs($locationProvider): tag as a provider rather than object 2014-02-16 19:03:44 +00:00
Peter Bacon Darwin f5575782c4 docs(docs.css): add initial type-hint styles 2014-02-16 19:03:44 +00:00
Peter Bacon Darwin d85505d019 docs(content): fix bad links 2014-02-16 19:03:43 +00:00
Peter Bacon Darwin daa83f2864 chore(doc-gen): remove console.log statements 2014-02-16 19:03:43 +00:00
Peter Bacon Darwin 7c7477ce45 docs(ngHref): fix example that navigates away from the page 2014-02-16 19:03:43 +00:00
Peter Bacon Darwin 6f0503514f docs(ngRoute): ask for examples to have their base[href] fixed 2014-02-16 19:03:43 +00:00
Peter Bacon Darwin 5c6f9f8e81 docs(ngHref): don't run the breaking protractor test 2014-02-16 19:03:43 +00:00
Peter Bacon Darwin 64403ff36f chore(package.json): get dgeni from the npm registry 2014-02-16 19:03:43 +00:00
Peter Bacon Darwin 9878fee299 test(docs-app-e2e): refactor test inline with new docs app
The links to code elements have now changed: api/ng.directive:ngClick ->
api/ng/directive/ngClick.

Examples now run inside iframes, so we need to instruct Protractor to
switch to the example iframe.
2014-02-16 19:03:43 +00:00
Peter Bacon Darwin 8849d70af8 docs(api/index): fix ambiguous ngClick link
ngClick appears in more than one module so we must make it explicit.
2014-02-16 19:03:43 +00:00
Peter Bacon Darwin 102f986555 docs(ngShowHide): fix icons in example
The protractor tests were failing because the spans containing the icons
were not displaying anymore.
2014-02-16 19:03:43 +00:00
Peter Bacon Darwin 457cf0a702 docs(examples): fix example dependencies 2014-02-16 19:03:43 +00:00
Peter Bacon Darwin 8c121b94e7 docs(ngSanitize): add dependency on angular-sanitize to example 2014-02-16 19:03:42 +00:00
Peter Bacon Darwin 24a87d90f2 chore(doc-gen): provide example dependencyPath in config 2014-02-16 19:03:42 +00:00
Peter Bacon Darwin 0b35521d8f chore(doc-gen): move git info into its own processor 2014-02-16 19:03:42 +00:00
Peter Bacon Darwin 4a938213df chore(docs-indexPage.template): add onload handler for Google Analytics 2014-02-16 19:03:42 +00:00
Peter Bacon Darwin 6a5a8970a0 chore(indexPage.template): add back Google analytics and offline support 2014-02-16 19:03:42 +00:00
Peter Bacon Darwin 69a687e04e docs(injector): move angular.injector to the ng module
Even though it is defined in the auto folder, it makes more sense for this
function to appear in the ng module in the docs.
2014-02-16 19:03:42 +00:00
Peter Bacon Darwin b2dc078943 chore(docs): remove 'AngularJS ' prefix from version drop-down 2014-02-16 19:03:42 +00:00
Julie 9565cca15b chore(protractor tests): fix up e2e tests 2014-02-16 19:03:42 +00:00
Julie cd508678cd chore(protractor-generator): add dgeni processor for protractor 2014-02-16 19:03:42 +00:00
Peter Bacon Darwin 0f77bd6d0a docs(misc): add landing page for the miscellaneous area 2014-02-16 19:03:42 +00:00
Peter Bacon Darwin 9b6fc8a4cf docs(tutorial): give the tutorial landing page a better name 2014-02-16 19:03:42 +00:00
Peter Bacon Darwin 389d4879da chore(doc-gen): new docs
chore(doc-gen): implement dgeni
2014-02-16 19:03:41 +00:00
Peter Bacon Darwin a564160511 docs(bike-shed-migration): fix url-based links refs to AUTO module 2014-02-16 19:03:41 +00:00
Peter Bacon Darwin 06f2ba899f docs(bike-shed-migration): fix invalid </file name=""> HTML in examples 2014-02-16 19:03:41 +00:00
Peter Bacon Darwin 9f828a07dc docs(ngResource): fix over-length line 2014-02-16 19:03:41 +00:00
Peter Bacon Darwin 655da39c01 docs(sce): fix invalid @name tags 2014-02-16 19:03:41 +00:00
Peter Bacon Darwin 2f7c57233a docs(bike-shed-migration): let markdown deal with extenal links
It is problematic to use {@link} tags with external links because the
markdown parser converts them to links for us before we parse the @links.
This means that the following tag:

```
{@link http://www.google.com Google}
```

get converted to:

```
{@link <a href="http://www.google.com/"></a> Google}
```

Our {@link} parser then converts this to:

```
<a href="<a">&lt;</a>href="http://www.google.com/"></a> Google}
```

which is clearly a mess.  The best solution is not to use {@link} tags
for external links and just use the standard markdown syntax:

```
[Google](http://www.google.com)
```

In the long run, we could look into configuring or modifying `marked` not
to convert these external links or we could provide a "pre-parser"
processor that dealt with such links before `marked` gets its hands on it.
2014-02-16 19:03:41 +00:00
Peter Bacon Darwin 1192ae44f1 docs(bike-shed-migration): convert <doc:...> examples to <example>... 2014-02-16 19:03:40 +00:00
Peter Bacon Darwin f7c8bcb329 docs(sce): fix reference to $sceDelegateProvider 2014-02-16 19:03:40 +00:00
Caitlin Potter f7d28cd377 docs(all): convert <pre>/</pre> snippets to GFM snippets 2014-02-16 19:03:40 +00:00
Peter Bacon Darwin 2e641ac49f docs(bike-shed-migration): convert doctype and names 2014-02-16 19:03:40 +00:00
Peter Bacon Darwin 1ca22a3dc8 docs(bike-shed-migration): move ng module doc into Angular.js 2014-02-16 19:03:40 +00:00
Peter Bacon Darwin bd4ffaba53 docs(bike-shed-migration): change tutorial doctype and add @step tag 2014-02-16 19:03:40 +00:00
Peter Bacon Darwin c7e815f63b docs(bike-shed-migration): fix up links outside the domain
It is safer to use markdown style links and save jsdoc style links for
internal links and code references
2014-02-16 19:03:40 +00:00
Peter Bacon Darwin 6483dea08c docs(bike-shed-migration): Add missing module tag
The generator is able to imply the module from the containing folder for
most files but these are in the ng module but are stored at the root folder.
2014-02-16 19:03:40 +00:00
Sergei Z cceb455fb1 fix(numberFilter): convert all non-finite/non-numbers/non-numeric strings to the empty string
The previous code for filtering out non-finite numbers was broken, as it would convert `null` to `0`,
as well as arrays.

This change fixes this by converting null/undefined/NaN/Infinity/any object to the empty string.

Closes #6188
Closes #6261
2014-02-15 13:48:52 -05:00
jenkins 3018ff7130 chore(release): update cdn version 2014-02-14 17:30:52 -08:00
Brian Ford c086f831fb docs(changelog): release notes for 1.2.13 2014-02-14 16:41:02 -08:00
Igor Minar fab2d3c92f style(animate): remove ws 2014-02-14 16:31:57 -08:00
Matias Niemelä 4f84f6b3e4 fix($animate): ensure $animate doesn't break natural CSS transitions
BREAKING CHANGE: ngClass and {{ class }} will now call the `setClass`
animation callback instead of addClass / removeClass when both a
addClass/removeClass operation is being executed on the element during the animation.

Please include the setClass animation callback as well as addClass and removeClass within
your JS animations to work with ngClass and {{ class }} directives.

Closes #6019
2014-02-14 16:30:48 -08:00
Matias Niemelä cf5e463abd pref($animate): only trigger DOM callbacks if registered on the element being animated
BREAKING CHANGE: Both the `$animate:before` and `$animate:after` DOM events must be now
registered prior to the $animate operation taking place. The `$animate:close` event
can be registered anytime afterwards.

DOM callbacks used to fired for each and every animation operation that occurs within the
$animate service provided in the ngAnimate module. This may end up slowing down an
application if 100s of elements are being inserted into the page. Therefore after this
change callbacks are only fired if registered on the element being animated.
2014-02-14 16:28:56 -08:00
Matias Niemelä f288b8f010 pref($animate): group all asynchronous requests into one shared buffer 2014-02-14 16:28:34 -08:00
Matias Niemelä b7e4e92014 chore(jqLite): expose the _data lookup function to angular.element 2014-02-14 15:49:08 -08:00
Caitlin Potter 31c450bcee fix($compile) support templates with table content root nodes
If the first element in a template is a <tr>, <th>, <td>, or <tbody> tag,
the HTML compiler will ensure that the template is wrapped in a <table>
element so that the table content is not discarded.

Closes #2848
Closes #1459
Closes #3647
Closes #3241
2014-02-14 14:42:55 -05:00
Tim Whitbeck a9fcb0d0fc fix(input): don't apply textInput to <input type="file">
textInput shouldn't be applied to file inputs to ease writing of custom file input directives.

This change prevents file inputs from instantiating the text input parser/formatter pipelines.

Closes #6247
Closes #6231
2014-02-13 16:43:18 -05:00
Naomi Black a3846ab837 Merge pull request #6245 from brianhall/master
Google logo in AngularJS.exports to vector format.
2014-02-13 10:35:05 -08:00
Brian Hall 1953b0bed9 docs(logo): change logo to vector format in .eps file
Browser: Other
Component: docs
Regression: no

Closes issue #6092
2014-02-13 09:51:11 -08:00
Caitlin Potter 2b73027136 fix(input): setViewValue on compositionend
Because of a4e6d962, model is not updated on input/change between the
compositionstart and compositionend events. Unfortunately, the compositionend
event does not always happen prior to an input/change event.

This changeset calls the listener function to update the model after a
compositionend event is received.

Closes #6058
Closes #5433
2014-02-12 20:28:13 -05:00
Caitlin Potter 1079105443 docs($interpolate): fix link to $interpolateProvider#endSymbol
The markup here was missing the methods_ prefix and behaved incorrectly.

Closes #5802
2014-02-12 14:41:37 -05:00
Caitlin Potter d119e36302 docs($location): fix link to $rootScope.Scope.$on
Previously missing the methods_ prefix.

Closes #5798
2014-02-12 14:39:41 -05:00
James Kyle 98b2f8ef18 docs(currencyFilter): added missing line break in currency doc ptor test
Closes #6229
2014-02-12 10:05:35 -05:00
Stéphane Reynaud e7ab857ddb docs(guide/$location): correct link to HTML5 draft section 5.5 (history api)
Previous link url is no longer served, responds with bad link (error 404). This change corrects the
URL to point to section 5.5 of the draft. The old URL appears to have been removed from service in
2012.

Corrects the link to "History API"

Closes #6225
2014-02-12 08:26:21 -05:00
Mathieu Tricoire 46cba2e05d docs(input): document NgModelController.$isEmpty parameters / return value
Closes #6224
2014-02-12 08:19:24 -05:00
Jason Schapiro 72894f0dd2 docs(tutorial): inject phonecapApp module into unit test
When I was reading this doc I was thinking "but what about phonecatApp?" and when I looked in the
file from the step-11 branch there it is. Should be reflected in the docs as well

Closes #6209
2014-02-11 21:29:47 -05:00
Caitlin Potter 760f49de10 chore(dependencies): upgrade kriskowal/q to version ~1.0.0
CI builds on travis occasionally freak out because of the recursive use of process.nextTick, which
has been deprecated in Node relatively recently, to be replaced with setImmediate. Unfortunately,
this change does not resolve the issue. However, it does not hurt, either.

Closes #6161
2014-02-11 18:54:38 -05:00
Jesse Palmer 686b13bf60 docs(core): add closing tag to ngApp directive example
added missing closing tag to ngApp example.

Closes #6066
2014-02-11 18:42:16 -05:00
Evgeniy Tkachenko 56cc7bcc98 docs(jqLite): link to jQuery.fn.bind/unbind docs rather than jQuery.fn.on/off docs
Сorrect link.

Closes #6171
2014-02-11 18:23:25 -05:00
Caitlin Potter b4eed8ad94 feat(filterFilter): support deeply nested predicate objects
Due to 339a165, it became impossible to filter nested properties of an object using the filterFilter.
A proposed solution to this was to enable the use of nested predicate objects. This change enables the
use of these nested predicate objects.

Example:

```html
<div ng-repeat="it in items | filter:{ address: { country: 'Canuckistan'}}"></div>
```

Or

```js
$filter('filter')(items, { address: { country: 'Canuckistan' } });
```

Closes #6215
Related to #6009
2014-02-11 17:08:41 -05:00
Daniel Tabuenca 08793a690a refactor(ngTransclude): use transclusion function passed in to link
Since we now pass in the transclusion function directly to the link function, we no longer need
the old scheme whereby we saved the transclude function injected into the controller for later
use in during linking.

Additionally, this change may aid in correcting a memory leak of detached DOM nodes (see #6181
for details).

This commit removes the controller and simplifies ngTransclude.

Closes #5375
Closes #6181
2014-02-11 14:57:56 -05:00
Stéphane Reynaud ef4bf8c77c docs(guide/index): replace "shold" to "should"
Replace "shold" to "should"

Closes #6216
2014-02-11 11:46:36 -05:00
Igor Minar b6ab826c4b style(guide): remove ws 2014-02-10 17:09:35 -08:00
Jeremy Likness 71f974b459 docs(guide): add new resource links
Added a link to 10 reasons to use and online courses for Angular

Closes #6194
2014-02-10 17:09:34 -08:00
James Wagoner a68624444a docs(ngSubmit): ngSubmit also works with the data-action/x-action attributes
The documentation states only the "action" attribute triggers this, which is incorrect. When using
the attribute "data-action" (as for AJAX control, attempting to bypass the "action" attribute but
still make it obvious what its for), Angular thinks this is also classified as "action" and
continues with the page submission.

Closes #6196
2014-02-10 19:35:22 -05:00
Igor Minar 945fc1a4bc style(guide/concepts): remove ws 2014-02-10 16:19:10 -08:00
Sequoia McDowell ec900cabfc docs(guide/concepts): removing confusing use of hoisting
Closes #6207
2014-02-10 16:19:10 -08:00
Mark Miyashita f99fe799e2 docs(faq): add link to MIT license
Closes #6197
2014-02-10 15:58:34 -08:00
Caitlin Potter e7338d3f27 fix($compile): ensure element transclusion directives are linked with comment element
This corrects a complicated compiler issue, described in detail below:

Previously, if an element transclusion directive contained an asynchronous directive whose template
contained another element transclusion directive, the inner element transclusion directive would be
linked with the element, rather than the expected comment node.

An example manifestation of this bug would look like so:

```html
<div ng-repeat="i in [1,2,3,4,5]">
  <div my-directive>
  </div>
</div>
```

`my-directive` would be a replace directive, and its template would contain another element
transclusion directive, like so:

```html
<div ng-if="true">{{i}}</div>
```

ngIf would be linked with this template content, rather than the comment node, and the template element
would be attached to the DOM, rather than the comment. As a result, this caused ng-if to duplicate the
template when its expression evaluated to true.

Closes #6006
Closes #6101
2014-02-10 18:41:28 -05:00
Sequoia McDowell 2dfbc083c5 docs(concepts): Remove pointless * 1s
Closes #6206
2014-02-10 15:15:30 -08:00
Victor Berchet 27613fd500 docs(guide/scope): fix a typo
Signed-off-by: Caitlin Potter <caitpotter88@gmail.com>

Closes #6202
2014-02-10 18:09:03 -05:00
Julie e645f7cae1 refactor(testing): split travis end to end tests into separate jobs for jquery and jqlite
Closes #6159
2014-02-07 20:41:39 -08:00
Julie ad275b2265 refactor(doc): separate end to end tests into jquery and jqlite files 2014-02-07 20:41:11 -08:00
Julie 600e6218fe chore(testing): switch Jenkins to test e2e only on chrome
End to end tests will continue to be run on Safari and Firefox on Travis.

Closes #6187
2014-02-07 20:23:26 -08:00
jenkins 5218c7bbdc chore(release): update cdn version 2014-02-07 14:38:15 -08:00
Matias Niemelä 5cc5cc13b9 docs(changelog): release notes for 1.2.12 2014-02-07 17:00:28 -05:00
Igor Minar d5c7ef0f78 revert: refactor(mocks): simplify the inject implementation
This reverts commit 64d58a5b52.

For some weird reason this is causing regressions at Google.
I'm not sure why and I'm running out of time to investigate, so I'm taking
a safe route here and reverting the commit since it's just a refactoring.
2014-02-07 12:14:32 -08:00
Brian Ford 84fd3a18a3 docs(contributing): add code of conduct 2014-02-07 11:16:17 -08:00
Tobias Bosch fcf4393680 chore(build): Update closure i18n integration
Use git repo as source and use q-io instead of q-fs
2014-02-06 17:53:37 -08:00
Julie 16301bed28 chore(testing): de-flake a ngHref test for navigating away from the Angular page 2014-02-06 17:03:39 -08:00
Kasparas Galdikas 95be253fe5 fix($locale): Minor grammar amends for locale_lt
Closes #6164
2014-02-06 16:11:29 -08:00
asif22 bf4b0dbd46 docs(misc): fix typo in "getting started" docs
changed "building and application" to "building an application"

Closes #6156
2014-02-06 11:15:13 -05:00
sunderls 95d119ebb2 docs(injector): correct typo in example
$provide misused into $provider

maybe this should be corrected I think

Closes #6146
2014-02-06 10:44:31 -05:00
Igor Minar e609239fab chore(travis): remove double bower install to test if it's still needed
We did this due to travis-ci/travis-ci#1293 but since it's possible that this hack is not needed, I'm removing it.

If it turns out that we do need it still then we should ping the travis issue and revert this commit
2014-02-06 02:31:23 -08:00
Matias Niemelä 4224cd5182 fix(mocks): rename mock.animate to ngAnimateMock and ensure it contains all test helper code for ngAnimate
Closes #5822
Closes #5917
2014-02-06 01:22:14 -05:00
Matias Niemelä 906fdad0f9 fix(mocks): remove usage of $animate.flushNext in favour of queing
The flushNext method of testing is difficult and highly coupled with the behavior
of ngAnimate's $animate workflow. It is much better instead to just queue all
$animate animation calls into a queue collection which is available on the $animate
service when mock.animate is included as a module within test code.
2014-02-06 01:21:41 -05:00
Franziskus Domig a8c1d9c978 docs(angular.forEach): add missing space in test
Closes #6130
2014-02-05 16:25:03 -08:00
Julie 8829a2a86d chore(testing): fix Jenkins breakage due to test directory already being present 2014-02-05 16:13:06 -08:00
Julie 84467d8697 refactor(testing): run end to end tests on separate browsers in parallel 2014-02-05 15:40:16 -08:00
Julie 0e85ca9ddb chore(testing): run end to end tests on firefox and safari as well as chrome
Update the Travis and Jenkins configs to run protractor tests on Safari and Firefox as well,
and make the Travis tests run output XML and turn off color.

Fix tests which were failing in Firefox due to clear() not working as expected.

Fix tests which were failing in Safari due to SafariDriver not understanding the minus key,
and disable tests which SafariDriver has no support for.
2014-02-05 15:39:59 -08:00
Julie e7face4728 chore(end2end): remove old references to the scenario runner and update to point to protractor 2014-02-05 15:39:46 -08:00
Tobias Bosch a29bff1c98 chore(build): remove MINERR_ASSET from source map
The actual change happened in ng-closure-runner.
The change here just includes the new version.

Closes #4675
2014-02-05 15:34:56 -08:00
Hopiu 95522cc11f docs(forEach): correct spelling error
Closes #6124
2014-02-05 09:58:26 -05:00
Nicolas Leger c5f69e3f64 chore(ngdoc): fix misspellling of Naturally in sortVersionsNatrually
Corrects "sortVersionsNatrually" method name in `ngdoc.js` in "sortVersionsNaturally"
2014-02-04 16:43:39 -08:00
Daniel Luxemburg dd24c78373 fix(ngMock): return false from mock $interval.cancel() when no argument is supplied
Closes #6103.
Closed #6099.
2014-02-04 16:41:25 -08:00
Caitlin Potter 36d37c0e38 fix(jqLite): trim HTML string in jqLite constructor
jQuery will construct DOM nodes containing leading whitespace. Prior to this change, jqLite would
throw a nosel minErr due to the first character of the string not being '<'. This change corrects
this behaviour by trimming the element string in jqLite constructor before testing for '<'.

Closes #6053
2014-02-04 16:39:52 -08:00
Caitlin Potter 24699ee8f0 fix($http): ignore xhr.responseType setter exception if value is "json"
WebKit added support for the json responseType value on 09/03/2013
https://bugs.webkit.org/show_bug.cgi?id=73648. Versions of Safari prior to 7 are known to throw when
setting the value "json" as the response type. Other older browsers implementing the responseType.
Other browsers with infrequent update cycles may also be affected.

The json responseType value can be ignored if not supported, because JSON payloads are parsed on the
client-side regardless.

Closes #6115
Closes #6122
2014-02-04 19:34:31 -05:00
GiffenGood aa6a0e3fc6 docs(log.js): param debugEnabled is a boolean and not a string 2014-02-04 16:26:36 -08:00
Tobias Bosch 8761ddc0e3 chore(release): be able to release any commit
The version information is now stored only in the tags.
By this we are able to release commits in the past, which
have already been tested, so we don't need a code freeze
or run tests any more. This is also the first step for
letting Travis do the releases in the future.

The package.json now contains the new
property 'branchVersion' that defines which tags are
valid on this branch.

Closes #6116
2014-02-04 16:20:22 -08:00
Caitlin Potter 058842ad04 revert: "fix($http): ignore xhr.responseType setter exception if value is "json""
This reverts commit 431bad0183.
2014-02-04 19:09:53 -05:00
Caitlin Potter 431bad0183 fix($http): ignore xhr.responseType setter exception if value is "json"
WebKit added support for the json responseType value on 09/03/2013
https://bugs.webkit.org/show_bug.cgi?id=73648. Versions of Safari prior to 7 are known to throw when
setting the value "json" as the response type. Other older browsers implementing the responseType.
Other browsers with infrequent update cycles may also be affected.

The json responseType value can be ignored if not supported, because JSON payloads are parsed on the
client-side regardless.

Closes #6115
Closes #6122
2014-02-04 18:46:54 -05:00
Caitlin Potter 5850e61c82 docs(CHANGELOG): add breaking change notice for 1.2.9 $http default headers change
Add a mention for the slightly breaking change introduced in 1.2.9.

Closes #6022
2014-02-04 10:59:44 -05:00
Thomas Belin d2e4e49986 fix(ngResource): don't filter "$"-prefixed properties from ngResource requests/responses
ngResource no longer filters properties prefixed with a single "$" character from requests or
responses, correcting a regression introduced in 1.2.6 (cb29632a) which caused shallowCopy and
shallowClearAndCopy to ignore properties prefixed with a single "$".

Closes #5666
Closes #6080
Closes #6033
2014-02-04 10:51:24 -05:00
Kamil Pekala 0da6cc9118 docs($compile): fixed syntax error.
"how to" was written twice in a row.

Closes #6110
2014-02-04 08:45:48 -05:00
John Kurlak cc60ba1f35 docs($q): fixed grammatical error
"Promises" should be of the possessive form.

Closes #6082
2014-02-04 00:00:31 -08:00
Igor Minar 64d58a5b52 refactor(mocks): simplify the implementation 2014-02-03 22:41:18 -08:00
Wes Alvaro 3bf4390339 fix(mocks): always call functions injected with inject with this set to the current spec
Currently when a function is injected inside of a test we set the context to undefined which
is a bug.

Closes #6102
2014-02-03 22:25:30 -08:00
gdi2290 e7ac7aa43b chore(Gruntfile.js, package.json): use load-grunt-tasks and move grunt-contrib-jshint into devDependencies
Closes #6085
2014-02-03 19:25:47 -05:00
PatrickJS 37781ed145 style(License): update copyright year
Closes #6090
2014-02-03 19:19:29 -05:00
Igor Minar 19ba6510d0 chore(ngClass): remove debugger statement from an e2e test 2014-02-03 11:43:14 -08:00
jenkins bc5ceee275 chore(release): update cdn version 2014-02-03 10:03:06 -08:00
jenkins 106af49258 chore(release): start v1.2.12 (1.2.12) 2014-02-03 09:41:17 -08:00
jenkins d5eedf38db chore(release): cut v1.2.11 release 2014-02-03 09:40:03 -08:00
Tobias Bosch c0c0b2b674 docs(changelog): release notes for 1.2.11 2014-02-03 09:28:45 -08:00
Caitlin Potter ce1f1f97f0 fix(ngResource): don't append number to '$' in url param value when encoding URI
Previously, if a URL parameter value included a $, it would replace the dollar sign with a literal
'$1' for mysterious reasons. Using a function rather than a replacement string circumvents this
behaviour and produces a more expected result.

Closes #6003
Closes #6004
2014-02-03 11:12:07 -05:00
Alan Rubin 8205158e47 docs(animations): ngClass usage should link to ngClass documentation
Fixing reference to ngClass documentation

Closes #6089
2014-02-03 09:14:45 -05:00
Igor Minar 6609e3da76 fix(http): make jshint happy 2014-01-31 17:03:30 -08:00
Jorg ef210e5e11 fix($http): update httpBackend to use ActiveXObject on IE8 if necessary
window.XMLHttpRequest is not always available in IE8 despite it not running in quirks mode,
in which case Angular should be using the ActiveXObject instead. Just checking the browser
version is taking too many shortcuts.

Closes #5677
Closes #5679
2014-01-31 16:52:42 -08:00
Stéphane Reynaud fd61e222c3 docs(guide/templates.css-styling): fix "{{}}"
Replace {{}} to `{{}}` so that "{{}}" is rendered in the HTML page

Closes #5950
2014-01-31 16:31:06 -08:00
Lucas Galfasó 074b0675a1 fix($q): make $q.reject support finally and catch
Add support for the functions `finally` and `catch` to the
promise returned by `$q.reject`

Closes #6048
Closes #6076
2014-01-31 14:38:06 -05:00
Caitlin Potter 5ed721b9b5 fix($compile): retain CSS classes added in cloneAttachFn on asynchronous directives
Previously, classes added to asynchronous directive elements during the clone
attach function would not persist after the node is merged with the template, prior
to linking. This change corrects this behaviour and brings it in line with synchronous
directives.

Closes #5439
Closes #5617
2014-01-31 12:45:35 -05:00
Vojta Jina c22ab5d2e2 chore(travis): remove BrowserStack credentials
Closes #5596
2014-01-31 07:48:36 -08:00
Igor Minar 339a1658cd fix(filterFilter): don't interpret dots in predicate object fields as paths
Closes #6005
Closes #6009
2014-01-31 03:16:46 -08:00
Shawn Flahave 29432ffe37 Edited the 'Flushing HTTP requests' section
Minor grammatical edits in the Flushing HTTP requests section.
2014-01-30 16:52:06 -08:00
Brad Williams caed2dfe4f fix(docs): clarify doc for "args" in $broadcast and $emit
Closes #6047.
2014-01-30 16:50:08 -08:00
Igor Minar 7f4edaff6e chore(build): add jscs code style check to our build
Closes #6062
2014-01-30 11:39:53 -08:00
Igor Minar 6dcfccb32c chore(grunt): sort the grunt task load statements 2014-01-30 10:51:20 -08:00
Clark Pan e2173f9101 docs($provide): return instance of Ping, rather than constructor
Updating $provide.service method docs

The previous example provided for the service method did not work.  I've updated the example to a working example.

I think this version of the example will probably make more sense to most people, and the factory method would be
a better place for this sort of example.

Closes #6008
2014-01-29 09:10:01 -05:00
Manan 7a78aed160 docs(compile/nodomevents): fix typo ng-mode -> ng-model
correcting directive name to ng-model instead of ng-mode in nodomevents.ngdoc

Correcting use of ng-model directive

Closes #6036
2014-01-29 08:51:02 -05:00
Julie 7aef2d54e0 test(docs): convert example end to end doc tests from scenario runner to protractor
Thanks to jeffbcross, petebacondarwin, btford, jdeboer, tbosch for contributions!

Closes #6023
2014-01-28 14:14:20 -05:00
Julie ce37ae2868 docs(cookbook): remove the cookbook docs
The cookbook docs are now superceded by the guide. They are no longer available
in any menus and the only way to find them is to search for them. Remove!

Closes #5967
2014-01-28 14:12:52 -05:00
John Papa 95f0bf9b52 fix(mocks): refactor currentSpec to work w/ Jasmine 2
Closes #5662
2014-01-27 22:26:18 -08:00
Igor Minar 8a0be355a9 docs(triaging.md): update the 'PRs plz!' label name 2014-01-27 21:17:53 -08:00
Igor Minar 849a1489c7 style(triaging.md): removing ws 2014-01-27 12:06:17 -08:00
Brian Ford f54f0f98a0 chore(docs): remove note about removing disqus 2014-01-27 11:46:18 -08:00
David Nelson 766b3d5c87 docs(select): rephase note on ngOptions
added 'an' and 'the' to ngOptions sentence

Closes #5993
2014-01-26 15:45:04 -05:00
David Nelson 4f735b0605 docs(ngSwitch): fixed typo 'choses' to 'chooses'
Closes #5992
2014-01-26 15:42:27 -05:00
jenkins 319dd1a449 chore(release): update cdn version 2014-01-24 19:27:18 -08:00
jenkins 88a14b4e25 chore(release): start v1.2.11 (1.2.11) 2014-01-24 15:42:49 -08:00
374 changed files with 10356 additions and 12700 deletions
+5
View File
@@ -0,0 +1,5 @@
{
"disallowKeywords": ["with"],
"disallowTrailingWhitespace": true,
"requireRightStickedOperators": ["!"]
}
+20
View File
@@ -0,0 +1,20 @@
// This is an incomplete TODO list of checks we want to start enforcing
//
// The goal is to enable these checks one by one by moving them to .jscs.json along with commits
// that correct the existing code base issues and make the new check pass.
{
"requireCurlyBraces": ["if", "else", "for", "while", "do", "try", "catch"],
"requireSpaceAfterKeywords": ["if", "else", "for", "while", "do", "switch", "return", "try", "catch"],
"disallowLeftStickedOperators": ["?", "+", "-", "/", "*", "=", "==", "===", "!=", "!==", ">", ">=", "<", "<="],
"disallowRightStickedOperators": ["?", "+", "/", "*", ":", "=", "==", "===", "!=", "!==", ">", ">=", "<", "<="],
"requireLeftStickedOperators": [","],
"disallowImplicitTypeConversion": ["string"],
"disallowMultipleLineBreaks": true,
"disallowKeywordsOnNewLine": ["else"],
"requireLineFeedAtFileEnd": true,
"validateJSDoc": {
"checkParamNames": true,
"requireParamTypes": true
}
}
+16 -6
View File
@@ -2,15 +2,19 @@ language: node_js
node_js:
- 0.10
branches:
except:
- /^g3_.*$/
env:
matrix:
- JOB=unit
- JOB=e2e
- JOB=e2e TEST_TARGET=jqlite
- JOB=e2e TEST_TARGET=jquery
- JOB=e2e TEST_TARGET=doce2e
global:
- SAUCE_USERNAME=angular-ci
- SAUCE_ACCESS_KEY=9b988f434ff8-fbca-8aa4-4ae3-35442987
- BROWSER_STACK_USERNAME=VojtaJina
- BROWSER_STACK_ACCESS_KEY=HAfHZaypxAc3PEUrUU9a
- LOGS_DIR=/tmp/angular-build/logs
- BROWSER_PROVIDER_READY_FILE=/tmp/sauce-connect-ready
@@ -18,9 +22,7 @@ before_script:
- mkdir -p $LOGS_DIR
- ./lib/sauce/sauce_connect_setup.sh
- npm install -g grunt-cli
- grunt bower
- grunt bower
- grunt package-without-bower
- grunt package
- ./scripts/travis/wait_for_browser_provider.sh
script:
@@ -28,3 +30,11 @@ script:
after_script:
- ./scripts/travis/print_logs.sh
notifications:
webhooks:
urls:
- https://webhooks.gitter.im/e/d2120f3f2bb39a4531b2
on_success: change # options: [always|never|change] default: always
on_failure: always # options: [always|never|change] default: always
on_start: false # default: false
+241 -3
View File
@@ -1,3 +1,217 @@
<a name="1.2.14"></a>
# 1.2.14 feisty-cryokinesis (2014-03-01)
## Bug Fixes
- **$animate:**
- delegate down to addClass/removeClass if setClass is not found
([18c41af0](https://github.com/angular/angular.js/commit/18c41af065006a804a3d38eecca7ae184103ece9),
[#6463](https://github.com/angular/angular.js/issues/6463))
- ensure all comment nodes are removed during a leave animation
([f4f1f43d](https://github.com/angular/angular.js/commit/f4f1f43d5140385bbf070510975f72b65196e08a),
[#6403](https://github.com/angular/angular.js/issues/6403))
- only block keyframes if a stagger is set to occur
([e71e7b6c](https://github.com/angular/angular.js/commit/e71e7b6cae57f25c5837dda98551c8e0a5cb720d),
[#4225](https://github.com/angular/angular.js/issues/4225))
- ensure that animateable directives cancel expired leave animations
([e9881991](https://github.com/angular/angular.js/commit/e9881991ca0a5019d3a4215477738ed247898ba0),
[#5886](https://github.com/angular/angular.js/issues/5886))
- ensure all animated elements are taken care of during the closing timeout
([99720fb5](https://github.com/angular/angular.js/commit/99720fb5ab7259af37f708bc4eeda7cbbe790a69),
[#6395](https://github.com/angular/angular.js/issues/6395))
- fix for TypeError Cannot call method 'querySelectorAll' in cancelChildAnimations
([c914cd99](https://github.com/angular/angular.js/commit/c914cd99b3aaf932e3c0e2a585eead7b76621f1b),
[#6205](https://github.com/angular/angular.js/issues/6205))
- **$http:**
- do not add trailing question
([c8e03e34](https://github.com/angular/angular.js/commit/c8e03e34b27a8449d8e1bfe0e3801d6a67ae2c49),
[#6342](https://github.com/angular/angular.js/issues/6342))
- send GET requests by default
([267b2173](https://github.com/angular/angular.js/commit/267b217376ed466e9f260ecfdfa15a8227c103ff),
[#5985](https://github.com/angular/angular.js/issues/5985), [#6401](https://github.com/angular/angular.js/issues/6401))
- **$parse:** reduce false-positives in isElement tests
([5fe1f39f](https://github.com/angular/angular.js/commit/5fe1f39f027c6f2c6a530975dd5389d788d3c0eb),
[#4805](https://github.com/angular/angular.js/issues/4805), [#5675](https://github.com/angular/angular.js/issues/5675))
- **input:** use ValidityState to determine validity
([c2d447e3](https://github.com/angular/angular.js/commit/c2d447e378dd72d1b955f476bd5bf249625b4dab),
[#4293](https://github.com/angular/angular.js/issues/4293), [#2144](https://github.com/angular/angular.js/issues/2144), [#4857](https://github.com/angular/angular.js/issues/4857), [#5120](https://github.com/angular/angular.js/issues/5120), [#4945](https://github.com/angular/angular.js/issues/4945), [#5500](https://github.com/angular/angular.js/issues/5500), [#5944](https://github.com/angular/angular.js/issues/5944))
- **isElement:** reduce false-positives in isElement tests
([75515852](https://github.com/angular/angular.js/commit/75515852ea9742d3d84a0f463c2a2c61ef2b7323))
- **jqLite:**
- properly toggle multiple classes
([4e73c80b](https://github.com/angular/angular.js/commit/4e73c80b17bd237a8491782bcf9e19f1889e12ed),
[#4467](https://github.com/angular/angular.js/issues/4467), [#6448](https://github.com/angular/angular.js/issues/6448))
- make jqLite('<iframe src="someurl">').contents() return iframe document, as in jQuery
([05fbed57](https://github.com/angular/angular.js/commit/05fbed5710b702c111c1425a9e241c40d13b0a54),
[#6320](https://github.com/angular/angular.js/issues/6320), [#6323](https://github.com/angular/angular.js/issues/6323))
- **numberFilter:** convert all non-finite/non-numbers/non-numeric strings to the empty string
([cceb455f](https://github.com/angular/angular.js/commit/cceb455fb167571e26341ded6b595dafd4d92bc6),
[#6188](https://github.com/angular/angular.js/issues/6188), [#6261](https://github.com/angular/angular.js/issues/6261))
- **$parse:** support trailing commas in object & array literals
([6b049c74](https://github.com/angular/angular.js/commit/6b049c74ccc9ee19688bb9bbe504c300e61776dc))
- **ngHref:** bind ng-href to xlink:href for SVGAElement
([2bce71e9](https://github.com/angular/angular.js/commit/2bce71e9dc10c8588f9eb599a0cd2e831440fc48),
[#5904](https://github.com/angular/angular.js/issues/5904))
## Features
- **$animate:** animate dirty, pristine, valid, invalid for form/fields
([33443966](https://github.com/angular/angular.js/commit/33443966c8e8cac85a863bb181d4a4aff00baab4),
[#5378](https://github.com/angular/angular.js/issues/5378))
## Performance Improvements
- **$animate:** use rAF instead of timeouts to issue animation callbacks
([4c4537e6](https://github.com/angular/angular.js/commit/4c4537e65e6cf911c9659b562d89e3330ce3ffae))
- **$cacheFactory:** skip LRU bookkeeping for caches with unbound capacity
([a4078fca](https://github.com/angular/angular.js/commit/a4078fcae4a33295675d769a1cd067837029da2f),
[#6193](https://github.com/angular/angular.js/issues/6193), [#6226](https://github.com/angular/angular.js/issues/6226))
<a name="1.2.13"></a>
# 1.2.13 romantic-transclusion (2014-02-14)
## Bug Fixes
- **$animate:** ensure $animate doesn't break natural CSS transitions
([4f84f6b3](https://github.com/angular/angular.js/commit/4f84f6b3e4210ae1eb14728a46d43dd961700a0c),
[#6019](https://github.com/angular/angular.js/issues/6019))
- **$compile:**
- ensure element transclusion directives are linked with comment element
([e7338d3f](https://github.com/angular/angular.js/commit/e7338d3f27e8824196136a18e1c3e0fcf51a0e28),
[#6006](https://github.com/angular/angular.js/issues/6006), [#6101](https://github.com/angular/angular.js/issues/6101))
- support templates with table content root nodes
([e7338d3f](https://github.com/angular/angular.js/commit/31c450bcee53d0a3827b7e0a611e9013b2496506),
[#2848](https://github.com/angular/angular.js/issues/2848), [#1459](https://github.com/angular/angular.js/issues/1459), [#3647](https://github.com/angular/angular.js/issues/3647), [#3241](https://github.com/angular/angular.js/issues/3241))
- **input:**
- don't apply textInput to `<input type="file">`
([a9fcb0d0](https://github.com/angular/angular.js/commit/a9fcb0d0fc6456f80501b8820d02b04d7c15b6d6),
[#6247](https://github.com/angular/angular.js/issues/6247), [#6231](https://github.com/angular/angular.js/issues/6231))
- setViewValue on compositionend
([2b730271](https://github.com/angular/angular.js/commit/2b7302713674506fdbcdc396c38f18dcb90dee8c),
[#6058](https://github.com/angular/angular.js/issues/6058), [#5433](https://github.com/angular/angular.js/issues/5433))
## Features
- **filterFilter:** support deeply nested predicate objects
([b4eed8ad](https://github.com/angular/angular.js/commit/b4eed8ad94ce9719540462c1ee969dfd3c6b2355),
[#6215](https://github.com/angular/angular.js/issues/6215))
## Breaking Changes
- **$animate:**
- due to [4f84f6b3](https://github.com/angular/angular.js/commit/4f84f6b3e4210ae1eb14728a46d43dd961700a0c),
ngClass and {{ class }} will now call the `setClass`
animation callback instead of addClass / removeClass when both a
addClass/removeClass operation is being executed on the element during the animation.
Please include the setClass animation callback as well as addClass and removeClass within
your JS animations to work with ngClass and {{ class }} directives.
- due to [cf5e463a](https://github.com/angular/angular.js/commit/cf5e463abd2c23f62e9c2e6361e6c53048c8910e),
Both the `$animate:before` and `$animate:after` DOM events must be now
registered prior to the $animate operation taking place. The `$animate:close` event
can be registered anytime afterwards.
DOM callbacks used to fired for each and every animation operation that occurs within the
$animate service provided in the ngAnimate module. This may end up slowing down an
application if 100s of elements are being inserted into the page. Therefore after this
change callbacks are only fired if registered on the element being animated.
<a name="1.2.12"></a>
# 1.2.12 cauliflower-eradication (2014-02-07)
## Bug Fixes
- **$compile:** retain CSS classes added in cloneAttachFn on asynchronous directives
([5ed721b9](https://github.com/angular/angular.js/commit/5ed721b9b5e95ae08450e1ae9d5202e7f3f79295),
[#5439](https://github.com/angular/angular.js/issues/5439), [#5617](https://github.com/angular/angular.js/issues/5617))
- **$http:**
- ignore xhr.responseType setter exception if value is "json"
([24699ee8](https://github.com/angular/angular.js/commit/24699ee8f04c1f1459be1d36207e654421d58ff0),
[#6115](https://github.com/angular/angular.js/issues/6115), [#6122](https://github.com/angular/angular.js/issues/6122))
- update httpBackend to use ActiveXObject on IE8 if necessary
([ef210e5e](https://github.com/angular/angular.js/commit/ef210e5e119db4f5bfc9d2428b19f9b335c4f976),
[#5677](https://github.com/angular/angular.js/issues/5677), [#5679](https://github.com/angular/angular.js/issues/5679))
- **$locale:** minor grammar amends for the locale `locale_lt`
([95be253f](https://github.com/angular/angular.js/commit/95be253fe55d35336d425d3d600a36158fc3519d),
[#6164](https://github.com/angular/angular.js/issues/6164))
- **$q:** make $q.reject support `finally` and `catch`
([074b0675](https://github.com/angular/angular.js/commit/074b0675a1f97dce07f520f1ae6198ed3c604000),
[#6048](https://github.com/angular/angular.js/issues/6048), [#6076](https://github.com/angular/angular.js/issues/6076))
- **docs:** clarify doc for "args" in $broadcast and $emit
([caed2dfe](https://github.com/angular/angular.js/commit/caed2dfe4feeac5d19ecea2dbb1456b7fde21e6d),
[#6047](https://github.com/angular/angular.js/issues/6047))
- **filterFilter:** don't interpret dots in predicate object fields as paths
([339a1658](https://github.com/angular/angular.js/commit/339a1658cd9bfa5e322a01c45aa0a1df67e3a842),
[#6005](https://github.com/angular/angular.js/issues/6005), [#6009](https://github.com/angular/angular.js/issues/6009))
- **http:** make jshint happy
([6609e3da](https://github.com/angular/angular.js/commit/6609e3da76dd898cfe85f75f23ab2e39fee65fe5))
- **jqLite:** trim HTML string in jqLite constructor
([36d37c0e](https://github.com/angular/angular.js/commit/36d37c0e3880c774d20c014ade60d2331beefa15),
[#6053](https://github.com/angular/angular.js/issues/6053))
- **mocks:**
- rename mock.animate to ngAnimateMock and ensure it contains all test helper code for ngAnimate
([4224cd51](https://github.com/angular/angular.js/commit/4224cd5182bc93e4a210f75e0a4e4de7f3c544e8),
[#5822](https://github.com/angular/angular.js/issues/5822), [#5917](https://github.com/angular/angular.js/issues/5917))
- remove usage of $animate.flushNext in favour of queing
([906fdad0](https://github.com/angular/angular.js/commit/906fdad0f95465842e336e057ea97d0633712189))
- always call functions injected with `inject` with `this` set to the current spec
([3bf43903](https://github.com/angular/angular.js/commit/3bf43903397c703aa2e9ba1e1a48dbc9e8286ee2),
[#6102](https://github.com/angular/angular.js/issues/6102))
- refactor currentSpec to work w/ Jasmine 2
([95f0bf9b](https://github.com/angular/angular.js/commit/95f0bf9b526fda8964527c6d4aef1ad50a47f1f3),
[#5662](https://github.com/angular/angular.js/issues/5662))
- **ngMock:** return false from mock $interval.cancel() when no argument is supplied
([dd24c783](https://github.com/angular/angular.js/commit/dd24c78373b5d24ecb3b9d19e61e1b3b6c74d155),
[#6103](https://github.com/angular/angular.js/issues/6103))
- **ngResource:**
- don't filter "$"-prefixed properties from ngResource requests/responses
([d2e4e499](https://github.com/angular/angular.js/commit/d2e4e499862aeca157dbe7a7422c465e7c79205e),
[#5666](https://github.com/angular/angular.js/issues/5666), [#6080](https://github.com/angular/angular.js/issues/6080), [#6033](https://github.com/angular/angular.js/issues/6033))
- don't append number to '$' in url param value when encoding URI
([ce1f1f97](https://github.com/angular/angular.js/commit/ce1f1f97f0ebf77941b2bdaf5e8352d33786524d),
[#6003](https://github.com/angular/angular.js/issues/6003), [#6004](https://github.com/angular/angular.js/issues/6004))
## Breaking Changes
The animation mock module has been renamed from `mock.animate` to `ngAnimateMock`. In addition to the rename, animations will not block within test code even when ngAnimateMock is used. However, all function calls to $animate will be recorded into `$animate.queue` and are available within test code to assert animation calls. In addition, `$animate.triggerReflow()` is now only available when `ngAnimateMock` is used.
<a name="1.2.11"></a>
# 1.2.11 cryptocurrency-hyperdeflation (2014-02-03)
## Bug Fixes
- **$compile:** retain CSS classes added in cloneAttachFn on asynchronous directives
([5ed721b9](https://github.com/angular/angular.js/commit/5ed721b9b5e95ae08450e1ae9d5202e7f3f79295),
[#5439](https://github.com/angular/angular.js/issues/5439), [#5617](https://github.com/angular/angular.js/issues/5617))
- **$http:** update httpBackend to use ActiveXObject on IE8 if necessary
([ef210e5e](https://github.com/angular/angular.js/commit/ef210e5e119db4f5bfc9d2428b19f9b335c4f976),
[#5677](https://github.com/angular/angular.js/issues/5677), [#5679](https://github.com/angular/angular.js/issues/5679))
- **$q:** make $q.reject support `finally` and `catch`
([074b0675](https://github.com/angular/angular.js/commit/074b0675a1f97dce07f520f1ae6198ed3c604000),
[#6048](https://github.com/angular/angular.js/issues/6048), [#6076](https://github.com/angular/angular.js/issues/6076))
- **filterFilter:** don't interpret dots in predicate object fields as paths
([339a1658](https://github.com/angular/angular.js/commit/339a1658cd9bfa5e322a01c45aa0a1df67e3a842),
[#6005](https://github.com/angular/angular.js/issues/6005), [#6009](https://github.com/angular/angular.js/issues/6009))
- **mocks:** refactor currentSpec to work w/ Jasmine 2
([95f0bf9b](https://github.com/angular/angular.js/commit/95f0bf9b526fda8964527c6d4aef1ad50a47f1f3),
[#5662](https://github.com/angular/angular.js/issues/5662))
- **ngResource:** don't append number to '$' in url param value when encoding URI
([ce1f1f97](https://github.com/angular/angular.js/commit/ce1f1f97f0ebf77941b2bdaf5e8352d33786524d),
[#6003](https://github.com/angular/angular.js/issues/6003), [#6004](https://github.com/angular/angular.js/issues/6004))
<a name="1.2.10"></a>
# 1.2.10 augmented-serendipity (2014-01-24)
@@ -58,6 +272,30 @@
([4ae3184c](https://github.com/angular/angular.js/commit/4ae3184c5915aac9aa00889aa2153c8e84c14966),
[#4278](https://github.com/angular/angular.js/issues/4278), [#4225](https://github.com/angular/angular.js/issues/4225))
## Breaking Changes
- **$http:** due to [e1cfb195](https://github.com/angular/angular.js/commit/e1cfb1957feaf89408bccf48fae6f529e57a82fe),
it is now necessary to separately specify default HTTP headers for PUT, POST and PATCH requests, as these no longer share a single object.
To migrate your code, follow the example below:
Before:
// Will apply to POST, PUT and PATCH methods
$httpProvider.defaults.headers.post = {
"X-MY-CSRF-HEADER": "..."
};
After:
// POST, PUT and PATCH default headers must be specified separately,
// as they do not share data.
$httpProvider.defaults.headers.post =
$httpProvider.defaults.headers.put =
$httpProviders.defaults.headers.patch = {
"X-MY-CSRF-HEADER": "..."
};
<a name="1.2.8"></a>
# 1.2.8 interdimensional-cartography (2014-01-10)
@@ -2200,7 +2438,7 @@ _Note: This release also contains all bug fixes available in [1.0.5](#1.0.5)._
- **ngClass:** keep track of old ngClass value manually
([5f5d4fea](https://github.com/angular/angular.js/commit/5f5d4feadbfa9d8ecc8150041dfd2bca2b2e9fea),
[#1637](https://github.com/angular/angular.js/issues/1637))
- **ngSwitch:** make ngSwitch compatible with controller backwards-compatiblity module
- **ngSwitch:** make ngSwitch compatible with controller backwards-compatibility module
([9b7c1d0f](https://github.com/angular/angular.js/commit/9b7c1d0f7ce442d4ad2ec587e66d2d335e64fa4e))
- **Filters:**
- **date:** invert timezone sign and always display sign
@@ -3556,7 +3794,7 @@ behavior and migrate your controllers one at a time: <https://gist.github.com/16
## Bug Fixes:
- [ng:view]: ignore stale xhr callbacks - fixes issues caused by race-conditions which occured when
- [ng:view]: ignore stale xhr callbacks - fixes issues caused by race-conditions which occurred when
user navigated to a new route before the current route finished loading
(issue [#619](https://github.com/angular/angular.js/issues/619))
- [ng:form] should always be a block level (css) element
@@ -3873,7 +4111,7 @@ behavior and migrate your controllers one at a time: <https://gist.github.com/16
- [jqLite]
- added `show()`, `hide()` and `eq()` methods to jqlite
([commit](https://github.com/angular/angular.js/commit/7a3fdda9650a06792d9278a8cef06d544d49300f))
- added $defer.cancel to support cancelation of tasks defered via the [$defer] service
- added $defer.cancel to support cancellation of tasks defered via the [$defer] service
- [date] filter
- added support for `full`, `long`, `medium` and `short` date-time format flags
([commit](https://github.com/angular/angular.js/commit/3af1e7ca2ee8c2acd69e5bcbb3ffc1bf51239285))
+23 -17
View File
@@ -3,12 +3,25 @@
We'd love for you to contribute to our source code and to make AngularJS even better than it is
today! Here are the guidelines we'd like you to follow:
## Got a Question or Problem?
- [Code of Conduct](#coc)
- [Question or Problem?](#question)
- [Issues and Bugs](#issue)
- [Feature Requests](#feature)
- [Submission Guidelines](#submit)
- [Coding Rules](#rules)
- [Commit Message Guidelines](#commit)
- [Signing the CLA](#cla)
- [Further Info](#info)
## <a name="coc"></a> Code of Conduct
Help us keep Angular open and inclusive. Please read and follow our [Code of Conduct][coc].
## <a name="question"></a> Got a Question or Problem?
If you have questions about how to use AngularJS, please direct these to the [Google Group][groups]
discussion list or [StackOverflow][stackoverflow]. We are also available on [IRC][irc].
## Found an Issue?
## <a name="issue"></a> Found an Issue?
If you find a bug in the source code or a mistake in the documentation, you can help us by
submitting and issue to our [GitHub Repository][github]. Even better you can submit a Pull Request
with a fix.
@@ -19,7 +32,7 @@ approach is to submit a patch to the I18N project directly, instead of submittin
**Please see the Submission Guidelines below**.
## Want a Feature?
## <a name="feature"></a> Want a Feature?
You can request a new feature by submitting an issue to our [GitHub Repository][github]. If you
would like to implement a new feature then consider what kind of change it is:
@@ -30,7 +43,7 @@ project.
* **Small Changes** can be crafted and submitted to [GitHub Repository][github] as a Pull Request.
## Want a Doc Fix?
## <a name="docs"></a> Want a Doc Fix?
If you want to help improve the docs, it's a good idea to let others know what you're working on to
minimize duplication of effort. Before starting, check out the issue queue for [Milestone:Docs Only](https://github.com/angular/angular.js/issues?milestone=24&state=open).
Comment on an issue to let others know what you're working on, or create a new issue if your work
@@ -42,7 +55,7 @@ is labeled "docs:" and follows the **Git Commit Guidelines** outlined below.
If you're just making a small change, don't worry about filing an issue first. Use the friendly blue "Improve this doc" button at the top right of the doc page to fork the repository in-place and make a quick change on the fly.
## Submission Guidelines
## <a name="submit"></a> Submission Guidelines
### Submitting an Issue
Before you submit your issue search the archive, maybe your question was already answered.
@@ -140,15 +153,7 @@ from the main (upstream) repository:
git pull --ff upstream master
```
### GitHub Pull Request Helper
We track Pull Requests by attaching labels and assigning to milestones. For some reason GitHub
does not provide a good UI for managing labels on Pull Requests (unlike Issues). We have developed
a simple Chrome Extension that enables you to view (and manage if you have permission) the labels
on Pull Requests. You can get the extension from the Chrome WebStore -
[GitHub PR Helper][github-pr-helper]
## Coding Rules
## <a name="rules"></a> Coding Rules
To ensure consistency throughout the source code, keep these rules in mind as you are working:
* All features or bug fixes **must be tested** by one or more [specs][unit-testing].
@@ -168,7 +173,7 @@ To ensure consistency throughout the source code, keep these rules in mind as yo
* We **don't go crazy with type annotations** for private internal APIs unless it's an internal API
that is used throughout AngularJS. The best guidance is to do what makes the most sense.
## Git Commit Guidelines
## <a name="commit"></a> Git Commit Guidelines
We have very precise rules over how our git commit messages can be formatted. This leads to **more
readable messages** that are easy to follow when looking through the **project history**. But also,
@@ -225,7 +230,7 @@ reference GitHub issues that this commit **Closes**.
A detailed explanation can be found in this [document][commit-message-format].
## 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!
@@ -234,7 +239,7 @@ changes to be accepted, the CLA must be signed. It's a quick process, we promise
* For corporations we'll need you to
[print, sign and one of scan+email, fax or mail the form][corporate-cla].
## Further Information
## <a name="info"></a> Further Information
You can find out more detailed information about contributing in the
[AngularJS documentation][contributing].
@@ -258,5 +263,6 @@ You can find out more detailed information about contributing in the
[corporate-cla]: http://code.google.com/legal/corporate-cla-v1.0.html
[commit-message-format]: https://docs.google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y/edit#
[github-pr-helper]: https://chrome.google.com/webstore/detail/github-pr-helper/mokbklfnaddkkbolfldepnkfmanfhpen
[coc]: https://github.com/angular/code-of-conduct/blob/master/CODE_OF_CONDUCT.md
[![Analytics](https://ga-beacon.appspot.com/UA-8594346-11/angular.js/CONTRIBUTING.md?pixel)](https://github.com/igrigorik/ga-beacon)
+21 -32
View File
@@ -4,17 +4,8 @@ var path = require('path');
module.exports = function(grunt) {
//grunt plugins
grunt.loadNpmTasks('grunt-bump');
grunt.loadNpmTasks('grunt-contrib-clean');
grunt.loadNpmTasks('grunt-contrib-copy');
grunt.loadNpmTasks('grunt-contrib-connect');
grunt.loadNpmTasks('grunt-contrib-compress');
grunt.loadNpmTasks('grunt-jasmine-node');
grunt.loadNpmTasks('grunt-ddescribe-iit');
grunt.loadNpmTasks('grunt-merge-conflict');
grunt.loadNpmTasks('grunt-parallel');
grunt.loadNpmTasks('grunt-shell');
grunt.loadNpmTasks('grunt-contrib-jshint');
require('load-grunt-tasks')(grunt);
grunt.loadTasks('lib/grunt');
var NG_VERSION = util.getVersion();
@@ -32,7 +23,7 @@ module.exports = function(grunt) {
parallel: {
travis: {
tasks: [
util.parallelTask(['test:unit', 'test:docgen', 'test:promises-aplus', 'tests:docs'], {stream: true}),
util.parallelTask(['test:unit', 'test:promises-aplus', 'tests:docs'], {stream: true}),
util.parallelTask(['test:e2e'])
]
}
@@ -87,9 +78,7 @@ module.exports = function(grunt) {
jqlite: 'karma-jqlite.conf.js',
jquery: 'karma-jquery.conf.js',
docs: 'karma-docs.conf.js',
modules: 'karma-modules.conf.js',
//NOTE run grunt test:e2e instead and it will start a webserver for you
end2end: 'karma-e2e.conf.js'
modules: 'karma-modules.conf.js'
},
@@ -101,8 +90,10 @@ module.exports = function(grunt) {
},
runprotractor: {
normal: 'protractor-conf.js'
protractor: {
normal: 'protractor-conf.js',
travis: 'protractor-travis-conf.js',
jenkins: 'protractor-jenkins-conf.js'
},
@@ -147,6 +138,13 @@ module.exports = function(grunt) {
}
},
jscs: {
src: ['src/**/*.js', 'test/**/*.js'],
options: {
config: ".jscs.json"
}
},
build: {
scenario: {
dest: 'build/angular-scenario.js',
@@ -219,14 +217,6 @@ module.exports = function(grunt) {
},
docs: {
process: ['build/docs/*.html', 'build/docs/.htaccess']
},
"jasmine_node": {
projectRoot: 'docs/spec'
},
"ddescribe-iit": {
files: [
'test/**/*.js',
@@ -288,22 +278,21 @@ module.exports = function(grunt) {
//alias tasks
grunt.registerTask('test', 'Run unit, docs and e2e tests with Karma', ['jshint', 'package','test:unit','test:promises-aplus', 'tests:docs', 'test:e2e', 'webdriver', 'runprotractor:normal']);
grunt.registerTask('test', 'Run unit, docs and e2e tests with Karma', ['jshint', 'package','test:unit','test:promises-aplus', 'tests:docs', 'test:protractor']);
grunt.registerTask('test:jqlite', 'Run the unit tests with Karma' , ['tests:jqlite']);
grunt.registerTask('test:jquery', 'Run the jQuery unit tests with Karma', ['tests:jquery']);
grunt.registerTask('test:modules', 'Run the Karma module tests with Karma', ['tests:modules']);
grunt.registerTask('test:docs', 'Run the doc-page tests with Karma', ['package', 'tests:docs']);
grunt.registerTask('test:unit', 'Run unit, jQuery and Karma module tests with Karma', ['tests:jqlite', 'tests:jquery', 'tests:modules']);
grunt.registerTask('test:e2e', 'Run the end to end tests with Karma and keep a test server running in the background', ['connect:testserver', 'tests:end2end']);
// This should eventually replace test:e2e
grunt.registerTask('test:protractor', 'Run the end to end tests with Protractor and keep a test server running in the background', ['webdriver', 'connect:testserver', 'runprotractor:normal']);
grunt.registerTask('test:docgen', ['jasmine_node']);
grunt.registerTask('test:protractor', 'Run the end to end tests with Protractor and keep a test server running in the background', ['webdriver', 'connect:testserver', 'protractor:normal']);
grunt.registerTask('test:travis-protractor', 'Run the end to end tests with Protractor for Travis CI builds', ['connect:testserver', 'protractor:travis']);
grunt.registerTask('test:ci-protractor', 'Run the end to end tests with Protractor for Jenkins CI builds', ['webdriver', 'connect:testserver', 'protractor:jenkins']);
grunt.registerTask('test:e2e', 'Alias for test:protractor', ['test:protractor']);
grunt.registerTask('test:promises-aplus',['build:promises-aplus-adapter','shell:promises-aplus-tests']);
grunt.registerTask('minify', ['bower','clean', 'build', 'minall']);
grunt.registerTask('webserver', ['connect:devserver']);
grunt.registerTask('package', ['bower','clean', 'buildall', 'minall', 'collect-errors', 'docs', 'copy', 'write', 'compress']);
grunt.registerTask('package-without-bower', ['clean', 'buildall', 'minall', 'collect-errors', 'docs', 'copy', 'write', 'compress']);
grunt.registerTask('ci-checks', ['ddescribe-iit', 'merge-conflict', 'jshint']);
grunt.registerTask('ci-checks', ['ddescribe-iit', 'merge-conflict', 'jshint', 'jscs']);
grunt.registerTask('default', ['package']);
};
+1 -1
View File
@@ -1,6 +1,6 @@
The MIT License
Copyright (c) 2010-2012 Google, Inc. http://angularjs.org
Copyright (c) 2010-2014 Google, Inc. http://angularjs.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
+115 -44
View File
@@ -1,63 +1,134 @@
# Triage new issues/PRs on github
This document shows the steps the Angular team is using to triage issues.
The labels are used later on for planning releases.
## Tips ##
* install [github pr helper extension](https://github.com/petebacondarwin/github-pr-helper) and become 356% more productive
* Label "resolution:*"
* these tags can be used for labeling a closed issue/PR with a reason why it was closed. (we can add reasons as we need them, right there are only a few rejection reasons. it doesn't make sense to label issues that were fixed or prs that were merged)
The labels are used later on for [planning releases](#assigning-work).
## Automatic processing ##
## Automatic processing
We have automatic tools (e.g. Mary Poppins) that automatically add comments / labels to issues and PRs.
The following is done automatically and should not be done manually:
We have tools (e.g. [Mary Poppins]) that automatically add comments and labels to issues and PRs.
The following is done automatically so you don't have to worry about it:
* Label "cla: yes" or "cla: no" for pull requests
* Label `cla: yes` or `cla: no` for pull requests
* Label `GH: *`
* `PR` - issue is a PR
* `issue` - otherwise
## Process ##
1. Open list of [non triaged issues](https://github.com/angular/angular.js/issues?direction=desc&milestone=none&page=1&sort=created&state=open)
## Triaging Process
This process based on the idea of minimizing user pain
[from this blog post](http://www.lostgarden.com/2008/05/improving-bug-triage-with-user-pain.html).
1. Open the list of [non triaged issues](https://github.com/angular/angular.js/issues?direction=desc&milestone=none&page=1&sort=created&state=open)
* Sort by submit date, with the newest issues first
* You don't have to do issues in order; feel free to pick and choose issues as you please.
* You can triage older issues as well
* Triage to your heart's content
1. Assign yourself: Pick an issue that is not assigned to anyone and assign it to you
1. Assign milestone:
* "Docs only" milestone - for documentation PR -> **Done**.
* Current/next milestone - regressions
* 1.2.x - everything else
1. Label "GH: *" (to be automated via Mary Poppins)
* PR - issue is a PR
* issue - otherwise
1. Understandable? - verify if the description of the request is clear.
* If not, [close it][] according to the instructions below and go to the last step.
1. Duplicate?
* If you've seen this issue before [close it][], and go to the last step.
* 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"
* Label "Type: Regression" - if the bug is a regression
* Duplicate? - Check if there are comments pointing out that this is a dupe, if they do exist verify that this is indeed a dupe and close it and go to the last step
* Reproducible? - Steps to reproduce the bug are clear, if not ask for clarification (ideally plunker or fiddle)
* Reproducible on master? - http://code.angularjs.org/snapshot/
* Label `Type: Bug`
* Reproducible? - Steps to reproduce the bug are clear. If they are not,
* Reproducible on master? - <http://code.angularjs.org/snapshot/>
1. Non bugs:
* Label "Type: Feature" or "Type: Chore" or "Type: Perf"
* Label "needs: breaking change" - if needed
* Label "needs: public api" - if a new public api is needed
* Understandable? - verify if the description of the request is clear. if not ask for clarification
* Goals of angular core? - Often new features should be implemented as a third-party module rather than an addition to the core.
* Label `Type: Feature`, `Type: Chore`, or `Type: Perf`
* Belongs in core? Often new features should be implemented as a third-party module rather than an addition to the core.
If this doesn't belong, [close it][], and go to the last step.
* 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?
* 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?
* security issue
* regression
* memory leak
* broken expected use - it's hard or impossible for a developer using Angular to accomplish something that Angular should be able to do
* confusing - unexpected or inconsistent behavior; hard-to-debug
* inconvenience - causes ugly/boilerplate code in apps
1. Label `component: *`
* In rare cases, it's ok to have multiple components.
1. Label `PRs plz!` - These issues are good targets for PRs from the open source community. Apply to issues where the problem and solution are well defined in the comments, and it's not too complex.
1. Label `origin: google` for issues from Google
1. Label "component: *"
* In rare cases, it's ok to have multiple components.
1. Label "impact: *"
* small - obscure issue affecting one or handful of developers
* medium - impacts some usage patterns
* large - impacts most or all of angular apps
1. Label "complexity: *"
* small - trivial change
* medium - non-trivial but straightforward change
* large - changes to many components in angular or any changes to $compile, ngRepeat or other "fun" components
1. Label "PRs welcome" for "GH: issue"
* if complexity is small or medium and the problem as well as solution are well captured in the issue
1. Label "origin: google" for issues from Google
1. Label "high priority" for security issues, major performance regressions or memory leaks
1. Assign a milestone:
* Current 1.x.y milestone - regressions and urgent bugs only
* Backlog - fixes; changes that should go into a patch release
* Ice Box - new features; changes that belong inß a major/minor release
1. Unassign yourself from the issue
## Tips
* Label `resolution: *`
* these tags can be used for labeling a closed issue/PR with a reason why it was closed.
* Right now there are only a few rejection reasons, but we can add more as needed. Feel free to suggest one to a core team member. We don't use this label for issues that were fixed or PRs that were merged.
## Closing an Issue or PR
We're grateful to anyone who takes the time to submit an issue, even if we ultimately decide not to act on it.
Be kind and respectful as you close issues. Be sure to follow the [code of conduct][].
1. Always thank the person who submitted it.
1. If it's a duplicate, link to the older or more descriptive issue that supersedes the one you are closing.
1. Let them know if there's some way for them to follow-up.
* When the issue is unclear or reproducible, note that you'll reopen it if they can clarify or provide a better example. Mention [plunker] or [fiddle] for examples. Watch your notifications and follow-up if they do provide clarification. :)
* If appropriate, suggest implementing a feature as a third-party module.
If in doubt, ask a core team member what to do.
[Brian](https://github.com/btford) is probably the person to ask.
You can mention him in the relevant thread like this: `@btford`.
**Example:**
> Thanks for submitting this issue!
> Unfortunately, we don't think this functionality belongs in core.
> The good news is that you could easily implement this as a third-party module and publish it on Bower and/or npm.
## Assigning Work
These criteria are then used to calculate a "user pain" score.
Work is assigned weekly to core team members starting with the highest pain, descending down to the lowest.
```
pain = severity × frequency
```
**severity:**
- security issue (6)
- regression (5)
- memory leak (4)
- broken expected use (3)
- confusing (2)
- inconvenience (1)
**frequency:**
- low (1)
- moderate (2)
- high (3)
**Note:** Security issues, regressions, and memory leaks should almost always be set to `frequency: high`.
[![Analytics](https://ga-beacon.appspot.com/UA-8594346-11/angular.js/TRIAGING.md?pixel)](https://github.com/igrigorik/ga-beacon)
[close it]: #closing-an-issue-or-pr
[code of conduct]: https://github.com/angular/code-of-conduct/blob/master/CODE_OF_CONDUCT.md
[Mary Poppins]: https://github.com/btford/mary-poppins
[plunker]: http://plnkr.co/
[fiddle]: http://jsfiddle.net/
+2 -5
View File
@@ -11,6 +11,7 @@ angularFiles = {
'src/ng/anchorScroll.js',
'src/ng/animate.js',
'src/ng/asyncCallback.js',
'src/ng/browser.js',
'src/ng/cacheFactory.js',
'src/ng/compile.js',
@@ -26,6 +27,7 @@ angularFiles = {
'src/ng/log.js',
'src/ng/parse.js',
'src/ng/q.js',
'src/ng/raf.js',
'src/ng/rootScope.js',
'src/ng/sanitizeUri.js',
'src/ng/sce.js',
@@ -142,8 +144,6 @@ angularFiles = {
'@angularSrcModules',
'@angularScenario',
'@angularTest',
'example/personalLog/*.js',
'example/personalLog/test/*.js'
],
'karmaExclude': [
@@ -178,9 +178,6 @@ angularFiles = {
'@angularSrcModules',
'@angularScenario',
'@angularTest',
'example/personalLog/*.js',
'example/personalLog/test/*.js'
],
'karmaJqueryExclude': [
+5 -5
View File
@@ -2,11 +2,11 @@
"name": "AngularJS",
"devDependencies": {
"jquery": "1.10.2",
"lunr.js": "0.4.0",
"google-code-prettify": "1.0.0",
"components-font-awesome": "3.1.0",
"bootstrap": "https://raw.github.com/twbs/bootstrap/v2.0.2/docs/assets/bootstrap.zip",
"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.2/assets/ng-closure-runner.zip"
"ng-closure-runner": "https://raw.github.com/angular/ng-closure-runner/v0.2.3/assets/ng-closure-runner.zip",
"bootstrap": "3.1.1"
}
}
+5
View File
@@ -9,3 +9,8 @@
ng\:form {
display: block;
}
.ng-animate-block-transitions {
transition:0s all!important;
-webkit-transition:0s all!important;
}
View File
+664
View File
@@ -0,0 +1,664 @@
html, body {
position:relative;
height:100%;
}
#wrapper {
min-height:100%;
position:relative;
padding-bottom:120px;
}
.footer {
border-top:20px solid white;
position:absolute;
bottom:0;
left:0;
right:0;
z-index:100;
padding-top: 2em;
background-color: #333;
color: white;
padding-bottom: 2em;
}
.header-fixed {
position:fixed;
z-index:1000;
top:0;
left:0;
right:0;
}
.header-branding {
min-height:41px!important;
}
.docs-navbar-primary {
border-radius:0!important;
margin-bottom:0!important;
}
/* Logo */
/*.dropdown-menu {
display:none;
}
*/
h1,h2,h3,h4,h5,h6 {
font-family: "Open Sans";
}
.subnav-body {
margin:70px 0 20px;
}
.header .brand {
padding-top: 6px;
padding-bottom: 0px;
}
.header .brand img {
margin-top:5px;
height: 30px;
}
.docs-search {
margin:10px 0;
padding:4px 0 4px 20px;
background:white;
border-radius:20px;
vertical-align:middle;
}
.docs-search > .search-query {
font-size:14px;
border:0;
width:80%;
color:#555;
}
.docs-search > .search-icon {
font-size:15px;
margin-right:10px;
}
.docs-search > .search-query:focus {
outline:0;
}
/* end: Logo */
.spacer {
height: 1em;
}
.icon-cog {
line-height: 13px;
}
.naked-list,
.naked-list ul,
.naked-list li {
list-style:none;
margin:0;
padding:0;
}
.nav-index-section a {
font-weight:bold;
font-family: "Open Sans";
color:black!important;
margin-top:10px;
display:block;
}
.nav-index-group {
margin-bottom:20px!important;
}
.nav-index-group-heading {
color:#6F0101;
font-weight:bold;
font-size:1.2em;
padding:0;
margin:0;
border-bottom:1px soild #aaa;
margin-bottom:5px;
}
.nav-breadcrumb {
margin:4px 0;
padding:0;
}
.nav-breadcrumb-entry {
font-family: "Open Sans";
padding:0;
margin:0;
font-size:18px;
display:inline-block;
vertical-align:middle;
}
.nav-breadcrumb-entry > .divider {
color:#555;
display:inline-block;
padding-left:8px;
}
.nav-breadcrumb-entry > span,
.nav-breadcrumb-entry > a {
color:#6F0101;
}
.step-list > li:nth-child(1) {
padding-left:20px;
}
.step-list > li:nth-child(2) {
padding-left:40px;
}
.step-list > li:nth-child(3) {
padding-left:60px;
}
.api-profile-header-heading {
margin:0;
padding:0;
}
.api-profile-header-structure,
.api-profile-header-structure a {
font-family: "Open Sans";
font-weight:bold;
color:#999;
}
.api-profile-section {
margin-top:30px;
padding-top:30px;
border-top:1px solid #aaa;
}
pre {
padding:15px;
border:1px solid #ddd;
display:block;
border-radius:5px;
}
.aside-nav a,
.aside-nav a:link,
.aside-nav a:visited,
.aside-nav a:active {
color:#999;
}
.aside-nav a:hover {
color:black;
}
.api-profile-description > p:first-child {
margin:15px 0;
font-size:18px;
}
p > code,
code.highlighted {
background:#f4f4f4;
border-radius:5px;
padding:2px 5px;
color:maroon;
}
.docs-version-jump {
min-width:100%;
max-width:100%;
}
.picker {
position: relative;
width: auto;
display: inline-block;
margin: 0 0 2px 1.2%;
overflow: hidden;
border: 1px solid #e5e5e5;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
-ms-border-radius: 4px;
-o-border-radius: 4px;
border-radius: 4px;
font-family: "Open Sans";
font-weight: 600;
height: auto;
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #ffffff), color-stop(100%, #f2f2f2));
background-image: -webkit-linear-gradient(#ffffff, #f2f2f2);
background-image: -moz-linear-gradient(#ffffff, #f2f2f2);
background-image: -o-linear-gradient(#ffffff, #f2f2f2);
background-image: linear-gradient(#ffffff, #f2f2f2);
}
.picker select {
position: relative;
display: block;
min-width: 100%;
width: 120%;
height: 34px;
padding: 6px 30px 6px 15px;
color: #555555;
border: none;
background: transparent;
outline: none;
-webkit-appearance: none;
z-index: 99;
cursor: pointer;
font-size: 16px;
}
.picker:after {
content:"";
position: absolute;
right: 8%;
top: 50%;
z-index: 0;
color: #999;
width: 0;
margin-top:-2px;
height: 0;
border-top: 6px solid;
border-right: 6px solid transparent;
border-left: 6px solid transparent;
}
iframe.example {
width: 100%;
border: 1px solid black;
}
.search-results-frame {
clear:both;
display:table;
width:100%;
}
.search-results.ng-hide {
display:none;
}
.search-results-container {
padding-bottom:1em;
border-top:1px solid #111;
background:#181818;
box-shadow:inset 0 0 10px #111;
}
.search-results-container .search-results-group {
vertical-align:top;
padding:10px 10px;
display:inline-block;
}
.search-results-group-heading {
font-family: "Open Sans";
padding-left:10px;
color:white;
}
.search-results-frame > .search-results-group:first-child > .search-results {
border-right:1px solid #050505;
}
.search-results-group.col-group-api { width:30%; }
.search-results-group.col-group-guide { width:30%; }
.search-results-group.col-group-tutorial { width:25%; }
.search-results-group.col-group-misc,
.search-results-group.col-group-error { float:right; clear:both; width:15% }
.search-results-group.col-group-api .search-result {
width:48%;
display:inline-block;
}
.search-close {
position: absolute;
bottom: 0;
left: 50%;
margin-left: -100px;
color: white;
text-align: center;
padding: 5px;
background: #333;
border-top-right-radius: 5px;
border-top-left-radius: 5px;
width: 200px;
box-shadow:0 0 10px #111;
}
.variables-matrix {
border:1px solid #ddd;
width:100%;
margin:10px 0;
}
.variables-matrix td,
.variables-matrix th {
padding:10px;
}
.variables-matrix td {
border-top:1px solid #eee;
}
.variables-matrix td + td,
.variables-matrix th + th {
border-left:1px solid #eee;
}
.variables-matrix tr:nth-child(even) td {
background:#f5f5f5;
}
.variables-matrix th {
background:#f1f1f1;
}
.sup-header {
padding-top:10px;
padding-bottom:5px;
background:rgba(245,245,245,0.88);
box-shadow:0 0 2px #999;
}
.main-body-grid {
margin-top:120px;
position:relative;
}
.main-body-grid > .grid-left,
.main-body-grid > .grid-right {
padding:20px 0;
}
.main-body-grid > .grid-left {
position:fixed;
top:120px;
bottom:0;
padding-bottom:120px;
overflow:auto;
}
.main-header-grid > .grid-left,
.main-body-grid > .grid-left {
width:260px;
}
.main-header-grid > .grid-right,
.main-body-grid > .grid-right {
margin-left:270px;
position:relative;
}
.main-header-grid > .grid-left {
float:left;
}
.main-body-grid .side-navigation {
position:relative;
}
.main-body-grid .side-navigation.ng-hide {
display:block!important;
}
.variables-matrix td {
vertical-align:top;
padding:5px;
}
.type-hint {
display:inline-block;
}
.variables-matrix .type-hint {
text-align:center;
min-width:60px;
margin:1px 5px;
}
.type-hint + .type-hint {
margin-top:5px;
}
.type-hint-expression {
background:purple;
}
.type-hint-date {
background:pink;
}
.type-hint-string {
background:#3a87ad;
}
.type-hint-function {
background:green;
}
.type-hint-object {
background:#999;
}
.type-hint-array {
background:#F90;;
}
.type-hint-boolean {
background:rgb(18, 131, 39);
}
.type-hint-number {
background:rgb(189, 63, 66);
}
.runnable-example-frame {
width:100%;
height:300px;
border: 1px solid #ddd;
border-radius:5px;
}
.runnable-example-tabs {
margin-top:10px;
margin-bottom:20px;
}
.tutorial-nav {
display:block;
}
h1 + ul, h1 + ul > li,
h2 + ul, h2 + ul > li,
ul.tutorial-nav, ul.tutorial-nav > li,
.usage > ul, .usage > ul > li,
ul.methods, ul.methods > li,
ul.events, ul.events > li {
list-style:none;
padding:0;
}
h2 {
border-top:1px solid #eee;
margin-top:30px;
padding-top:30px;
}
h4 {
margin-top:20px;
padding-top:20px;
}
.improve-docs {
float:right;
}
.btn {
color:#428bca;
position: relative;
width: auto;
display: inline-block;
margin: 0 0 2px;
overflow: hidden;
border: 1px solid #e5e5e5;
-webkit-border-radius: 4px;
-moz-border-radius: 4px;
-ms-border-radius: 4px;
-o-border-radius: 4px;
border-radius: 4px;
font-family: "Open Sans";
font-weight: 600;
height: auto;
background-image: -webkit-gradient(linear, 50% 0%, 50% 100%, color-stop(0%, #ffffff), color-stop(100%, #f2f2f2));
background-image: -webkit-linear-gradient(#ffffff, #f2f2f2);
background-image: -moz-linear-gradient(#ffffff, #f2f2f2);
background-image: -o-linear-gradient(#ffffff, #f2f2f2);
background-image: linear-gradient(#ffffff, #f2f2f2);
}
.btn + .btn {
margin-left:10px;
}
.btn:hover {
color:black!important;
border: 1px solid #ddd!important;
background:white!important;
}
.view-source {
margin-right:10px;
padding-right:10px;
border-right:1px solid #999;
}
.return-arguments,
.return-arguments th,
.return-arguments th + th,
.return-arguments td,
.return-arguments td + td {
border-radius:0;
border:0;
}
.return-arguments td:first-child {
width:100px;
}
ul.methods > li,
ul.events > li {
margin-bottom:40px;
}
@media only screen and (max-width : 768px) {
.picker, .picker select {
width:auto;
display:block;
margin-bottom:10px;
}
.docs-navbar-primary {
text-align:center;
}
.main-body-grid {
margin-top:0;
}
.main-header-grid > .grid-left,
.main-body-grid > .grid-left,
.main-header-grid > .grid-right,
.main-body-grid > .grid-right {
display:block;
float:none;
width:auto!important;
margin-left:0;
}
.main-body-grid > .grid-left,
.header-fixed, .footer {
position:static!important;
}
.main-body-grid > .grid-left {
background:#efefef;
margin-left:-1em;
margin-right:-1em;
padding:1em;
width:auto!important;
overflow:visible;
}
.main-header-grid > .grid-right,
.main-body-grid > .grid-right {
margin-left:0;
}
.main-body-grid .side-navigation {
display:block!important;
}
.main-body-grid .side-navigation.ng-hide {
display:none!important;
}
.nav-index-group .nav-index-listing {
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:last-child {
content:"";
}
.nav-index-group .nav-index-section {
display:block;
}
.toc-toggle {
margin-bottom:20px;
}
.toc-close {
position: absolute;
bottom: -50px;
left: 50%;
margin-left: -50%;
text-align: center;
padding: 5px;
background: #eee;
border-radius: 5px;
width: 90%;
border:1px solid #ddd;
box-shadow:0 0 10px #bbb;
}
.navbar-brand {
float:none;
text-align:center;
}
.search-results-container {
padding-bottom:60px;
text-align:left;
}
.search-results-group {
float:none!important;
display:block!important;
width:auto!important;
border:0!important;
padding:0!important;
}
.search-results-group .search-result {
display:inline-block!important;
padding:0 5px;
width:auto!important;
}
.search-results-group .search-result:after {
content:", ";
}
#wrapper {
padding-bottom:0px;
}
}
+138
View File
@@ -0,0 +1,138 @@
/* GitHub Theme */
.prettyprint {
background: white;
font-family: Menlo, 'Bitstream Vera Sans Mono', 'DejaVu Sans Mono', Monaco, Consolas, monospace;
font-size: 12px;
line-height: 1.5;
}
.pln {
color: #333333;
}
@media screen {
.str {
color: #dd1144;
}
.kwd {
color: #333333;
}
.com {
color: #999988;
}
.typ {
color: #445588;
}
.lit {
color: #445588;
}
.pun {
color: #333333;
}
.opn {
color: #333333;
}
.clo {
color: #333333;
}
.tag {
color: navy;
}
.atn {
color: teal;
}
.atv {
color: #dd1144;
}
.dec {
color: #333333;
}
.var {
color: teal;
}
.fun {
color: #990000;
}
}
@media print, projection {
.str {
color: #006600;
}
.kwd {
color: #006;
font-weight: bold;
}
.com {
color: #600;
font-style: italic;
}
.typ {
color: #404;
font-weight: bold;
}
.lit {
color: #004444;
}
.pun, .opn, .clo {
color: #444400;
}
.tag {
color: #006;
font-weight: bold;
}
.atn {
color: #440044;
}
.atv {
color: #006600;
}
}
/* Specify class=linenums on a pre to get line numbering */
ol.linenums {
margin-top: 0;
margin-bottom: 0;
}
/* IE indents via margin-left */
li.L0,
li.L1,
li.L2,
li.L3,
li.L4,
li.L5,
li.L6,
li.L7,
li.L8,
li.L9 {
/* */
}
/* Alternate shading for lines */
li.L1,
li.L3,
li.L5,
li.L7,
li.L9 {
/* */
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 3.1 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

@@ -0,0 +1,41 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 15.0.0, SVG Export Plug-In -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
<!ENTITY ns_flows "http://ns.adobe.com/Flows/1.0/">
]>
<svg version="1.1"
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns:a="http://ns.adobe.com/AdobeSVGViewerExtensions/3.0/"
x="0px" y="0px" width="687px" height="176px" viewBox="0 0 687 176" overflow="visible" enable-background="new 0 0 687 176"
xml:space="preserve">
<defs>
</defs>
<path fill="#FFFFFF" d="M179.011,125.328V54.527h9.158l43.322,57.035V54.527h8.666v70.801h-9.158l-43.326-57.536v57.536H179.011z
M179.011,125.328"/>
<path fill="#FFFFFF" d="M310.46,122.554c-5.708,2.182-11.864,3.269-18.467,3.269c-25.644,0-38.469-12.294-38.469-36.887
c0-23.27,12.378-34.908,37.134-34.908c7.096,0,13.7,0.994,19.802,2.976v7.921c-6.103-2.311-12.378-3.468-18.813-3.468
c-19.306,0-28.96,9.162-28.96,27.479c0,19.639,9.504,29.463,28.517,29.463c3.034,0,6.404-0.396,10.103-1.193V93.145h9.154V122.554z
M310.46,122.554"/>
<path fill="#FFFFFF" d="M325.067,97.996V54.523h9.154v43.473c0,13.598,6.768,20.4,20.303,20.4c13.531,0,20.301-6.803,20.301-20.4
V54.523h9.158v43.473c0,18.556-9.82,27.825-29.459,27.825C334.886,125.821,325.067,116.552,325.067,97.996L325.067,97.996z
M325.067,97.996"/>
<path fill="#FFFFFF" d="M409.48,54.523v63.376h37.037v7.425h-46.191V54.523H409.48z M409.48,54.523"/>
<path fill="#FFFFFF" d="M459.736,125.327h-9.504l35.201-80.146l35.199,80.146h-10.15l-9.158-22.282h-23.418l2.527-7.424h17.82
l-13.217-32.088L459.736,125.327z M459.736,125.327"/>
<path fill="#FFFFFF" d="M530.289,125.328V54.527h30.203c13.469,0,20.197,5.659,20.197,16.982c0,9.207-6.578,16.028-19.75,20.445
l24.309,33.374h-12.086l-22.521-31.835v-5.992c13.531-2.151,20.301-7.344,20.301-15.598c0-6.533-3.766-9.801-11.293-9.801h-20.201
v63.226H530.289z M530.289,125.328"/>
<path fill="#B52E31" d="M619.561,54.523v50.405c0,13.603-8.006,20.396-24.016,20.396V117.9c9.902,0,14.857-4.329,14.857-12.973
V54.523H619.561z M619.561,54.523"/>
<path fill="#B52E31" d="M635.896,122.849v-8.418c7.428,2.639,15.447,3.965,24.064,3.965c12.178,0,18.271-4.457,18.271-13.372
c0-7.584-4.492-11.385-13.469-11.385h-9.113c-14.818,0-22.234-6.435-22.234-19.31c0-13.531,9.492-20.303,28.479-20.303
c8.25,0,15.922,0.998,23.021,2.976v8.418c-7.1-2.644-14.771-3.965-23.021-3.965c-12.875,0-19.311,4.293-19.311,12.875
c0,7.588,4.352,11.385,13.066,11.385h9.113c15.08,0,22.627,6.439,22.627,19.31c0,13.864-9.141,20.796-27.43,20.796
C651.344,125.819,643.324,124.826,635.896,122.849L635.896,122.849z M635.896,122.849"/>
<path fill="#B2B2B2" d="M82.688,0L0,29.1l13.066,108.335l69.71,38.314l70.069-38.834l13.062-108.331L82.688,0z M82.688,0"/>
<path fill="#B52E31" d="M157.66,34.846L82.496,9.214v157.381l62.991-34.861L157.66,34.846z M157.66,34.846"/>
<path fill="#E23237" d="M9.279,35.308l11.196,96.889l62.019,34.398V9.211L9.279,35.308z M9.279,35.308"/>
<path fill="#F2F2F2" d="M99.918,87.493L82.632,51.396L67.415,87.493H99.918z M106.508,102.672h-45.82l-10.251,25.64l-19.067,0.352
L82.496,14.929l52.908,113.734h-17.673L106.508,102.672z M106.508,102.672"/>
<path fill="#B2B2B2" d="M82.496,14.929l0.136,36.467l17.268,36.125H82.534l-0.039,15.127l24.012,0.023l11.223,25.996l18.245,0.339
L82.496,14.929z M82.496,14.929"/>
</svg>

After

Width:  |  Height:  |  Size: 3.3 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 212 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 65 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 48 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 62 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 78 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 34 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 116 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 124 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 196 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 209 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 205 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 141 KiB

@@ -89,29 +89,6 @@ directive.jsFiddle = function(getEmbeddedTemplate, escape, script) {
};
directive.code = function() {
return {restrict: 'E', terminal: true};
};
directive.prettyprint = ['reindentCode', function(reindentCode) {
return {
restrict: 'C',
compile: function(element) {
var html = element.html();
//ensure that angular won't compile {{ curly }} values
html = html.replace(/\{\{/g, '<span>{{</span>')
.replace(/\}\}/g, '<span>}}</span>');
if (window.RUNNING_IN_NG_TEST_RUNNER) {
element.html(html);
}
else {
element.html(window.prettyPrintOne(reindentCode(html), undefined, true));
}
}
};
}];
directive.ngSetText = ['getEmbeddedTemplate', function(getEmbeddedTemplate) {
return {
@@ -2,6 +2,56 @@
var directive = {};
directive.runnableExample = ['$templateCache', '$document', function($templateCache, $document) {
var exampleClassNameSelector = '.runnable-example-file';
var doc = $document[0];
var tpl =
'<nav class="runnable-example-tabs" ng-if="tabs">' +
' <a ng-class="{active:$index==activeTabIndex}"' +
'ng-repeat="tab in tabs track by $index" ' +
'href="" ' +
'class="btn"' +
'ng-click="setTab($index)">' +
' {{ tab }}' +
' </a>' +
'</nav>';
return {
restrict: 'C',
scope : true,
controller : ['$scope', function($scope) {
$scope.setTab = function(index) {
var tab = $scope.tabs[index];
$scope.activeTabIndex = index;
$scope.$broadcast('tabChange', index, tab);
};
}],
compile : function(element) {
element.html(tpl + element.html());
return function(scope, element) {
var node = element[0];
var examples = node.querySelectorAll(exampleClassNameSelector);
var tabs = [], now = Date.now();
angular.forEach(examples, function(child, index) {
tabs.push(child.getAttribute('name'));
});
if(tabs.length > 0) {
scope.tabs = tabs;
scope.$on('tabChange', function(e, index, title) {
angular.forEach(examples, function(child) {
child.style.display = 'none';
});
var selected = examples[index];
selected.style.display = 'block';
});
scope.setTab(0);
}
}
}
};
}];
directive.dropdownToggle =
['$document', '$location', '$window',
function ($document, $location, $window) {
+145
View File
@@ -0,0 +1,145 @@
/* This code is taken from the AngularUI - Bootstrap Project (https://github.com/angular-ui/bootstrap)
*
* The MIT License
*
* Copyright (c) 2012-2014 the AngularUI Team, https://github.com/organizations/angular-ui/teams/291112
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*
*/
angular.module('ui.bootstrap.dropdown', [])
.constant('dropdownConfig', {
openClass: 'open'
})
.service('dropdownService', ['$document', function($document) {
var self = this, openScope = null;
this.open = function( dropdownScope ) {
if ( !openScope ) {
$document.bind('click', closeDropdown);
$document.bind('keydown', escapeKeyBind);
}
if ( openScope && openScope !== dropdownScope ) {
openScope.isOpen = false;
}
openScope = dropdownScope;
};
this.close = function( dropdownScope ) {
if ( openScope === dropdownScope ) {
openScope = null;
$document.unbind('click', closeDropdown);
$document.unbind('keydown', escapeKeyBind);
}
};
var closeDropdown = function() {
openScope.$apply(function() {
openScope.isOpen = false;
});
};
var escapeKeyBind = function( evt ) {
if ( evt.which === 27 ) {
closeDropdown();
}
};
}])
.controller('DropdownController', ['$scope', '$attrs', 'dropdownConfig', 'dropdownService', '$animate', function($scope, $attrs, dropdownConfig, dropdownService, $animate) {
var self = this, openClass = dropdownConfig.openClass;
this.init = function( element ) {
self.$element = element;
$scope.isOpen = angular.isDefined($attrs.isOpen) ? $scope.$parent.$eval($attrs.isOpen) : false;
};
this.toggle = function( open ) {
return $scope.isOpen = arguments.length ? !!open : !$scope.isOpen;
};
// Allow other directives to watch status
this.isOpen = function() {
return $scope.isOpen;
};
$scope.$watch('isOpen', function( value ) {
$animate[value ? 'addClass' : 'removeClass'](self.$element, openClass);
if ( value ) {
dropdownService.open( $scope );
} else {
dropdownService.close( $scope );
}
$scope.onToggle({ open: !!value });
});
$scope.$on('$locationChangeSuccess', function() {
$scope.isOpen = false;
});
}])
.directive('dropdown', function() {
return {
restrict: 'CA',
controller: 'DropdownController',
scope: {
isOpen: '=?',
onToggle: '&'
},
link: function(scope, element, attrs, dropdownCtrl) {
dropdownCtrl.init( element );
}
};
})
.directive('dropdownToggle', function() {
return {
restrict: 'CA',
require: '?^dropdown',
link: function(scope, element, attrs, dropdownCtrl) {
if ( !dropdownCtrl ) {
return;
}
element.bind('click', function(event) {
event.preventDefault();
event.stopPropagation();
if ( !element.hasClass('disabled') && !element.prop('disabled') ) {
scope.$apply(function() {
dropdownCtrl.toggle();
});
}
});
// WAI-ARIA
element.attr({ 'aria-haspopup': true, 'aria-expanded': false });
scope.$watch(dropdownCtrl.isOpen, function( isOpen ) {
element.attr('aria-expanded', !!isOpen);
});
}
};
});
+23
View File
@@ -0,0 +1,23 @@
angular.module('docsApp', [
'ngRoute',
'ngCookies',
'ngSanitize',
'ngAnimate',
'DocsController',
'versionsData',
'pagesData',
'directives',
'errors',
'examples',
'search',
'tutorials',
'versions',
'bootstrap',
'bootstrapPrettify',
'ui.bootstrap.dropdown'
])
.config(function($locationProvider) {
$locationProvider.html5Mode(true).hashPrefix('!');
});
+35
View File
@@ -0,0 +1,35 @@
angular.module('directives', [])
.directive('code', function() {
return { restrict:'E', terminal: true };
})
/**
* backToTop Directive
* @param {Function} $anchorScroll
*
* @description Ensure that the browser scrolls when the anchor is clicked
*/
.directive('backToTop', ['$anchorScroll', function($anchorScroll) {
return function link(scope, element) {
element.on('click', function(event) {
scope.$apply($anchorScroll);
});
};
}])
.directive('code', function() {
return {
restrict: 'E',
terminal: true,
compile: function(element) {
var linenums = element.hasClass('linenum') || element.parent()[0].nodeName === 'PRE';
var match = /lang-(\S)+/.exec(element.className);
var lang = match && match[1];
var html = element.html();
element.html(window.prettyPrintOne(html, lang, linenums));
}
};
});
+121
View File
@@ -0,0 +1,121 @@
angular.module('DocsController', [])
.controller('DocsController', function($scope, $rootScope, $location, $window, $cookies, NG_PAGES, NG_NAVIGATION, NG_VERSION) {
$scope.fold = function(url) {
if(url) {
$scope.docs_fold = '/notes/' + url;
if(/\/build/.test($window.location.href)) {
$scope.docs_fold = '/build/docs' + $scope.docs_fold;
}
window.scrollTo(0,0);
}
else {
$scope.docs_fold = null;
}
};
var OFFLINE_COOKIE_NAME = 'ng-offline',
INDEX_PATH = /^(\/|\/index[^\.]*.html)$/;
/**********************************
Publish methods
***********************************/
$scope.navClass = function(navItem) {
return {
active: navItem.href && this.currentPage.path,
'nav-index-section': navItem.type === 'section'
};
};
$scope.afterPartialLoaded = function() {
var pagePath = $scope.currentPage ? $scope.currentPage.path : $location.path();
$window._gaq.push(['_trackPageview', pagePath]);
};
/** stores a cookie that is used by apache to decide which manifest ot send */
$scope.enableOffline = function() {
//The cookie will be good for one year!
var date = new Date();
date.setTime(date.getTime()+(365*24*60*60*1000));
var expires = "; expires="+date.toGMTString();
var value = angular.version.full;
document.cookie = OFFLINE_COOKIE_NAME + "="+value+expires+"; path=" + $location.path;
//force the page to reload so server can serve new manifest file
window.location.reload(true);
};
/**********************************
Watches
***********************************/
$scope.$watch(function docsPathWatch() {return $location.path(); }, function docsPathWatchAction(path) {
var currentPage = $scope.currentPage = NG_PAGES[path];
if ( !currentPage && path.charAt(0)==='/' ) {
// Strip off leading slash
path = path.substr(1);
}
currentPage = $scope.currentPage = NG_PAGES[path];
if ( !currentPage && path.charAt(path.length-1) === '/' && path.length > 1 ) {
// Strip off trailing slash
path = path.substr(0, path.length-1);
}
currentPage = $scope.currentPage = NG_PAGES[path];
if ( !currentPage && /\/index$/.test(path) ) {
// Strip off index from the end
path = path.substr(0, path.length - 6);
}
currentPage = $scope.currentPage = NG_PAGES[path];
if ( currentPage ) {
$scope.currentArea = currentPage && NG_NAVIGATION[currentPage.area];
var pathParts = currentPage.path.split('/');
var breadcrumb = $scope.breadcrumb = [];
var breadcrumbPath = '';
angular.forEach(pathParts, function(part) {
breadcrumbPath += part;
breadcrumb.push({ name: (NG_PAGES[breadcrumbPath]&&NG_PAGES[breadcrumbPath].name) || part, url: breadcrumbPath });
breadcrumbPath += '/';
});
} else {
$scope.currentArea = null;
$scope.breadcrumb = [];
}
});
/**********************************
Initialize
***********************************/
$scope.versionNumber = angular.version.full;
$scope.version = angular.version.full + " " + angular.version.codeName;
$scope.subpage = false;
$scope.offlineEnabled = ($cookies[OFFLINE_COOKIE_NAME] == angular.version.full);
$scope.futurePartialTitle = null;
$scope.loading = 0;
$scope.$cookies = $cookies;
$cookies.platformPreference = $cookies.platformPreference || 'gitUnix';
if (!$location.path() || INDEX_PATH.test($location.path())) {
$location.path('/api').replace();
}
// bind escape to hash reset callback
angular.element(window).on('keydown', function(e) {
if (e.keyCode === 27) {
$scope.$apply(function() {
$scope.subpage = false;
});
}
});
});
+62
View File
@@ -0,0 +1,62 @@
angular.module('errors', ['ngSanitize'])
.filter('errorLink', ['$sanitize', function ($sanitize) {
var LINKY_URL_REGEXP = /((ftp|https?):\/\/|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s\.\;\,\(\)\{\}<>]/g,
MAILTO_REGEXP = /^mailto:/,
STACK_TRACE_REGEXP = /:\d+:\d+$/;
var truncate = function (text, nchars) {
if (text.length > nchars) {
return text.substr(0, nchars - 3) + '...';
}
return text;
};
return function (text, target) {
var targetHtml = target ? ' target="' + target + '"' : '';
if (!text) return text;
return $sanitize(text.replace(LINKY_URL_REGEXP, function (url) {
if (STACK_TRACE_REGEXP.test(url)) {
return url;
}
// if we did not match ftp/http/mailto then assume mailto
if (!/^((ftp|https?):\/\/|mailto:)/.test(url)) url = 'mailto:' + url;
return '<a' + targetHtml + ' href="' + url +'">' +
truncate(url.replace(MAILTO_REGEXP, ''), 60) +
'</a>';
}));
};
}])
.directive('errorDisplay', ['$location', 'errorLinkFilter', function ($location, errorLinkFilter) {
var interpolate = function (formatString) {
var formatArgs = arguments;
return formatString.replace(/\{\d+\}/g, function (match) {
// Drop the braces and use the unary plus to convert to an integer.
// The index will be off by one because of the formatString.
var index = +match.slice(1, -1);
if (index + 1 >= formatArgs.length) {
return match;
}
return formatArgs[index+1];
});
};
return {
link: function (scope, element, attrs) {
var search = $location.search(),
formatArgs = [attrs.errorDisplay],
i;
for (i = 0; angular.isDefined(search['p'+i]); i++) {
formatArgs.push(search['p'+i]);
}
element.html(errorLinkFilter(interpolate.apply(null, formatArgs), '_blank'));
}
};
}]);
+266
View File
@@ -0,0 +1,266 @@
angular.module('examples', [])
.directive('sourceEdit', function(getEmbeddedTemplate) {
return {
template: '<div class="btn-group pull-right">' +
'<a class="btn dropdown-toggle btn-primary" data-toggle="dropdown" href>' +
' <i class="icon-pencil icon-white"></i> Edit<span class="caret"></span>' +
'</a>' +
'<ul class="dropdown-menu">' +
' <li><a ng-click="plunkr($event)" href="">In Plunkr</a></li>' +
' <li><a ng-click="fiddle($event)" href="">In JsFiddle</a></li>' +
'</ul>' +
'</div>',
scope: true,
controller: function($scope, $attrs, openJsFiddle, openPlunkr) {
var sources = {
module: $attrs.sourceEdit,
deps: read($attrs.sourceEditDeps),
html: read($attrs.sourceEditHtml),
css: read($attrs.sourceEditCss),
js: read($attrs.sourceEditJs),
json: read($attrs.sourceEditJson),
unit: read($attrs.sourceEditUnit),
scenario: read($attrs.sourceEditScenario)
};
$scope.fiddle = function(e) {
e.stopPropagation();
openJsFiddle(sources);
};
$scope.plunkr = function(e) {
e.stopPropagation();
openPlunkr(sources);
};
}
};
function read(text) {
var files = [];
angular.forEach(text ? text.split(' ') : [], function(refId) {
// refId is index.html-343, so we need to strip the unique ID when exporting the name
files.push({name: refId.replace(/-\d+$/, ''), content: getEmbeddedTemplate(refId)});
});
return files;
}
})
.factory('angularUrls', function($document) {
var urls = {};
angular.forEach($document.find('script'), function(script) {
var match = script.src.match(/^.*\/(angular[^\/]*\.js)$/);
if (match) {
urls[match[1].replace(/(\-\d.*)?(\.min)?\.js$/, '.js')] = match[0];
}
});
return urls;
})
.factory('formPostData', function($document) {
return function(url, fields) {
var form = angular.element('<form style="display: none;" method="post" action="' + url + '" target="_blank"></form>');
angular.forEach(fields, function(value, name) {
var input = angular.element('<input type="hidden" name="' + name + '">');
input.attr('value', value);
form.append(input);
});
$document.find('body').append(form);
form[0].submit();
form.remove();
};
})
.factory('prepareDefaultAppModule', function() {
return function(content) {
var deps = [];
angular.forEach(content.deps, function(file) {
if(file.name == 'angular-animate.js') {
deps.push('ngAnimate');
}
});
var moduleName = 'App';
return {
module : moduleName,
script : "angular.module('" + moduleName + "', [" +
(deps.length ? "'" + deps.join("','") + "'" : "") + "]);\n\n"
};
};
})
.factory('prepareEditorAssetTags', function(angularUrls) {
return function(content, options) {
options = options || {};
var includeLocalFiles = options.includeLocalFiles;
var html = makeScriptTag(angularUrls['angular.js']);
var allFiles = [].concat(content.js, content.css, content.html, content.json);
angular.forEach(content.deps, function(file) {
if (file.name !== 'angular.js') {
var isLocal = false;
for(var i=0;i<allFiles.length;i++) {
if(allFiles[i].name == file.name) {
isLocal = true;
break;
}
}
if(!(isLocal && !includeLocalFiles)) {
var assetUrl = angularUrls[file.name] || file.name;
html += makeScriptTag(assetUrl);
}
}
});
if(includeLocalFiles) {
angular.forEach(content.css, function(file, index) {
html += makeCssLinkTag(file.name);
});
}
return html;
function makeScriptTag(src) {
return '<script type="text/javascript" src="' + src + '"></script>\n';
}
function makeCssLinkTag(src) {
return '<link rel="stylesheet" type="text/css" href="' + src + '" />\n';
}
};
})
.factory('openPlunkr', function(templateMerge, formPostData, prepareEditorAssetTags, prepareDefaultAppModule) {
return function(content) {
var hasRouting = false;
angular.forEach(content.deps, function(file) {
hasRouting = hasRouting || file.name == 'angular-route.js';
});
var indexHtmlContent = '<!doctype html>\n' +
'<html ng-app="{{module}}">\n' +
' <head>\n' +
'{{scriptDeps}}';
if(hasRouting) {
indexHtmlContent += '<script type="text/javascript">\n' +
'//this is here to make plunkr work with AngularJS routing\n' +
'angular.element(document.getElementsByTagName(\'head\')).append(' +
'angular.element(\'<base href="\' + window.location.pathname + \'" />\')' +
');\n' +
'</script>\n';
}
indexHtmlContent += '</head>\n' +
' <body>\n\n' +
'{{indexContents}}\n\n' +
' </body>\n' +
'</html>\n';
indexProp = {
module: content.module,
scriptDeps: prepareEditorAssetTags(content, { includeLocalFiles : true }),
indexContents: content.html[0].content
};
var allFiles = [].concat(content.js, content.css, content.html, content.json);
if(!content.module) {
var moduleData = prepareDefaultAppModule(content);
indexProp.module = moduleData.module;
var found = false;
angular.forEach(content.js, function(file) {
if(file.name == 'script.js') {
file.content = moduleData.script + file.content;
found = true;
}
});
if(!found) {
indexProp.scriptDeps += '<script type="text/javascript" src="script.js"></script>\n';
allFiles.push({
name : 'script.js',
content : moduleData.script
});
}
}
var postData = {};
angular.forEach(allFiles, function(file, index) {
if (file.content && file.name != 'index.html') {
postData['files[' + file.name + ']'] = file.content;
}
});
postData['files[index.html]'] = templateMerge(indexHtmlContent, indexProp);
postData['tags[]'] = "angularjs";
postData.private = true;
postData.description = 'AngularJS Example Plunkr';
formPostData('http://plnkr.co/edit/?p=preview', postData);
};
})
.factory('openJsFiddle', function(templateMerge, formPostData, prepareEditorAssetTags, prepareDefaultAppModule) {
var HTML = '<div ng-app=\"{{module}}\">\n{{html:2}}</div>',
CSS = '</style> <!-- Ugly Hack to make remote files preload in jsFiddle --> \n' +
'{{head:0}}<style>{{css}}',
SCRIPT = '{{script}}',
SCRIPT_CACHE = '\n\n<!-- {{name}} -->\n<script type="text/ng-template" id="{{name}}">\n{{content:2}}</script>',
BASE_HREF_TAG = '<!-- Ugly Hack to make AngularJS routing work inside of jsFiddle -->\n' +
'<base href="/" />\n\n';
return function(content) {
var prop = {
module: content.module,
html: '',
css: '',
script: ''
};
if(!prop.module) {
var moduleData = prepareDefaultAppModule(content);
prop.script = moduleData.script;
prop.module = moduleData.module;
}
angular.forEach(content.html, function(file, index) {
if (index) {
prop.html += templateMerge(SCRIPT_CACHE, file);
} else {
prop.html += file.content;
}
});
prop.head = prepareEditorAssetTags(content, { includeLocalFiles : false });
angular.forEach(content.js, function(file, index) {
prop.script += file.content;
});
angular.forEach(content.css, function(file, index) {
prop.css += file.content;
});
var hasRouting = false;
angular.forEach(content.deps, function(file) {
hasRouting = hasRouting || file.name == 'angular-route.js';
});
var compiledHTML = templateMerge(HTML, prop);
if(hasRouting) {
compiledHTML = BASE_HREF_TAG + compiledHTML;
}
formPostData("http://jsfiddle.net/api/post/library/pure/", {
title: 'AngularJS Example',
html: compiledHTML,
js: templateMerge(SCRIPT, prop),
css: templateMerge(CSS, prop)
});
};
});
+24
View File
@@ -0,0 +1,24 @@
angular.module('docsApp.navigationService', [])
.factory('navigationService', function($window) {
var service = {
currentPage: null,
currentVersion: null,
changePage: function(newPage) {
},
changeVersion: function(newVersion) {
//TODO =========
// var currentPagePath = '';
// // preserve URL path when switching between doc versions
// if (angular.isObject($rootScope.currentPage) && $rootScope.currentPage.section && $rootScope.currentPage.id) {
// currentPagePath = '/' + $rootScope.currentPage.section + '/' + $rootScope.currentPage.id;
// }
// $window.location = version.url + currentPagePath;
}
};
});
+149
View File
@@ -0,0 +1,149 @@
angular.module('search', [])
.controller('DocsSearchCtrl', ['$scope', '$location', 'docsSearch', function($scope, $location, docsSearch) {
function clearResults() {
$scope.results = [];
$scope.colClassName = null;
$scope.hasResults = false;
}
$scope.search = function(q) {
var MIN_SEARCH_LENGTH = 3;
if(q.length >= MIN_SEARCH_LENGTH) {
var results = docsSearch(q);
var totalAreas = 0;
for(var i in results) {
++totalAreas;
}
if(totalAreas > 0) {
$scope.colClassName = 'cols-' + totalAreas;
}
$scope.hasResults = totalAreas > 0;
$scope.results = results;
}
else {
clearResults();
}
if(!$scope.$$phase) $scope.$apply();
};
$scope.submit = function() {
var result;
for(var i in $scope.results) {
result = $scope.results[i][0];
if(result) {
break;
}
}
if(result) {
$location.path(result.url);
$scope.hideResults();
}
};
$scope.hideResults = function() {
clearResults();
$scope.q = '';
};
}])
.factory('lunrSearch', function() {
return function(properties) {
if (window.RUNNING_IN_NG_TEST_RUNNER) return null;
var engine = lunr(properties);
return {
store : function(values) {
engine.add(values);
},
search : function(q) {
return engine.search(q);
}
};
};
})
.factory('docsSearch', ['$rootScope','lunrSearch', 'NG_PAGES',
function($rootScope, lunrSearch, NG_PAGES) {
if (window.RUNNING_IN_NG_TEST_RUNNER) {
return null;
}
var index = lunrSearch(function() {
this.ref('id');
this.field('title', {boost: 50});
this.field('keywords', { boost : 20 });
});
angular.forEach(NG_PAGES, function(page, key) {
if(page.searchTerms) {
index.store({
id : key,
title : page.searchTerms.titleWords,
keywords : page.searchTerms.keywords
});
};
});
return function(q) {
var results = {
api : [],
tutorial : [],
guide : [],
error : [],
misc : []
};
angular.forEach(index.search(q), function(result) {
var key = result.ref;
var item = NG_PAGES[key];
var area = item.area;
item.path = key;
var limit = area == 'api' ? 40 : 14;
if(results[area].length < limit) {
results[area].push(item);
}
});
return results;
};
}])
.directive('focused', function($timeout) {
return function(scope, element, attrs) {
element[0].focus();
element.on('focus', function() {
scope.$apply(attrs.focused + '=true');
});
element.on('blur', function() {
// have to use $timeout, so that we close the drop-down after the user clicks,
// otherwise when the user clicks we process the closing before we process the click.
$timeout(function() {
scope.$eval(attrs.focused + '=false');
});
});
scope.$eval(attrs.focused + '=true');
};
})
.directive('docsSearchInput', ['$document',function($document) {
return function(scope, element, attrs) {
var ESCAPE_KEY_KEYCODE = 27,
FORWARD_SLASH_KEYCODE = 191;
angular.element($document[0].body).bind('keydown', function(event) {
var input = element[0];
if(event.keyCode == FORWARD_SLASH_KEYCODE && document.activeElement != input) {
event.stopPropagation();
event.preventDefault();
input.focus();
}
});
element.bind('keydown', function(event) {
if(event.keyCode == ESCAPE_KEY_KEYCODE) {
event.stopPropagation();
event.preventDefault();
scope.$apply(function() {
scope.hideResults();
});
}
});
};
}]);
+58
View File
@@ -0,0 +1,58 @@
angular.module('tutorials', [])
.directive('docTutorialNav', function(templateMerge) {
var pages = [
'',
'step_00', 'step_01', 'step_02', 'step_03', 'step_04',
'step_05', 'step_06', 'step_07', 'step_08', 'step_09',
'step_10', 'step_11', 'step_12', 'the_end'
];
return {
compile: function(element, attrs) {
var seq = 1 * attrs.docTutorialNav,
props = {
seq: seq,
prev: pages[seq],
next: pages[2 + seq],
diffLo: seq ? (seq - 1): '0~1',
diffHi: seq
};
element.addClass('btn-group');
element.addClass('tutorial-nav');
element.append(templateMerge(
'<a href="tutorial/{{prev}}"><li class="btn btn-primary"><i class="icon-step-backward"></i> Previous</li></a>\n' +
'<a href="http://angular.github.com/angular-phonecat/step-{{seq}}/app"><li class="btn btn-primary"><i class="icon-play"></i> Live Demo</li></a>\n' +
'<a href="https://github.com/angular/angular-phonecat/compare/step-{{diffLo}}...step-{{diffHi}}"><li class="btn btn-primary"><i class="icon-search"></i> Code Diff</li></a>\n' +
'<a href="tutorial/{{next}}"><li class="btn btn-primary">Next <i class="icon-step-forward"></i></li></a>', props));
}
};
})
.directive('docTutorialReset', function() {
function tab(name, command, id, step) {
return '' +
' <div class=\'tab-pane well\' title="' + name + '" value="' + id + '">\n' +
' <ol>\n' +
' <li><p>Reset the workspace to step ' + step + '.</p>' +
' <pre>' + command + '</pre></li>\n' +
' <li><p>Refresh your browser or check the app out on <a href="http://angular.github.com/angular-phonecat/step-' + step + '/app">Angular\'s server</a>.</p></li>\n' +
' </ol>\n' +
' </div>\n';
}
return {
compile: function(element, attrs) {
var step = attrs.docTutorialReset;
element.html(
'<div ng-hide="show">' +
'<p><a href="" ng-click="show=true;$event.stopPropagation()">Workspace Reset Instructions ➤</a></p>' +
'</div>\n' +
'<div class="tabbable" ng-show="show" ng-model="$cookies.platformPreference">\n' +
tab('Git on Mac/Linux', 'git checkout -f step-' + step, 'gitUnix', step) +
tab('Git on Windows', 'git checkout -f step-' + step, 'gitWin', step) +
'</div>\n');
}
};
});
+15
View File
@@ -0,0 +1,15 @@
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];
$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;
};
}]);
+33
View File
@@ -0,0 +1,33 @@
describe("DocsController", function() {
var $scope;
angular.module('fake', [])
.value('$cookies', {})
.value('NG_PAGES', {})
.value('NG_NAVIGATION', {})
.value('NG_VERSION', {});
beforeEach(module('fake', 'DocsController'));
beforeEach(inject(function($rootScope, $controller) {
$scope = $rootScope;
$controller('DocsController', { $scope: $scope });
}));
describe('afterPartialLoaded', function() {
it("should update the Google Analytics with currentPage path if currentPage exists", inject(function($window) {
$window._gaq = [];
$scope.currentPage = { path: 'a/b/c' };
$scope.afterPartialLoaded();
expect($window._gaq.pop()).toEqual(['_trackPageview', 'a/b/c']);
}));
it("should update the Google Analytics with $location.path if currentPage is missing", inject(function($window, $location) {
$window._gaq = [];
spyOn($location, 'path').andReturn('x/y/z');
$scope.afterPartialLoaded();
expect($window._gaq.pop()).toEqual(['_trackPageview', 'x/y/z']);
}));
});
});
-72
View File
@@ -1,72 +0,0 @@
describe("DocsNavigationCtrl", function() {
beforeEach(module('docsApp'));
var ctrl, $scope;
beforeEach(function() {
module(function($provide) {
$provide.value('docsPages', []);
$provide.factory('docsSearch', function() {
return function(q) {
return ['one','two','three'];
};
});
});
inject(function($controller, $rootScope, $location, docsSearch) {
$scope = $rootScope.$new();
ctrl = $controller('DocsNavigationCtrl', {
$scope : $scope,
$location : $location,
docsSearch : docsSearch
});
});
});
it("should search and return data from docsSearch", function() {
$scope.search('1234')
expect($scope.results.join(',')).toBe('one,two,three');
expect($scope.hasResults).toBe(true);
});
it("should avoid searching if the search term is too short", function() {
$scope.search('1')
expect($scope.results.length).toBe(0);
expect($scope.hasResults).toBe(false);
});
it("should set the columns classname based on the total grouped results", function() {
$scope.search('1234');
expect($scope.colClassName).toBe('cols-3');
$scope.search('1');
expect($scope.colClassName).toBe(null);
});
it("should hide and clear the results when called", function() {
$scope.hasResults = true;
$scope.results = ['one'];
$scope.colClassName = '...';
$scope.hideResults();
expect($scope.hasResults).toBe(false);
expect($scope.results.length).toBe(0);
expect($scope.colClassName).toBe(null);
});
it("should hide, clear and change the path of the page when submitted", inject(function($location) {
$scope.hasResults = true;
$scope.results = {
api : [
{url : '/home'}
],
tutorial : [
{url : '/tutorial'}
]
};
$scope.submit();
expect($location.path()).toBe('/home');
expect($scope.results.length).toBe(0);
expect($scope.hasResults).toBe(false);
}));
});
-195
View File
@@ -1,195 +0,0 @@
describe('Docs Annotations', function() {
beforeEach(module('docsApp'));
var body;
beforeEach(function() {
body = angular.element(document.body);
body.empty();
});
var normalizeHtml = function(html) {
return html.toLowerCase().replace(/\s*$/, '');
};
describe('popover directive', function() {
var $scope, element;
beforeEach(inject(function($rootScope, $compile) {
$scope = $rootScope.$new();
element = angular.element(
'<div style="margin:200px;" data-title="title_text" data-content="content_text" popover></div>'
);
element.attr('id','idx');
body.append(element);
$compile(element)($scope);
$scope.$apply();
}));
it('should be hidden by default', inject(function(popoverElement) {
expect(popoverElement.visible()).toBe(false);
}));
it('should capture the click event and set the title and content and position the tip', inject(function(popoverElement) {
element.triggerHandler('click');
expect(popoverElement.isSituatedAt(element)).toBe(true);
expect(popoverElement.visible()).toBe(true);
expect(popoverElement.title()).toBe('title_text');
expect(popoverElement.content()).toContain('content_text');
expect(popoverElement.besideElement.attr('id')).toBe('idx');
}));
it('should hide and clear the title and content if the same element is clicked again', inject(function(popoverElement) {
//show the element
element.triggerHandler('click');
expect(popoverElement.isSituatedAt(element)).toBe(true);
//hide the element
element.triggerHandler('click');
expect(popoverElement.isSituatedAt(element)).toBe(false);
expect(popoverElement.visible()).toBe(false);
expect(popoverElement.title()).toBe('');
expect(popoverElement.content()).toBe('');
}));
it('should parse markdown content', inject(function(popoverElement, $compile) {
element = angular.element(
'<div style="margin:200px;" data-title="#title_text" data-content="#heading" popover></div>'
);
body.append(element);
$compile(element)($scope);
$scope.$apply();
element.triggerHandler('click');
expect(popoverElement.title()).toBe('#title_text');
expect(normalizeHtml(popoverElement.content())).toMatch('<h1>heading</h1>');
}));
});
describe('foldout directive', function() {
// Do not run this suite on Internet Explorer.
if (msie < 10) return;
var $scope, parent, element, url;
beforeEach(function() {
module(function($provide, $animateProvider) {
$animateProvider.register('.foldout', function($timeout) {
return {
enter : function(element, done) {
$timeout(done, 1000);
},
removeClass : function(element, className, done) {
$timeout(done, 500);
},
addClass : function(element, className, done) {
$timeout(done, 200);
}
}
});
});
inject(function($rootScope, $compile, $templateCache, $rootElement, $animate) {
$animate.enabled(true);
url = '/page.html';
$scope = $rootScope.$new();
parent = angular.element('<div class="parent"></div>');
//we're injecting the element to the $rootElement since the changes in
//$animate only detect and perform animations if the root element has
//animations enabled. If the element is not apart of the DOM
//then animations are skipped.
element = angular.element('<div data-url="' + url + '" class="foldout" foldout></div>');
parent.append(element);
$rootElement.append(parent);
body.append($rootElement);
$compile(parent)($scope);
$scope.$apply();
});
});
it('should inform that it is loading', inject(function($httpBackend) {
$httpBackend.expect('GET', url).respond('hello');
element.triggerHandler('click');
var kids = body.children();
var foldout = angular.element(kids[kids.length-1]);
expect(foldout.html()).toContain('loading');
}));
//TODO(matias): this test is bad. it's not clear what is being tested and what the assertions are.
// Additionally, now that promises get auto-flushed there are extra tasks in the deferred queue which screws up
// these brittle tests.
xit('should download a foldout HTML page and animate the contents', inject(function($httpBackend, $timeout, $sniffer) {
$httpBackend.expect('GET', url).respond('hello');
element.triggerHandler('click');
$httpBackend.flush();
$timeout.flushNext(0);
$timeout.flushNext(1000);
var kids = body.children();
var foldout = angular.element(kids[kids.length-1]);
expect(foldout.text()).toContain('hello');
}));
//TODO(matias): this test is bad. it's not clear what is being tested and what the assertions are.
// Additionally, now that promises get auto-flushed there are extra tasks in the deferred queue which screws up
// these brittle tests.
xit('should hide then show when clicked again', inject(function($httpBackend, $timeout, $sniffer) {
$httpBackend.expect('GET', url).respond('hello');
//enter
element.triggerHandler('click');
$httpBackend.flush();
$timeout.flushNext(0);
$timeout.flushNext(1000);
//hide
element.triggerHandler('click');
$timeout.flushNext(0);
$timeout.flushNext(200);
//show
element.triggerHandler('click');
$timeout.flushNext(0);
$timeout.flushNext(500);
$timeout.flushNext(0);
}));
});
describe('DocsController fold', function() {
var $scope, ctrl;
beforeEach(function() {
inject(function($rootScope, $controller, $location, $cookies, sections) {
$scope = $rootScope.$new();
ctrl = $controller('DocsController',{
$scope : $scope,
$location : $location,
$cookies : $cookies,
sections : sections
});
});
});
it('should download and reveal the foldover container', inject(function($compile, $httpBackend) {
var url = '/page.html';
var fullUrl = '/notes/' + url;
$httpBackend.expect('GET', fullUrl).respond('hello');
var element = angular.element('<div ng-include="docs_fold"></div>');
$compile(element)($scope);
$scope.$apply();
$scope.fold(url);
$httpBackend.flush();
}));
});
});
-157
View File
@@ -1,157 +0,0 @@
'use strict';
describe('bootstrap', function() {
var $compile, $rootScope, element;
function clickTab(element, index) {
browserTrigger(element.children().eq(0).children().eq(index));
}
beforeEach(module('bootstrap'));
beforeEach(inject(function(_$compile_, _$rootScope_) {
$compile = _$compile_;
$rootScope = _$rootScope_;
}));
beforeEach(function(){
function findTab(element, index) {
return _jQuery(element[0]).find('> .nav-tabs > li').eq(index);
}
function findTabPane(element, index) {
return _jQuery(element[0]).find('> .tab-content > .tab-pane').eq(index);
}
this.addMatchers({
toHaveTab: function(index, title) {
var tab = findTab(element, index);
this.message = function() {
if (tab.length) {
return 'Expect tab index ' + index + ' to be ' + toJson(title) + ' but was ' + toJson(tab.text());
} else {
return 'Expect tab index ' + index + ' to be ' + toJson(title) + ' but there are only ' +
element.children().length + ' tabs.';
}
};
return tab.length && tab.text() == title;
},
toHaveTabPane: function(index, title) {
var tabPane = findTabPane(element, index);
this.message = function() {
if (tabPane.length) {
return 'Expect tab pane index ' + index + ' to be ' + toJson(title) + ' but was ' + toJson(tabPane.text());
} else {
return 'Expect tab pane index ' + index + ' to be ' + toJson(title) + ' but there are only ' +
element.children().length + 'tab panes.';
}
};
return tabPane.length && tabPane.text() == title;
},
toHaveSelected: function(index) {
var tab = findTab(element, index);
var tabPane = findTabPane(element, index);
this.message = function() {
return 'Expect tab index ' + index + ' to be selected\n' +
' TAB: ' + angular.mock.dump(tab) + '\n' +
'TAB-PANE: ' + angular.mock.dump(tabPane);
};
return tabPane.hasClass('active') && tab.hasClass('active');
}
});
});
afterEach(function() {
dealoc(element);
});
describe('tabbable', function() {
it('should create the right structure', function() {
element = $compile(
'<div class="tabbable">' +
'<div class="tab-pane" title="first">tab1</div>' +
'<div class="tab-pane" title="second">tab2</div>' +
'</div>')($rootScope);
$rootScope.$apply();
expect(element).toHaveTab(0, 'first');
expect(element).toHaveTab(1, 'second');
expect(element).toHaveTabPane(0, 'tab1');
expect(element).toHaveTabPane(1, 'tab2');
expect(element).toHaveSelected(0);
});
it('should respond to tab click', function(){
element = $compile(
'<div class="tabbable">' +
'<div class="tab-pane" title="first">tab1</div>' +
'<div class="tab-pane" title="second">tab2</div>' +
'</div>')($rootScope);
expect(element).toHaveSelected(0);
clickTab(element, 1);
expect(element).toHaveSelected(1);
});
it('should select the first tab in repeater', function() {
element = $compile(
'<div class="tabbable">' +
'<div class="tab-pane" ng-repeat="id in [1,2,3]" title="Tab {{id}}" value="tab-{{id}}">' +
'Tab content {{id}}!' +
'</div>' +
'</div>')($rootScope);
$rootScope.$apply();
expect(element).toHaveSelected(0);
});
describe('ngModel', function() {
it('should bind to model', function() {
$rootScope.tab = 'B';
element = $compile(
'<div class="tabbable" ng-model="tab">' +
'<div class="tab-pane" title="first" value="A">tab1</div>' +
'<div class="tab-pane" title="second" value="B">tab2</div>' +
'</div>')($rootScope);
$rootScope.$apply();
expect(element).toHaveSelected(1);
$rootScope.tab = 'A';
$rootScope.$apply();
expect(element).toHaveSelected(0);
clickTab(element, 1);
expect($rootScope.tab).toEqual('B');
expect(element).toHaveSelected(1);
});
it('should not overwrite the model', function() {
$rootScope.tab = 'tab-2';
element = $compile(
'<div class="tabbable" ng-model="tab">' +
'<div class="tab-pane" ng-repeat="id in [1,2,3]" title="Tab {{id}}" value="tab-{{id}}">' +
'Tab content {{id}}!' +
'</div>' +
'</div>')($rootScope);
$rootScope.$apply();
expect(element).toHaveSelected(1);
});
});
});
});
-91
View File
@@ -1,91 +0,0 @@
<!doctype html>
<html>
<head>
<script src="../../src/angular-bootstrap.js"></script>
<script type="text/javascript">
$script('src/bootstrap/google-prettify/prettify', 'prettify');
$script.ready('angular', function() {
$script(['src/bootstrap/bootstrap-prettify', 'src/bootstrap/bootstrap'], 'myCode');
angular.module('myApp', []).run(function($rootScope){ $rootScope.text = 'WORKS!' });
});
$script.ready(['myCode', 'prettify'], function() {
angular.bootstrap(document, ['bootstrapPrettify', 'bootstrap']);
});
</script>
<link rel="stylesheet" href="../../src/bootstrap/google-prettify/prettify.css" type="text/css">
<link rel="stylesheet" href="../../src/bootstrap/css/bootstrap.css" type="text/css">
</head>
<body>
<div class="container">
<div class="row">
<div class="span12">
<h1>AngularJS is {{'working'}}</h1>
<h2>Directive: <code>prettify</code></h2>
<pre class="prettyprint linenums">
&lt;p&gt;Sample text here...&lt;/p&gt;
</pre>
<h2>Directive: <code>ng-set-text</code></h2>
<pre class="prettyprint linenums" ng-set-text="hello.html"></pre>
<script type="text/html" id="hello.html">
<h1>Hello World!</h1>
</script>
<h2>Directive: <code>ng-html-wrap</code></h2>
<pre class="prettyprint linenums" ng-set-text="hello.html" ng-html-wrap="angular.js angular-resource.js myApp abc.js abc.css"></pre>
<h2>Directive <code>ng-embed-app</code></h2>
<div ng-embed-app="myApp">{{text}}</div>
<h1>Bootstrap</h1>
<h2>Directive <code>drop-down-toggle</code></h2>
<div class="btn btn-primary dropdown">
<a href="#ABC" class="dropdown-toggle">
Account
<b class="caret"></b>
</a>
<ul class="dropdown-menu">
<li>One</li>
<li>Two</li>
</ul>
</div>
<h2 ng-init="state = 'tab-2' ">Directive <code>tabbable</code></h2>
state = {{state}}
<div class="tabbable" ng-model="state">
<div class="tab-pane" ng-repeat="id in [1,2,3]" title="Tab {{id}}" value='tab-{{id}}'>
Tab content {{id}}!
</div>
</div>
<hr/>
<div class="tabbable" ng-model="state">
<div class="tab-pane" ng-repeat="id in [1,2,3]" title="Tab {{id}}" value='tab-{{id}}'>
Tab content {{id}}!
</div>
</div>
<hr/>
<div class="tabbable">
<div class="tab-pane" ng-repeat="id in [1,2,3]" title="Tab {{id}}" value='tab-{{id}}'>
Tab content {{id}}!
</div>
</div>
</div>
</div>
</div>
<br/>
<br/>
<br/>
<br/>
<br/>
<br/>
</body>
</html>
-59
View File
@@ -1,59 +0,0 @@
describe("docsSearch", function() {
beforeEach(module('docsApp'));
var interceptedLunrResults;
beforeEach(function() {
interceptedLunrResults = [];
});
beforeEach(function() {
module(function($provide) {
var results = [];
results[0] = { section: 'tutorial', shortName: 'item one', keywords: 'item, one, 1' };
results[1] = { section: 'tutorial', shortName: 'item man', keywords: 'item, man' };
results[2] = { section: 'api', shortName: 'item other', keywords: 'item, other' };
results[3] = { section: 'cookbook', shortName: 'item cookbook', keywords: 'item, other' };
results[4] = { section: 'api', shortName: 'ngRepeat', keywords: 'item, other' };
$provide.value('NG_PAGES', results);
$provide.factory('lunrSearch', function() {
return function() {
return {
store : function(value) {
interceptedLunrResults.push(value);
},
search : function(q) {
var data = [];
angular.forEach(results, function(res, i) {
data.push({ ref : i });
});
return data;
}
}
};
});
});
});
it("should lookup and organize values properly", inject(function(docsSearch) {
var items = docsSearch('item');
expect(items['api'].length).toBe(2);
}));
it("should place cookbook items in the tutorial", inject(function(docsSearch) {
var items = docsSearch('item');
expect(items['tutorial'].length).toBe(3);
}));
it("should return all results without a search", inject(function(docsSearch) {
var items = docsSearch();
expect(items['tutorial'].length).toBe(3);
expect(items['api'].length).toBe(2);
}));
it("should store values with and without a ng prefix", inject(function(docsSearch) {
expect(interceptedLunrResults[4].title).toBe('ngRepeat repeat');
}));
});
-76
View File
@@ -1,76 +0,0 @@
describe("errorDisplay", function () {
var $location, compileHTML;
beforeEach(module('docsApp'));
beforeEach(inject(function ($injector) {
var $rootScope = $injector.get('$rootScope'),
$compile = $injector.get('$compile');
$location = $injector.get('$location');
compileHTML = function (code) {
var elm = angular.element(code);
$compile(elm)($rootScope);
$rootScope.$digest();
return elm;
};
this.addMatchers({
toInterpolateTo: function (expected) {
// Given a compiled DOM node with a minerr-display attribute,
// assert that its interpolated string matches the expected text.
return this.actual.text() === expected;
}
});
}));
it('should interpolate a template with no parameters', function () {
var elm;
spyOn($location, 'search').andReturn({});
elm = compileHTML('<div error-display="This is a test"></div>');
expect(elm).toInterpolateTo('This is a test');
});
it('should interpolate a template with no parameters when search parameters are present', function () {
var elm;
spyOn($location, 'search').andReturn({ p0: 'foobaz' });
elm = compileHTML('<div error-display="This is a test"></div>');
expect(elm).toInterpolateTo('This is a test');
});
it('should correctly interpolate search parameters', function () {
var elm;
spyOn($location, 'search').andReturn({ p0: '42' });
elm = compileHTML('<div error-display="The answer is {0}"></div>');
expect(elm).toInterpolateTo('The answer is 42');
});
it('should interpolate parameters in the specified order', function () {
var elm;
spyOn($location, 'search').andReturn({ p0: 'second', p1: 'first' });
elm = compileHTML('<div error-display="{1} {0}"></div>');
expect(elm).toInterpolateTo('first second');
});
it('should preserve interpolation markers when fewer arguments than needed are provided', function () {
var elm;
spyOn($location, 'search').andReturn({ p0: 'Fooooo' });
elm = compileHTML('<div error-display="This {0} is {1} on {2}"></div>');
expect(elm).toInterpolateTo('This Fooooo is {1} on {2}');
});
it('should correctly handle the empty string as an interpolation parameter', function () {
var elm;
spyOn($location, 'search').andReturn({ p0: 'test', p1: '' });
elm = compileHTML('<div error-display="This {0} is a {1}"></div>');
expect(elm).toInterpolateTo('This test is a ');
});
});
@@ -1,52 +0,0 @@
describe("errorLinkFilter", function () {
var errorLinkFilter;
beforeEach(module('docsApp'));
beforeEach(inject(function ($filter) {
errorLinkFilter = $filter('errorLink');
}));
it('should not change text that does not contain links', function () {
expect(errorLinkFilter('This is a test')).toBe('This is a test');
});
it('should find links in text and linkify them', function () {
var output = errorLinkFilter("http://ab/ (http://a/) http://1.2/v:~-123. c");
//temporary fix for IE8 sanitization whitespace bug
output = output.replace('</a>(','</a> (');
expect(output).
toBe('<a href="http://ab/">http://ab/</a> ' +
'(<a href="http://a/">http://a/</a>) ' +
'<a href="http://1.2/v:~-123">http://1.2/v:~-123</a>. c');
expect(errorLinkFilter(undefined)).not.toBeDefined();
});
it('should handle mailto', function () {
expect(errorLinkFilter("mailto:me@example.com")).
toBe('<a href="mailto:me@example.com">me@example.com</a>');
expect(errorLinkFilter("me@example.com")).
toBe('<a href="mailto:me@example.com">me@example.com</a>');
expect(errorLinkFilter("send email to me@example.com, but")).
toBe('send email to <a href="mailto:me@example.com">me@example.com</a>, but');
});
it('should handle target', function () {
expect(errorLinkFilter("http://example.com", "_blank")).
toBe('<a target="_blank" href="http://example.com">http://example.com</a>')
expect(errorLinkFilter("http://example.com", "someNamedIFrame")).
toBe('<a target="someNamedIFrame" href="http://example.com">http://example.com</a>')
});
it('should not linkify stack trace URLs', function () {
expect(errorLinkFilter("http://example.com/angular.min.js:42:1337")).
toBe("http://example.com/angular.min.js:42:1337");
});
it('should truncate linked URLs at 60 characters', function () {
expect(errorLinkFilter("http://errors.angularjs.org/very-long-version-string/$injector/nomod?p0=myApp")).
toBe('<a href="http://errors.angularjs.org/very-long-version-string/$injector/nomod?p0=myApp">' +
'http://errors.angularjs.org/very-long-version-string/$inj...</a>');
});
});
-32
View File
@@ -1,32 +0,0 @@
// Copy/pasted from src/Angular.js, so that we can disable specific tests on IE.
var msie = parseInt((/msie (\d+)/.exec(navigator.userAgent.toLowerCase()) || [])[1], 10);
var createMockWindow = function() {
var mockWindow = {};
var setTimeoutQueue = [];
mockWindow.location = window.location;
mockWindow.document = window.document;
mockWindow.getComputedStyle = angular.bind(window, window.getComputedStyle);
mockWindow.scrollTo = angular.bind(window, window.scrollTo);
mockWindow.navigator = window.navigator;
mockWindow.setTimeout = function(fn, delay) {
setTimeoutQueue.push({fn: fn, delay: delay});
};
mockWindow.setTimeout.queue = setTimeoutQueue;
mockWindow.setTimeout.expect = function(delay) {
if (setTimeoutQueue.length > 0) {
return {
process: function() {
var tick = setTimeoutQueue.shift();
expect(tick.delay).toEqual(delay);
tick.fn();
}
};
} else {
expect('SetTimoutQueue empty. Expecting delay of ').toEqual(delay);
}
};
return mockWindow;
};
-50
View File
@@ -1,50 +0,0 @@
describe('Docs Syntax', function() {
beforeEach(module('bootstrap'));
describe('syntax', function() {
var id, element, document;
beforeEach(inject(function($compile, $rootScope, $document) {
document = $document[0];
//create the HTML elements missing in IE8 for this directive
document.createElement('nav');
element = angular.element(
'<div>' +
'<pre syntax ' +
'syntax-github="gh-url" ' +
'syntax-plunkr="pl-url" ' +
'syntax-fiddle="jf-url">' +
'</pre>' +
'</div>'
);
$compile(element)($rootScope);
$rootScope.$digest();
element = element[0];
document.body.appendChild(element);
}));
it("should properly prepare a github link in the page", function() {
var github = element.querySelector('.syntax-github');
expect(github.innerHTML).toMatch(/View on Github/i);
expect(github.getAttribute('href')).toBe('gh-url');
});
it("should properly prepare a plunkr link in the page", function() {
var plunkr = element.querySelector('.syntax-plunkr');
expect(plunkr.innerHTML).toMatch(/View on Plunkr/i);
expect(plunkr.getAttribute('href')).toBe('pl-url');
});
it("should properly prepare a jsfiddle link in the page", function() {
var jsfiddle = element.querySelector('.syntax-jsfiddle');
expect(jsfiddle.innerHTML).toMatch(/View on JSFiddle/i);
expect(jsfiddle.getAttribute('href')).toBe('jf-url');
});
});
});
-33
View File
@@ -1,33 +0,0 @@
describe('DocsApp', function() {
// Do not run this suite on Internet Explorer.
if (msie < 10) return;
beforeEach(module('docsApp'));
describe('DocsVersionsCtrl', function() {
var $scope, ctrl, window, version = '9.8.7';
beforeEach(function() {
module(function($provide) {
$provide.value('$window', window = createMockWindow());
});
inject(function($controller, $rootScope) {
$scope = $rootScope.$new();
$scope.version = version;
ctrl = $controller('DocsVersionsCtrl',{
$scope : $scope,
$window : window
});
});
});
describe('changing the URL', function() {
it('should jump to the url provided', function() {
$scope.jumpToDocsVersion({ version: '1.0.1', url : 'page123'});
expect(window.location).toBe('page123');
});
});
});
});
-227
View File
@@ -1,227 +0,0 @@
/*!
* $script.js Async loader & dependency manager
* https://github.com/ded/script.js
* (c) Dustin Diaz, Jacob Thornton 2011
* License: MIT
*/
(function (name, definition, context) {
if (typeof context['module'] != 'undefined' && context['module']['exports']) context['module']['exports'] = definition()
else if (typeof context['define'] != 'undefined' && context['define'] == 'function' && context['define']['amd']) define(name, definition)
else context[name] = definition()
})('$script', function () {
var doc = document
, head = doc.getElementsByTagName('head')[0]
, validBase = /^https?:\/\//
, list = {}, ids = {}, delay = {}, scriptpath
, scripts = {}, s = 'string', f = false
, push = 'push', domContentLoaded = 'DOMContentLoaded', readyState = 'readyState'
, addEventListener = 'addEventListener', onreadystatechange = 'onreadystatechange'
function every(ar, fn) {
for (var i = 0, j = ar.length; i < j; ++i) if (!fn(ar[i])) return f
return 1
}
function each(ar, fn) {
every(ar, function(el) {
return !fn(el)
})
}
if (!doc[readyState] && doc[addEventListener]) {
doc[addEventListener](domContentLoaded, function fn() {
doc.removeEventListener(domContentLoaded, fn, f)
doc[readyState] = 'complete'
}, f)
doc[readyState] = 'loading'
}
function $script(paths, idOrDone, optDone) {
paths = paths[push] ? paths : [paths]
var idOrDoneIsDone = idOrDone && idOrDone.call
, done = idOrDoneIsDone ? idOrDone : optDone
, id = idOrDoneIsDone ? paths.join('') : idOrDone
, queue = paths.length
function loopFn(item) {
return item.call ? item() : list[item]
}
function callback() {
if (!--queue) {
list[id] = 1
done && done()
for (var dset in delay) {
every(dset.split('|'), loopFn) && !each(delay[dset], loopFn) && (delay[dset] = [])
}
}
}
setTimeout(function () {
each(paths, function (path) {
if (scripts[path]) {
id && (ids[id] = 1)
return scripts[path] == 2 && callback()
}
scripts[path] = 1
id && (ids[id] = 1)
create(!validBase.test(path) && scriptpath ? scriptpath + path + '.js' : path, callback)
})
}, 0)
return $script
}
function create(path, fn) {
var el = doc.createElement('script')
, loaded = f
el.onload = el.onerror = el[onreadystatechange] = function () {
if ((el[readyState] && !(/^c|loade/.test(el[readyState]))) || loaded) return;
el.onload = el[onreadystatechange] = null
loaded = 1
scripts[path] = 2
fn()
}
el.async = 1
el.src = path
head.insertBefore(el, head.firstChild)
}
$script.get = create
$script.order = function (scripts, id, done) {
(function callback(s) {
s = scripts.shift()
if (!scripts.length) $script(s, id, done)
else $script(s, callback)
}())
}
$script.path = function (p) {
scriptpath = p
}
$script.ready = function (deps, ready, req) {
deps = deps[push] ? deps : [deps]
var missing = [];
!each(deps, function (dep) {
list[dep] || missing[push](dep);
}) && every(deps, function (dep) {return list[dep]}) ?
ready() : !function (key) {
delay[key] = delay[key] || []
delay[key][push](ready)
req && req(missing)
}(deps.join('|'))
return $script
}
return $script
}, this);
/**
* @license AngularJS
* (c) 2010-2012 Google, Inc. http://angularjs.org
* License: MIT
*/
(function(window, document) {
var filename = /^(.*\/)angular-bootstrap.js(#.*)?$/,
scripts = document.getElementsByTagName("SCRIPT"),
serverPath,
match,
globalVars = {},
IGNORE = {
innerHeight: true, innerWidth: true,
onkeyup: true, onkeydown: true, onresize: true,
event: true, frames: true, external: true,
sessionStorage: true, clipboardData: true, localStorage: true};
for(var j = 0; j < scripts.length; j++) {
match = (scripts[j].src || "").match(filename);
if (match) {
serverPath = match[1];
}
}
document.write('<link rel="stylesheet" type="text/css" href="' + serverPath + '../css/angular.css"/>');
$script.path(serverPath+'../');
$script('angularFiles', function() {
var index = 0,
scripts = angularFiles.angularSrc;
try { delete window.angularFiles; } catch(e) { window.angularFiles = undefined; }
// initialize the window property cache
for (var prop in window) {
if (IGNORE[prop] || prop.match(/^moz[A-Z]/)) { //skip special variables which keep on changing
continue;
}
try {
globalVars[key(prop)] = window[prop];
} catch(e) {} //ignore properties that throw exception when accessed (common in FF)
}
(function next() {
if (index < scripts.length) {
var file = scripts[index++],
last = index == scripts.length,
name = last ? 'angular' : file;
$script(file.replace(/\.js$/, ''), name, function() {
angularClobberTest(file);
next();
});
} else {
// empty the cache to prevent mem leaks
globalVars = {};
bindJQuery();
publishExternalAPI(window.angular);
angularInit(document, angular.bootstrap);
}
})();
});
function key(prop) {
return "ng-clobber_" + prop;
}
function angularClobberTest(file) {
var varKey, prop,
clobbered = {};
for (prop in window) {
varKey = key(prop);
if (IGNORE[prop] || prop.match(/^moz[A-Z]/)) { //skip special variables which keep on changing
continue;
} else if (!globalVars.hasOwnProperty(varKey)) {
//console.log('new global variable found: ', prop);
try {
globalVars[varKey] = window[prop];
} catch(e) {} //ignore properties that throw exception when accessed (common in FF)
} else if (globalVars[varKey] !== window[prop] && !isActuallyNaN(window[prop]) && prop != 'jqLite') {
clobbered[prop] = true;
console.error("Global variable clobbered by script " + file + "! Variable name: " + prop);
globalVars[varKey] = window[prop];
}
}
for (varKey in globalVars) {
prop = varKey.substr(11);
if (prop === 'event' || prop.match(/^moz[A-Z]/)) { //skip special variables which keep on changing
continue;
}
if (!clobbered[prop] &&
prop != 'event' &&
prop != 'jqLite' &&
!isActuallyNaN(globalVars[varKey]) &&
globalVars[varKey] !== window[prop]) {
delete globalVars[varKey];
console.warn("Global variable unexpectedly deleted in script " + file + "! " +
"Variable name: " + prop);
}
}
function isActuallyNaN(val) {
return (typeof val === 'number') && isNaN(val);
}
}
})(window, document);
+35
View File
@@ -0,0 +1,35 @@
var _ = require('lodash');
var path = require('canonical-path');
var packagePath = __dirname;
var basePackage = require('dgeni-packages/ngdoc');
var examplesPackage = require('dgeni-packages/examples');
module.exports = function(config) {
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')
]);
config.set('processing.search.ignoreWordsFile', path.resolve(packagePath, 'ignore.words'));
config.prepend('rendering.templateFolders', [
path.resolve(packagePath, 'templates')
]);
return config;
};
+26
View File
@@ -0,0 +1,26 @@
var writer = require('dgeni/lib/utils/doc-writer');
var log = require('winston');
var util = require("util");
var filter, outputPath, depth;
module.exports = {
name: 'debug-dump',
runBefore: ['write-files'],
description: 'This processor dumps docs that match a filter to a file',
init: function(config, injectables) {
filter = config.get('processing.debug-dump.filter');
outputPath = config.get('processing.debug-dump.outputPath');
depth = config.get('processing.debug-dump.depth', 2);
},
process: function(docs) {
if ( filter && outputPath ) {
log.info('Dumping docs:', filter, outputPath);
var filteredDocs = filter(docs);
var dumpedDocs = util.inspect(filteredDocs, depth);
return writer.writeFile(outputPath, dumpedDocs).then(function() {
return docs;
});
}
}
};
+51
View File
@@ -0,0 +1,51 @@
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'],
init: function(config, injectables) {
injectables.value('errorNamespaces', {});
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');
}
injectables.value('minerrInfo', require(minerrInfoPath));
},
process: function(docs, partialNames, errorNamespaces, minerrInfo) {
// Create error namespace docs and attach error docs to each
_.forEach(docs, function(doc) {
if ( doc.docType === 'error' ) {
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'
};
}
// 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));
}
};
+17
View File
@@ -0,0 +1,17 @@
var gruntUtils = require('../../../lib/grunt/utils');
module.exports = {
name: 'git-data',
runBefore: ['loading-files'],
description: 'This processor adds information from the local git repository to the extraData injectable',
init: function(config, injectables) {
injectables.value('gitData', {
version: gruntUtils.getVersion(),
versions: gruntUtils.getPreviousVersions(),
info: gruntUtils.getGitRepoInfo()
});
},
process: function(extraData, gitData) {
extraData.git = gitData;
}
};
+42
View File
@@ -0,0 +1,42 @@
var _ = require('lodash');
var log = require('winston');
var path = require('canonical-path');
var deployment;
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',
init: function(config) {
deployment = config.deployment;
if ( !deployment || !deployment.environments ) {
throw new Error('No deployment environments found in the config.');
}
},
process: function(docs) {
// 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);
});
}
};
+91
View File
@@ -0,0 +1,91 @@
var _ = require('lodash');
var log = require('winston');
var fs = require('fs');
var path = require('canonical-path');
// 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\-_]+)/;
module.exports = {
name: 'keywords',
runAfter: ['docs-processed'],
runBefore: ['adding-extra-docs'],
description: 'This processor extracts all the keywords from the document',
init: function(config) {
// Load up the keywords to ignore, if specified in the config
if ( config.processing.search && config.processing.search.ignoreWordsFile ) {
var ignoreWordsPath = path.resolve(config.basePath, config.processing.search.ignoreWordsFile);
wordsToIgnore = fs.readFileSync(ignoreWordsPath, 'utf8').toString().split(/[,\s\n\r]+/gm);
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);
},
process: function(docs) {
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) {
var tokens = text.toLowerCase().split(/[\.\s,`'"#]+/mg);
_.forEach(tokens, function(token){
var match = token.match(KEYWORD_REGEX);
if (match){
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]; });
_.forEach(docs, function(doc) {
var words = [];
var keywordMap = _.clone(ignoreWordsMap);
// 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);
}
});
doc.searchTerms = {
titleWords: extractTitleWords(doc.name),
keywords: _.sortBy(words).join(' ')
};
});
}
};
+220
View File
@@ -0,0 +1,220 @@
var _ = require('lodash');
var path = require('canonical-path');
var log = require('winston');
var AREA_NAMES = {
api: 'API',
guide: 'Developer Guide',
misc: 'Miscellaneous',
tutorial: 'Tutorial',
error: 'Error Reference'
};
function getNavGroup(pages, area, pageSorter, pageMapper) {
var navItems = _(pages)
// We don't want the child to include the index page as this is already catered for
.omit(function(page) { return page.id === 'index'; })
// Apply the supplied sorting function
.sortBy(pageSorter)
// Apply the supplied mapping function
.map(pageMapper)
.value();
return {
name: area.name,
type: 'group',
href: area.id,
navItems: navItems
};
}
var navGroupMappers = {
api: function(areaPages, area) {
var navGroups = _(areaPages)
.filter('module') // We are not interested in docs that are not in a module
.groupBy('module')
.map(function(modulePages, moduleName) {
log.debug('moduleName: ' + moduleName);
var navItems = [];
var modulePage;
_(modulePages)
.groupBy('docType')
.tap(function(docTypes) {
log.debug(_.keys(docTypes));
// Extract the module page from the collection
modulePage = docTypes.module[0];
delete docTypes.module;
})
.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;
}
})
.forEach(function(sectionPages, sectionName) {
sectionPages = _.sortBy(sectionPages, 'name');
if ( sectionPages.length > 0 ) {
// Push a navItem for this section
navItems.push({
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: 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'
};
})];
}
};
var outputFolder;
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'],
runBefore: ['extra-docs-added'],
init: function(config) {
outputFolder = config.rendering.outputFolder;
},
process: function(docs) {
_(docs)
.filter(function(doc) { return doc.area === 'api'; })
.filter(function(doc) { return doc.docType === 'module'; })
.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]
};
areas[areaId] = area;
var navGroupMapper = navGroupMappers[area.id] || navGroupMappers['pages'];
area.navGroups = navGroupMapper(pages, area);
});
_.forEach(docs, function(doc) {
if ( !doc.path ) {
log.warn('Missing path property for ', doc.id);
}
});
// Extract a list of basic page information for mapping paths to paritals 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);
}
};
@@ -0,0 +1,52 @@
var _ = require('lodash');
var log = require('winston');
var path = require('canonical-path');
var trimIndentation = require('dgeni/lib/utils/trim-indentation');
var code = require('dgeni/lib/utils/code');
var protractorFolder;
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;
}
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'],
init: function(config, injectables) {
protractorFolder = config.get('rendering.protractor.outputFolder', 'ptore2e');
},
process: function(docs, examples) {
_.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'));
});
});
}
};
+38
View File
@@ -0,0 +1,38 @@
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) {
var version = gitData.version;
var versions = gitData.versions;
if ( !version ) {
throw new Error('Invalid configuration. Please provide a valid `source.currentVersion` property');
}
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);
}
};
+9
View File
@@ -0,0 +1,9 @@
module.exports = {
name: 'step',
transformFn: function(doc, tag) {
if ( doc.docType !== 'tutorial' ) {
throw new Error('Invalid tag, step. You should only use this tag on tutorial docs');
}
return parseInt(tag.description,10);
}
};
+17
View File
@@ -0,0 +1,17 @@
{% extends "base.template.html" %}
{% block content %}
<h1>Error: {$ doc.id $}
<div><span class='hint'>{$ doc.fullName $}</span></div>
</h1>
<div>
<pre class="minerr-errmsg" error-display="{$ doc.formattedErrorMessage $}">{$ doc.formattedErrorMessage $}</pre>
</div>
<h2>Description</h2>
<div class="description">
{$ doc.description | marked $}
</div>
{% endblock %}
@@ -0,0 +1,28 @@
{% extends 'base.template.html' %}
{% block content %}
<h1>{$ doc.name $}</h1>
<div class="description">
Here are the list of errors in the {$ doc.name $} namespace.
</div>
<div class="component-breakdown">
<div>
<table class="definition-table">
<tr>
<th>Name</th>
<th>Description</th>
</tr>
{% for errorDoc in doc.errors -%}
<tr>
<td><a href="{$ errorDoc.path $}">{$ errorDoc.name $}</td>
<td>{$ errorDoc.fullName $}</td>
</tr>
{% endfor %}
</table>
</div>
</div>
{% endblock %}
@@ -0,0 +1,249 @@
<!doctype html>
<html lang="en" ng-app="docsApp" ng-controller="DocsController">
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="Description"
content="AngularJS is what HTML would have been, had it been designed for building web-apps.
Declarative templates with data-binding, MVC, dependency injection and great
testability story all implemented with pure client-side JavaScript!">
<meta name="fragment" content="!">
<title ng-bind-template="AngularJS: {{ currentArea.name }}: {{ currentPage.name || 'Error: Page not found'}}">AngularJS</title>
<script type="text/javascript">
// dynamically add base tag as well as css and javascript files.
// we can't add css/js the usual way, because some browsers (FF) eagerly prefetch resources
// before the base attribute is added, causing 404 and terribly slow loading of the docs app.
(function() {
var indexFile = (location.pathname.match(/\/(index[^\.]*\.html)/) || ['', ''])[1],
rUrl = /(#!\/|api|guide|misc|tutorial|error|index[^\.]*\.html).*$/,
baseUrl = location.href.replace(rUrl, indexFile),
production = location.hostname === 'docs.angularjs.org',
headEl = document.getElementsByTagName('head')[0],
sync = true;
addTag('base', {href: baseUrl});
{% for stylesheet in doc.stylesheets %}addTag('link', {rel: 'stylesheet', href: '{$ stylesheet $}', type: 'text/css'});
{% endfor %}
{% for script in doc.scripts %}addTag('script', {src: '{$ script $}' }, sync);
{% endfor %}
function addTag(name, attributes, sync) {
var el = document.createElement(name),
attrName;
for (attrName in attributes) {
el.setAttribute(attrName, attributes[attrName]);
}
sync ? document.write(outerHTML(el)) : headEl.appendChild(el);
}
function outerHTML(node){
// if IE, Chrome take the internal method otherwise build one
return node.outerHTML || (
function(n){
var div = document.createElement('div'), h;
div.appendChild(n);
h = div.innerHTML;
div = null;
return h;
})(node);
}
})();
// force page reload when new update is available
window.applicationCache && window.applicationCache.addEventListener('updateready', function(e) {
if (window.applicationCache.status == window.applicationCache.UPDATEREADY) {
window.applicationCache.swapCache();
window.location.reload();
}
}, false);
// GA asynchronous tracker
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-8594346-3']);
_gaq.push(['_setDomainName', '.angularjs.org']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
</head>
<body>
<div id="wrapper">
<header class="header header-fixed">
<section class="navbar navbar-inverse docs-navbar-primary" ng-controller="DocsSearchCtrl">
<div class="container">
<div class="row">
<div class="col-md-9 header-branding">
<a class="brand navbar-brand" href="http://angularjs.org">
<img class="logo" src="img/angularjs-for-header-only.svg">
</a>
<ul class="nav navbar-nav">
<li class="divider-vertical"></li>
<li><a href="http://angularjs.org"><i class="icon-home icon-white"></i> Home</a></li>
<li class="divider-vertical"></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
<i class="icon-eye-open icon-white"></i> Learn <b class="caret"></b>
</a>
<ul class="dropdown-menu">
<li class="disabled"><a href="http://angularjs.org/">Why AngularJS?</a></li>
<li><a href="http://www.youtube.com/user/angularjs">Watch</a></li>
<li><a href="tutorial">Tutorial</a></li>
<li><a href="http://builtwith.angularjs.org/">Case Studies</a></li>
<li><a href="https://github.com/angular/angular-seed">Seed App project template</a></li>
<li><a href="misc/faq">FAQ</a></li>
</ul>
</li>
<li class="divider-vertical"></li>
<li class="dropdown active">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
<i class="icon-book icon-white"></i> Develop <b class="caret"></b>
</a>
<ul class="dropdown-menu">
<li><a href="tutorial">Tutorial</a></li>
<li><a href="guide">Developer Guide</a></li>
<li><a href="api">API Reference</a></li>
<li><a href="error">Error Reference</a></li>
<li><a href="misc/contribute">Contribute</a></li>
<li><a href="http://code.angularjs.org/">Download</a></li>
</ul>
</li>
<li class="divider-vertical"></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown">
<i class="icon-comment icon-white"></i> Discuss <b class="caret"></b>
</a>
<ul class="dropdown-menu">
<li><a href="http://blog.angularjs.org">Blog</a></li>
<li><a href="http://groups.google.com/group/angular">Mailing List</a></li>
<li><a href="http://webchat.freenode.net/?channels=angularjs&uio=d4">Chat Room</a></li>
<li class="divider"></li>
<li><a href="https://twitter.com/#!/angularjs">Twitter</a></li>
<li><a href="https://plus.google.com/110323587230527980117">Google+</a></li>
<li class="divider"></li>
<li><a href="https://github.com/angular/angular.js">GitHub</a></li>
<li><a href="https://github.com/angular/angular.js/issues">Issue Tracker</a></li>
</ul>
</li>
<li class="divider-vertical"></li>
</ul>
</div>
<form ng-class="{focus:focus}" class="navbar-search col-md-3 docs-search" ng-submit="submit()">
<span class="glyphicon glyphicon-search search-icon"></span>
<input type="text"
name="as_q"
class="search-query"
placeholder="Click or press / to search"
ng-focus="focus=true"
ng-blur="focus=false"
ng-change="search(q)"
ng-model="q"
docs-search-input
autocomplete="off" />
</form>
</div>
</div>
<div class="search-results-container" ng-show="hasResults">
<div class="container">
<a href="" ng-click="hideResults()" class="search-close">
<span class="glyphicon glyphicon-remove search-close-icon"></span> Close
</a>
<div class="search-results-frame">
<div ng-repeat="(key, value) in results" class="search-results-group" ng-class="colClassName + ' col-group-' + key">
<h4 class="search-results-group-heading">{{ key }}</h4>
<div class="search-results">
<div ng-repeat="item in value" class="search-result">
- <a ng-click="hideResults()" ng-href="{{ item.path }}">{{ item.name }}</a>
</div>
</div>
</div>
</div>
</div>
</div>
</section>
<section class="sup-header">
<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.full) group by (v.isStable?'Stable':'Unstable') for v in docs_versions"
ng-model="docs_version"
ng-change="jumpToDocsVersion(docs_version)"
class="docs-version-jump">
</select>
</div>
</div>
<div class="grid-right">
<ul class="nav-breadcrumb">
<li ng-repeat="crumb in breadcrumb" class="nav-breadcrumb-entry naked-list">
<span class="divider"> /</span>
<a ng-href="{{crumb.url}}">{{crumb.name}}</a>
</li>
</ul>
</div>
</div>
</section>
</header>
<section role="main" class="container main-body">
<div class="main-grid main-body-grid">
<div class="grid-left">
<a class="btn toc-toggle visible-xs" ng-click="toc=!toc">Show / Hide Table of Contents</a>
<div class="side-navigation" ng-show="toc==true">
<ul class="nav-list naked-list">
<li ng-repeat="navGroup in currentArea.navGroups track by navGroup.name" class="nav-index-group">
<a href="{{ navGroup.href }}" ng-class="navClass(navGroup)" class="nav-index-group-heading">{{ navGroup.name }}</a>
<ul class="aside-nav">
<li ng-repeat="navItem in navGroup.navItems" ng-class="navClass(navItem)" class="nav-index-listing">
<a ng-if="navItem.extra.href" ng-class="navClass(navItem.extra)" href="{{navItem.extra.href}}">
{{navItem.extra.text}}<i ng-if="navItem.extra.icon" class="icon-{{navItem.extra.icon}}"></i>
</a>
<a tabindex="2" ng-class="linkClass(navItem)" href="{{navItem.href}}">{{navItem.name}}</a>
</li>
</ul>
</li>
</ul>
<a href="" ng-click="toc=false" class="toc-close visible-xs">
<span class="glyphicon glyphicon-remove toc-close-icon"></span> Close
</a>
</div>
</div>
<div class="grid-right">
<div id="loading" ng-show="loading">Loading...</div>
<div ng-hide="loading" ng-include="currentPage.outputPath" onload="afterPartialLoaded()" autoscroll></div>
</div>
</div>
</section>
<footer class="footer">
<div class="container">
<p class="pull-right"><a back-to-top href="#">Back to top</a></p>
<p>
Super-powered by Google ©2010-2014
( <a id="version"
ng-href="https://github.com/angular/angular.js/blob/master/CHANGELOG.md#{{versionNumber}}"
ng-bind-template="v{{version}}">
</a>
)
</p>
<p>
Code licensed under the
<a href="https://github.com/angular/angular.js/blob/master/LICENSE" target="_blank">The
MIT License</a>. Documentation licensed under <a
href="http://creativecommons.org/licenses/by/3.0/">CC BY 3.0</a>.
</p>
</div>
</footer>
</div>
</body>
</html>
@@ -0,0 +1,4 @@
// Meta data used by the AngularJS docs app
angular.module('pagesData', [])
.value('NG_PAGES', {$ doc.pages | json $})
.value('NG_NAVIGATION', {$ doc.areas | json $});
@@ -0,0 +1,7 @@
describe("{$ doc.description $}", function() {
beforeEach(function() {
browser.get("{$ doc.pathPrefix $}/{$ doc.examplePath $}");
});
{$ doc.innerTest $}
});
@@ -0,0 +1 @@
{% include 'overview.template.html' %}
@@ -0,0 +1,4 @@
// Meta data used by the AngularJS docs app
angular.module('versionsData', [])
.value('NG_VERSION', {$ doc.currentVersion | json $})
.value('NG_VERSIONS', {$ doc.versions | json $});
+3 -4
View File
@@ -33,8 +33,8 @@ This module is provided by default and contains the core components of AngularJS
<p>
Some examples include:
{@link ng.directive:ngClick ngClick},
{@link ng.directive:ngInclude ngInclude},
{@link ng.directive:ngRepeat ngRepeat},
{@link directive:ngInclude ngInclude},
{@link directive:ngRepeat ngRepeat},
etc… <br />
</p>
</td>
@@ -51,7 +51,6 @@ This module is provided by default and contains the core components of AngularJS
Some examples include:
{@link ng.$compile $compile},
{@link ng.$http $http},
{@link ngRoute.$routeParams $routeParams},
{@link ng.$location $location},
etc…
<p>
@@ -157,7 +156,7 @@ or JavaScript callbacks.
{@link ngAnimate JS-based animations}
</td>
<td>
Use {@link angular.Module#methods_animation module.animation()} to register a JavaScript animation. Once registered the animation can be triggered by referencing the CSS class within the HTML template code.
Use {@link angular.Module#animation module.animation()} to register a JavaScript animation. Once registered the animation can be triggered by referencing the CSS class within the HTML template code.
</td>
</tr>
</table>
-11
View File
@@ -1,11 +0,0 @@
@ngdoc overview
@name ng
@description
# ng (core module)
The ng module is loaded by default when an AngularJS application is started. The module itself
contains the essential components for an AngularJS application to function. The table below
lists a high level breakdown of each of the services/factories, filters, directives and testing
components available within this core module.
<div doc-module-components="ng"></div>
-122
View File
@@ -1,122 +0,0 @@
@ngdoc overview
@name Cookbook: Advanced Form
@description
Here we extend the basic form example to include common features such as reverting, dirty state
detection, and preventing invalid form submission.
<doc:example>
<doc:source>
<script>
function UserForm($scope) {
var master = {
name: 'John Smith',
address:{
line1: '123 Main St.',
city:'Anytown',
state:'AA',
zip:'12345'
},
contacts:[
{type:'phone', value:'1(234) 555-1212'}
]
};
$scope.state = /^\w\w$/;
$scope.zip = /^\d\d\d\d\d$/;
$scope.cancel = function() {
$scope.form = angular.copy(master);
};
$scope.save = function() {
master = $scope.form;
$scope.cancel();
};
$scope.addContact = function() {
$scope.form.contacts.push({type:'', value:''});
};
$scope.removeContact = function(index) {
$scope.form.contacts.splice(index, 1);
};
$scope.isCancelDisabled = function() {
return angular.equals(master, $scope.form);
};
$scope.isSaveDisabled = function() {
return $scope.myForm.$invalid || angular.equals(master, $scope.form);
};
$scope.cancel();
}
</script>
<div ng-controller="UserForm">
<form name="myForm">
<label>Name:</label><br/>
<input type="text" ng-model="form.name" required/> <br/><br/>
<label>Address:</label> <br/>
<input type="text" ng-model="form.address.line1" size="33" required/> <br/>
<input type="text" ng-model="form.address.city" size="12" required/>,
<input type="text" ng-model="form.address.state" size="2"
ng-pattern="state" required/>
<input type="text" ng-model="form.address.zip" size="5"
ng-pattern="zip" required/><br/><br/>
<label>Contacts:</label>
[ <a href="" ng-click="addContact()">add</a> ]
<div ng-repeat="contact in form.contacts">
<select ng-model="contact.type">
<option>email</option>
<option>phone</option>
<option>pager</option>
<option>IM</option>
</select>
<input type="text" ng-model="contact.value" required/>
[ <a href="" ng-click="removeContact($index)">X</a> ]
</div>
<button ng-click="cancel()" ng-disabled="isCancelDisabled()">Cancel</button>
<button ng-click="save()" ng-disabled="isSaveDisabled()">Save</button>
</form>
<hr/>
Debug View:
<pre>form={{form}}</pre>
</div>
</doc:source>
<doc:scenario>
it('should enable save button', function() {
expect(element(':button:contains(Save)').attr('disabled')).toBeTruthy();
input('form.name').enter('');
expect(element(':button:contains(Save)').attr('disabled')).toBeTruthy();
input('form.name').enter('change');
expect(element(':button:contains(Save)').attr('disabled')).toBeFalsy();
element(':button:contains(Save)').click();
expect(element(':button:contains(Save)').attr('disabled')).toBeTruthy();
});
it('should enable cancel button', function() {
expect(element(':button:contains(Cancel)').attr('disabled')).toBeTruthy();
input('form.name').enter('change');
expect(element(':button:contains(Cancel)').attr('disabled')).toBeFalsy();
element(':button:contains(Cancel)').click();
expect(element(':button:contains(Cancel)').attr('disabled')).toBeTruthy();
expect(element(':input[ng\\:model="form.name"]').val()).toEqual('John Smith');
});
</doc:scenario>
</doc:example>
#Things to notice
* Cancel & save buttons are only enabled if the form is dirty — there is something to cancel or
save.
* Save button is only enabled if there are no validation errors on the form.
* Cancel reverts the form changes back to original state.
* Save updates the internal model of the form.
* Debug view shows the two models. One presented to the user form and the other being the pristine
copy master.
-63
View File
@@ -1,63 +0,0 @@
@ngdoc overview
@name Cookbook: Resources - Buzz
@description
External resources are URLs that provide JSON data, which are then rendered with the help of
templates. Angular has a resource factory that can be used to give names to the URLs and then
attach behavior to them. For example you can use the
{@link http://code.google.com/apis/buzz/v1/getting_started.html#background-operations| Google Buzz
API}
to retrieve Buzz activity and comments.
<doc:example>
<doc:source>
<script>
BuzzController.$inject = ['$scope', '$resource'];
function BuzzController($scope, $resource) {
$scope.userId = 'googlebuzz';
$scope.Activity = $resource(
'https://www.googleapis.com/buzz/v1/activities/:userId/:visibility/:activityId/:comments',
{alt: 'json', callback: 'JSON_CALLBACK'},
{ get: {method: 'JSONP', params: {visibility: '@self'}},
replies: {method: 'JSONP', params: {visibility: '@self', comments: '@comments'}}
});
$scope.fetch = function() {
$scope.activities = $scope.Activity.get({userId:this.userId});
}
$scope.expandReplies = function(activity) {
activity.replies = $scope.Activity.replies({userId: this.userId, activityId: activity.id});
}
};
</script>
<div ng-controller="BuzzController">
<input ng-model="userId"/>
<button ng-click="fetch()">fetch</button>
<hr/>
<div class="buzz" ng-repeat="item in activities.data.items">
<h1 style="font-size: 15px;">
<img ng-src="{{item.actor.thumbnailUrl}}" style="max-height:30px;max-width:30px;"/>
<a ng-href="{{item.actor.profileUrl}}">{{item.actor.name}}</a>
<a href ng-click="expandReplies(item)" style="float: right;">
Expand replies: {{item.links.replies[0].count}}
</a>
</h1>
{{item.object.content | html}}
<div class="reply" ng-repeat="reply in item.replies.data.items" style="margin-left: 20px;">
<img ng-src="{{reply.actor.thumbnailUrl}}" style="max-height:30px;max-width:30px;"/>
<a ng-href="{{reply.actor.profileUrl}}">{{reply.actor.name}}</a>:
{{reply.content | html}}
</div>
</div>
</div>
</doc:source>
<doc:scenario>
xit('fetch buzz and expand', function() {
element(':button:contains(fetch)').click();
expect(repeater('div.buzz').count()).toBeGreaterThan(0);
element('.buzz a:contains(Expand replies):first').click();
expect(repeater('div.reply').count()).toBeGreaterThan(0);
});
</doc:scenario>
</doc:example>
-151
View File
@@ -1,151 +0,0 @@
@ngdoc overview
@name Cookbook: Deep Linking
@description
Deep linking allows you to encode the state of the application in the URL so that it can be
bookmarked and the application can be restored from the URL to the same state.
While Angular does not force you to deal with bookmarks in any particular way, it has services
which make the common case described here very easy to implement.
# Assumptions
Your application consists of a single HTML page which bootstraps the application. We will refer
to this page as the chrome.
Your application is divided into several screens (or views) which the user can visit. For example,
the home screen, settings screen, details screen, etc. For each of these screens, we would like to
assign a URL so that it can be bookmarked and later restored. Each of these screens will be
associated with a controller which define the screen's behavior. The most common case is that the
screen will be constructed from an HTML snippet, which we will refer to as the partial. Screens can
have multiple partials, but a single partial is the most common construct. This example makes the
partial boundary visible using a blue line.
You can make a routing table which shows which URL maps to which partial view template and which
controller.
# Example
In this example we have a simple app which consist of two screens:
* Welcome: url `welcome` Show the user contact information.
* Settings: url `settings` Show an edit screen for user contact information.
<example module="deepLinking" deps="angular-route.js, angular-sanitize.js">
<file name="script.js">
angular.module('deepLinking', ['ngRoute', 'ngSanitize'])
.config(function($routeProvider) {
$routeProvider.
when("/welcome", {templateUrl:'welcome.html', controller:WelcomeCntl}).
when("/settings", {templateUrl:'settings.html', controller:SettingsCntl});
});
AppCntl.$inject = ['$scope', '$route']
function AppCntl($scope, $route) {
$scope.$route = $route;
// initialize the model to something useful
$scope.person = {
name:'anonymous',
contacts:[{type:'email', url:'anonymous@example.com'}]
};
}
function WelcomeCntl($scope) {
$scope.greet = function() {
alert("Hello " + $scope.person.name);
};
}
function SettingsCntl($scope, $location) {
$scope.cancel = function() {
$scope.form = angular.copy($scope.person);
};
$scope.save = function() {
angular.copy($scope.form, $scope.person);
$location.path('/welcome');
};
$scope.cancel();
}
</file>
<file name="style.css">
[ng-view] {
border: 1px solid blue;
margin: 0;
padding:1em;
}
.partial-info {
background-color: blue;
color: white;
padding: 3px;
}
</file>
<file name="index.html">
<div ng-controller="AppCntl">
<h1>Your App Chrome</h1>
[ <a href="welcome">Welcome</a> | <a href="settings">Settings</a> ]
<hr/>
<span class="partial-info">
Partial: {{$route.current.template}}
</span>
<div ng-view></div>
<small>Your app footer </small>
</div>
</file>
<file name="settings.html">
<label>Name:</label>
<input type="text" ng:model="form.name" required>
<div ng:repeat="contact in form.contacts">
<select ng:model="contact.type">
<option>url</option>
<option>email</option>
<option>phone</option>
</select>
<input type="text" ng:model="contact.url">
[ <a href="" ng:click="form.contacts.$remove(contact)">X</a> ]
</div>
<div>
[ <a href="" ng:click="form.contacts.$add()">add</a> ]
</div>
<button ng:click="cancel()">Cancel</button>
<button ng:click="save()">Save</button>
</file>
<file name="welcome.html">
Hello {{person.name}},
<div>
Your contact information:
<div ng:repeat="contact in person.contacts">{{contact.type}}:
<span ng-bind-html="contact.url|linky"></span>
</div>
</div>
</file>
<file name="scenario.js">
it('should navigate to URL', function() {
element('a:contains(Welcome)').click();
expect(element('[ng-view]').text()).toMatch(/Hello anonymous/);
element('a:contains(Settings)').click();
input('form.name').enter('yourname');
element(':button:contains(Save)').click();
element('a:contains(Welcome)').click();
expect(element('[ng-view]').text()).toMatch(/Hello yourname/);
});
</file>
</example>
# Things to notice
* Routes are defined in the `AppCntl` class. The initialization of the controller causes the
initialization of the {@link api/ngRoute.$route $route} service with the proper URL
routes.
* The {@link api/ngRoute.$route $route} service then watches the URL and instantiates the
appropriate controller when the URL changes.
* The {@link api/ngRoute.directive:ngView ngView} widget loads the
view when the URL changes. It also sets the view scope to the newly instantiated controller.
* Changing the URL is sufficient to change the controller and view. It makes no difference whether
the URL is changed programmatically or by the user.
-114
View File
@@ -1,114 +0,0 @@
@ngdoc overview
@name Cookbook: Form
@description
A web application's main purpose is to present and gather data. For this reason Angular strives
to make both of these operations trivial. This example shows off how you can build a simple form to
allow a user to enter data.
<doc:example>
<doc:source>
<script>
function FormController($scope) {
var user = $scope.user = {
name: 'John Smith',
address:{line1: '123 Main St.', city:'Anytown', state:'AA', zip:'12345'},
contacts:[{type:'phone', value:'1(234) 555-1212'}]
};
$scope.state = /^\w\w$/;
$scope.zip = /^\d\d\d\d\d$/;
$scope.addContact = function() {
user.contacts.push({type:'email', value:''});
};
$scope.removeContact = function(contact) {
for (var i = 0, ii = user.contacts.length; i < ii; i++) {
if (contact === user.contacts[i]) {
$scope.user.contacts.splice(i, 1);
}
}
};
}
</script>
<div ng-controller="FormController" class="example">
<label>Name:</label><br>
<input type="text" ng-model="user.name" required/> <br><br>
<label>Address:</label><br>
<input type="text" ng-model="user.address.line1" size="33" required> <br>
<input type="text" ng-model="user.address.city" size="12" required>,
<input type="text" ng-model="user.address.state"
ng-pattern="state" size="2" required>
<input type="text" ng-model="user.address.zip" size="5"
ng-pattern="zip" required><br><br>
<label>Phone:</label>
[ <a href="" ng-click="addContact()">add</a> ]
<div ng-repeat="contact in user.contacts">
<select ng-model="contact.type">
<option>email</option>
<option>phone</option>
<option>pager</option>
<option>IM</option>
</select>
<input type="text" ng-model="contact.value" required>
[ <a href="" ng-click="removeContact(contact)">X</a> ]
</div>
<hr/>
Debug View:
<pre>user={{user | json}}</pre>
</div>
</doc:source>
<doc:scenario>
it('should show debug', function() {
expect(binding('user')).toMatch(/John Smith/);
});
it('should add contact', function() {
using('.example').element('a:contains(add)').click();
using('.example div:last').input('contact.value').enter('you@example.org');
expect(binding('user')).toMatch(/\(234\) 555\-1212/);
expect(binding('user')).toMatch(/you@example.org/);
});
it('should remove contact', function() {
using('.example').element('a:contains(X)').click();
expect(binding('user')).not().toMatch(/\(234\) 555\-1212/);
});
it('should validate zip', function() {
expect(using('.example').
element(':input[ng\\:model="user.address.zip"]').
prop('className')).not().toMatch(/ng-invalid/);
using('.example').input('user.address.zip').enter('abc');
expect(using('.example').
element(':input[ng\\:model="user.address.zip"]').
prop('className')).toMatch(/ng-invalid/);
});
it('should validate state', function() {
expect(using('.example').element(':input[ng\\:model="user.address.state"]').prop('className'))
.not().toMatch(/ng-invalid/);
using('.example').input('user.address.state').enter('XXX');
expect(using('.example').element(':input[ng\\:model="user.address.state"]').prop('className'))
.toMatch(/ng-invalid/);
});
</doc:scenario>
</doc:example>
# Things to notice
* The user data model is initialized {@link api/ng.directive:ngController controller} and is
available in the {@link api/ng.$rootScope.Scope scope} with the initial data.
* For debugging purposes we have included a debug view of the model to better understand what
is going on.
* The {@link api/ng.directive:input input directives} simply refer
to the model and are data-bound.
* The inputs validate. (Try leaving them blank or entering non digits in the zip field)
* In your application you can simply read from or write to the model and the form will be updated.
* By clicking the 'add' link you are adding new items into the `user.contacts` array which are then
reflected in the view.
-39
View File
@@ -1,39 +0,0 @@
@ngdoc overview
@name Cookbook: Hello World
@description
<doc:example>
<doc:source>
<script>
function HelloCntl($scope) {
$scope.name = 'World';
}
</script>
<div ng-controller="HelloCntl">
Your name: <input type="text" ng-model="name"/>
<hr/>
Hello {{name || "World"}}!
</div>
</doc:source>
<doc:scenario>
it('should change the binding when user enters text', function() {
expect(binding('name')).toEqual('World');
input('name').enter('angular');
expect(binding('name')).toEqual('angular');
});
</doc:scenario>
</doc:example>
# Things to notice
Take a look through the source and note:
* The script tag that {@link guide/bootstrap bootstraps} the Angular environment.
* The text {@link api/ng.directive:input input form control} which is
bound to the greeting name text.
* There is no need for listener registration and event firing on change events.
* The implicit presence of the `name` variable which is in the root {@link api/ng.$rootScope.Scope scope}.
* The double curly brace `{{markup}}`, which binds the name variable to the greeting text.
* The concept of {@link guide/databinding data binding}, which reflects any
changes to the
input field in the greeting text.

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