Compare commits

..

317 Commits

Author SHA1 Message Date
Igor Minar d2a769e196 chore(release): cut the 1.0.5 flatulent-propulsion release 2013-02-20 12:58:02 -08:00
Igor Minar 68a8c8907d docs(changelog): add release notes for 1.0.5 and 1.1.3 2013-02-20 12:57:08 -08:00
Igor Minar 701d61080a chore(matchers): fix hasBeenCalledOnceWith matcher
the error message was wrong and misleading
2013-02-20 08:44:53 -08:00
Igor Minar a8cc449706 fix($compile): sanitize values bound to a[href] 2013-02-20 00:40:51 -08:00
Per Rovegård 2aa212b19c fix(ngClass): keep track of old ngClass value manually
ngClassWatchAction, when called as a $watch function, gets the wrong old
value after it has been invoked previously due to observation of the
interpolated class attribute. As a result it doesn't remove classes
properly. Keeping track of the old value manually seems to fix this.

Closes #1637
2013-02-18 20:35:40 -08:00
Pete Bacon Darwin 1f23cfe9c7 fix(compile): should not leak memory when there are top level empty text nodes
The change to prevent <span> elements being wrapped around empty text nodes caused these empty text nodes to have scopes and controllers attached, through jqLite.data() calls, which led to memory leaks and errors in IE8.
Now we exclude all but document nodes and elements from having jqLite.data() set both in the compiler and in ng-view.

Fixes: #1968 and #1876
2013-02-18 13:04:24 +00:00
Will Moore 0fa8e47fb5 fix($httpBackend): patch for Firefox bug w/ CORS and response headers
A workaround for https://bugzilla.mozilla.org/show_bug.cgi?id=608735
In FF getAllResponseHeaders() returns null if the request is the result of CORS.

Tried to format the code so that when a FF patch is released and gains enough
traction it can easily be selected and deleted. Heavily inspired by jQuery's
patch for the same bug. This patch falls short of passing through custom headers
but covers all of the "simple response headers" in the spec at
http://www.w3.org/TR/cors/

This commit should get reverted once Firefox 21 gets out.

Closes #1468

Conflicts:
	src/ng/httpBackend.js
2013-02-14 16:52:02 -08:00
Igor Minar 8043784fd7 fix(a): workaround IE bug affecting mailto urls
Apparently there is a really weird bug in IE6-8 that causes anchor textContent
to be reset with href content when both contain @ symbol.

Inserting a bogus comment node into all anchor elements in IE works around this
browser bug.

I'm fixing the issue via directive because that way we'll fix it for jQuery as
well.

I fixed an e2e test too because it was incorrect.

Closes #1949
2013-02-14 16:43:28 -08:00
Igor Minar 526a6b31e5 fix(*): don't use instanceof to detect arrays
this breaks when multiple javascript contexts are involved - like in node-webkit

see original PR: #1966

Closes #1966
2013-02-14 16:40:58 -08:00
Cedric Soulas 14fd064a62 docs($resource): fix bad indentation producing a code block 2013-02-14 15:45:37 -08:00
Ewen Cumming 3178afbf0c docs($rootScope): rearrange event listener docs 2013-02-14 15:42:51 -08:00
deboer ce3b616432 fix(ngSwitch): make ngSwitch compatible with controller BC module
add a $scope to the ngSwitch's controller to fool the controller
BC (backwards compatibility) module used by DFA.
2013-02-14 15:38:20 -08:00
Vineet Kumar 54a761905d docs($q): fix a few typos 2013-02-14 15:19:49 -08:00
Dylan Pyle aa531d7bd1 docs(guide): fix some invalid javascript in directive documentation
Use double quotes to maintain consistency with other HTML
2013-02-14 15:15:06 -08:00
Daniel Luz d7e9ae1215 fix($rootScope): minor typo fixes 2013-02-14 14:43:32 -08:00
Daniel Luz 6cf9ede88e docs($parse): document function argument types, fix minor typo 2013-02-14 14:43:32 -08:00
Trotter Cashion 6092291bd7 chore(reakefile): auto install npm packages 2013-02-14 14:43:31 -08:00
Shyam Seshadri 3d0f11212f fix(compiler): Allow startingTag method to handle text / comment nodes 2013-02-14 14:43:31 -08:00
Fredrik Bonander 6194e002e2 fix(resource): Update RegExp to allow urlParams with out leading slash
Will allow reoucese to be loaded from a relative path
Example:
var R = $resource(':path');
R.get({ path : 'data.json' });

Example usage:
Load resources in applications not using webserver, ie local webapp in
on a tablet.
2013-02-14 14:43:31 -08:00
Kury Kruitbosch 75545d4d1c fix(numberFilter): fix formatting when "0" passed as fractionSize
When checking to add decimal and trialing 0s number filter used to check
trueness of fractionSize. "0" evaluating to true causes "123" to return "123."
2013-02-14 13:46:07 -08:00
Jesse Cooke d67eb2f2db docs(guide): Fix typos in concepts/model,view. 2013-02-14 13:09:40 -08:00
Igor Minar 6b8153ff0f chore(Rakefile): parallelize the build on Travis
now that the forking issue is solved we can run regular build there

https://github.com/travis-ci/travis-ci/issues/845
2013-02-14 12:52:20 -08:00
Cedric Soulas fb132732f1 docs($resource): fix missing punctuation 2013-02-14 12:14:13 -08:00
Igor Minar 336b157497 test(angular.copy): add tests for scenarios when target is missing 2013-02-11 22:10:58 -08:00
Igor Minar d16975a9de revert: refactor(angular.copy): use slice(0) to clone arrays
This reverts commit a5b3bcf41c.

slice(0) doesn't perform deep copy of the array so its unsuitable
for our purposes.
2013-02-11 22:01:15 -08:00
Igor Minar 87f6b36bab chore(docs): improve docs parser type
previously we barfed on function type definition with optional arguments
like {function(number=)}

this fixes it

I also added a bunch of code that helps to debug incorrectly parsed docs.
2013-02-11 14:08:27 -08:00
Igor Minar 43fccf5617 refactor(angular.copy): use array.length=0 to empty arrays 2013-02-11 14:07:57 -08:00
Igor Minar a5b3bcf41c refactor(angular.copy): use slice(0) to clone arrays
slice(0) is way faster on most browsers
2013-02-11 14:07:10 -08:00
Igor Minar 8801d9c286 fix(angular.forEach): correctly iterate over objects with length prop
Should handle JQLite, jQuery, NodeList and other objects like arrays
but not other generic objects or instances of user defined types
with length property.

Closes #1840
2013-02-11 12:46:13 -08:00
radu a8e114f351 docs($q): fix typos 2013-02-07 04:16:49 -08:00
Julie 9a3a9b46e5 fix(scenario): include error messages in XML output
Fix the XML output of scenario tests so that it properly includes error
messages from failing specs.
2013-02-07 04:10:17 -08:00
Enrique Paredes 934204ec18 fix($compile): rename $compileNote to compileNode
Directives was observing different instances of Attributes than the one
that interpolation was registered with because we failed to realize
that the compile node and link node were the same (one of them
was a wrapper rather than raw node)

Closes #1941
2013-02-07 02:49:18 -08:00
Fredrik Bonander 7cb8f8fb44 fix($cookies): set cookies on Safari&IE when base[href] is undefined
Safari and IE don't like being told to store cookies with path set to
undefined. This change ensures that if base[href] (from which cookie path
is derived) is undefined then the cookie path defaults to ''.

The test verifies that the cookie is set instead of checking that cookie has correct path,
this is due to that cookie meta information is not avabile once the cookie is set.

Closes #1190, #1191
2013-02-07 02:36:52 -08:00
Philip Roberts 8d34bf2fea fix(date): invert timezone sign and always display sign
This commit fixes #1261 and #1532. This covers
two separate issues:

- Positive timezones were being formatted without
a leading `+` resulting in a formatting string
like: "HH:MM:ssZ" giving "12:13:141000" instead
of "12:13:14+1000". Fixed by checking if timezone
is > 0 and adding a leading "+".

- Timezone output signs were inverted.
mock.TzDate expects the timezone _offset_ as it's
first argument, _not_ the timezone. This means
that a mock.TzDate with a positive offset should
result in a date string with a negative timezone,
and vice-versa.

Closes #1261, #1532
2013-02-07 01:47:19 -08:00
Igor Minar 8801e69dba docs(guide): remove stale info about filters changing DOM
as of v0.10.6 this is not the case any more
2013-02-06 14:15:43 -08:00
Thomas Schultz f4afa398a1 docs(tutorial): remove extra back-tick character 2013-02-06 22:22:55 +01:00
theotheo 32063278bd docs(module): fix code example 2013-02-06 21:36:21 +01:00
radu 92208d2f85 docs(ngApp): fix typo 2013-02-05 22:14:43 +01:00
Igor Minar ab7c74b4b9 docs(contributing): add CLA anchor for deeplinking 2013-02-04 09:38:55 -08:00
PowerKiKi e283abe171 docs(ngClass): fix typo in description 2013-02-04 10:37:19 +00:00
Brian Ford d7620f68bb feat(Scope): expose transcluded and isolate scope info for batarang
test($compile): add test for exposing transclude and isolate scope info to batarang
2013-01-30 10:44:35 -05:00
Dean Sofer 971d97e2ec docs($cookies): added example to $cookies api docs
Better than nothing.
2013-01-29 16:17:12 -08:00
radu 559d5efc04 docs(nextUid): fix typo
Update src/Angular.js

removed redundant 'the' from nextUid()'s ngdoc
2013-01-29 15:50:03 -08:00
radu 85042820fb docs(tutorial): fix typo
Update docs/content/tutorial/step_00.ngdoc

removed redundant verb
2013-01-29 15:47:43 -08:00
Fred Sauer 24a2eec815 docs(Scope): fix argument docs for $on 2013-01-29 15:39:10 -08:00
metaweta d987a79ab1 test(ngBindHtml): prevent variable name leak
Add "var" so element is local instead of global

Strict mode doesn't allow undeclared global vars, and these really should be local anyway.
2013-01-29 15:35:03 -08:00
metaweta eba09353e6 refactor(Angular.js): prevent Error variable name leak in tests
Remove var Error = window.Error

window.Error is a read-only property in Apps Script.

Igor says, "we should just delete that line instead. I think it was
misko's attempt to get better closure minification, but it turns out
that it's actually hurting us after gzip (I verified it)."
2013-01-29 15:35:03 -08:00
Igor Minar 297660c9a3 chore(release): start 1.0.5 flatulent-propulsion iteration 2013-01-29 15:34:04 -08:00
Fred Sauer 8343c05fd8 docs(a): escape sample code in ng a directive 2013-01-26 23:03:40 +01:00
Igor Minar 7c3d064786 fix(docs): properly generate angular.js urls in doc examples 2013-01-24 11:36:42 -08:00
Igor Minar c2ccc1cbdf docs(date): add missing doc about TZ behavior 2013-01-24 10:51:47 -08:00
Igor Minar 04e080660a docs(changelog): correct 1.0.4 release notes 2013-01-24 09:50:51 -08:00
Vineet Kumar f3cca88384 docs($injector): clarify $inject property description
Section heading about `$inject` property refers to it as `$injector` property.
2013-01-24 00:18:48 -05:00
Igor Minar 978bbd2d49 chore(release): update the CDN version 2013-01-23 12:07:01 -08:00
Igor Minar 652feebd86 chore(release): cut the 1.0.4 bewildering-hair release 2013-01-23 10:57:51 -08:00
Igor Minar 16ccbc4f61 docs(changelog): release notes for 1.1.2 and 1.0.4 2013-01-23 10:57:51 -08:00
Igor Minar 072d45fd01 chore(changelog.js): improve the changelog script 2013-01-23 10:57:51 -08:00
pavelgj 4439e39319 fix(ngResource): correct leading slash removal.
Fixed an issues with ngResource param substitution where it was incorrectly removing leading slash when param was followed by a non-slash character.
Ex:
'/:foo/:bar.baz/:aux'

params = {
  foo: 'aaa',
  bar: undefined,
  aux: undefined
}

The above params were incorrectly producing '/aaa.baz' but now it results in '/aaa/.baz'.
2013-01-22 11:32:27 -08:00
Miško Hevery b49c3a1a1e docs(q): added testing information 2013-01-22 11:32:27 -08:00
Igor Minar c7addd4886 fix(angular.equals): relax the comparison for undefined properties
in 5ae63fd3 the comparison was made consistent but strict, so that

angular.equals({}, {foo: undefined}) // always returns false

this turns out to cause issues for data that is being roundtripped via network
and serialized via JSON because JSON.stringify serializes {foo: undefined} as {}.

Since angular.equals() behaved like this before the 5ae63fd3 in 50% of the cases,
changing the behavior in this way should not introduce any significant issues.

Closes #1648
2013-01-22 07:35:06 -08:00
Igor Minar 6df60aff52 chore(Rakefile): skip build parallelization on Travis
Due to a infrastructure change on Travis starting JVMs in forked
processes doesn't currently work. Since we don't really care that
much about the build speed on Travis, I'm going to disable it there.

Related issue: https://github.com/travis-ci/travis-ci/issues/845
2013-01-21 07:50:24 -08:00
sergiopantoja e7a080d6e6 docs(jqLite): fix typo 2013-01-20 18:59:43 +01:00
Will Moore 661a728764 docs(contribute): adding npm install to step-by-step
npm install is listed in the dependencies section of the contribute guide but
is missing from the step-by-step. This adds it as step 4.
2013-01-18 21:33:58 -08:00
danilsomsikov 89303fd2dc fix(ngSwitch): don't leak when destroyed while not attached
The leak can occur when ngSwich is used inside ngRepeat or any other
directive which is destroyed while its transcluded content (which
includes ngSwitch) is not attached to the DOM.

Refactor ngSwitch to use controller instead of storing data on compile
node. This means that we don't need to clean up the jq data cache.
Controller reference is released when the linking fn is released.

Closes #1621
2013-01-18 00:03:42 -08:00
Fred Sauer 1f8be1ca66 docs(exceptionHandler): document testing
Update src/ng/exceptionHandler.js

Here's an iniitla attempt at documenting how one might write a
test using $exceptionHandlerProvider. The key take-away is the use
of this pattern:

it(...

 module(...
   $exceptionHandlerProvider.mode('log');
 });

 inject(...
 );

});
2013-01-17 23:11:02 -08:00
Matthew Browne cbc2024092 docs(rootScope): correct code examples 2013-01-17 23:11:02 -08:00
Amir H. Hajizamani f0ff7023c3 docs(cookbook): change prototype methods to scope methods in Buzz
As explained in 'Understanding the Controller Component', Controllers
written for new (post 1.0 RC) versions of Angular need to add methods to
the scope directly, not the function's prototype. Correcting this
example should remove any ambiguity, especially for beginners.
2013-01-18 00:56:52 -05:00
Amir H. Hajizamani 6e8728a364 docs(guide): change prototype methods to scope methods in DI examples
As explained in 'Understanding the Controller Component', Controllers
written for new (post 1.0 RC) versions of Angular need to add methods to
the scope directly, not the function's prototype. Correcting this
example should remove any ambiguity, especially for beginners.
2013-01-18 00:56:52 -05:00
Fred Sauer f179a63dd4 docs(ngMock.$httpBackend): fix variable declaration 2013-01-18 00:15:20 -05:00
Shai Reznik 3a71c1e595 doc(guide): Fix examples of $location.html5mode 2013-01-17 23:46:19 -05:00
Shai Reznik ef7a61a67e doc(guide): Fixed typos at the unit tests guide 2013-01-17 23:46:19 -05:00
Igor Minar a6b2ee785b fix(angular.equals): consistently compare undefined object props
previously:

a = {};
b = {x:undefined};
angular.equals(a, b) == angular.equals(b, a) // returns false.

both should return false because these objects are not equal.

unlike in implemented in #1695 the comparison should be stricter
and return false not true. if we need to relax this in the future
we can always do so.

Closes #1648
2013-01-17 17:49:07 -08:00
Daniel Demmel d5a1336e6b docs: recommend using Google CDN 2013-01-17 16:53:32 -08:00
Matt Rohrer d4312b731a docs(guide): minor grammar fixes 2013-01-17 19:36:14 -05:00
Martin Probst 66f051386e feat($compile): support modifying the DOM structure in postlink fn
Support modifying the DOM structure in the post link function of a directive
by creating a defensive copy of the node list, as opposed to a live DOM list.
This is useful for directives to actually replace their entire DOM fragment,
e.g. with the HTML fragment generated by a 3rd party component (Closure, Bootstrap ...).
Fix the indentation of the compileNodes function (was one too little).
2013-01-17 12:57:36 -08:00
Igor Minar 8b3f9684e0 style($compile): fix indentation 2013-01-17 12:55:21 -08:00
Gergely Imreh 331f32deac chore(Rakefile): force 32bit JVM mode only when java supports it
Some Java installs don't have '-d32' flag (e.g. OpenJDK which is standard
for some Linux systems), and the closure_compile fails because of forcing
that flag. Test, and only run in faster 32bit mode if supported, or
else just run with no flag (default mode).
2013-01-17 10:44:39 -08:00
Igor Minar bb80c96754 chore(docs): use done() instead of end() in gen-docs.js 2013-01-17 00:52:19 -08:00
Pete Bacon Darwin 0d8e19c26f fix($compile): do not wrap empty root text nodes in spans
Closes #1059
2013-01-17 00:28:56 -08:00
Pete Bacon Darwin ed2fd2d0ca fix(ngRepeat): correctly apply $last if repeating over object
If the $last property is calculated from the original collectionLength
on an object and properties starting with $ were filtered out, then $last
is never applied and $middle is applied erroniously.

Closes #1789
2013-01-17 00:25:07 -08:00
James deBoer 7c60151cb8 chore(Rakefile): remove a duplicate file in angularFiles.js 2013-01-16 23:45:13 -08:00
James deBoer 965308a32c chore(Rakefile): generate version.json
Changes 'rake version' to output a version.json file which
contains the structured version info which can be used in other tools.
2013-01-16 23:41:51 -08:00
Igor Minar 92c612a9de fix(scenario): don't trigger input events on IE9
input.enter() should trigger 'change' rather than 'input' event on IE9 because
input events on IE9 are broken and angular doesn't rely on them
2013-01-16 23:30:16 -08:00
Kanwei Li a7b53abcad docs(CHANGELOG): fix typo 2013-01-16 23:29:11 -08:00
Martin Probst d575e1f613 fix($route): support route params not separated with slashes.
Commit 773ac4a broke support for route parameters that are not seperated
from other route parts by slashes, which this change fixes. It also adds
some documentation about path parameters to the when() method and
escapes all regular expression special characters in the URL, not just
some.
2013-01-16 09:42:35 -08:00
Igor Minar 2ba458387d fix($compile): safely create transclude comment nodes
Closes #1740
2013-01-14 21:59:23 -08:00
Lucas Galfasó 98489a1d0c doc(directive): Fix typos in dialog widget
Fixes #1799
2013-01-13 10:09:22 +00:00
Igor Minar 51d501aab2 chore(*): remove obsolete files 2013-01-09 21:29:13 -08:00
naomiblack 841bdf1c07 Update docs/content/misc/faq.ngdoc
Updated the canonical video to a recent one. Fixed a typo.
2013-01-09 09:50:27 +00:00
Pete Bacon Darwin 86cac55c7c fix(jqLite): children() should only return elements
The jQuery implementation of children only returns child nodes of the given element that are elements themselves. The previous jqLite implementation was returning all nodes except those that are text nodes. Use jQLite.contents() to get all the child nodes.

The jQuery implementation of contents returns [] if the object has no child nodes.  The previous jqLite implementation was returning undefined, causing a stack overflow in test/testabilityPatch.js when it tried to `cleanup()` a window object.

The testabilityPatch was incorrectly using children() rather than contents() inside cleanup() to iterate down through all the child nodes of the element to clean up.
2013-01-09 09:42:05 +00:00
Keyamoon c0995399d4 fix(jqLite): make next() ignore non-element nodes
next() is supposed to return the next sibling *element* so it
should ignore text nodes. To achieve this, nextElementSibling()
should be used instead of nextSibling().
2013-01-08 14:54:56 -08:00
Igor Minar de6cc287e5 fix($injector): remove bogus fn arg
getService fn takes only one argument, removing the second one.

Closes #1711
2013-01-08 14:36:36 -08:00
Igor Minar afd6771163 refactor($browser): remove faulty 20+ cookies warning
the warning is defunct (and the test is incorrect) so obviously nobody is using
it and it just takes up space.

also the browser behavior varies (ff and chrome allow up to 150 cookies, safari
even more), so it's not very useful.

Closes #1712
2013-01-08 14:27:51 -08:00
Igor Minar 4cda028609 revert: fix(a): prevent Opera from incorrectly navigating on link click
This reverts commit c81d8176cc.

This commit causes several issues (#1651, #1674, #1662) and doesn't even
contain a test that proves that anything on Opera got actually fixed.

If the original Opera resurfaces, we'll fix it properly.
2013-01-08 11:51:17 -08:00
kim lokoy 8ecce7642b docs(guide): fix typos in unit test guide 2013-01-07 21:00:13 +01:00
Pawel Kozlowski d1d5761232 docs(forms): fix code example for a custom form control
Closes #1021
2013-01-05 23:04:33 +01:00
naomiblack 759cba1a8d docs(faq): add info on logo reuse and how to get t-shirts and stickers 2013-01-04 19:22:00 +01:00
Jonathan Card 23cd40a8ec docs(form): minor form doc and example fixes
Form documentation fixes:
- Fix broken form example in docs
- A few small other corrections in form docs.
2013-01-04 17:25:24 +01:00
Per Rovegård f3188c1d09 docs($http): clarify documentation on error status codes
Modify the documentation for $http to correspond to what Angular
considers a success status code.

Closes #1693
2013-01-03 20:47:55 +01:00
Matt Hardy 2f4967f100 docs(guide): change example controller to properly call greet method on greeter 2012-12-31 13:21:29 +01:00
Murilo da Silva 4fe4e7457c docs(anchorScroll): correct word "location" 2012-12-19 21:14:09 +01:00
John Fletcher d4e7274d4b docs(guide): minor English corrections to the Directive guide 2012-12-19 20:55:22 +01:00
Miško Hevery cffa015554 docs(directive): old syntax 2012-12-18 20:39:17 -08:00
Pawel Kozlowski 1104c7d75b docs(ngView): fix code example (change template to templateUrl)
Closes #1715
2012-12-18 17:56:04 +01:00
Gonzalo Ruiz de Villa 4c6b4447db fix($route): correctly extract $routeParams from urls
Routes like '/bar/foovalue/barvalue' matching '/bar/:foo/:bar'
now are well mapped in $routeParams to:
{bar:'barvalue', foo:'foovalue'}

Closes: #1501
Signed-off-by: Gonzalo Ruiz de Villa <gonzaloruizdevilla@gmail.com>
2012-12-14 01:16:07 +01:00
ggoodman 741a37b338 feat(docs): Add angularjs tag to plunks and make private
This is a minor edit to allow Plunks created by way of the docs.angularjs.org site to be appropriately tagged as `angularjs`.
Also, make these generated Plunks private by default.
2012-12-12 21:00:41 +00:00
Peter Evjan 1157c5d341 docs(README.md): add missing 'you' and a comma 2012-12-11 19:33:28 +01:00
Romain Neutron e48adebfb7 docs(guide): fix injector service code example
Fix syntax and update code to the latest API
2012-12-10 23:50:12 +01:00
Juha Syrjälä 0a61dcb486 docs($resource): document port number escaping and fix typo 2012-12-09 17:49:42 +01:00
Eric Case 4b51eaadf8 docs(tutorial): typo fix commandx -> command 2012-12-08 11:39:56 +01:00
Eric Case e2457ca16d docs($q): typo fix - programing -> programming 2012-12-07 21:00:25 +01:00
János Rusiczki bd62790080 doc(concepts): Fix typo in $render() function 2012-12-07 10:19:08 +00:00
Jeremy Tymes 53fdcafa44 docs($http): fix link typo in $http doc
Should be $httpBackend instead of $httpBacked

Closes #1516
2012-12-06 21:50:21 +01:00
Fred Sauer af6f2483be docs(mocks): update src/ngMock/angular-mocks.js documentation
Clarify how to use `$exceptionHandlerProvider.mode('log')` in tests
2012-12-06 21:50:21 +01:00
Fred Sauer d8522aa349 docs(mocks): fix documentation bug: angular.mock.debug 2012-12-06 21:50:20 +01:00
Igor Minar bae3121683 chore(bootstrap-prettify): update urls to code.angularjs.org
Closes #1599
2012-12-05 02:55:19 +01:00
_pants 54c0d464b0 fix(select): support optgroup + select[multiple] combo
Closes #1553
2012-12-05 02:21:31 +01:00
Sudhir Jonathan cf89e8653c fix($injector): provider can now be defined in the array format
`injector.instantiate` is now called for arrays too, instead of only for functions.

Closes #1452
2012-12-01 19:09:36 +01:00
Sudhir Jonathan 0c3500f532 fix($resource): HTTP method should be case-insensitive
Perform call `angular.uppercase` on all given action methods.

Closes #1403
2012-11-30 23:23:34 +01:00
Cezar Berea c12f525df4 refactor($resource): fix indentation and move a method definition
Moved Resource.bind out of the actions forEach
2012-11-30 22:47:25 +01:00
Igor Minar e7ba830691 fix(Scope): ensure that a scope is destroyed only once
Due to bd524fc4 calling $destroy() on a scope mupltiple times cases NPE.

Closes #1627
2012-11-30 13:09:50 +01:00
Daniel Luz 4eb0716711 docs(directive): correct expression, fix typo and re-wrap lines 2012-11-29 20:22:41 +01:00
Johannes Hansen ed90f3b7ea fix(docs): add missing </div> tag to sourceEdit directive template 2012-11-29 20:22:40 +01:00
Igor Minar 14b19ecf5e docs(menu): fix the navbar drop down links 2012-11-28 23:56:21 +01:00
Igor Minar 644432a14c chore(release): start 1.0.4 bewildering-hair iteration 2012-11-28 15:51:23 +01:00
Igor Minar a03e370a09 chore(release): cut the 1.0.3 bouncy-thunder release 2012-11-27 01:44:46 +01:00
Igor Minar 23677d3ddb docs(CHANGELOG): release notes for 1.0.3 and 1.1.1 releases 2012-11-27 01:44:46 +01:00
Rado Kirov fc781560a3 fix($location): reset $location.$$replace with every watch call
Closes #1111
2012-11-26 23:24:39 +01:00
Vojta Jina c9199ee663 docs: load angular from CDN only on production
So that when running the docs locally, eg. during e2e testing, we use the latest build version of angular, rather than the stable one from CDN.

This fixes e2e tests running with Testacular.
2012-11-26 21:33:45 +01:00
Igor Minar 6f18adedef fix(ngClassOdd/ngClassEven): support shrinking/reordering in repeaters
We need to watch $index in addition to cssClasses because only then
we can correctly respond to shrinking or reordered repeaters.

Closes #1076
2012-11-26 21:33:45 +01:00
Igor Minar 6ad894cd58 style(jqLite): better variable names
selector => cssClasses
2012-11-26 21:33:45 +01:00
Igor Minar cde2f1a868 fix(ngRepeat): support mostly-stable repeating for primitives
I'm reverting changes that were originally done to ngRepeat to fix #933,
because these are now not necessary after the previous changes to keep
ngModel always synced with the DOM.
2012-11-26 21:33:45 +01:00
Igor Minar 6a831495de fix(ngModel): sync ngModel state with scope state
In cases when we reuse elements in a repeater but associate
them with a new scope (see #933 - repeating over array of
primitives) it's possible for the internal ngModel state and
the scope state to get out of sync. This change ensure that
the two are always sync-ed up even in cases where we
reassociate an element with a different (but similar) scope.

In the case of repeating over array of primitives it's still
possible to run into issue if we iterate over primitives and
use form controls or similar widgets without ngModel - oh well,
we'd likely need a special repeater for primitives to deal
with this properly, even then there might be cornercases.

Closes #933
2012-11-26 21:33:45 +01:00
Igor Minar 6e2c38f54d test(ngRepeat): clean up and improve tests 2012-11-26 20:39:10 +01:00
Igor Minar 00e7e31418 fix(ngRepeat): attempt to simplify and improve existing fix for #933
I'm keeping this in for future reference. The issue with this solution
is that if we shift() the first item in the array, the whole repeater
DOM will be rebuilt from scratch, we need to do better than that.
2012-11-26 20:39:00 +01:00
Igor Minar ff4b3e20c1 test(ngRepeat): add test for issue #1076 2012-11-26 20:38:51 +01:00
Igor Minar 269fb43b36 fix(jqLite): fire $destroy event via triggerHandler
in jQuery 1.8.x the data() data structure is changed and events are
not accessible via data().events. Since all we need is to trigger
all event handlers, we can do so via triggerHandler() api instead of
mocking with the internal jQuery data structures.

This fix was originally proposed by PeteAppleton via PR #1512.

Closes #1512
2012-11-26 16:03:43 +01:00
Igor Minar 7530654328 feat(jqLite): add triggerHandler()
we need triggerHandler() to become jQuery 1.8.x compatible.

this is not fully featured triggerHandler() implementation - it doesn't
bother creating new DOM events and passing them into the event handlers.

this is intentional, we don't need access to the native DOM event for our
own purposes and creating these event objects is really tricky.
2012-11-26 16:03:39 +01:00
Iristyle c7bd464384 docs(CONTRIBUTING.md): add contrib info file for GitHub 2012-11-25 21:00:56 +01:00
Vojta Jina ef1874d1f3 fix(Scope): allow removing a listener during event 2012-11-25 11:41:32 +01:00
Kevin Western c6d8205fdd docs(README.md): fix "API Docs" link
use direct link to api docs
2012-11-25 01:24:03 +01:00
Dean Sofer 55150a669a docs(api): add ngRequired to input/select/textarea directives
Closes #1202
2012-11-25 01:19:47 +01:00
Jeremy Tymes 1eb9e22d45 fix($cacheFactory): return undefined when removing non-existent entry
Instead of throwning an exception, remove should return undefined when
cache entry to be removed doesn't exist.

Closes #1497
2012-11-24 21:58:17 +01:00
Adrian Gheorghe c0de8fb737 fix($resource): prevent default params to be shared between actions
Having a $resource defined as:

var R = $resource('/Path', {}, {
  get: {method: 'GET', params: {objId: '1'}},
  perform: {method: 'GET'}
});

was causing both actions to call the same URI (if called in this order):

R.get({}); // => /Path?objId=1
R.perform({}); // => /Path?objId=1
2012-11-24 21:29:16 +01:00
Kris Jenkins 557e3894d7 docs(): Fix a couple of typos in the documentation 2012-11-22 08:28:49 +01:00
Dave Clayton 38a9695413 docs(guide/concepts): some typo/grammar fixes 2012-11-22 08:28:49 +01:00
John Hume 293e0336b0 docs(guide/directive): fix typo 2012-11-22 08:28:49 +01:00
Uri Goldshtein 1f5bc0a1cd docs($q): fix missing bracket in the example 2012-11-22 08:28:49 +01:00
Igor Minar 1fe666192b fix($rootScope): workaround for Chrome's memleak
Under certain circumstances chrome fails to GC scopes
because of buggy optimizations and caching. Nulling out
references to (not from!) other scopes helps Chrome to
realize that this object should be GC-ed.

This is really just a workaround as the real problem needs
to be fixed in Chrome.

See discusstion at:
https://github.com/angular/angular.js/issues/1313#issuecomment-10378451

And chrome bug at:
https://code.google.com/p/v8/issues/detail?id=2073

Closes #1313
2012-11-14 19:53:29 +01:00
Igor Minar 29541e735d revert($resource): support custom headers per action
This reverts commit b936e52874.

This commit introduces a feature and should haven't been merged
into the stable branch.
2012-11-11 12:07:26 +01:00
Igor Minar f5b567d44b chore(validate-commit-msg): recognize 'revert' as valid commit type 2012-11-11 12:06:05 +01:00
Haralan Dobrev 5ee3bbee90 docs(angular.module): improve angular.Module#run docs 2012-11-11 11:40:52 +01:00
Jamison Dance 80927c5811 docs(guide): fix run-on sentence in modules guide 2012-11-11 11:35:20 +01:00
Jamison Dance ca8b344e20 docs(tutorial): change module name in step-7 2012-11-11 11:35:15 +01:00
Wes Alvaro 3dab93874d docs($timeout): set return type to Promise instead of *.
The cancel function accepts a Promise, but the timeout function
fails to specify returning a Promise.
2012-11-11 11:32:00 +01:00
Josh Adams 7550f90a57 docs(ngList): fix typo 2012-11-11 11:25:40 +01:00
Josh Adams d78fea87d1 docs(encodeUriSegment): fix typo 2012-11-11 11:23:46 +01:00
Tim Macfarlane 27cee7db0a docs(guide/directive): fix names in scope '='; easier to grok 2012-11-11 11:20:57 +01:00
Christian Vuerings 60acba3840 docs(ngHide): Fix typo and make it more in line with ngShow 2012-11-11 10:37:59 +01:00
Igor Minar 51bed36370 chore(docs): fix docs-scenario.html 2012-11-08 22:18:34 +01:00
Igor Minar 6d940213ac chore(docs): remove obsolete gae files 2012-11-08 22:18:34 +01:00
Miško Hevery 494b527fa7 docs(directive): fix typo 2012-11-05 19:35:31 -08:00
Sudhir Jonathan 8ce84cb2ea chore(testacular): use local testacular version
Making testacular a dependency to avoid having to install it globally.
(Causes npm issues on some machines)
2012-10-31 17:00:00 -07:00
Sudhir Jonathan d981c2a3ec fix(select): select option with a label of 0 is not shown
Bug caused by the use of the `||` operator to replace all non-truthy
values with an empty string. Changed to replace only `undefined` values.

Closes #1401
2012-10-31 15:03:48 -07:00
Igor Minar 537e20065a chore(validate-commit-msg): allow '/' in scope 2012-10-31 14:48:24 -07:00
Fred Sauer 97578b4dae docs(guide/location): fix table formatting
Fix table formatting so headings are bold, rows are separated by lines, and rows have :hover style
2012-10-31 14:48:18 -07:00
Tim Macfarlane fa12564607 docs(module): fix typo in example
fixed example app, `simpleAppModule` should have been `myAppModule`.
2012-10-31 14:22:12 -07:00
sqwishy trick 54bcb9ae25 chore(injector): fix typo in injector documentation 2012-10-31 14:19:52 -07:00
Adam Macejak ad7ce0d402 fix(scenario-runner): support data-ng and x-ng based attributes
Prefixed attributes like data-ng-model and x-ng-model were not being
found by the Selector. It was only looking at ng: and ng- prefixed
attributes.
Added a few tests as well to ensure the aforementioned prefixed
attributes are being matched properly.

Closes #1020
2012-10-31 14:10:26 -07:00
Daniel Luz 085e0ea8ef docs(contribute): fix task name for continuous testing 2012-10-31 13:13:33 -07:00
Igor Minar bb52c4e8d3 fix(docs): correctly generate filenames for plunkr/fiddle
previously examples like $http where broken because we would strip part of the
filename (http-hello.html -> http)

we really want to strip only the id suffix that we append to disambiguate
common filenames (like index.html) which appear in many examples.
2012-10-31 13:06:22 -07:00
Shyam Seshadri 295af335c1 feat(docs): add plunkr support
Add option to edit source in Angular Docs in Plunkr in addition to JsFiddle
2012-10-31 13:06:16 -07:00
Daniel Luz 2c2e18c37a fix(doc): typo on FAQ
Closes #1493
2012-10-31 10:26:00 -07:00
Igor Minar adfb75e3c6 fix($compile): don't look for class directives in empty string
if className is undefined or empty string, don't bother looking for directives in there
2012-10-29 19:39:34 -07:00
Igor Minar 9bff5c60df fix($compile): compilation should not recurse into empty nodes
if a node doesn't have children then don't try to compile these non-existent children
2012-10-29 19:39:21 -07:00
Igor Minar 3ba008d4b2 style($compile): better fn names for debugging 2012-10-29 19:38:57 -07:00
Igor Minar 4e45a2f8e2 refactor($compile): simplify nodeLinkFn 2012-10-29 19:38:29 -07:00
Igor Minar 4dbd8452eb fix($compile): prevent double attr interpolation w/ templateUrl
This fixes the issue that caused two attr interpolation observers
to be registered for the same attribute as a result of isolate
scope definition with attr (@) property for this attribute.

Duplicate observers would then fight with each other updating the
model.

The issue occured only when this directive was used in a repeater
because that's when we clone the template node which caused the
two observers to point to two different sets of $attr instances.

Closes #1166, #836
2012-10-29 19:38:03 -07:00
Braden Shepherdson 45a8db9c08 fix(currency): Handle not-quite-zero values
IEEE 754 floating point sometimes results in values that are very small,
rather than zero. One example is 1.0 + 1.07 - 2.07, which returns
4.440892098500626e-16 instead of 0.

This change tweaks the number formatting logic so that an exponential
value with a negative exponent that is larger than the precision+1
returns 0 instead. For example: with precision 2, anything with an
exponent of -4, -5 or more would become 0. 9e-3 = 0.009 = 0.01, but 9e-4
= 0.0009 = 0.001 = 0.00. This detail is unlikely to matter since this
quirk is usually only triggered with values very close to zero.

Closes #1469
2012-10-29 19:37:52 -07:00
Braden Shepherdson d930a410fb doc(faq): Add Common Pitfalls section
Describes several common pitfalls new users of Angular fall into that
I've observed in #angularjs.
2012-10-29 19:37:38 -07:00
Braden Shepherdson 66505ffc40 doc(faq): Fix minor spelling and wording errors 2012-10-29 19:37:29 -07:00
Igor Minar 045de959b9 chore(check-size.sh): fix rake target 2012-10-29 19:37:21 -07:00
Igor Minar 3ca11d5235 docs(contribute): add CLA note to code submission section 2012-10-19 09:15:34 -07:00
Igor Minar d5d8ac01e3 docs(contribute): add visible link to github project 2012-10-19 09:15:34 -07:00
Igor Minar ace81c053c chore(validate-commit-msg): allow * and - in scope string 2012-10-18 03:29:12 -07:00
Igor Minar 1e95c419b8 chore(jasmine): remove Jasmine from our repo
it's bundled with Testacular, so we don't need it here
2012-10-18 03:29:12 -07:00
Igor Minar 49ed63d26a chore(jstd): remove JsTestDriver from our repo
Testacular FTW!
2012-10-18 03:29:12 -07:00
Igor Minar 6ff2685668 docs(tutorial): replace JsTD with Testacular + drop snapshots
JsTD references have been replaced with Testacular stuff.

snapshots are PITA to maintain so I'm dropping them, everyone loves the Git
version anyway.
2012-10-18 02:34:27 -07:00
Igor Minar c4573c04aa chore(Rakefile): remove test_out dir when cleaning 2012-10-17 20:20:54 -07:00
Igor Minar d57abdb3f7 chore(Rakefile): tune JVM for closure compiler
Using the client VM and forcing 32bit mode gives us huge perf boost.

before:

reali   0m8.173s
user    0m39.984s
sys     0m1.408s

after:

real    0m3.000s
user    0m12.687s
sys     0m0.852s
2012-10-17 20:20:53 -07:00
Igor Minar 4050e89446 chore(Rakefile): paralelize closure compilation
this speeds up the build by paralelizing closure compilation (the slowest
piece of the build process)

before:

real  0m14.372s
user  0m31.649s
sys   0m1.006s

after:

real  0m8.191s
user  0m40.473s
sys   0m1.378s
2012-10-17 20:16:36 -07:00
Vojta Jina b6620c737f chore(test): add junit config for testacular 2012-10-17 20:16:36 -07:00
Igor Minar 0c8e908841 chore(Rakefile): misc_options should support + -> , conversion 2012-10-17 20:16:35 -07:00
Igor Minar 5595e196a8 chore(Rakefile): use exec for webserver
exec unlike system replaces the current process. this way when we kill
the webserver process we don't get scary looking 'rake aborted' error
2012-10-17 12:44:38 -07:00
Misko Hevery f92e4146d1 fix(doc): disable directory listing in docs.angularjs.org 2012-10-08 15:09:06 -07:00
Vojta Jina 8b7108e3c9 chore: add travis config 2012-10-05 10:20:02 -07:00
Igor Minar caf702cc88 docs(downloading): update the downloading docs 2012-10-05 03:15:11 -07:00
Vojta Jina cf2c49ed7f fix($compile): reference local in isolate scope
This was really corner case:
Watcher needs to return changed value, to notify that model might have changed and one more $digest cycle needs to be performed.

The watcher, that takes care of reference binding into an isolate scope ("="), did not return changed value, if the change was from the isolate scope to the parent.

If any other watcher returned change, it worked fine, as this change caused re-digest.

Closes #1272
2012-09-22 12:00:16 -07:00
Igor Minar ccd52abf5d docs(README): update README.md with new rake tasks 2012-09-17 14:52:06 -07:00
Igor Minar 74c574015d chore(Rakefile): fix test:jquery task 2012-09-17 14:52:06 -07:00
Igor Minar 1f1a6fb6d2 docs(contribute): update contribute docs 2012-09-17 09:46:34 -07:00
Igor Minar 8632e893b0 chore(): remove unused files 2012-09-17 09:46:34 -07:00
Igor Minar c2b6e127fa docs(contribute): update misc/contribute docs with Testacular info 2012-09-17 09:46:34 -07:00
Igor Minar 06eceeb09f chore(testing): Testacular config files + rake tasks
- adds testacular config files for jqlite, jquery, modules and e2e tests
- replaces obsolete JsTD Rake tasks with Testacular onces
- rake tasks are parameterazied so that they can be used locally as well as on CI server

usage:

rake test  # run all tests on Chrome
rake test[Safari+Chrome+Opera]  # run all tests on Safari, Chrome and Opera
rake test[Safari]  # run all tests on Safari
rake test:jqlite # run unit tests using jqlite on Chrome
rake test:jqlite[Safari,"--reporter=dots"]  # run jqlite-based unit tests on Safari with dots reporter
rake autotest:jquery  # start testacular with jquery-based config and watch fs for changes
rake test:e2e # run end to end tests
2012-09-17 09:46:13 -07:00
Miško Hevery 8133d468b9 docs(directive): remove reference to old isolation syntax 2012-09-13 11:32:13 -07:00
Misko Hevery 074a354fa9 fix($route): support inline annotation on .resolve 2012-09-11 23:16:41 -07:00
Vojta Jina e191582a02 chore(scripts): add init-repo script 2012-09-11 23:16:38 -07:00
Jay Zeng 6fbe926cda docs(ngResource): Spelling typo (agressive => aggressive) 2012-09-11 16:39:46 -07:00
Igor Minar ebbc224e09 fix($resource): fix isDefined -> angular.isDefined 2012-09-11 16:39:46 -07:00
Shyam Seshadri 2c6aa4c300 fix(*): name all anonymous watch functions in Angular
This will allow us to see function names in Batarang and debugger.

Closes #1119
2012-09-11 16:39:46 -07:00
Zhenbo Zhang f7a8f17fc7 fix(ng-repeat) to work with primitive types 2012-09-11 16:38:42 -07:00
Brian Ford 191efbb558 docs(guide): fix directive interpolation example code
Closes #1339
2012-09-11 16:19:45 -07:00
Shyam Seshadri bf873d6f02 fix(scenario): emit RunnerBegin event 2012-09-11 16:19:44 -07:00
Vojta Jina e741107c55 chore(scripts): add commit-msg hook (validation) 2012-09-11 16:19:44 -07:00
Jimmy Zhuo 82f4b99d99 fix(scenario): NPE when no angular loaded in test page 2012-09-11 16:19:44 -07:00
Daniel Luz 7210b7ae1d docs($rootScope): fix iteration limit described by $watch, it's actually 10 as of now 2012-09-11 16:19:44 -07:00
Daniel Luz afed23c001 docs($rootScope): fix typos and minor wording tweaks on $watch 2012-09-11 16:19:44 -07:00
Daniel Luz 1f69cc2989 docs($rootScope): fix quoting on expression 2012-09-11 16:19:43 -07:00
Daniel Luz 3401833c83 docs($rootScope): standardize on present, third-person actions for descriptions 2012-09-11 16:19:43 -07:00
Daniel Luz 06606e2816 docs($rootScope): backquote attribute types too on $on 2012-09-11 16:19:43 -07:00
Daniel Luz eba64e1f31 docs($cacheFactory): fix backquotes on method descriptions 2012-09-11 16:19:43 -07:00
Daniel Luz 81dd1df1b1 docs($rootScope): fix typos on $new 2012-09-11 16:19:43 -07:00
Daniel Luz dbafbb0de5 docs($rootScope): fix typo on $eval 2012-09-11 16:19:42 -07:00
Daniel Luz 1d0aa7b7c6 docs($rootScope): fix typos on $watch 2012-09-11 16:19:42 -07:00
Igor Minar afd02ca48c fix(docs): update docs top menu links 2012-09-06 15:56:11 -07:00
sgtpep 67db7616ad fix(a): prevent Opera from incorrectly navigating on link click
we handle the navigation by ourselves, so we need to prevent the default action.

Opera ignores event.preventDefault() call so we must return false.
2012-09-06 15:54:20 -07:00
Kai Groner 3d7c752e27 fix(FormController): propagate dirty state to parent forms 2012-09-06 15:54:19 -07:00
Jonathan Zacsh f02833d634 chore(docs): get correct location for jasmine-node 2012-09-06 15:54:19 -07:00
Misko Hevery 0eb373e0e6 fix($injector): more conservative annotation parsing 2012-09-06 15:49:50 -07:00
Xiangru Chen fd3071843c fix(ngSrc): don't set src if value is empty string
Current implementation of ngSrc may lead to empty src attribute when page is loading.

For example:

<img ng-src="{{image.url}}">
can be temporarily rendered as

<img src="">
before the image resource is loaded.

Some browser emits a request to the current page when seeing <img src=""> (Firefox13 and IE8 will, Chromium20 won't), which leads to performance problems.
2012-09-06 15:49:49 -07:00
Iwein Fuld a631ceb223 fix(dateFilter): make timezone optional
Makes the time zone optional in the date filter

Problem with the current R_ISO8601_STR regex was that the time was optional, but the zone was not.
This results in the filter not formatting local date times, which it could easily do.

For example:
2012-08-30 -> formatted
2012-08-30T06:06:06.123Z -> formatted
2012-08-30T06:06:06.123 -> NOT formatted

A simple change in the regex fixes this. Arguably this is closer to the ISO8601 spec which specifies
local dates being in the "current time zone" and not requiring a Z. In any case it behaves more like
a user would expect.
2012-09-06 15:49:49 -07:00
Misko Hevery a713928210 docs(concept): correct example for creating injector 2012-09-06 15:49:49 -07:00
Godmar Back 05fa20df81 docs(module): fixed module example and corrected typos 2012-09-06 15:49:49 -07:00
Benjamín Eidelman 125573602f fix($resource): allow falsy values in URL parameters
Close #1212

when a param value was 0 (or false) it was ignored and removed from url.
after this fix that only happens if the value is undefined or null.
2012-09-06 15:49:49 -07:00
Jay Zeng ed5dfbcd66 docs(module): myAppModule -> simpleAppModule 2012-09-06 15:49:49 -07:00
petrovalex d2e52b2376 fix($resource): ignore undefined parameters
- $resource should handle multiple params with same name
- ignore slashes of undefined parameters
- fix default parameters issue, mentioned in #875

Closes #875
Closes #782
2012-09-06 15:49:49 -07:00
petrovalex a56aaa9877 fix(ngClassEven/Odd): filtering/ordering and repeater
Closes #1076
2012-09-06 15:49:48 -07:00
Max Martinsson 79bb7b1f0b fix(ngClass): works with class interpolation
Closes #1016
2012-09-06 15:49:48 -07:00
Max Martinsson b936e52874 feat($resource): support custom headers per action
Closes #736
2012-09-06 15:49:48 -07:00
petrovalex 0d52ff0f10 fix($parser): string concatination with undefined model
Closes #988
2012-09-06 15:49:48 -07:00
Stein Jakob Nordbø baf52e902d fix(dateFilter): support sub-second precision on dateFilter 2012-09-06 15:49:48 -07:00
Igor Minar dffea9e2b7 docs($route): rename leftover $afterRouteChange to $routeChangeSuccess 2012-09-06 15:03:58 -07:00
Igor Minar 4a411b8f82 chore(release): prepare 1.0.3 bouncy-thunder iteration 2012-09-06 08:42:51 -07:00
Misko Hevery 278bfc4bb2 fix(docs): broken url to angular-bootstrap 2012-09-04 18:16:52 -07:00
Igor Minar 18731173f9 chore(Rakefile): add 'version' rake task to generate version.txt 2012-09-04 16:38:29 -07:00
Igor Minar d43fb404d7 chore(docs): bump up the stable version 2012-09-04 16:30:33 -07:00
Igor Minar da984ad187 chore(release): cut the 1.0.2 debilitating-awesomeness release 2012-09-04 11:08:40 -07:00
Igor Minar 4015357ce5 chore(docs): don't rewrite colons in doc filenames 2012-09-04 11:08:40 -07:00
Igor Minar dc3d11ad19 chore(Rakefile): zip only the build dir 2012-09-04 11:08:40 -07:00
Igor Minar 0e1545eb04 revert: fix(ng-repeat) to work with primitive types
this commit was accidentaly merged. it needs more work and we don't
have CLA signature

This reverts commit 98d489712e.
2012-08-31 13:44:36 -07:00
Igor Minar ec7cabf5c9 docs(changelog): release notes for 1.0.2 and 1.1.0 releases 2012-08-31 13:23:23 -07:00
Jonathan Zacsh 3051beba2f fix(docs): Making sure gen_docs.sh looks for a globally installed copy of jasmine-node as well as local. 2012-08-30 22:38:54 -07:00
Fernando Correia 92304323b1 docs(tutorial): correct typos and clarify a few sections 2012-08-30 22:38:54 -07:00
Brice Burgess c28123a872 fix(docs): indicate support for passing a string as the controller property on $routeProvider's route object 2012-08-30 22:38:53 -07:00
brettcannon d798423813 doc(misc) Mention how attribute names map to directive names. 2012-08-30 22:38:52 -07:00
Sahat Yalkabov 2583e77cc7 doc(module) changed simpleApp to myApp in the Module page guide for consistency 2012-08-30 21:34:43 -07:00
Steve Nicolai f66836fee4 doc(devguide) - Fix typos and small grammatical errors in the developer guide. 2012-08-30 21:34:42 -07:00
Uri Goldshtein 0ccc445d53 Loading from Google CDN
As you guys had mansion, we can and need to do it through Google CDN for better performance,
so i've updated it accordingly
2012-08-30 21:34:42 -07:00
Tyson Benson b7d5fa1cbe docs(typos): fix typos in dev guide 2012-08-30 21:34:42 -07:00
German Galvis 8bb3942453 fix(scenario): Adding meta tag to avoid cache issues 2012-08-30 21:34:42 -07:00
phil 51a79cebcb docs(api): fix typo on home page
Refference -> Reference
2012-08-30 21:34:41 -07:00
csugden 36bcf64008 Update docs/content/guide/overview.ngdoc
Corrects video information
2012-08-30 21:34:41 -07:00
Jamie Krug 5c6630605b fix(docs): Fix typos and improve grammar. 2012-08-30 21:34:41 -07:00
Jamie Krug 125827406c fix(docs): Fix bad links. 2012-08-30 21:34:41 -07:00
Colin Frei 62c21422a6 docs(module) fix typo 2012-08-30 21:34:41 -07:00
Zhenbo Zhang 98d489712e fix(ng-repeat) to work with primitive types 2012-08-30 21:34:41 -07:00
Igor Minar 2cab2d8ef1 test(locationSpec): fix broken tests after vojta's commit 2012-08-30 16:54:07 -07:00
Vojta Jina 8fa2bb72bc fix(mocks): free up memory after every spec 2012-08-30 16:53:52 -07:00
Igor Minar d151f94937 chore(docs): ask GAE to serve docs-keywords.js 2012-08-30 15:59:29 -07:00
Igor Minar 5b74b7185b test(bootstrap): test exception siling during bootstrap
Closes #1018
2012-08-30 15:18:11 -07:00
Igor Minar 4f0be2ae4e test(ngApp): add missing test for [ng-app] bootstrap 2012-08-30 15:18:02 -07:00
Igor Minar bb9badeb2a fix(jqLite): better support for xhtml
it turns out that some stuff doesn't work in xhtml as it does in html.

for example &nbsp; can't be innerHTML-ed and auto-closing of elements
doesn't work.

the reporter of the referenced issue claimed that innerHTML vs text on
script made a difference but that doesn't appear to be true in my testing.

I'm not including test for this because testacular doesn't currently
run tests in xhtml yet.

Closes #1301
2012-08-30 10:52:36 -07:00
Igor Minar c287c8361d chore(docs): correctly link docs images 2012-08-30 08:59:17 -07:00
Igor Minar ade7127c79 chore(Rakefile): fix the default task 2012-08-30 08:58:51 -07:00
Igor Minar d341483f1f chore(Rakefile): remove bogus symlink from build 2012-08-30 08:58:39 -07:00
Igor Minar b36acbc857 chore(docs): use symlinks to build docs
so that we can just edit source files without rebuilding docs.

this works for all docs files, except for those that are generated
or rewritten during build.
2012-08-28 16:08:03 -07:00
Igor Minar a4fea38b94 chore(Rakefile): various build script changes
- restructure rake tasks

  this splits up the concatination and minification into two
  tasks so that we can just build angular.js quickly without wasting
  time with minification which is often not needed when just debugging
  some issue on 3rd party site.

- use symlinks when creating final zip file

- switch from btar to zip

- get rid of version numbers from filenames

- rewrite version numbers in all index files

Closes #1226
2012-08-28 16:07:47 -07:00
Misko Hevery 300c5c0c99 doc($log): correct non-working example 2012-08-27 21:20:51 -07:00
Misko Hevery 152537c4e9 doc(guide): add concepts 2012-08-27 21:20:51 -07:00
Misko Hevery 8b46bf6bc9 fix(ngdoc): failing test 2012-08-27 21:20:50 -07:00
Colin Frei aef861eb41 doc(directive) correct typos 2012-08-27 21:20:50 -07:00
Misko Hevery f61d36861d fix(docs) typo 2012-08-27 21:20:50 -07:00
Misko Hevery 2af0348cea fix(ng-list): remove data bound flicker 2012-08-27 21:20:50 -07:00
Misko Hevery 78c5743494 doc(misc) updated getting started to reflect the new homepage 2012-08-27 21:20:49 -07:00
Misko Hevery 2cb9fbd043 doc(guide) simplify the guide home page 2012-08-27 21:20:49 -07:00
Igor Minar e9dad5dbf4 chore(Rakefile): rewrite version numbers in all index files 2012-08-27 12:25:40 -07:00
Igor Minar 54895fc2a1 chore(docs): support _escaped_fragment_ hack for crawler 2012-08-25 02:31:20 -07:00
Igor Minar 60a12b4161 chore(docs): use GAE and Google CDN for docs
Short summary: if you use local node server everything should work as before,
if you use GAE, everything should work now as well, but we pull assets from CDN.

- GAE doesn't support ':' in filenames, so I had to replace it with '_'
  but only in the filename, all servers were reconfigured to rewrite the
  urls from : to _ when doing file lookup
- We now pull angular assets from google CDN when deployed on GAE (locally
  or in production). When running on a non GAE server we pull assets from
  ../ directory as before
- Since only certain versions of Angular are available on CDN and we want
  to be able to autodeploy docs, I had to pin down the Angular files
  to a "stable" version when running on GAE
2012-08-24 15:00:36 -07:00
Igor Minar cd7e58ba41 docs(a): expose hidden docs
It seems that docs for these directive were previously hidden by accident
2012-08-24 14:59:52 -07:00
johnlindquist 9391475dc3 docs(ngRoute): fix typo
aftre -> after
2012-08-24 14:59:43 -07:00
phil 7840803add docs(tutorial): fix typo in step_00
Just removed an extra comma. No big deal.
2012-08-24 14:59:21 -07:00
Igor Minar 7d77de2834 fix($compile): denormalize directive templates
Since developers are allowed to customize start/end interpolation
strings, but third-party directive creators don't know about these
customizations, we should standardize on {{ }} in templates of
reusable (third-party) directives. During the compilation, these
templates are then denormalized to use whatever the custom
start/end symbol is, effectively translating the template into the
syntax of the runtime environment.

This addresses an issue raised at http://goo.gl/e8VPV

Existing code should not be affected by this change since project
that do use custom interpolation markers are not expected to use
{{ }} in existing directive templates.
2012-08-13 14:35:32 -07:00
Igor Minar ab044cada6 refactor($compile): code cleanup 2012-08-13 12:36:42 -07:00
Brian Ford d010e0cc7d fix(ngPluralize): fixes ng-pluralize when using non-standard start/end symbols
Closes #1134
2012-08-13 12:36:33 -07:00
Igor Minar 40f728b1aa style(ngPluralizeSpec): fix indentation 2012-08-13 12:36:22 -07:00
Igor Minar 23abb26405 feat($interpolate): expose start/end symbols in run phase
previously the startSymbol() and endSymbol() getters were exposed only via provider
in the config phase
2012-08-13 12:36:14 -07:00
Igor Minar fd55bc8e1d docs($interpolateProvider): fixing docs 2012-08-13 09:51:57 -07:00
Igor Minar 541aaa4e08 fix($interpolate): $interpolateProvider.endSymbol() returns startSymbol
I also added missing tests.
2012-08-13 09:51:45 -07:00
Igor Minar f22c422547 docs($interpolate): fix typo in description 2012-08-13 09:51:35 -07:00
Vojta Jina 0e461f0c07 docs($compileProvider): remove duplicate of .directive() 2012-08-12 11:04:32 -07:00
Vojta Jina 5074448443 docs: fix broken links to $compileProvider.directive() 2012-08-12 11:04:20 -07:00
Brian Ford 8d66af11e6 fix(docs): fixed documentation for using linky 2012-08-10 16:38:01 -07:00
Brian Ford 169948bb47 chore(ngDoc): add support for custom @usage metadata 2012-08-10 16:37:54 -07:00
Brian Ford 58d9469574 fix(docs): added note about using JSON3 as a polyfill for IE7 2012-08-10 16:37:42 -07:00
Brian Ford 8d858a2360 fix(docs): added note about needing JSON shim for IE7 and earlier 2012-08-10 16:36:56 -07:00
Igor Minar 5540748890 fix(option): support option elements in datalist
previously we expected to find option elements only within select element and if
that was not the case we throw an error. This made it impossible to include datalist
element with nested option elements in the template.

Closes #1165
2012-08-10 16:14:49 -07:00
unirgy f8a52be817 docs($rootScope): fix $on listener signature doc
Added args in $on() listener syntax declaration
2012-08-10 14:52:57 -07:00
Igor Minar 3b5f1105f6 test(jqLite): add missing test for $destroy event 2012-08-10 14:21:11 -07:00
Igor Minar 663ccc5449 fix(form): prevent page reload when form destroyed
this fix ensures that we prevent the default action on form submission
(full page reload) even in cases when the form is being destroyed as
a result of the submit event handler (e.g. when route change is
triggered).

The fix is more complicated than I'd like it to be mainly because
we need to ensure that we don't create circular references between
js closures and dom elements via DOM event handlers that would then
result in a memory leak.

Also the differences between IE8, IE9 and normal browsers make testing
this ugly.

Closes #1238
2012-08-10 14:21:02 -07:00
Igor Minar 263f47819f test(form): fix broken preventDefault test
the original test relied on incorrect assumptions about how jasmine async
tests work (when setTimeout is triggered) and how browser reloads a page
(the sequence of events) and thus the test passes even when the default
is not prevented.

this change fixes the test by registering an extra submit event handler
that checks if the default was prevented.

if the default was not prevented, the test will fail and the page will
be reloaded causing the test runner to panic.
2012-08-10 14:20:52 -07:00
Igor Minar 6b75475ce3 refactor(formSpec): group preventDefault specs into a describe 2012-08-10 14:20:28 -07:00
Igor Minar 07c354a8c0 docs(faq): update faq docs 2012-08-10 14:20:13 -07:00
Igor Minar 1391579599 docs(styles): fix the cog icon alignment 2012-08-10 14:19:57 -07:00
Vojta Jina 5d2bd1d84c chore(nodeserver): add font mime type 2012-08-10 14:19:47 -07:00
Vojta Jina bf77e212af docs(guide): hide scenario for directive example
scenario test for this example would be tricky, we need to teach
the runner how to inject mocks first.
2012-08-10 14:19:37 -07:00
Vojta Jina eef2f9c31e docs(design): fix icons
Copy fontawesome during build
2012-08-10 14:18:45 -07:00
brettcannon 438627c2c3 fix(docs): "in depth" -> "in-depth" 2012-08-10 14:18:06 -07:00
1812 changed files with 66603 additions and 451849 deletions
-509
View File
@@ -1,509 +0,0 @@
# Configuration file for https://circleci.com/gh/angular/angular.js
# Note: YAML anchors allow an object to be re-used, reducing duplication.
# The ampersand declares an alias for an object, then later the `<<: *name`
# syntax dereferences it.
# See http://blog.daemonl.com/2016/02/yaml.html
# To validate changes, use an online parser, eg.
# http://yaml-online-parser.appspot.com/
# CircleCI configuration version
# Version 2.1 allows for extra config reuse features
# https://circleci.com/docs/2.0/reusing-config/#getting-started-with-config-reuse
version: 2.1
# Workspace persisted by the `setup` job to share build artifacts with other jobs.
# https://circleci.com/docs/2.0/workflows/#using-workspaces-to-share-data-among-jobs
# https://circleci.com/blog/deep-diving-into-circleci-workspaces/
var_workspace_location: &workspace_location ~/
# Executor Definitions
# https://circleci.com/docs/2.0/reusing-config/#authoring-reusable-executors
# **NOTE 1**: Pin to exact images using an ID (SHA). See https://circleci.com/docs/2.0/circleci-images/#using-a-docker-image-id-to-pin-an-image-to-a-fixed-version.
# (Using the tag in not necessary when pinning by ID, but include it anyway for documentation purposes.)
executors:
default-executor:
parameters:
resource_class:
type: string
default: medium
docker:
- image: circleci/node:14.16.1@sha256:b094e85848b43209ca83d9bb114d406fe62c75cb73b18c9d8eb1a9c6462c97d4
resource_class: << parameters.resource_class >>
working_directory: ~/ng
cloud-sdk:
description: The docker container to use when running gcp-gcs commands
docker:
- image: google/cloud-sdk:alpine@sha256:7d0cae28cb282b76f2d9babe278c63c910d54f0cceca7a65fdf6806e2b43882e
working_directory: ~/ng
# Filter Definitions
# Filter to run a job on all branches and any `v1.X.Y(-Z)` tags.
# Since the jobs need to run on tagged builds too, a `tags` section has to be explicitly specified.
# (The `branches` section could be omitted, since it defaults to all branches - just being explicit
# here).
# See also https://circleci.com/docs/2.0/workflows/#executing-workflows-for-a-git-tag.
var-filter-run-always: &run-always
filters:
branches:
only: /.*/
tags:
only: /v1\.\d+\.\d.*/
# Filter to run a job when code might need to be deployed - i.e. on builds for the `master` branch.
# (Further checks are needed to determine whether a deployment is actually needed, but these are not
# possible via filters.)
var-filter-run-on-master: &run-on-master
filters:
branches:
only:
- master
tags:
ignore: /.*/
# Filter to run a job when code/docs might need to be deployed - i.e. on tagged builds and on builds
# for master and `v1.*.x` branches.
# (Further checks are needed to determine whether a deployment is actually needed, but these are not
# possible via filters.)
var-filter-run-on-tags-and-master-and-version-branches: &run-on-tags-and-master-and-version-branches
filters:
branches:
only:
- master
- /v1\.\d+\.x/
tags:
only: /v1\.\d+\.\d.*/
# Filter to run a job when docs might need to be deployed - i.e. on builds for `v1.*.x` branches,
# which might correspond to the stable branch.
# (Further checks are needed to determine whether a deployment is actually needed, but these are not
# possible via filters.)
var-filter-run-on-version-branches: &run-on-version-branches
filters:
branches:
only:
- /v1\.\d+\.x/
tags:
ignore: /.*/
# Command Definitions
# https://circleci.com/docs/2.0/reusing-config/#authoring-reusable-commands
commands:
skip_on_pr_and_fork_builds:
description: Skip a job on pull request and fork builds
steps:
- run:
name: Skip this job if this is a pull request or fork build
# Note: Using `CIRCLE_*` env variables (instead of those defined in `env.sh` so that this
# step can be run before `init_environment`.
command: >
if [[ -n "$CIRCLE_PR_NUMBER" ]] ||
[[ "$CIRCLE_PROJECT_USERNAME" != "angular" ]] ||
[[ "$CIRCLE_PROJECT_REPONAME" != "angular.js" ]]; then
echo "Skipping this job, because this is either a pull request or a fork build."
circleci step halt
fi
skip_unless_stable_branch:
description: Skip a job unless this is the stable branch
steps:
- run:
name: Skip this job unless this is the stable branch
command: >
if [[ "$DIST_TAG" != "latest" ]]; then
echo "Skipping deployment, because this is not the stable branch."
circleci step halt
fi
skip_unless_tag_or_master_or_stable_branch:
description: Skip a job unless this is a tag or the master or stable branch
steps:
- run:
name: Skip this job unless this is a tag or the master or stable branch
command: >
if [[ "$CI_GIT_TAG" == "false" ]] &&
[[ "$CI_BRANCH" != "master" ]] &&
[[ "$DIST_TAG" != "latest" ]]; then
echo "Skipping this job, because this is neither a tag nor the master or stable branch."
circleci step halt
fi
custom_attach_workspace:
description: Attach workspace at a predefined location
steps:
- attach_workspace:
at: *workspace_location
# Java is needed for running the Closure Compiler (during the `minall` task).
install_java:
description: Install java
steps:
- run:
name: Install java
command: |
sudo apt-get update
# Install java runtime
sudo apt-get install default-jre
# Initializes the CI environment by setting up common environment variables.
init_environment:
description: Initializing environment (setting up variables)
steps:
- run:
name: Set up environment
environment:
CIRCLE_GIT_BASE_REVISION: << pipeline.git.base_revision >>
CIRCLE_GIT_REVISION: << pipeline.git.revision >>
command: ./.circleci/env.sh
- run:
# Configure git as the CircleCI `checkout` command does.
# This is needed because we only checkout on the setup job.
# Add GitHub to known hosts
name: Configure git
command: |
mkdir -p ~/.ssh
echo 'github.com ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==' >> ~/.ssh/known_hosts
git config --global url."ssh://git@github.com".insteadOf "https://github.com" || true
git config --global gc.auto 0 || true
init_saucelabs_environment:
description: Sets up a domain that resolves to the local host.
steps:
- run:
name: Preparing environment for running tests on Saucelabs.
command: |
# For SauceLabs jobs, we set up a domain which resolves to the machine which launched
# the tunnel. We do this because devices are sometimes not able to properly resolve
# `localhost` or `127.0.0.1` through the SauceLabs tunnel. Using a domain that does not
# resolve to anything on SauceLabs VMs ensures that such requests are always resolved
# through the tunnel, and resolve to the actual tunnel host machine (i.e. the CircleCI VM).
# More context can be found in: https://github.com/angular/angular/pull/35171.
setPublicVar SAUCE_LOCALHOST_ALIAS_DOMAIN "angular-ci.local"
setSecretVar SAUCE_ACCESS_KEY $(echo $SAUCE_ACCESS_KEY | rev)
- run:
# Sets up a local domain in the machine's host file that resolves to the local
# host. This domain is helpful in Saucelabs tests where devices are not able to
# properly resolve `localhost` or `127.0.0.1` through the sauce-connect tunnel.
name: Setting up alias domain for local host.
command: echo "127.0.0.1 $SAUCE_LOCALHOST_ALIAS_DOMAIN" | sudo tee -a /etc/hosts
start_saucelabs:
steps:
- run:
name: Starting Saucelabs tunnel service
command: ./lib/saucelabs/sauce-service.sh start-ready-wait
stop_saucelabs:
steps:
- run:
name: Stopping Saucelabs tunnel service
command: ./lib/saucelabs/sauce-service.sh stop
run_e2e_tests:
parameters:
specs:
type: string
steps:
- custom_attach_workspace
- init_environment
- init_saucelabs_environment
- start_saucelabs
- run:
command: yarn grunt test:circleci-protractor --specs="<< parameters.specs >>"
no_output_timeout: 30m
- stop_saucelabs
run_e2e_tests_jquery:
parameters:
specs:
type: string
steps:
- custom_attach_workspace
- init_environment
- init_saucelabs_environment
- start_saucelabs
- run:
environment:
USE_JQUERY: 1
command: yarn grunt test:circleci-protractor --specs="<< parameters.specs >>"
no_output_timeout: 30m
- stop_saucelabs
# Job definitions
# Jobs can include parameters that are passed in the workflow job invocation.
# https://circleci.com/docs/2.0/reusing-config/#authoring-parameterized-jobs
jobs:
setup:
executor: default-executor
steps:
- checkout
- init_environment
- install_java
- run:
name: Running Yarn install
command: yarn install --frozen-lockfile --non-interactive
# Yarn's requests sometimes take more than 10mins to complete.
no_output_timeout: 45m
- run: yarn grunt package
# Persist any changes at this point to be reused by further jobs.
# **NOTE**: To add new content to the workspace, always persist on the same root.
- persist_to_workspace:
root: *workspace_location
paths:
- ./ng
lint:
executor: default-executor
steps:
- custom_attach_workspace
- init_environment
- run: yarn grunt ci-checks
- run: yarn commitplease "$CI_COMMIT_RANGE"
- run: yarn grunt validate-angular-files
unit-test:
executor:
name: default-executor
steps:
- custom_attach_workspace
- init_environment
- install_java
- init_saucelabs_environment
- run: yarn grunt test:promises-aplus
- run:
command: yarn grunt test:jqlite --browsers="$BROWSERS" --reporters=spec
no_output_timeout: 10m
- run:
command: yarn grunt test:modules --browsers="$BROWSERS" --reporters=spec
no_output_timeout: 10m
- run:
command: yarn grunt test:docs --browsers="$BROWSERS" --reporters=spec
no_output_timeout: 10m
unit-test-jquery:
executor:
name: default-executor
steps:
- custom_attach_workspace
- init_environment
- init_saucelabs_environment
- run:
command: yarn grunt test:jquery --browsers="$BROWSERS" --reporters=spec
no_output_timeout: 10m
- run:
command: yarn grunt test:jquery-2.2 --browsers="$BROWSERS" --reporters=spec
no_output_timeout: 10m
- run:
command: yarn grunt test:jquery-2.1 --browsers="$BROWSERS" --reporters=spec
no_output_timeout: 10m
e2e-test-1:
executor:
name: default-executor
steps:
- run_e2e_tests:
specs: test/e2e/tests/**/*.js
e2e-test-2a:
executor:
name: default-executor
steps:
- run_e2e_tests:
specs: build/docs/ptore2e/example-ng*/**/default_test.js
e2e-test-2b:
executor:
name: default-executor
steps:
- run_e2e_tests:
specs: "build/docs/ptore2e/!(example-ng*)/**/default_test.js"
e2e-test-jquery-1:
executor:
name: default-executor
steps:
- run_e2e_tests_jquery:
specs: test/e2e/tests/**/*.js
e2e-test-jquery-2a:
executor:
name: default-executor
steps:
- run_e2e_tests_jquery:
specs: build/docs/ptore2e/example-ng*/**/jquery_test.js
e2e-test-jquery-2b:
executor:
name: default-executor
steps:
- run_e2e_tests_jquery:
specs: build/docs/ptore2e/!(example-ng*)/**/jquery_test.js
prepare-deployment:
executor:
name: default-executor
steps:
- skip_on_pr_and_fork_builds
- custom_attach_workspace
- init_environment
- run: yarn grunt prepareDeploy
# Write the deployment files to the workspace to be used by deploy-docs and deploy-code
- persist_to_workspace:
root: *workspace_location
paths:
- ./ng
# The `deploy-code-files` job should only run when all of these conditions are true for the build:
# - It is for the `angular/angular.js` repository (not a fork).
# - It is not for a pull request.
# - It is for a tag or the master branch or the stable branch(*).
#
# *: The stable branch is the one that has the value `latest` in `package.json > distTag`.
deploy-code-files:
executor:
name: cloud-sdk
steps:
- skip_on_pr_and_fork_builds
- custom_attach_workspace
- init_environment
- skip_unless_tag_or_master_or_stable_branch
- run: ls scripts/code.angularjs.org-firebase/deploy
- run:
name: Authenticate and configure Docker
command: |
echo $GCLOUD_SERVICE_KEY | gcloud auth activate-service-account --key-file=-
gcloud --quiet config set project ${GOOGLE_PROJECT_ID}
- run:
name: Sync files to code.angularjs.org
command: |
gsutil -m rsync -r scripts/code.angularjs.org-firebase/deploy gs://code-angularjs-org-338b8.appspot.com
# The `deploy-code-firebase` job should only run when all of these conditions are true for the build:
# - It is for the `angular/angular.js` repository (not a fork).
# - It is not for a pull request.
# - It is for the master branch.
# (This is enforced via job filters, so we don't need to a step to check it here.)
deploy-code-firebase:
executor:
name: default-executor
steps:
- skip_on_pr_and_fork_builds
- custom_attach_workspace
- init_environment
# Install dependencies for Firebase functions to prevent parsing errors during deployment.
# See https://github.com/angular/angular.js/pull/16453.
- run:
name: Install dependencies in `scripts/code.angularjs.org-firebase/functions/`.
working_directory: scripts/code.angularjs.org-firebase/functions
command: yarn install --frozen-lockfile --ignore-engines --non-interactive
- run:
name: Deploy to Firebase from `scripts/code.angularjs.org-firebase/`.
working_directory: scripts/code.angularjs.org-firebase
command: |
# Do not use `yarn firebase` as that causes the Firebase CLI to look for `firebase.json`
# in the root directory, even if run from inside `scripts/code.angularjs.org-firebase/`.
firebase=$(yarn bin)/firebase
$firebase use
$firebase deploy --message "Commit:\ $CI_COMMIT" --non-interactive --token "$FIREBASE_TOKEN"
# The `deploy-docs` job should only run when all of these conditions are true for the build:
# - It is for the `angular/angular.js` repository (not a fork).
# - It is not for a pull request.
# - It is for the stable branch(*).
#
# *: The stable branch is the one that has the value `latest` in `package.json > distTag`.
deploy-docs:
executor:
name: default-executor
steps:
- skip_on_pr_and_fork_builds
- custom_attach_workspace
- init_environment
- skip_unless_stable_branch
# Install dependencies for Firebase functions to prevent parsing errors during deployment.
# See https://github.com/angular/angular.js/pull/16453.
- run:
name: Install dependencies in `scripts/docs.angularjs.org-firebase/functions/`.
working_directory: scripts/docs.angularjs.org-firebase/functions
command: yarn install --frozen-lockfile --ignore-engines --non-interactive
- run:
name: Deploy to Firebase from `scripts/docs.angularjs.org-firebase/`.
working_directory: scripts/docs.angularjs.org-firebase
command: |
# Do not use `yarn firebase` as that causes the Firebase CLI to look for `firebase.json`
# in the root directory, even if run from inside `scripts/docs.angularjs.org-firebase/`.
firebase=$(yarn bin)/firebase
$firebase use
$firebase deploy --message "Commit:\ $CI_COMMIT" --non-interactive --token "$FIREBASE_TOKEN"
workflows:
version: 2
default_workflow:
jobs:
- setup:
<<: *run-always
- lint:
<<: *run-always
requires:
- setup
- unit-test:
<<: *run-always
requires:
- setup
- unit-test-jquery:
<<: *run-always
requires:
- setup
- e2e-test-1:
<<: *run-always
requires:
- setup
- e2e-test-2a:
<<: *run-always
requires:
- setup
- e2e-test-2b:
<<: *run-always
requires:
- setup
- e2e-test-jquery-1:
<<: *run-always
requires:
- setup
- e2e-test-jquery-2a:
<<: *run-always
requires:
- setup
- e2e-test-jquery-2b:
<<: *run-always
requires:
- setup
- prepare-deployment:
<<: *run-on-tags-and-master-and-version-branches
requires:
- setup
- lint
- unit-test
- unit-test-jquery
- e2e-test-1
- e2e-test-2a
- e2e-test-2b
- e2e-test-jquery-1
- e2e-test-jquery-2a
- e2e-test-jquery-2b
- deploy-code-files:
<<: *run-on-tags-and-master-and-version-branches
requires:
- prepare-deployment
- deploy-code-firebase:
<<: *run-on-master
requires:
- prepare-deployment
- deploy-docs:
<<: *run-on-version-branches
requires:
- prepare-deployment
-73
View File
@@ -1,73 +0,0 @@
####################################################################################################
# Helpers for defining environment variables for CircleCI.
#
# In CircleCI, each step runs in a new shell. The way to share ENV variables across steps is to
# export them from `$BASH_ENV`, which is automatically sourced at the beginning of every step (for
# the default `bash` shell).
#
# See also https://circleci.com/docs/2.0/env-vars/#using-bash_env-to-set-environment-variables.
####################################################################################################
# Set and print an environment variable.
#
# Use this function for setting environment variables that are public, i.e. it is OK for them to be
# visible to anyone through the CI logs.
#
# Usage: `setPublicVar <name> <value>`
function setPublicVar() {
setSecretVar $1 "$2";
echo "$1=$2";
}
# Set (without printing) an environment variable.
#
# Use this function for setting environment variables that are secret, i.e. should not be visible to
# everyone through the CI logs.
#
# Usage: `setSecretVar <name> <value>`
function setSecretVar() {
# WARNING: Secrets (e.g. passwords, access tokens) should NOT be printed.
# (Keep original shell options to restore at the end.)
local -r originalShellOptions=$(set +o);
set +x -eu -o pipefail;
echo "export $1=\"${2:-}\";" >> $BASH_ENV;
# Restore original shell options.
eval "$originalShellOptions";
}
# Create a function to set an environment variable, when called.
#
# Use this function for creating setter for public environment variables that require expensive or
# time-consuming computaions and may not be needed. When needed, you can call this function to set
# the environment variable (which will be available through `$BASH_ENV` from that point onwards).
#
# Arguments:
# - `<name>`: The name of the environment variable. The generated setter function will be
# `setPublicVar_<name>`.
# - `<code>`: The code to run to compute the value for the variable. Since this code should be
# executed lazily, it must be properly escaped. For example:
# ```sh
# # DO NOT do this:
# createPublicVarSetter MY_VAR "$(whoami)"; # `whoami` will be evaluated eagerly
#
# # DO this isntead:
# createPublicVarSetter MY_VAR "\$(whoami)"; # `whoami` will NOT be evaluated eagerly
# ```
#
# Usage: `createPublicVarSetter <name> <code>`
#
# Example:
# ```sh
# createPublicVarSetter MY_VAR 'echo "FOO"';
# echo $MY_VAR; # Not defined
#
# setPublicVar_MY_VAR;
# source $BASH_ENV;
# echo $MY_VAR; # FOO
# ```
function createPublicVarSetter() {
echo "setPublicVar_$1() { setPublicVar $1 \"$2\"; }" >> $BASH_ENV;
}
-69
View File
@@ -1,69 +0,0 @@
#!/usr/bin/env bash
# Variables
readonly projectDir=$(realpath "$(dirname ${BASH_SOURCE[0]})/..")
readonly envHelpersPath="$projectDir/.circleci/env-helpers.inc.sh";
# Load helpers and make them available everywhere (through `$BASH_ENV`).
source $envHelpersPath;
echo "source $envHelpersPath;" >> $BASH_ENV;
####################################################################################################
# Define PUBLIC environment variables for CircleCI.
####################################################################################################
# See https://circleci.com/docs/2.0/env-vars/#built-in-environment-variables for more info.
####################################################################################################
setPublicVar CI "$CI"
setPublicVar PROJECT_ROOT "$projectDir";
# This is the branch being built; e.g. `pull/12345` for PR builds.
setPublicVar CI_BRANCH "$CIRCLE_BRANCH";
setPublicVar CI_BUILD_URL "$CIRCLE_BUILD_URL";
setPublicVar CI_COMMIT "$CIRCLE_SHA1";
setPublicVar CI_GIT_BASE_REVISION "${CIRCLE_GIT_BASE_REVISION}";
setPublicVar CI_GIT_REVISION "${CIRCLE_GIT_REVISION}";
setPublicVar CI_GIT_TAG "${CIRCLE_TAG:-false}";
setPublicVar CI_COMMIT_RANGE "$CIRCLE_GIT_BASE_REVISION..$CIRCLE_GIT_REVISION";
setPublicVar CI_PULL_REQUEST "${CIRCLE_PR_NUMBER:-false}";
setPublicVar CI_REPO_NAME "$CIRCLE_PROJECT_REPONAME";
setPublicVar CI_REPO_OWNER "$CIRCLE_PROJECT_USERNAME";
setPublicVar CI_PR_REPONAME "$CIRCLE_PR_REPONAME";
setPublicVar CI_PR_USERNAME "$CIRCLE_PR_USERNAME";
####################################################################################################
# Define SauceLabs environment variables for CircleCI.
####################################################################################################
setPublicVar BROWSER_PROVIDER "saucelabs"
# The currently latest-1 version of desktop Safari on Saucelabs (v12.0) is unstable and disconnects
# consistently. The latest version (v12.1) works fine.
# TODO: Add `SL_Safari-1` back, once it no longer corresponds to v12.0.
setPublicVar BROWSERS "SL_Chrome,SL_Chrome-1,\
SL_Firefox,SL_Firefox-1,\
SL_Safari,\
SL_iOS,SL_iOS-1,\
SL_IE_9,SL_IE_10,SL_IE_11,\
SL_EDGE,SL_EDGE-1"
setPublicVar SAUCE_LOG_FILE /tmp/angular/sauce-connect.log
setPublicVar SAUCE_READY_FILE /tmp/angular/sauce-connect-ready-file.lock
setPublicVar SAUCE_PID_FILE /tmp/angular/sauce-connect-pid-file.lock
setPublicVar SAUCE_TUNNEL_IDENTIFIER "angularjs-framework-${CIRCLE_BUILD_NUM}-${CIRCLE_NODE_INDEX}"
# Amount of seconds we wait for sauceconnect to establish a tunnel instance. In order to not
# acquire CircleCI instances for too long if sauceconnect failed, we need a connect timeout.
setPublicVar SAUCE_READY_FILE_TIMEOUT 120
####################################################################################################
# Define additional environment variables
####################################################################################################
# NOTE: Make sure the tools used to compute this are available in all executors in `config.yml`.
setPublicVar DIST_TAG $( cat package.json | grep distTag | sed -E 's/^\s*"distTag"\s*:\s*"([^"]+)"\s*,\s*$/\1/' )
####################################################################################################
####################################################################################################
## Source `$BASH_ENV` to make the variables available immediately. ##
## *** NOTE: This must remain the last command in this script. *** ##
####################################################################################################
####################################################################################################
source $BASH_ENV;
-18
View File
@@ -1,18 +0,0 @@
# https://editorconfig.org
root = true
[*]
charset = utf-8
indent_style = space
indent_size = 2
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true
[dropdown-toggle.js]
trim_trailing_whitespace = false
insert_final_newline = false
[htmlparser.js]
insert_final_newline = false
-10
View File
@@ -1,10 +0,0 @@
build/**
docs/app/assets/js/angular-bootstrap/**
docs/config/templates/**
node_modules/**
lib/htmlparser/**
src/angular.bind.js
src/ngParseExt/ucd.js
i18n/closure/**
tmp/**
vendor/**
-117
View File
@@ -1,117 +0,0 @@
{
"rules": {
// Rules are divided into sections from http://eslint.org/docs/rules/
// Possible errors
"comma-dangle": ["error", "never"],
"no-cond-assign": ["error", "except-parens"],
"no-constant-condition": ["error", {"checkLoops": false}],
"no-control-regex": "error",
"no-debugger": "error",
"no-dupe-args": "error",
"no-dupe-keys": "error",
"no-duplicate-case": "error",
"no-empty-character-class": "error",
"no-empty": "error",
"no-ex-assign": "error",
"no-extra-boolean-cast": "error",
"no-extra-semi": "error",
"no-func-assign": "error",
"no-inner-declarations": "error",
"no-invalid-regexp": "error",
"no-irregular-whitespace": "error",
"no-negated-in-lhs": "error",
"no-obj-calls": "error",
"no-regex-spaces": "error",
"no-sparse-arrays": "error",
"no-unreachable": "error",
"use-isnan": "error",
"no-unsafe-finally": "error",
"valid-typeof": "error",
"no-unexpected-multiline": "error",
// Best practices
"accessor-pairs": "error",
"array-callback-return": "error",
"eqeqeq": ["error", "allow-null"],
"no-alert": "error",
"no-caller": "error",
"no-case-declarations": "error",
"no-eval": "error",
"no-extend-native": "error",
"no-extra-bind": "error",
"no-extra-label": "error",
"no-fallthrough": "error",
"no-floating-decimal": "error",
"no-implied-eval": "error",
"no-invalid-this": "error",
"no-iterator": "error",
"no-multi-str": "error",
"no-new-func": "error",
"no-new-wrappers": "error",
"no-new": "error",
"no-octal-escape": "error",
"no-octal": "error",
"no-proto": "error",
"no-redeclare": "error",
"no-return-assign": "error",
"no-script-url": "error",
"no-self-assign": "error",
"no-self-compare": "error",
"no-sequences": "error",
"no-throw-literal": "error",
"no-unmodified-loop-condition": "error",
"no-unused-expressions": "error",
"no-unused-labels": "error",
"no-useless-call": "error",
"no-useless-concat": "error",
"no-useless-escape": "error",
"no-void": "error",
"no-with": "error",
"radix": "error",
"wrap-iife": ["error", "inside"],
// Strict mode
"strict": ["error", "global"],
// Variables
"no-delete-var": "error",
"no-label-var": "error",
"no-restricted-globals": ["error", "event"],
"no-shadow-restricted-names": "error",
"no-undef-init": "error",
"no-undef": "error",
"no-unused-vars": ["error", { "vars": "local", "args": "none" }],
// Node.js
"handle-callback-err": "error",
// Stylistic issues
"array-bracket-spacing": ["error", "never"],
"brace-style": ["error", "1tbs", { "allowSingleLine": true }],
"comma-style": ["error", "last"],
"eol-last": "error",
"keyword-spacing": "error",
"linebreak-style": ["error", "unix"],
"max-len": ["error", { "code": 200, "ignoreComments": true, "ignoreUrls": true }],
"new-cap": "error",
"new-parens": "error",
"no-array-constructor": "error",
"no-bitwise": "error",
"no-mixed-spaces-and-tabs": "error",
"no-multiple-empty-lines": ["error", { "max": 3, "maxEOF": 1 }],
"no-whitespace-before-property": "error",
"no-spaced-func": "error",
"no-trailing-spaces": "error",
"no-unneeded-ternary": "error",
"quotes": ["error", "single"],
"semi-spacing": "error",
"semi": "error",
"space-before-blocks": ["error", "always"],
"space-before-function-paren": ["error", "never"],
"space-in-parens": ["error", "never"],
"space-infix-ops": "error",
"space-unary-ops": ["error", { "words": true, "nonwords": false }],
"unicode-bom": ["error", "never"]
}
}
-17
View File
@@ -1,17 +0,0 @@
{
"extends": "./.eslintrc-base.json",
"env": {
// Note: don't set `"browser": true`; code in "src/" should be compatible with
// non-browser environments like Node.js with a custom window implementation
// like jsdom. All browser globals should be taken from window.
"browser": false,
"node": false
},
"globals": {
"window": false,
"angular": false
}
}
-13
View File
@@ -1,13 +0,0 @@
{
"extends": "./.eslintrc-base.json",
"env": {
"browser": false,
"node": true
},
"parserOptions": {
"ecmaVersion": 2017
},
"plugins": [
"promise"
]
}
-25
View File
@@ -1,25 +0,0 @@
{
// This config contains proposed rules that we'd like to have enabled but haven't
// converted the code to adhere yet. If a decision comes to not enable one of these
// rules, it should be removed from the file. Every rule that got enabled in the
// end should be moved from here to a respective section in .eslintrc.json
"rules": {
// Rules are divided into sections from http://eslint.org/docs/rules/
// Best practices
"complexity": ["error", 10],
"dot-notation": "error",
"dot-location": ["error", "property"],
// Stylistic issues
"block-spacing": ["error", "always"],
"comma-spacing": "error",
"id-denylist": ["error", "event"],
"indent": ["error", 2],
"key-spacing": ["error", { "beforeColon": false, "afterColon": true, "mode": "minimum" }],
"object-curly-spacing": ["error", "never"],
"object-property-newline": ["error", { "allowMultiplePropertiesPerLine": true }],
"operator-linebreak": ["error", "after", { "overrides": { "?": "before", ":": "before" }}]
}
}
-4
View File
@@ -1,4 +0,0 @@
{
"root": true,
"extends": "./.eslintrc-node.json"
}
-5
View File
@@ -1,5 +0,0 @@
# Auto detect text files and perform LF normalization
* text=auto
# JS files must always use LF for tools to work
*.js eol=lf
-42
View File
@@ -1,42 +0,0 @@
# AngularJS is in LTS mode
We are no longer accepting changes that are not critical bug fixes into this project.
See https://blog.angular.io/stable-angularjs-and-long-term-support-7e077635ee9c for more detail.
<!--
IF YOU DON'T FILL OUT THE FOLLOWING INFORMATION WE MIGHT CLOSE YOUR ISSUE WITHOUT INVESTIGATION
-->
<!--
- For *SUPPORT QUESTIONS*, use one of the
[support channels](https://github.com/angular/angular.js/blob/master/CONTRIBUTING.md#question).
- Before submitting, please **SEARCH GITHUB** for a similar issue or PR. -->
**I'm submitting a ...**
<!-- (check one with "x") -->
- [ ] regression from 1.7.0
- [ ] security issue
- [ ] issue caused by a new browser version
- [ ] other <!--(Please do not submit support requests here - see above)-->
**Current behavior:**
<!-- Describe how the bug manifests / how the current features are insufficient. -->
**Expected / new behavior:**
<!-- Describe what the behavior would be without the bug / how the feature would improve AngularJS -->
**Minimal reproduction of the problem with instructions:**
<!--
If the current behavior is a bug or you can illustrate your feature request better with an example,
please provide the *STEPS TO REPRODUCE* and if possible a *MINIMAL DEMO* of the problem via
https://plnkr.co or similar (you can use this template as a starting point: http://plnkr.co/edit/tpl:yBpEi4).
-->
**AngularJS version:** 1.8.x
<!-- Check whether this is still an issue in the most recent stable or in the snapshot AngularJS
version (https://code.angularjs.org/snapshot/) -->
**Browser:** [all | Chrome XX | Firefox XX | Edge XX | IE XX | Safari XX | Mobile Chrome XX | Android X.X Web Browser | iOS XX Safari | iOS XX UIWebView | iOS XX WKWebView | Opera XX ]
<!-- All browsers where this could be reproduced (and Operating System if relevant) -->
**Anything else:**
<!-- e.g. stacktraces, related issues, suggestions how to fix -->
-29
View File
@@ -1,29 +0,0 @@
# AngularJS is in LTS mode
We are no longer accepting changes that are not critical bug fixes into this project.
See https://blog.angular.io/stable-angularjs-and-long-term-support-7e077635ee9c for more detail.
<!-- General PR submission guidelines https://github.com/angular/angular.js/blob/master/CONTRIBUTING.md#submit-pr -->
**Does this PR fix a regression since 1.7.0, a security flaw, or a problem caused by a new browser version?**
<!-- If the answer is no, then we will not merge this PR -->
**What is the current behavior? (You can also link to an open issue here)**
**What is the new behavior (if this is a feature change)?**
**Does this PR introduce a breaking change?**
**Please check if the PR fulfills these requirements**
- [ ] The commit message follows our [guidelines](https://github.com/angular/angular.js/blob/master/DEVELOPERS.md#commits)
- [ ] Fix/Feature: [Docs](https://github.com/angular/angular.js/blob/master/DEVELOPERS.md#documentation) have been added/updated
- [ ] Fix/Feature: Tests have been added; existing tests pass
**Other information**:
+4 -17
View File
@@ -1,5 +1,6 @@
/build/
/benchpress-build/
build/
angularjs.netrc
jstd.log
.DS_Store
gen_docs.disable
test.disable
@@ -7,21 +8,7 @@ regression/temp*.html
performance/temp*.html
.idea/workspace.xml
*~
*.swp
angular.js.tmproj
node_modules/
node_modules
angular.xcodeproj
.firebase/
.idea
*.iml
.agignore
.lvimrc
libpeerconnection.log
npm-debug.log
/tmp/
.vscode
*.log
*.stackdump
scripts/code.angularjs.org-firebase/deploy
scripts/docs.angularjs.org-firebase/deploy
scripts/docs.angularjs.org-firebase/functions/content
-29
View File
@@ -1,29 +0,0 @@
Andres Ornelas <aornelas@google.com>
Caitlin Potter <caitpotter88@gmail.com>
Caitlin Potter <caitpotter88@gmail.com> <snowball@defpixel.com>
Di Peng <pengdi@google.com>
Di Peng <pengdi@google.com> <pengdi@go.wustl.edu>
Georgios Kalpakas <kalpakas.g@gmail.com>
Georgios Kalpakas <kalpakas.g@gmail.com> <g.kalpakas@hotmail.com>
Julie Ralph <ju.ralph@gmail.com>
Lucas Galfaso <lgalfaso@gmail.com>
Martin Staffa <mjstaffa@gmail.com>
Martin Staffa <mjstaffa@gmail.com> <mjstaffa@googlemail.com>
Matias Niemelä <matias@yearofmoo.com>
Michał Gołębiowski-Owczarek <m.goleb@gmail.com>
Misko Hevery <misko@hevery.com>
Misko Hevery <misko@hevery.com> <misko@google.com>
Igor Minar <igor@angularjs.org>
Igor Minar <igor@angularjs.org> <iiminar@gmail.com>
Igor Minar <igor@angularjs.org> <iminar@google.com>
Igor Minar <igor@angularjs.org> <iminar@dhcp-172-19-37-154.mtv.corp.google.com>
Pawel Kozlowski <pkozlowski.opensource@gmail.com>
Peter Bacon Darwin <pete@bacondarwin.com>
Rodric Haddad <rody@rodyhaddad.com>
Shahar Talmi <shahar.talmi@gmail.com>
Shahar Talmi <shahar.talmi@gmail.com> <shahart@wix.com>
Shyam Seshadri <shyamseshadri@google.com>
Shyam Seshadri <shyamseshadri@google.com> <shyamseshadri@gmail.com>
Vojta Jina <vojta.jina@gmail.com>
Vojta Jina <vojta.jina@gmail.com> <vojta@gemin-i.org>
Vojta Jina <vojta.jina@gmail.com> <vojta@google.com>
-1
View File
@@ -1 +0,0 @@
14.16.1
+13
View File
@@ -0,0 +1,13 @@
language: node_js
node_js:
- 0.8
before_script:
- export DISPLAY=:99.0
- sh -e /etc/init.d/xvfb start
- npm install -g testacular@canary
- rake package
- ./nodeserver.sh > /dev/null &
script:
- rake test[Firefox,"--reporters=dots"]
+20 -15551
View File
File diff suppressed because it is too large Load Diff
-3
View File
@@ -1,3 +0,0 @@
# Contributor Code of Conduct
The AngularJS project follows the Code of Conduct defined in [the angular/code-of-conduct repository](https://github.com/angular/code-of-conduct/blob/master/CODE_OF_CONDUCT.md). Please read it.
+25 -239
View File
@@ -1,246 +1,32 @@
# Contributing to AngularJS
## Submitting issues
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:
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].
* [Code of Conduct](#coc)
* [Questions and Problems](#question)
* [Issues and Bugs](#issue)
* [Feature Requests](#feature)
* [Improving Documentation](#docs)
* [Issue Submission Guidelines](#submit)
* [Pull Request Submission Guidelines](#submit-pr)
* [Signing the CLA](#cla)
### Guidelines
## <a name="coc"></a> Code of Conduct
* Search the archive first, it's likely that your question was already answered.
* A live example demonstrating your problem or question, will get an answer faster.
* Create one using this [template][template]
* If you get help, help others. Good karma rulez!
Help us keep AngularJS open and inclusive. Please read and follow our [Code of Conduct][coc].
If your issue appears to be a bug, and hasn't been reported, open a new issue.
Help us to maximize the effort we can spend fixing issues and adding new
features, by not reporting duplicate issues.
## <a name="requests"></a> Questions, Bugs, Features
### <a name="question"></a> Got a Question or Problem?
Do not open issues for general support questions as we want to keep GitHub issues for bug reports
and feature requests. You've got much better chances of getting your question answered on dedicated
support platforms, the best being [Stack Overflow][stackoverflow].
Stack Overflow is a much better place to ask questions since:
- there are thousands of people willing to help on Stack Overflow
- questions and answers stay available for public viewing so your question / answer might help
someone else
- Stack Overflow's voting system assures that the best answers are prominently visible.
To save your and our time, we will systematically close all issues that are requests for general
support and redirect people to the section you are reading right now.
Other channels for support are:
- the [Google Group][groups] discussion list
- the [AngularJS IRC][irc]
- the [AngularJS Gitter][gitter]
### <a name="issue"></a> Found an Issue or Bug?
If you find a bug in the source code, you can help us by submitting an issue to our
[GitHub Repository][github]. Even better, you can submit a Pull Request with a fix.
**Please see the [Submission Guidelines](#submit) below.**
**Special Note for Localization Issues:** AngularJS uses the [Google Closure I18N library] to
generate its own I18N files (the ngLocale module). This means that any changes to these files
would be lost the next time that we import the library.
Since the Closure library i18n data is itself auto-generated from the data of the
[Common Locale Data Repository (CLDR)] project, errors in the data should
be reported there. See also the [Closure guide to i18n changes].
### <a name="feature"></a> Missing a Feature?
You can request a new feature by submitting an issue to our [GitHub Repository][github-issues].
If you would like to implement a new feature then consider what kind of change it is:
* **Major Changes** that you wish to contribute to the project should be discussed first in an
[GitHub issue][github-issues] that clearly outlines the changes and benefits of the feature.
* **Small Changes** can directly be crafted and submitted to the [GitHub Repository][github]
as a Pull Request. See the section about [Pull Request Submission Guidelines](#submit-pr), and
for detailed information the [core development documentation][developers].
### <a name="docs"></a> Want a Doc Fix?
Should you have a suggestion for the documentation, you can open an issue and outline the problem
or improvement you have - however, creating the doc fix yourself is much better!
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. Create a new issue (or comment on a related existing one) to let
others know what you're working on.
If you're making a small change (typo, phrasing) 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. The commit message is preformatted to the right type
and scope, so you only have to add the description.
For large fixes, please build and test the documentation before submitting the PR to be sure you
haven't accidentally introduced any layout or formatting issues. You should also make sure that your
commit message follows the **[Commit Message Guidelines][developers.commits]**.
## <a name="submit"></a> Issue Submission Guidelines
Before you submit your issue search the archive, maybe your question was already answered.
If your issue appears to be a bug, and hasn't been reported, open a new issue. Help us to maximize
the effort we can spend fixing issues and adding new features, by not reporting duplicate issues.
The "[new issue][github-new-issue]" form contains a number of prompts that you should fill out to
make it easier to understand and categorize the issue.
In general, providing the following information will increase the chances of your issue being dealt
with quickly:
* **Overview of the Issue** - if an error is being thrown a non-minified stack trace helps
* **Motivation for or Use Case** - explain why this is a bug for you
* **AngularJS Version(s)** - is it a regression?
* **Browsers and Operating System** - is this a problem with all browsers or only specific ones?
* **Reproduce the Error** - provide a live example (using [Plunker][plunker] or
[JSFiddle][jsfiddle]) or an unambiguous set of steps.
* **Related Issues** - has a similar issue been reported before?
* **Suggest a Fix** - if you can't fix the bug yourself, perhaps you can point to what might be
causing the problem (line of code or commit)
Here is a great example of a well defined issue: https://github.com/angular/angular.js/issues/5069.
**If you get help, help others. Good karma rulez!**
## <a name="submit-pr"></a> Pull Request Submission Guidelines
Before you submit your pull request consider the following guidelines:
* Search [GitHub](https://github.com/angular/angular.js/pulls) for an open or closed Pull Request
that relates to your submission. You don't want to duplicate effort.
* Create the [development environment][developers.setup]
* Make your changes in a new git branch:
```shell
git checkout -b my-fix-branch master
```
* Create your patch commit, **including appropriate test cases**.
* Follow our [Coding Rules][developers.rules].
* If the changes affect public APIs, change or add relevant [documentation][developers.documentation].
* Run the AngularJS [unit][developers.tests-unit] and [E2E test][developers.tests-e2e] suites, and ensure that all tests
pass. It is generally sufficient to run the tests only on Chrome, as our continuous integration test will
run the tests on additional browsers.
* Run `yarn grunt eslint` to check that you have followed the automatically enforced coding rules
* Commit your changes using a descriptive commit message that follows our
[commit message conventions][developers.commits]. Adherence to the
[commit message conventions][developers.commits] is required, because release notes are
automatically generated from these messages.
```shell
git commit -a
```
Note: the optional commit `-a` command line option will automatically "add" and "rm" edited files.
* Before creating the Pull Request, package and run all tests a last time:
```shell
yarn grunt test
```
* Push your branch to GitHub:
```shell
git push origin my-fix-branch
```
* In GitHub, send a pull request to `angular.js:master`. This will trigger the check of the
[Contributor License Agreement](#cla) and the continuous integration tests.
* If you find that the continuous integration tests have failed, look into the logs to find out
if your changes caused test failures, the commit message was malformed etc. If you find that the
tests failed or times out for unrelated reasons, you can ping a team member so that the build can be
restarted.
* If we suggest changes, then:
* Make the required updates.
* Re-run the AngularJS test suite to ensure tests are still passing.
* Commit your changes to your branch (e.g. `my-fix-branch`).
* Push the changes to your GitHub repository (this will update your Pull Request).
You can also amend the initial commits and force push them to the branch.
```shell
git rebase master -i
git push origin my-fix-branch -f
```
This is generally easier to follow, but separate commits are useful if the Pull Request contains
iterations that might be interesting to see side-by-side.
That's it! Thank you for your contribution!
#### After your pull request is merged
After your pull request is merged, you can safely delete your branch and pull the changes
from the main (upstream) repository:
* Delete the remote branch on GitHub either through the GitHub web UI or your local shell as follows:
```shell
git push origin --delete my-fix-branch
```
* Check out the master branch:
```shell
git checkout master -f
```
* Delete the local branch:
```shell
git branch -D my-fix-branch
```
* Update your master with the latest upstream version:
```shell
git pull --ff upstream master
```
## <a name="cla"></a> Signing the Contributor License Agreement (CLA)
Upon submmitting a Pull Request, a friendly bot will ask you to sign our CLA if you haven't done
so before. Unfortunately, this is necessary for documentation changes, too.
It's a quick process, we promise!
* For individuals we have a [simple click-through form][individual-cla].
* For corporations we'll need you to
[print, sign and one of scan+email, fax or mail the form][corporate-cla].
[Closure guide to i18n changes]: https://github.com/google/closure-library/wiki/Internationalization-%28i18n%29-changes-in-Closure-Library
[coc]: https://github.com/angular/code-of-conduct/blob/master/CODE_OF_CONDUCT.md
[Common Locale Data Repository (CLDR)]: http://cldr.unicode.org
[corporate-cla]: http://code.google.com/legal/corporate-cla-v1.0.html
[developers]: DEVELOPERS.md
[developers.commits]: DEVELOPERS.md#commits
[developers.documentation]: DEVELOPERS.md#documentation
[developers.rules]: DEVELOPERS.md#rules
[developers.setup]: DEVELOPERS.md#setup
[developers.tests-e2e]: DEVELOPERS.md#e2e-tests
[developers.tests-unit]: DEVELOPERS.md#unit-tests
[github-issues]: https://github.com/angular/angular.js/issues
[github-new-issue]: https://github.com/angular/angular.js/issues/new
[github]: https://github.com/angular/angular.js
[gitter]: https://gitter.im/angular/angular.js
[Google Closure I18N library]: https://github.com/google/closure-library/tree/master/closure/goog/i18n
[groups]: https://groups.google.com/forum/?fromgroups#!forum/angular
[individual-cla]: http://code.google.com/legal/individual-cla-v1.0.html
[irc]: http://webchat.freenode.net/?channels=angularjs&uio=d4
[jsfiddle]: http://jsfiddle.net/
[karma-browserstack]: https://github.com/karma-runner/karma-browserstack-launcher
[karma-saucelabs]: https://github.com/karma-runner/karma-sauce-launcher
[plunker]: http://plnkr.co/edit
[stackoverflow]: http://stackoverflow.com/questions/tagged/angularjs
[groups]: https://groups.google.com/forum/?fromgroups#!forum/angular
[irc]: http://webchat.freenode.net/?channels=angularjs&uio=d4
[template]: http://plnkr.co/edit/gist:3510140
[![Analytics](https://ga-beacon.appspot.com/UA-8594346-11/angular.js/CONTRIBUTING.md?pixel)](https://github.com/igrigorik/ga-beacon)
## Contributing to Source Code
We'd love for you to contribute to our source code and to make AngularJS even
better than it is today!
Please read the [contribution guidelines][contribute] to learn about how to submit code as well as
other useful info like how to build and test AngularJS code.
[list]: https://groups.google.com/forum/?fromgroups#!forum/angular
[contribute]: http://docs.angularjs.org/misc/contribute
-488
View File
@@ -1,488 +0,0 @@
# Developing AngularJS
* [Development Setup](#setup)
* [Running Tests](#tests)
* [Coding Rules](#rules)
* [Commit Message Guidelines](#commits)
* [Writing Documentation](#documentation)
## <a name="setup"> Development Setup
This document describes how to set up your development environment to build and test AngularJS, and
explains the basic mechanics of using `git`, `node`, `yarn` and `grunt`.
### Installing Dependencies
Before you can build AngularJS, you must install and configure the following dependencies on your
machine:
* [Git](http://git-scm.com/): The [Github Guide to
Installing Git][git-setup] is a good source of information.
* [Node.js v8.x (LTS)](http://nodejs.org): We use Node to generate the documentation, run a
development web server, run tests, and generate distributable files. Depending on your system,
you can install Node either from source or as a pre-packaged bundle.
We recommend using [nvm](https://github.com/creationix/nvm) (or
[nvm-windows](https://github.com/coreybutler/nvm-windows))
to manage and install Node.js, which makes it easy to change the version of Node.js per project.
* [Yarn](https://yarnpkg.com): We use Yarn to install our Node.js module dependencies
(rather than using npm). See the detailed [installation instructions][yarn-install].
* [Java](http://www.java.com): We minify JavaScript using
[Closure Tools](https://developers.google.com/closure/), which require Java (version 7 or higher)
to be installed and included in your
[PATH](http://docs.oracle.com/javase/tutorial/essential/environment/paths.html) variable.
* [Grunt](http://gruntjs.com): We use Grunt as our build system. We're using it as a local dependency,
but you can also add the grunt command-line tool globally (with `yarn global add grunt-cli`), which allows
you to leave out the `yarn` prefix for all our grunt commands.
### Forking AngularJS on Github
To contribute code to AngularJS, you must have a GitHub account so you can push code to your own
fork of AngularJS and open Pull Requests in the [GitHub Repository][github].
To create a Github account, follow the instructions [here](https://github.com/signup/free).
Afterwards, go ahead and [fork](http://help.github.com/forking) the
[main AngularJS repository][github].
### Building AngularJS
To build AngularJS, you clone the source code repository and use Grunt to generate the non-minified
and minified AngularJS files:
```shell
# Clone your Github repository:
git clone https://github.com/<github username>/angular.js.git
# Go to the AngularJS directory:
cd angular.js
# Add the main AngularJS repository as an upstream remote to your repository:
git remote add upstream "https://github.com/angular/angular.js.git"
# Install JavaScript dependencies:
yarn install
# Build AngularJS:
yarn grunt package
```
**Note:** If you're using Windows, you must use an elevated command prompt (right click, run as
Administrator). This is because `yarn grunt package` creates some symbolic links.
The build output is in the `build` directory. It consists of the following files and
directories:
* `angular-<version>.zip` — The complete zip file, containing all of the release build
artifacts.
* `angular.js` / `angular.min.js` — The regular and minified core AngularJS script file.
* `angular-*.js` / `angular-*.min.js` — All other AngularJS module script files.
* `docs/` — A directory that contains a standalone version of the docs
(same as served in `docs.angularjs.org`).
### <a name="local-server"></a> Running a Local Development Web Server
To debug code, run end-to-end tests, and serve the docs, it is often useful to have a local
HTTP server. For this purpose, we have made available a local web server based on Node.js.
1. To start the web server, run:
```shell
yarn grunt webserver
```
2. To access the local server, enter the following URL into your web browser:
```text
http://localhost:8000/
```
By default, it serves the contents of the AngularJS project directory.
3. To access the locally served docs, visit this URL:
```text
http://localhost:8000/build/docs/
```
## <a name="tests"> Running Tests
### <a name="unit-tests"></a> Running the Unit Test Suite
We write unit and integration tests with Jasmine and execute them with Karma. To run all of the
tests once on Chrome run:
```shell
yarn grunt test:unit
```
To run the tests on other browsers use the command line flag:
```shell
yarn grunt test:unit --browsers=Chrome,Firefox
```
**Note:** there should be _no spaces between browsers_. `Chrome, Firefox` is INVALID.
If you have a Saucelabs or Browserstack account, you can also run the unit tests on these services
via our pre-defined customLaunchers. See the [karma config file](/karma-shared.conf.js) for all pre-configured browsers.
For example, to run the whole unit test suite on selected browsers:
```shell
# Browserstack
yarn grunt test:unit --browsers=BS_Chrome,BS_Firefox,BS_Safari,BS_IE_9,BS_IE_10,BS_IE_11,BS_EDGE,BS_iOS_10
# Saucelabs
yarn grunt test:unit --browsers=SL_Chrome,SL_Firefox,SL_Safari,SL_IE_9,SL_IE_10,SL_IE_11,SL_EDGE,SL_iOS_10
```
Running these commands requires you to set up [Karma Browserstack][karma-browserstack] or
[Karma-Saucelabs][karma-saucelabs], respectively.
During development, however, it's more productive to continuously run unit tests every time the
source or test files change. To execute tests in this mode run:
1. To start the Karma server, capture Chrome browser and run unit tests, run:
```shell
yarn grunt autotest
```
2. To capture more browsers, open this URL in the desired browser (URL might be different if you
have multiple instance of Karma running, read Karma's console output for the correct URL):
```text
http://localhost:9876/
```
3. To re-run tests just change any source or test file.
To learn more about all of the preconfigured Grunt tasks run:
```shell
yarn grunt --help
```
### <a name="e2e-tests"></a> Running the End-to-end Test Suite
AngularJS's end to end tests are run with Protractor. Simply run:
```shell
yarn grunt test:e2e
```
This will start the webserver and run the tests on Chrome.
## <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].
* All public API methods **must be documented** with ngdoc, an extended version of jsdoc (we added
support for markdown and templating via @ngdoc tag). To see how we document our APIs, please check
out the existing source code and see the section about [writing documentation](#documentation)
* With the exceptions listed below, we follow the rules contained in
[Google's JavaScript Style Guide][js-style-guide]:
* **Do not use namespaces**: Instead, wrap the entire AngularJS code base in an anonymous
closure and export our API explicitly rather than implicitly.
* Wrap all code at **100 characters**.
* Instead of complex inheritance hierarchies, we **prefer simple objects**. We use prototypal
inheritance only when absolutely necessary.
* We **love functions and closures** and, whenever possible, prefer them over objects.
* To write concise code that can be better minified, we **use aliases internally** that map to
the external API. See our existing code to see what we mean.
* We **don't go crazy with type annotations** for private internal APIs unless it's an internal
API that is used throughout AngularJS. The best guidance is to do what makes the most sense.
### Specific topics
#### Provider configuration
When adding configuration (options) to [providers][docs.provider], we follow a special pattern.
- for each option, add a `method` that ...
- works as a getter and returns the current value when called without argument
- works as a setter and returns itself for chaining when called with argument
- for boolean options, uses the naming scheme `<option>Enabled([enabled])`
- non-primitive options (e.g. objects) should be copied or the properties assigned explicitly to a
new object so that the configuration cannot be changed during runtime.
For a boolean config example, see [`$compileProvider#debugInfoEnabled`][code.debugInfoEnabled]
For an object config example, see [`$location.html5Mode`][code.html5Mode]
#### Throwing errors
User-facing errors should be thrown with [`minErr`][code.minErr], a special error function that provides
errors ids, templated error messages, and adds a link to a detailed error description.
The `$compile:badrestrict` error is a good example for a well-defined `minErr`:
[code][code.badrestrict] and [description][docs.badrestrict].
## <a name="commits"></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,
we use the git commit messages to **generate the AngularJS change log**.
The commit message formatting can be added using a typical git workflow or through the use of a CLI
wizard ([Commitizen](https://github.com/commitizen/cz-cli)). To use the wizard, run `yarn run commit`
in your terminal after staging your changes in git.
### Commit Message Format
Each commit message consists of a **header**, a **body** and a **footer**. The header has a special
format that includes a **type**, a **scope** and a **subject**:
```
<type>(<scope>): <subject>
<BLANK LINE>
<body>
<BLANK LINE>
<footer>
```
The **header** is mandatory and the **scope** of the header is optional.
Any line of the commit message cannot be longer than 100 characters! This allows the message to be easier
to read on GitHub as well as in various git tools.
### Revert
If the commit reverts a previous commit, it should begin with `revert: `, followed by the header
of the reverted commit.
In the body it should say: `This reverts commit <hash>.`, where the hash is the SHA of the commit
being reverted.
### Type
Must be one of the following:
* **feat**: A new feature
* **fix**: A bug fix
* **docs**: Documentation only changes
* **style**: Changes that do not affect the meaning of the code (white-space, formatting, missing
semi-colons, etc)
* **refactor**: A code change that neither fixes a bug nor adds a feature
* **perf**: A code change that improves performance
* **test**: Adding missing or correcting existing tests
* **chore**: Changes to the build process or auxiliary tools and libraries such as documentation
generation
### Scope
The scope could be anything specifying place of the commit change. For example `$location`,
`$browser`, `$compile`, `$rootScope`, `ngHref`, `ngClick`, `ngView`, etc...
You can use `*` when the change affects more than a single scope.
### Subject
The subject contains succinct description of the change:
* use the imperative, present tense: "change" not "changed" nor "changes"
* don't capitalize first letter
* no dot (.) at the end
### Body
Just as in the **subject**, use the imperative, present tense: "change" not "changed" nor "changes".
The body should include the motivation for the change and contrast this with previous behavior.
### Footer
The footer should contain any information about **Breaking Changes** and is also the place to
[reference GitHub issues that this commit closes][closing-issues].
**Breaking Changes** should start with the word `BREAKING CHANGE:` with a space or two newlines.
The rest of the commit message is then used for this.
A detailed explanation can be found in this [document][commit-message-format].
## <a name="documentation"></a> Writing Documentation
The AngularJS project uses a form of [jsdoc](http://usejsdoc.org/) called ngdoc for all of its code
documentation.
This means that all the docs are stored inline in the source code and so are kept in sync as it
changes.
There is also extra content (the developer guide, error pages, the tutorial,
and misceallenous pages) that live inside the AngularJS repository as markdown files.
This means that since we generate the documentation from the source code, we can easily provide
version-specific documentation by simply checking out a version of AngularJS and running the build.
Extracting the source code documentation, processing and building the docs is handled by the
documentation generation tool [Dgeni][dgeni].
### Building and viewing the docs locally
The docs can be built from scratch using grunt:
```shell
yarn grunt docs
```
This defers the doc-building task to `gulp`.
Note that the docs app is using the local build files to run. This means you might first have to run
the build:
```shell
yarn grunt build
```
(This is also necessary if you are making changes to minErrors).
To view the docs, see [Running a Local Development Web Server](#local-server).
### Writing jsdoc
The ngdoc utility has basic support for many of the standard jsdoc directives. But in particular it
is interested in the following block tags:
* `@name name` - the name of the ngdoc document
* `@param {type} name description` - describes a parameter of a function
* `@returns {type} description` - describes what a function returns
* `@requires` - normally indicates that a JavaScript module is required; in an Angular service it is
used to describe what other services this service relies on
* `@property` - describes a property of an object
* `@description` - used to provide a description of a component in markdown
* `@link` - specifies a link to a URL or a type in the API reference.
Links to the API have the following structure:
* the module namespace, followed by `.` (optional, default `ng`)
* the `@ngdoc` type (see below), followed by `:` (optional, automatically inferred)
* the name
* the method, property, or anchor (optional)
* the display name
For example: `{@link ng.type:$rootScope.Scope#$new Scope.$new()}`.
* `@example` - specifies an example. This can be a simple code block, or a
[runnable example](#the-example-tag).
* `@deprecated` - specifies that the following code is deprecated and should not be used.
In The AngularJS docs, there are two specific patterns which can be used to further describe
the deprecation: `sinceVersion="<version>"` and `removeVersion="<version>"`
The `type` in `@param` and `@returns` must be wrapped in `{}` curly braces, e.g. `{Object|Array}`.
Parameters can be made optional by *either* appending a `=` to the type, e.g. `{Object=}`, *or* by
putting the `[name]` in square brackets.
Default values are only possible with the second syntax by appending `=<value>` to the parameter
name, e.g. `@param {boolean} [ownPropsOnly=false]`.
Descriptions can contain markdown formatting.
#### AngularJS-specific jsdoc directives
In addition to the standard jsdoc tags, there are a number that are specific to the Angular
code-base:
* `@ngdoc` - specifies the type of thing being documented. See below for more detail.
* `@eventType emit|broadcast` - specifies whether the event is emitted or broadcast
* `@usage` - shows how to use a `function` or `directive`. Is usually automatically generated.
* `@knownIssue` - adds info about known quirks, problems, or limitations with the API, and possibly,
workarounds. This section is not for bugs.
The following are specific to directives:
* `@animations` - specifies the animations a directive supports
* `@multiElement` - specifies if a directive can span over multiple elements
* `@priority` - specifies a directive's priority
* `@restrict` - is extracted to show the usage of a directive. For example, for [E]lement,
[A]ttribute, and [C]lass, use `@restrict ECA`
* `@scope` - specifies that a directive will create a new scope
### The `@ngdoc` Directive
This directive helps to specify the template used to render the item being documented. For instance,
a directive would have different properties to a filter and so would be documented differently. The
commonly used types are:
* `overview` - a general page (guide, api index)
* `provider` - AngularJS provider, such as `$compileProvider` or `$httpProvider`.
* `service` - injectable AngularJS service, such as `$compile` or `$http`.
* `object` - well defined object (often exposed as a service)
* `function` - function that will be available to other methods (such as a helper function within
the ng module)
* `method` - method on an object/service/controller
* `property` - property on an object/service/controller
* `event` - AngularJS event that will propagate through the `$scope` tree.
* `directive` - AngularJS directive
* `filter` - AngularJS filter
* `error` - minErr error description
### General documentation with Markdown
Any text in tags can contain markdown syntax for formatting. Generally, you can use any markdown
feature.
#### Headings
Only use *h2* headings and lower, as the page title is set in *h1*. Also make sure you follow the
heading hierarchy. This ensures correct table of contents are created.
#### Code blocks
In line code can be specified by enclosing the code in back-ticks (\`).
A block of multi-line code can be enclosed in triple back-ticks (\`\`\`) but it is formatted better
if it is enclosed in &lt;pre&gt;...&lt;/pre&gt; tags and the code lines themselves are indented.
### Writing runnable (live) examples and e2e tests
It is possible to embed examples in the documentation along with appropriate e2e tests. These
examples and scenarios will be converted to runnable code within the documentation. So it is
important that they work correctly. To ensure this, all these e2e scenarios are run as part of the
continuous integration tests.
If you are adding an example with an e2e test, you should [run the test locally](#e2e-tests) first
to ensure it passes. You can change `it(...)` to `fit(...)` to run only your test,
but make sure you change it back to `it(...)` before committing.
#### The `<example>` tag
This tag identifies a block of HTML that will define a runnable example. It can take the following
attributes:
* `animations` - if set to `true` then this example uses ngAnimate.
* `deps` - Semicolon-separated list of additional angular module files to be loaded,
e.g. `angular-animate.js`
* `name` - every example should have a name. It should start with the component, e.g directive name,
and not contain whitespace
* `module` - the name of the app module as defined in the example's JavaScript
Within this tag we provide `<file>` tags that specify what files contain the example code.
```
<example
module="angularAppModule"
name="exampleName"
deps="angular-animate.js;angular-route.js"
animations="true">
...
<file name="index.html">...</file>
<file name="script.js">...</file>
<file name="animations.css">...</file>
<file name="protractor.js">...</file>
...
</example>
```
You can see an example of a well-defined example [in the `ngRepeat` documentation][code.ngRepeat-example].
[closing-issues]: https://help.github.com/articles/closing-issues-via-commit-messages/
[Closure guide to i18n changes]: https://github.com/google/closure-library/wiki/Internationalization-%28i18n%29-changes-in-Closure-Library
[code.badrestrict]: https://github.com/angular/angular.js/blob/202f1809ad14827a6ac6a125157c605d65e0b551/src/ng/compile.js#L1107-L1110
[code.debugInfoEnabled]: https://github.com/angular/angular.js/blob/32fbb2e78f53d765fbb170f7cf99e42e072d363b/src/ng/compile.js#L1378-L1413
[code.html5Mode]: https://github.com/angular/angular.js/blob/202f1809ad14827a6ac6a125157c605d65e0b551/src/ng/location.js#L752-L797
[code.minErr]: https://github.com/angular/angular.js/blob/202f1809ad14827a6ac6a125157c605d65e0b551/src/minErr.js#L53-L113
[code.ngRepeat-example]: https://github.com/angular/angular.js/blob/0822d34b10ea0371c260c80a1486a4d508ea5a91/src/ng/directive/ngRepeat.js#L249-L340
[commit-message-format]: https://docs.google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y/edit#
[Common Locale Data Repository (CLDR)]: http://cldr.unicode.org
[corporate-cla]: http://code.google.com/legal/corporate-cla-v1.0.html
[dgeni]: https://github.com/angular/dgeni
[docs.badrestrict]: docs/content/error/$compile/badrestrict.ngdoc
[docs.provider]: https://code.angularjs.org/snapshot/docs/api/auto/service/$provide#provider
[git-revert]: https://git-scm.com/docs/git-revert
[git-setup]: https://help.github.com/articles/set-up-git
[github-issues]: https://github.com/angular/angular.js/issues
[github]: https://github.com/angular/angular.js
[js-style-guide]: https://google.github.io/styleguide/javascriptguide.xml
[karma-browserstack]: https://github.com/karma-runner/karma-browserstack-launcher
[karma-saucelabs]: https://github.com/karma-runner/karma-sauce-launcher
[unit-testing]: https://docs.angularjs.org/guide/unit-testing
[yarn-install]: https://yarnpkg.com/en/docs/install
-535
View File
@@ -1,535 +0,0 @@
'use strict';
var serveFavicon = require('serve-favicon');
var serveStatic = require('serve-static');
var serveIndex = require('serve-index');
var files = require('./angularFiles').files;
var mergeFilesFor = require('./angularFiles').mergeFilesFor;
var util = require('./lib/grunt/utils.js');
var versionInfo = require('./lib/versions/version-info');
var path = require('path');
var e2e = require('./test/e2e/tools');
var semver = require('semver');
var exec = require('shelljs').exec;
var pkg = require(__dirname + '/package.json');
var codeScriptFolder = util.codeScriptFolder;
var docsScriptFolder = util.docsScriptFolder;
// Node.js version checks
if (!semver.satisfies(process.version, pkg.engines.node)) {
reportOrFail('Invalid node version (' + process.version + '). ' +
'Please use a version that satisfies ' + pkg.engines.node);
}
// Yarn version checks
var expectedYarnVersion = pkg.engines.yarn;
var currentYarnVersion = exec('yarn --version', {silent: true}).stdout.trim();
if (!semver.satisfies(currentYarnVersion, expectedYarnVersion)) {
reportOrFail('Invalid yarn version (' + currentYarnVersion + '). ' +
'Please use a version that satisfies ' + expectedYarnVersion);
}
// Grunt CLI version checks
var expectedGruntVersion = pkg.engines['grunt-cli'];
var currentGruntVersions = exec('grunt --version', {silent: true}).stdout;
var match = /^grunt-cli v(.+)$/m.exec(currentGruntVersions);
if (!match) {
reportOrFail('Unable to compute the current grunt-cli version. We found:\n' +
currentGruntVersions);
} else {
if (!semver.satisfies(match[1], expectedGruntVersion)) {
reportOrFail('Invalid grunt-cli version (' + match[1] + '). ' +
'Please use a version that satisfies ' + expectedGruntVersion);
}
}
// Ensure Node.js dependencies have been installed
if (!process.env.CI) {
var yarnOutput = exec('yarn install');
if (yarnOutput.code !== 0) {
throw new Error('Yarn install failed: ' + yarnOutput.stderr);
}
}
module.exports = function(grunt) {
// this loads all the node_modules that start with `grunt-` as plugins
require('load-grunt-tasks')(grunt);
// load additional grunt tasks
grunt.loadTasks('lib/grunt');
grunt.loadNpmTasks('angular-benchpress');
// compute version related info for this build
var NG_VERSION = versionInfo.currentVersion;
NG_VERSION.cdn = versionInfo.cdnVersion;
var dist = 'angular-' + NG_VERSION.full;
var deployVersion = NG_VERSION.full;
if (NG_VERSION.isSnapshot) {
deployVersion = NG_VERSION.distTag === 'latest' ? 'snapshot-stable' : 'snapshot';
}
if (versionInfo.cdnVersion == null) {
throw new Error('Unable to read CDN version, are you offline or has the CDN not been properly pushed?\n' +
'Perhaps you want to set the NG1_BUILD_NO_REMOTE_VERSION_REQUESTS environment variable?');
}
//config
grunt.initConfig({
NG_VERSION: NG_VERSION,
bp_build: {
options: {
buildPath: 'build/benchmarks',
benchmarksPath: 'benchmarks'
}
},
connect: {
devserver: {
options: {
port: 8000,
hostname: '0.0.0.0',
base: '.',
keepalive: true,
middleware: function(connect, options) {
var base = Array.isArray(options.base) ? options.base[options.base.length - 1] : options.base;
return [
util.conditionalCsp(),
util.rewrite(),
e2e.middleware(),
serveFavicon('images/favicon.ico'),
serveStatic(base),
serveIndex(base)
];
}
}
},
testserver: {
options: {
// We start the webserver as a separate process from the E2E tests
port: 8000,
hostname: '0.0.0.0',
middleware: function(connect, options) {
var base = Array.isArray(options.base) ? options.base[options.base.length - 1] : options.base;
return [
function(req, resp, next) {
// cache GET requests to speed up tests
if (req.method === 'GET') {
resp.setHeader('Cache-control', 'public, max-age=3600');
}
next();
},
util.conditionalCsp(),
e2e.middleware(),
serveFavicon('images/favicon.ico'),
serveStatic(base)
];
}
}
}
},
tests: {
jqlite: 'karma-jqlite.conf.js',
jquery: 'karma-jquery.conf.js',
'jquery-2.2': 'karma-jquery-2.2.conf.js',
'jquery-2.1': 'karma-jquery-2.1.conf.js',
docs: 'karma-docs.conf.js',
modules: 'karma-modules.conf.js',
'modules-ngAnimate': 'karma-modules-ngAnimate.conf.js',
'modules-ngMock': 'karma-modules-ngMock.conf.js'
},
autotest: {
jqlite: 'karma-jqlite.conf.js',
jquery: 'karma-jquery.conf.js',
'jquery-2.2': 'karma-jquery-2.2.conf.js',
'jquery-2.1': 'karma-jquery-2.1.conf.js',
modules: 'karma-modules.conf.js',
docs: 'karma-docs.conf.js'
},
protractor: {
normal: 'protractor-conf.js',
circleci: 'protractor-circleci-conf.js'
},
clean: {
build: ['build'],
tmp: ['tmp'],
deploy: [
codeScriptFolder + '/deploy',
docsScriptFolder + '/deploy',
docsScriptFolder + '/functions/content'
]
},
eslint: {
all: {
src: [
'*.js',
'benchmarks/**/*.js',
'docs/**/*.js',
'lib/**/*.js',
'scripts/**/*.js',
'!scripts/*/*/node_modules/**',
'src/**/*.js',
'test/**/*.js',
'i18n/**/*.js',
'!docs/app/assets/js/angular-bootstrap/**',
'!docs/config/templates/**',
'!src/angular.bind.js',
'!i18n/closure/**',
'!src/ngParseExt/ucd.js'
]
}
},
build: {
angular: {
dest: 'build/angular.js',
src: util.wrap([files['angularSrc']], 'angular'),
styles: {
css: ['css/angular.css'],
generateCspCssFile: true,
minify: true
}
},
loader: {
dest: 'build/angular-loader.js',
src: util.wrap(files['angularLoader'], 'loader')
},
touch: {
dest: 'build/angular-touch.js',
src: util.wrap(files['angularModules']['ngTouch'], 'module')
},
touchModuleTestBundle: {
dest: 'build/test-bundles/angular-touch.js',
prefix: 'src/module.prefix',
src: mergeFilesFor('karmaModules-ngTouch'),
suffix: 'src/module.suffix'
},
mocks: {
dest: 'build/angular-mocks.js',
src: util.wrap(files['angularModules']['ngMock'], 'module'),
strict: false
},
sanitize: {
dest: 'build/angular-sanitize.js',
src: util.wrap(files['angularModules']['ngSanitize'], 'module')
},
sanitizeModuleTestBundle: {
dest: 'build/test-bundles/angular-sanitize.js',
prefix: 'src/module.prefix',
src: mergeFilesFor('karmaModules-ngSanitize'),
suffix: 'src/module.suffix'
},
resource: {
dest: 'build/angular-resource.js',
src: util.wrap(files['angularModules']['ngResource'], 'module')
},
resourceModuleTestBundle: {
dest: 'build/test-bundles/angular-resource.js',
prefix: 'src/module.prefix',
src: mergeFilesFor('karmaModules-ngResource'),
suffix: 'src/module.suffix'
},
messageformat: {
dest: 'build/angular-message-format.js',
src: util.wrap(files['angularModules']['ngMessageFormat'], 'module')
},
messageformatModuleTestBundle: {
dest: 'build/test-bundles/angular-message-format.js',
prefix: 'src/module.prefix',
src: mergeFilesFor('karmaModules-ngMessageFormat'),
suffix: 'src/module.suffix'
},
messages: {
dest: 'build/angular-messages.js',
src: util.wrap(files['angularModules']['ngMessages'], 'module')
},
messagesModuleTestBundle: {
dest: 'build/test-bundles/angular-messages.js',
prefix: 'src/module.prefix',
src: mergeFilesFor('karmaModules-ngMessages'),
suffix: 'src/module.suffix'
},
animate: {
dest: 'build/angular-animate.js',
src: util.wrap(files['angularModules']['ngAnimate'], 'module')
},
route: {
dest: 'build/angular-route.js',
src: util.wrap(files['angularModules']['ngRoute'], 'module')
},
routeModuleTestBundle: {
dest: 'build/test-bundles/angular-route.js',
prefix: 'src/module.prefix',
src: mergeFilesFor('karmaModules-ngRoute'),
suffix: 'src/module.suffix'
},
cookies: {
dest: 'build/angular-cookies.js',
src: util.wrap(files['angularModules']['ngCookies'], 'module')
},
cookiesModuleTestBundle: {
dest: 'build/test-bundles/angular-cookies.js',
prefix: 'src/module.prefix',
src: mergeFilesFor('karmaModules-ngCookies'),
suffix: 'src/module.suffix'
},
aria: {
dest: 'build/angular-aria.js',
src: util.wrap(files['angularModules']['ngAria'], 'module')
},
ariaModuleTestBundle: {
dest: 'build/test-bundles/angular-aria.js',
prefix: 'src/module.prefix',
src: mergeFilesFor('karmaModules-ngAria'),
suffix: 'src/module.suffix'
},
parseext: {
dest: 'build/angular-parse-ext.js',
src: util.wrap(files['angularModules']['ngParseExt'], 'module')
},
'promises-aplus-adapter': {
dest:'tmp/promises-aplus-adapter++.js',
src:['src/ng/q.js', 'lib/promises-aplus/promises-aplus-test-adapter.js']
}
},
min: {
angular: 'build/angular.js',
animate: 'build/angular-animate.js',
cookies: 'build/angular-cookies.js',
loader: 'build/angular-loader.js',
messageformat: 'build/angular-message-format.js',
messages: 'build/angular-messages.js',
touch: 'build/angular-touch.js',
resource: 'build/angular-resource.js',
route: 'build/angular-route.js',
sanitize: 'build/angular-sanitize.js',
aria: 'build/angular-aria.js',
parseext: 'build/angular-parse-ext.js'
},
'ddescribe-iit': {
files: [
'src/**/*.js',
'test/**/*.js',
'!src/ng/directive/attrs.js', // legitimate xit here
'!test/helpers/privateMocks*.js'
],
options: {
disallowed: [
'fit',
'iit',
'xit',
'fthey',
'tthey',
'xthey',
'fdescribe',
'ddescribe',
'xdescribe',
'it.only',
'describe.only'
]
}
},
'merge-conflict': {
files: [
'src/**/*',
'test/**/*',
'docs/**/*',
'css/**/*'
]
},
copy: {
i18n: {
files: [
{
src: 'src/ngLocale/**',
dest: 'build/i18n/',
expand: true,
flatten: true
}
]
},
deployFirebaseCode: {
files: [
{
cwd: 'build',
src: '**',
dest: codeScriptFolder + '/deploy/' + deployVersion + '/',
expand: true
}
]
},
deployFirebaseDocs: {
files: [
// The source files are needed by the embedded examples in the docs app.
{
src: ['build/angular*.{js,js.map,min.js}', 'build/sitemap.xml'],
dest: docsScriptFolder + '/deploy/',
expand: true,
flatten: true
},
{
cwd: 'build/docs',
src: ['**', '!ptore2e/**', '!index*.html'],
dest: docsScriptFolder + '/deploy/',
expand: true
},
{
src: 'build/docs/index-production.html',
dest: docsScriptFolder + '/deploy/index.html'
},
{
src: 'build/docs/index-production.html',
dest: docsScriptFolder + '/functions/content/index.html'
},
{
cwd: 'build/docs',
src: 'partials/**',
dest: docsScriptFolder + '/functions/content/',
expand: true
}
]
}
},
compress: {
build: {
options: {archive: 'build/' + dist + '.zip', mode: 'zip'},
src: ['**'],
cwd: 'build',
expand: true,
dot: true,
dest: dist + '/'
}
},
shell: {
'install-node-dependencies': {
command: 'yarn'
},
'promises-aplus-tests': {
options: {
stdout: false,
stderr: true,
failOnError: true
},
command: path.normalize('./node_modules/.bin/promises-aplus-tests tmp/promises-aplus-adapter++.js --timeout 2000')
}
},
write: {
versionTXT: {file: 'build/version.txt', val: NG_VERSION.full},
versionJSON: {file: 'build/version.json', val: JSON.stringify(NG_VERSION)}
},
bump: {
options: {
files: ['package.json'],
commit: false,
createTag: false,
push: false
}
}
});
//alias tasks
grunt.registerTask('test', 'Run unit, docs and e2e tests with Karma', [
'eslint',
'package',
'test:unit',
'test:promises-aplus',
'tests:docs',
'test:protractor'
]);
grunt.registerTask('test:jqlite', 'Run the unit tests with Karma' , ['tests:jqlite']);
grunt.registerTask('test:jquery', 'Run the jQuery (latest) unit tests with Karma', ['tests:jquery']);
grunt.registerTask('test:jquery-2.2', 'Run the jQuery 2.2 unit tests with Karma', ['tests:jquery-2.2']);
grunt.registerTask('test:jquery-2.1', 'Run the jQuery 2.1 unit tests with Karma', ['tests:jquery-2.1']);
grunt.registerTask('test:modules', 'Run the Karma module tests with Karma', [
'build',
'tests:modules',
'tests:modules-ngAnimate',
'tests:modules-ngMock'
]);
grunt.registerTask('test:docs', 'Run the doc-page tests with Karma', ['package', 'tests:docs']);
grunt.registerTask('test:unit', 'Run unit, jQuery and Karma module tests with Karma', [
'test:jqlite',
'test:jquery',
'test:jquery-2.2',
'test:jquery-2.1',
'test:modules'
]);
grunt.registerTask('test:protractor', 'Run the end to end tests with Protractor and keep a test server running in the background', [
'webdriver',
'connect:testserver',
'protractor:normal'
]);
grunt.registerTask('test:circleci-protractor', 'Run the end to end tests with Protractor for CircleCI builds', [
'connect:testserver',
'protractor:circleci'
]);
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', [
'clean',
'build',
'minall'
]);
grunt.registerTask('webserver', ['connect:devserver']);
grunt.registerTask('package', [
'validate-angular-files',
'clean',
'buildall',
'minall',
'collect-errors',
'write',
'docs',
'copy:i18n',
'compress:build'
]);
grunt.registerTask('ci-checks', [
'ddescribe-iit',
'merge-conflict',
'eslint'
]);
grunt.registerTask('prepareDeploy', [
'copy:deployFirebaseCode',
'copy:deployFirebaseDocs'
]);
grunt.registerTask('default', ['package']);
};
function reportOrFail(message) {
if (process.env.CI) {
throw new Error(message);
} else {
console.log('===============================================================================');
console.log(message);
console.log('===============================================================================');
}
}
+1 -1
View File
@@ -1,6 +1,6 @@
The MIT License
Copyright (c) 2010-2020 Google LLC. http://angularjs.org
Copyright (c) 2010-2012 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
-23
View File
@@ -1,23 +0,0 @@
Using AngularJS with the Closure Compiler
=========================================
The Closure Compiler project contains definitions for the AngularJS JavaScript
in its `contrib/externs` directory.
The definitions contain externs for use with the Closure compiler (aka
JSCompiler). Passing these files to the --externs parameter of a compiler
pass allows using type annotations for AngularJS objects. For example,
AngularJS's $scope objects can be annotated as:
```js
/** @type {angular.Scope} */
var scope = $scope;
```
This allows JSCompiler to type check accesses to scope, give warnings about
missing methods or incorrect arguments, and also prevents renaming of property
accesses with advanced compilation.
The externs are incomplete and maintained on an as-needed basis, but strive to
be correct. Externs for individual modules should be added in separate files.
See https://developers.google.com/closure/compiler/
+25 -93
View File
@@ -1,109 +1,41 @@
AngularJS [![CircleCI](https://circleci.com/gh/angular/angular.js/tree/master.svg?style=shield)](https://circleci.com/gh/angular/workflows/angular.js/tree/master)
AngularJS
=========
AngularJS lets you write client-side web applications as if you had a smarter browser. It lets you
use good old HTML (or HAML, Jade/Pug and friends!) as your template language and lets you extend HTMLs
use good old HTML (or HAML, Jade and friends!) as your template language and lets you extend HTMLs
syntax to express your applications components clearly and succinctly. It automatically
synchronizes data from your UI (view) with your JavaScript objects (model) through 2-way data
binding. To help you structure your application better and make it easy to test, AngularJS teaches
the browser how to do dependency injection and inversion of control.
the browser how to do dependency injection and inversion of control. Oh yeah and it also helps with
server-side communication, taming async callbacks with promises and deferreds; and make client-side
navigation and deeplinking with hashbang urls or HTML5 pushState a piece of cake. The best of all:
it makes development fun!
It also helps with server-side communication, taming async callbacks with promises and deferred objects,
and it makes client-side navigation and deep linking with hashbang urls or HTML5 pushState a
piece of cake. Best of all? It makes development fun!
* Web site: http://angularjs.org
* Tutorial: http://docs.angularjs.org/tutorial
* API Docs: http://docs.angularjs.org/api
* Developer Guide: http://docs.angularjs.org/guide
* Contribution guidelines: http://docs.angularjs.org/misc/contribute
--------------------
**AngularJS support has officially ended as of January 2022.
[See what ending support means](https://docs.angularjs.org/misc/version-support-status)
and [read the end of life announcement](https://goo.gle/angularjs-end-of-life).**
**Visit [angular.io](https://angular.io) for the actively supported Angular.**
--------------------
* Web site: https://angularjs.org
* Tutorial: https://docs.angularjs.org/tutorial
* API Docs: https://docs.angularjs.org/api
* Developer Guide: https://docs.angularjs.org/guide
* Contribution guidelines: [CONTRIBUTING.md](CONTRIBUTING.md)
* Core Development: [DEVELOPERS.md](DEVELOPERS.md)
* Dashboard: https://dashboard.angularjs.org
Documentation
--------------------
Go to https://docs.angularjs.org
Contribute
--------------------
We've set up a separate document for our
[contribution guidelines](https://github.com/angular/angular.js/blob/master/CONTRIBUTING.md).
Develop
--------------------
We've set up a separate document for
[developers](https://github.com/angular/angular.js/blob/master/DEVELOPERS.md).
[![Analytics](https://ga-beacon.appspot.com/UA-8594346-11/angular.js/README.md?pixel)](https://github.com/igrigorik/ga-beacon)
What to use AngularJS for and when to use it
Building AngularJS
---------
AngularJS is the next generation framework where each component is designed to work with every other
component in an interconnected way like a well-oiled machine. AngularJS is JavaScript MVC made easy
and done right. (Well it is not really MVC, read on, to understand what this means.)
[Once you have your environment setup](http://docs.angularjs.org/misc/contribute) just run:
#### MVC, no, MV* done the right way!
[MVC](https://en.wikipedia.org/wiki/Model%E2%80%93view%E2%80%93controller), short for
Model-View-Controller, is a design pattern, i.e. how the code should be organized and how the
different parts of an application separated for proper readability and debugging. Model is the data
and the database. View is the user interface and what the user sees. Controller is the main link
between Model and View. These are the three pillars of major programming frameworks present on the
market today. On the other hand AngularJS works on MV*, short for Model-View-_Whatever_. The
_Whatever_ is AngularJS's way of telling that you may create any kind of linking between the Model
and the View here.
rake package
Unlike other frameworks in any programming language, where MVC, the three separate components, each
one has to be written and then connected by the programmer, AngularJS helps the programmer by asking
him/her to just create these and everything else will be taken care of by AngularJS.
#### Interconnection with HTML at the root level
AngularJS uses HTML to define the user's interface. AngularJS also enables the programmer to write
new HTML tags (AngularJS Directives) and increase the readability and understandability of the HTML
code. Directives are AngularJSs way of bringing additional functionality to HTML. Directives
achieve this by enabling us to invent our own HTML elements. This also helps in making the code DRY
(Don't Repeat Yourself), which means once created, a new directive can be used anywhere within the
application.
Running Tests
-------------
To execute all unit tests, use:
HTML is also used to determine the wiring of the app. Special attributes in the HTML determine where
to load the app, which components or controllers to use for each element, etc. We specify "what"
gets loaded, but not "how". This declarative approach greatly simplifies app development in a sort
of WYSIWYG way. Rather than spending time on how the program flows and orchestrating the various
moving parts, we simply define what we want and AngularJS will take care of the dependencies.
rake test:unit
#### Data Handling made simple
Data and Data Models in AngularJS are plain JavaScript objects and one can add and change properties
directly on it and loop over objects and arrays at will.
To execute end-to-end (e2e) tests, use:
#### Two-way Data Binding
One of AngularJS's strongest features. Two-way Data Binding means that if something changes in the
Model, the change gets reflected in the View instantaneously, and the same happens the other way
around. This is also referred to as Reactive Programming, i.e. suppose `a = b + c` is being
programmed and after this, if the value of `b` and/or `c` is changed then the value of `a` will be
automatically updated to reflect the change. AngularJS uses its "scopes" as a glue between the Model
and View and makes these updates in one available for the other.
rake package
rake webserver &
rake test:e2e
#### Less Written Code and Easily Maintainable Code
Everything in AngularJS is created to enable the programmer to end up writing less code that is
easily maintainable and readable by any other new person on the team. Believe it or not, one can
write a complete working two-way data binded application in less than 10 lines of code. Try and see
for yourself!
#### Testing Ready
AngularJS has Dependency Injection, i.e. it takes care of providing all the necessary dependencies
to its controllers and services whenever required. This helps in making the AngularJS code ready for
unit testing by making use of mock dependencies created and injected. This makes AngularJS more
modular and easily testable thus in turn helping a team create more robust applications.
To learn more about the rake tasks, run `rake -T` and also read our
[contribution guidelines](http://docs.angularjs.org/misc/contribute) and instructions in this
[commit message](https://github.com/angular/angular.js/commit/9d168f058f9c6d7eeae0daa7cb72ea4e02a0003a).
-98
View File
@@ -1,98 +0,0 @@
# AngularJS Release instructions
## Compare the list of commits between stable and unstable
There is a script - compare-master-to-stable.js - that helps with this.
We just want to make sure that good commits (low risk fixes + docs fixes) got cherry-picked into stable branch and nothing interesting got merged only into stable branch.
## Pick a release name (for this version)
A super-heroic power (adverb-verb phrase).
## Generate release notes
Example Commit: https://github.com/angular/angular.js/commit/7ab5098c14ee4f195dbfe2681e402fe2dfeacd78
1) Run
```bash
node_modules/.bin/changez -o changes.md -v <new version> <base branch>
```
2) Review the generated file and manually fix typos, group and reorder stuff if needed.
3) Move the content into CHANGELOG.md add release code-names to headers.
4) Push the changes to your private github repo and review.
5) cherry-pick the release notes commit to the appropriate branches.
## Pick a commit to release (for this version)
Usually this will be the commit containing the release notes, but it may also be in the past.
## Run "release" script
```bash
scripts/release/release.sh --git-push-dryrun=false --commit-sha=8822a4f --version-number=1.7.6 --version-name=gravity-manipulation
```
1) The SHA is of the commit to release (could be in the past).
2) The version number and code-name that should be released, not the next version number (e.g. to release 1.2.12 you enter 1.2.12 as release version and the code-name that was picked for 1.2.12, cauliflower-eradication).
3) You will need to have write access to all the AngularJS github dist repositories and publish rights for the AngularJS packages on npm.
## Update GitHub milestones
1) Create the next milestone if it doesn't exist yet-giving ita due date.
2) Move all open issues and PRs for the current milestone to the next milestone<br>
You can do this by filtering the current milestone, selecting via checklist, and moving to the next milestone within the GH issues page.
3) Close the current milestone click the milestones tab and close from there.
4) Create a new holding milestone for the release after next-but don't give it a due date otherwise that will mess up the dashboard.
## Push build artifacts to CDN
Google CDNs are fed with data from google3 every day at 11:15am PT it takes only few minutes for the import to propagate).
If we want to make our files available, we need submit our CLs before this time on the day of the release.
## Don't update the package.json (branchVersion) until the CDN has updated
This is the version used to compute what version to link to in the CDN. If you update this too early then the CDN lookup fails and you end up with 'null, for the version, which breaks the docs.
## Verify angularjs.org download modal has latest version (updates via CI job)
The versions in the modal are updated (based on the versions available on CDN) as part of the CI deploy stage.
(You may need to explicitly trigger the CI job. e.g. re-running the last `deploy` job.)
## Announce the release (via official Google accounts)
Double check that angularjs.org is up to date with the new release version before sharing.
1) Collect a list of contributors
use: `git log --format='%aN' v1.2.12..v1.2.13 | sort -u`
2) Write a blog post (for minor releases, not patch releases) and publish it with the "release" tag
3) Post on twitter as yourself (tweet from your heart; there is no template for this), retweet as @AngularJS
## Party!
## Major Release Tasks
1) Update angularjs.org to use the latest branch.
2) Write up a migration document.
3) Create a new git branch for the version that has been released (e.g. 1.8.x).
4) Check that the build and release scripts still work.
5) Update the dist-tag of the old branch, see https://github.com/angular/angular.js/pull/12722.
6) Write a blog post.
+374
View File
@@ -0,0 +1,374 @@
require 'yaml'
include FileUtils
## High level flow of the build:
##
## clean -> init -> concat -> minify -> package
##
content = File.open('angularFiles.js', 'r') {|f| f.read }
files = eval(content.gsub(/\};(\s|\S)*/, '}').
gsub(/angularFiles = /, '').
gsub(/:/, '=>').
gsub(/\/\//, '#'));
BUILD_DIR = 'build'
task :default => [:package]
desc 'Init the build workspace'
task :init do
%x(npm install)
FileUtils.mkdir(BUILD_DIR) unless File.directory?(BUILD_DIR)
v = YAML::load( File.open( 'version.yaml' ) )
match = v['version'].match(/^([^-]*)(-snapshot)?$/)
NG_VERSION = Struct.new(:full, :major, :minor, :dot, :codename, :stable).
new(match[1] + (match[2] ? ('-' + %x(git rev-parse HEAD)[0..7]) : ''),
match[1].split('.')[0],
match[1].split('.')[1],
match[1].split('.')[2].sub(/\D+.*$/, ''),
v['codename'],
v['stable'])
end
desc 'Clean Generated Files'
task :clean do
FileUtils.rm_r(BUILD_DIR, :force => true)
FileUtils.mkdir(BUILD_DIR)
FileUtils.rm_r('test_out', :force => true)
end
desc 'Concat Scenario'
task :concat_scenario => :init do
concat_file('angular-scenario.js', [
'lib/jquery/jquery.js',
'src/ngScenario/angular.prefix',
files['angularSrc'],
files['angularScenario'],
'src/ngScenario/angular.suffix',
], gen_css('css/angular.css') + "\n" + gen_css('css/angular-scenario.css'))
end
desc 'Concat JSTD Scenario Adapter'
task :concat_jstd_scenario_adapter => :init do
concat_file('jstd-scenario-adapter.js', [
'src/ngScenario/jstd-scenario-adapter/angular.prefix',
'src/ngScenario/jstd-scenario-adapter/Adapter.js',
'src/ngScenario/jstd-scenario-adapter/angular.suffix',
])
# TODO(vojta) use jstd configuration when implemented
# (instead of including jstd-adapter-config.js)
File.open(path_to('jstd-scenario-adapter-config.js'), 'w') do |f|
f.write("/**\r\n" +
" * Configuration for jstd scenario adapter \n */\n" +
"var jstdScenarioAdapter = {\n relativeUrlPrefix: '/build/docs/'\n};\n")
end
end
desc 'Concat AngularJS files'
task :concat => :init do
concat_file('angular.js', [
'src/angular.prefix',
files['angularSrc'],
'src/angular.suffix',
], gen_css('css/angular.css', true))
FileUtils.cp_r 'src/ngLocale', path_to('i18n')
concat_file('angular-loader.js', [
'src/loader.prefix',
'src/loader.js',
'src/loader.suffix'])
concat_module('sanitize', [
'src/ngSanitize/sanitize.js',
'src/ngSanitize/directive/ngBindHtml.js',
'src/ngSanitize/filter/linky.js'])
concat_module('resource', ['src/ngResource/resource.js'])
concat_module('cookies', ['src/ngCookies/cookies.js'])
concat_module('bootstrap', ['src/bootstrap/bootstrap.js'])
concat_module('bootstrap-prettify', ['src/bootstrap/bootstrap-prettify.js',
'src/bootstrap/google-prettify/prettify.js'],
gen_css('src/bootstrap/google-prettify/prettify.css', true))
FileUtils.cp 'src/ngMock/angular-mocks.js', path_to('angular-mocks.js')
rewrite_file(path_to('angular-mocks.js')) do |content|
content.sub!('"NG_VERSION_FULL"', NG_VERSION.full)
end
end
desc 'Minify JavaScript'
task :minify => [:init, :concat, :concat_scenario, :concat_jstd_scenario_adapter] do
[ 'angular.js',
'angular-cookies.js',
'angular-loader.js',
'angular-resource.js',
'angular-sanitize.js',
'angular-bootstrap.js',
'angular-bootstrap-prettify.js'
].each do |file|
fork { closure_compile(file) }
end
Process.waitall
end
desc 'Generate version.txt and version.json files'
task :version => [:init] do
`echo #{NG_VERSION.full} > #{path_to('version.txt')}`
`echo '{
"full": "#{NG_VERSION.full}",
"major": "#{NG_VERSION.major}",
"minor": "#{NG_VERSION.minor}",
"dot": "#{NG_VERSION.dot}",
"codename": "#{NG_VERSION.codename}"\n}' > #{path_to('version.json')}`
end
desc 'Generate docs'
task :docs => [:init] do
`node docs/src/gen-docs.js`
[ path_to('docs/.htaccess'),
path_to('docs/index.html'),
path_to('docs/index-debug.html'),
path_to('docs/index-nocache.html'),
path_to('docs/index-jq.html'),
path_to('docs/index-jq-debug.html'),
path_to('docs/index-jq-nocache.html'),
path_to('docs/docs-scenario.html')
].each do |src|
rewrite_file(src) do |content|
content.sub!('"NG_VERSION_FULL"', NG_VERSION.full).
sub('"NG_VERSION_STABLE"', NG_VERSION.stable)
end
end
end
desc 'Create angular distribution'
task :package => [:clean, :minify, :version, :docs] do
zip_dir = "angular-#{NG_VERSION.full}"
zip_file = "#{zip_dir}.zip"
FileUtils.ln_s BUILD_DIR, zip_dir
%x(zip -r #{zip_file} #{zip_dir})
FileUtils.rm zip_dir
FileUtils.mv zip_file, path_to(zip_file)
puts "Package created: #{path_to(zip_file)}"
end
desc 'Start development webserver'
task :webserver, :port do |t, args|
exec "node lib/nodeserver/server.js #{args[:port]}"
end
desc 'Run all AngularJS tests'
task :test, :browsers, :misc_options do |t, args|
[ 'test:jqlite',
'test:jquery',
'test:modules',
'test:e2e'
].each do |task|
Rake::Task[task].invoke(args[:browsers], args[:misc_options])
end
end
namespace :test do
desc 'Run all unit tests (single run)'
task :unit, :browsers, :misc_options do |t, args|
[ 'test:jqlite',
'test:jquery',
'test:modules'
].each do |task|
Rake::Task[task].invoke(args[:browsers], args[:misc_options])
end
end
desc 'Run jqLite-based unit test suite (single run)'
task :jqlite, :browsers, :misc_options do |t, args|
start_testacular('testacular-jqlite.conf.js', true, args[:browsers], args[:misc_options])
end
desc 'Run jQuery-based unit test suite (single run)'
task :jquery, :browsers, :misc_options do |t, args|
start_testacular('testacular-jquery.conf.js', true, args[:browsers], args[:misc_options])
end
desc 'Run bundled modules unit test suite (single run)'
task :modules, :browsers, :misc_options do |t, args|
start_testacular('testacular-modules.conf.js', true, args[:browsers], args[:misc_options])
end
desc 'Run e2e test suite (single run)'
task :e2e, :browsers, :misc_options do |t, args|
start_testacular('testacular-e2e.conf.js', true, args[:browsers], args[:misc_options])
end
end
namespace :autotest do
desc 'Run jqLite-based unit test suite (autowatch)'
task :jqlite, :browsers, :misc_options do |t, args|
start_testacular('testacular-jqlite.conf.js', false, args[:browsers], args[:misc_options])
end
desc 'Run jQuery-based unit test suite (autowatch)'
task :jquery, :browsers, :misc_options do |t, args|
start_testacular('testacular-jquery.conf.js', false, args[:browsers], args[:misc_options])
end
end
###################
# utility methods #
###################
##
# generates css snippet from a given files and optionally applies simple minification rules
#
def gen_css(cssFile, minify = false)
css = ''
File.open(cssFile, 'r') do |f|
css = f.read
end
if minify
css.gsub! /\n/, ''
css.gsub! /\/\*.*?\*\//, ''
css.gsub! /:\s+/, ':'
css.gsub! /\s*\{\s*/, '{'
css.gsub! /\s*\}\s*/, '}'
css.gsub! /\s*\,\s*/, ','
css.gsub! /\s*\;\s*/, ';'
end
#escape for js
css.gsub! /\\/, "\\\\\\"
css.gsub! /'/, "\\\\'"
css.gsub! /\n/, "\\n"
return %Q{angular.element(document).find('head').append('<style type="text/css">#{css}</style>');}
end
##
# returns path to the file in the build directory
#
def path_to(filename)
return File.join(BUILD_DIR, *filename)
end
##
# returns the 32-bit mode force flags for java compiler if supported, this makes the build much
# faster
#
def java32flags
return '-d32 -client' unless Rake::Win32.windows? || `java -version -d32 2>&1`.match(/Error/i)
end
def closure_compile(filename)
puts "Minifying #{filename} ..."
min_path = path_to(filename.gsub(/\.js$/, '.min.js'))
%x(java \
#{java32flags()} \
-jar lib/closure-compiler/compiler.jar \
--compilation_level SIMPLE_OPTIMIZATIONS \
--language_in ECMASCRIPT5_STRICT \
--js #{path_to(filename)} \
--js_output_file #{min_path})
rewrite_file(min_path) do |content|
content.sub!("'use strict';", "").
sub!(/\(function\([^)]*\)\{/, "\\0'use strict';")
end
end
def concat_file(filename, deps, footer='')
puts "Creating #{filename} ..."
File.open(path_to(filename), 'w') do |f|
concat = 'cat ' + deps.flatten.join(' ')
content = %x{#{concat}}.
gsub('"NG_VERSION_FULL"', NG_VERSION.full).
gsub('"NG_VERSION_MAJOR"', NG_VERSION.major).
gsub('"NG_VERSION_MINOR"', NG_VERSION.minor).
gsub('"NG_VERSION_DOT"', NG_VERSION.dot).
gsub('"NG_VERSION_CODENAME"', NG_VERSION.codename).
gsub(/^\s*['"]use strict['"];?\s*$/, ''). # remove all file-specific strict mode flags
sub(/\(function\([^)]*\)\s*\{/, "\\0\n'use strict';") # add single strict mode flag
f.write(content)
f.write(footer)
end
end
def concat_module(name, files, footer='')
concat_file('angular-' + name + '.js', ['src/module.prefix'] + files + ['src/module.suffix'], footer)
end
def rewrite_file(filename)
File.open(filename, File::RDWR) do |f|
content = f.read
content = yield content
raise "File rewrite failed - No content!" unless content
f.truncate 0
f.rewind
f.write content
end
end
def start_testacular(config, singleRun, browsers, misc_options)
Rake::Task[:init].invoke
sh "./node_modules/testacular/bin/testacular start " +
"#{config} " +
"#{'--single-run=true' if singleRun} " +
"#{'--browsers=' + browsers.gsub('+', ',') if browsers} " +
"#{(misc_options || '').gsub('+', ',')}"
end
-16
View File
@@ -1,16 +0,0 @@
# Security Policy
## Supported Versions
**AngularJS support has officially ended as of January 2022.**
[See what ending support means](https://docs.angularjs.org/misc/version-support-status)
and [read the end of life announcement](https://goo.gle/angularjs-end-of-life).
Visit [angular.io](https://angular.io) for the actively supported Angular.
| Version | Supported | Status | Comments |
| ----------- | ------------------ | --------------------- | ------------------------------------ |
| 1.8.x | :x: | All support ended | |
| 1.3.x-1.7.x | :x: | All support ended | |
| 1.2.x | :x: | All support ended | Last version to provide IE 8 support |
| <1.2.0 | :x: | All support ended | |
-135
View File
@@ -1,135 +0,0 @@
# Triage new issues/PRs on github
This document shows the steps the AngularJS team is using to triage issues.
The labels are used later on for [planning releases](#assigning-work).
## Automatic processing
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 `GH: *`
* `PR` - issue is a PR
* `issue` - otherwise
## 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?q=is%3Aopen+sort%3Acreated-desc+no%3Amilestone)
* 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. 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`
* Reproducible? - Steps to reproduce the bug are clear. If they are not, ask for a clarification. If there's no reply after a week, [close it][].
* Reproducible on master? - <http://code.angularjs.org/snapshot/>
1. Non bugs:
* Label `Type: Feature`, `Type: Chore`, or `Type: Perf`
* Belongs in core? Often new features should be implemented as a third-party module rather than an addition to the core.
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? Chose just one of the following:
* low - obscure issue affecting a handful of developers
* moderate - impacts a common usage pattern
* high - impacts most or all AngularJS apps
1. Label `severity: *` - How bad is the issue? Chose just one of the following:
* security issue
* regression
* memory leak
* broken expected use - it's hard or impossible for a developer using AngularJS to accomplish something that AngularJS 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. In addition to applying this label, you must:
* Leave a comment explaining the problem and solution so someone can easily finish it.
* Assign the issue to yourself.
* Give feedback on PRs addressing this issue.
* You are responsible for mentoring contributors helping with this issue.
1. Label `origin: google` for issues from Google
1. Assign a milestone:
* Backlog - triaged fixes and features, should be the default choice
* Current 1.x.y milestone (e.g. 1.3.0-beta-2) - regressions and urgent bugs only
1. 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 to the npm registry.
## 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/
+139 -243
View File
@@ -1,12 +1,7 @@
'use strict';
var angularFiles = {
angularFiles = {
'angularSrc': [
'src/minErr.js',
'src/Angular.js',
'src/loader.js',
'src/shallowCopy.js',
'src/stringify.js',
'src/AngularPublic.js',
'src/jqLite.js',
'src/apis.js',
@@ -14,40 +9,26 @@ var angularFiles = {
'src/auto/injector.js',
'src/ng/anchorScroll.js',
'src/ng/animate.js',
'src/ng/animateRunner.js',
'src/ng/animateCss.js',
'src/ng/browser.js',
'src/ng/cacheFactory.js',
'src/ng/compile.js',
'src/ng/controller.js',
'src/ng/document.js',
'src/ng/exceptionHandler.js',
'src/ng/forceReflow.js',
'src/ng/http.js',
'src/ng/httpBackend.js',
'src/ng/interpolate.js',
'src/ng/interval.js',
'src/ng/intervalFactory.js',
'src/ng/jsonpCallbacks.js',
'src/ng/locale.js',
'src/ng/location.js',
'src/ng/log.js',
'src/ng/parse.js',
'src/ng/q.js',
'src/ng/raf.js',
'src/ng/route.js',
'src/ng/routeParams.js',
'src/ng/rootScope.js',
'src/ng/rootElement.js',
'src/ng/sanitizeUri.js',
'src/ng/sce.js',
'src/ng/sniffer.js',
'src/ng/taskTrackerFactory.js',
'src/ng/templateRequest.js',
'src/ng/testability.js',
'src/ng/timeout.js',
'src/ng/urlUtils.js',
'src/ng/window.js',
'src/ng/cookieReader.js',
'src/ng/http.js',
'src/ng/httpBackend.js',
'src/ng/locale.js',
'src/ng/timeout.js',
'src/ng/filter.js',
'src/ng/filter/filter.js',
@@ -57,272 +38,187 @@ var angularFiles = {
'src/ng/directive/directives.js',
'src/ng/directive/a.js',
'src/ng/directive/attrs.js',
'src/ng/directive/booleanAttrs.js',
'src/ng/directive/form.js',
'src/ng/directive/input.js',
'src/ng/directive/ngBind.js',
'src/ng/directive/ngChange.js',
'src/ng/directive/ngClass.js',
'src/ng/directive/ngCloak.js',
'src/ng/directive/ngController.js',
'src/ng/directive/ngCsp.js',
'src/ng/directive/ngEventDirs.js',
'src/ng/directive/ngIf.js',
'src/ng/directive/ngInclude.js',
'src/ng/directive/ngInit.js',
'src/ng/directive/ngList.js',
'src/ng/directive/ngModel.js',
'src/ng/directive/ngModelOptions.js',
'src/ng/directive/ngNonBindable.js',
'src/ng/directive/ngOptions.js',
'src/ng/directive/ngPluralize.js',
'src/ng/directive/ngRef.js',
'src/ng/directive/ngRepeat.js',
'src/ng/directive/ngShowHide.js',
'src/ng/directive/ngStyle.js',
'src/ng/directive/ngSwitch.js',
'src/ng/directive/ngTransclude.js',
'src/ng/directive/ngView.js',
'src/ng/directive/script.js',
'src/ng/directive/select.js',
'src/ng/directive/validators.js',
'src/angular.bind.js',
'src/publishExternalApis.js',
'src/ngLocale/angular-locale_en-us.js'
'src/ng/directive/style.js'
],
'angularLoader': [
'src/stringify.js',
'src/minErr.js',
'src/loader.js'
'angularSrcModules': [
'src/ngCookies/cookies.js',
'src/ngResource/resource.js',
'src/ngSanitize/sanitize.js',
'src/ngSanitize/directive/ngBindHtml.js',
'src/ngSanitize/filter/linky.js',
'src/ngMock/angular-mocks.js',
'src/bootstrap/bootstrap.js'
],
'angularModules': {
'ngAnimate': [
'src/ngAnimate/shared.js',
'src/ngAnimate/rafScheduler.js',
'src/ngAnimate/animateChildrenDirective.js',
'src/ngAnimate/animateCss.js',
'src/ngAnimate/animateCssDriver.js',
'src/ngAnimate/animateJs.js',
'src/ngAnimate/animateJsDriver.js',
'src/ngAnimate/animateQueue.js',
'src/ngAnimate/animateCache.js',
'src/ngAnimate/animation.js',
'src/ngAnimate/ngAnimateSwap.js',
'src/ngAnimate/module.js'
],
'ngCookies': [
'src/ngCookies/cookies.js',
'src/ngCookies/cookieWriter.js'
],
'ngMessageFormat': [
'src/ngMessageFormat/messageFormatCommon.js',
'src/ngMessageFormat/messageFormatSelector.js',
'src/ngMessageFormat/messageFormatInterpolationParts.js',
'src/ngMessageFormat/messageFormatParser.js',
'src/ngMessageFormat/messageFormatService.js'
],
'ngMessages': [
'src/ngMessages/messages.js'
],
'ngParseExt': [
'src/ngParseExt/ucd.js',
'src/ngParseExt/module.js'
],
'ngResource': [
'src/ngResource/resource.js'
],
'ngRoute': [
'src/shallowCopy.js',
'src/routeToRegExp.js',
'src/ngRoute/route.js',
'src/ngRoute/routeParams.js',
'src/ngRoute/directive/ngView.js'
],
'ngSanitize': [
'src/ngSanitize/sanitize.js',
'src/ngSanitize/filter/linky.js'
],
'ngMock': [
'src/routeToRegExp.js',
'src/ngMock/angular-mocks.js',
'src/ngMock/browserTrigger.js'
],
'ngTouch': [
'src/ngTouch/touch.js',
'src/ngTouch/swipe.js',
'src/ngTouch/directive/ngSwipe.js'
],
'ngAria': [
'src/ngAria/aria.js'
]
},
'angularScenario': [
'src/ngScenario/Scenario.js',
'src/ngScenario/Application.js',
'src/ngScenario/Describe.js',
'src/ngScenario/Future.js',
'src/ngScenario/ObjectModel.js',
'src/ngScenario/Runner.js',
'src/ngScenario/SpecRunner.js',
'src/ngScenario/dsl.js',
'src/ngScenario/matchers.js',
'src/ngScenario/output/Html.js',
'src/ngScenario/output/Json.js',
'src/ngScenario/output/Xml.js',
'src/ngScenario/output/Object.js'
],
'angularTest': [
'test/helpers/*.js',
'test/testabilityPatch.js',
'test/matchers.js',
'test/ngScenario/*.js',
'test/ngScenario/output/*.js',
'test/ngScenario/jstd-scenario-adapter/*.js',
'test/*.js',
'test/auto/*.js',
'test/ng/**/*.js',
'test/ngAnimate/*.js',
'test/ngMessageFormat/*.js',
'test/ngMessages/*.js',
'test/bootstrap/*.js',
'test/ng/*.js',
'test/ng/directive/*.js',
'test/ng/filter/*.js',
'test/ngCookies/*.js',
'test/ngResource/*.js',
'test/ngRoute/**/*.js',
'test/ngSanitize/**/*.js',
'test/ngSanitize/*.js',
'test/ngSanitize/directive/*.js',
'test/ngSanitize/filter/*.js',
'test/ngMock/*.js'
],
'jstd': [
'lib/jasmine/jasmine.js',
'lib/jasmine-jstd-adapter/JasmineAdapter.js',
'lib/jquery/jquery.js',
'test/jquery_remove.js',
'@angularSrc',
'src/publishExternalApis.js',
'@angularSrcModules',
'@angularScenario',
'src/ngScenario/jstd-scenario-adapter/Adapter.js',
'@angularTest',
'example/personalLog/*.js',
'example/personalLog/test/*.js'
],
'jstdExclude': [
'test/jquery_alias.js',
'src/angular-bootstrap.js',
'src/ngScenario/angular-bootstrap.js'
],
'jstdScenario': [
'build/angular-scenario.js',
'build/jstd-scenario-adapter-config.js',
'build/jstd-scenario-adapter.js',
'build/docs/docs-scenario.js'
],
"jstdModules": [
'lib/jasmine/jasmine.js',
'lib/jasmine-jstd-adapter/JasmineAdapter.js',
'build/angular.js',
'src/ngMock/angular-mocks.js',
'src/ngCookies/cookies.js',
'src/ngResource/resource.js',
'src/ngSanitize/sanitize.js',
'src/ngSanitize/directive/ngBindHtml.js',
'src/ngSanitize/filter/linky.js',
'test/matchers.js',
'test/ngMock/*.js',
'test/ngTouch/**/*.js',
'test/ngAria/*.js'
'test/ngCookies/*.js',
'test/ngResource/*.js',
'test/ngSanitize/*.js',
'test/ngSanitize/directive/*.js',
'test/ngSanitize/filter/*.js'
],
'karma': [
'node_modules/jquery/dist/jquery.js',
'test/jquery_remove.js',
'@angularSrc',
'@angularSrcModules',
'@angularTest'
'jstdPerf': [
'lib/jasmine/jasmine.js',
'lib/jasmine-jstd-adapter/JasmineAdapter.js',
'@angularSrc',
'@angularSrcModules',
'src/ngMock/angular-mocks.js',
'perf/data/*.js',
'perf/testUtils.js',
'perf/*.js'
],
'karmaExclude': [
'test/jquery_alias.js',
'src/angular-bootstrap.js',
'src/angular.bind.js'
'jstdPerfExclude': [
'src/ng/angular-bootstrap.js',
'src/ngScenario/angular-bootstrap.js'
],
'karmaModules-ngAnimate': [
'build/angular.js',
'build/angular-mocks.js',
'test/modules/no_bootstrap.js',
'test/helpers/matchers.js',
'test/helpers/privateMocks.js',
'test/helpers/support.js',
'test/helpers/testabilityPatch.js',
'@angularSrcModuleNgAnimate',
'test/ngAnimate/**/*.js'
],
'karmaModules-ngAria': [
'@angularSrcModuleNgAria',
'test/ngAria/**/*.js'
],
'karmaModules-ngCookies': [
'@angularSrcModuleNgCookies',
'test/ngCookies/**/*.js'
],
'karmaModules-ngMessageFormat': [
'@angularSrcModuleNgMessageFormat',
'test/ngMessageFormat/**/*.js'
],
'karmaModules-ngMessages': [
'build/angular-animate.js',
'@angularSrcModuleNgMessages',
'test/ngMessages/**/*.js'
],
// ngMock doesn't include the base because it must use the ngMock src files
'karmaModules-ngMock': [
'build/angular.js',
'src/ngMock/*.js',
'test/modules/no_bootstrap.js',
'test/helpers/matchers.js',
'test/helpers/privateMocks.js',
'test/helpers/support.js',
'test/helpers/testabilityPatch.js',
'src/routeToRegExp.js',
'build/angular-animate.js',
'test/ngMock/**/*.js'
],
'karmaModules-ngResource': [
'@angularSrcModuleNgResource',
'test/ngResource/**/*.js'
],
'karmaModules-ngRoute': [
'build/angular-animate.js',
'@angularSrcModuleNgRoute',
'test/ngRoute/**/*.js'
],
'karmaModules-ngSanitize': [
'@angularSrcModuleNgSanitize',
'test/ngSanitize/**/*.js'
],
'karmaModules-ngTouch': [
'@angularSrcModuleNgTouch',
'test/ngTouch/**/*.js'
],
'karmaJquery': [
'node_modules/jquery/dist/jquery.js',
'jstdJquery': [
'lib/jasmine/jasmine.js',
'lib/jasmine-jstd-adapter/JasmineAdapter.js',
'lib/jquery/jquery.js',
'test/jquery_alias.js',
'@angularSrc',
'src/publishExternalApis.js',
'@angularSrcModules',
'@angularTest'
'@angularScenario',
'src/ngScenario/jstd-scenario-adapter/Adapter.js',
'@angularTest',
'example/personalLog/*.js',
'example/personalLog/test/*.js'
],
'karmaJqueryExclude': [
'jstdJqueryExclude': [
'src/angular-bootstrap.js',
'test/jquery_remove.js',
'src/angular.bind.js'
'src/ngScenario/angular-bootstrap.js',
'test/jquery_remove.js'
]
};
['2.1', '2.2'].forEach(function(jQueryVersion) {
angularFiles['karmaJquery' + jQueryVersion] = []
.concat(angularFiles.karmaJquery)
.map(function(path) {
if (path.startsWith('node_modules/jquery')) {
return path.replace(/^node_modules\/jquery/, 'node_modules/jquery-' + jQueryVersion);
}
return path;
});
});
angularFiles['angularSrcModuleNgAnimate'] = angularFiles['angularModules']['ngAnimate'];
angularFiles['angularSrcModuleNgAria'] = angularFiles['angularModules']['ngAria'];
angularFiles['angularSrcModuleNgCookies'] = angularFiles['angularModules']['ngCookies'];
angularFiles['angularSrcModuleNgMessageFormat'] = angularFiles['angularModules']['ngMessageFormat'];
angularFiles['angularSrcModuleNgMessages'] = angularFiles['angularModules']['ngMessages'];
angularFiles['angularSrcModuleNgResource'] = angularFiles['angularModules']['ngResource'];
angularFiles['angularSrcModuleNgRoute'] = angularFiles['angularModules']['ngRoute'];
angularFiles['angularSrcModuleNgSanitize'] = angularFiles['angularModules']['ngSanitize'];
angularFiles['angularSrcModuleNgTouch'] = angularFiles['angularModules']['ngTouch'];
angularFiles['angularSrcModules'] = [].concat(
angularFiles['angularModules']['ngAnimate'],
angularFiles['angularModules']['ngMessageFormat'],
angularFiles['angularModules']['ngMessages'],
angularFiles['angularModules']['ngCookies'],
angularFiles['angularModules']['ngResource'],
angularFiles['angularModules']['ngRoute'],
angularFiles['angularModules']['ngSanitize'],
angularFiles['angularModules']['ngMock'],
angularFiles['angularModules']['ngTouch'],
angularFiles['angularModules']['ngAria']
);
if (exports) {
exports.files = angularFiles;
exports.mergeFilesFor = function() {
exports.files = angularFiles
exports.mergeFiles = function mergeFiles() {
var files = [];
Array.prototype.slice.call(arguments, 0).forEach(function(filegroup) {
angularFiles[filegroup].forEach(function(file) {
// replace @ref
var match = file.match(/^@(.*)/);
if (match) {
files = files.concat(angularFiles[match[1]]);
} else {
files.push(file);
}
});
[].splice.call(arguments, 0).forEach(function(file) {
if (file.match(/testacular/)) {
files.push(file);
} else {
angularFiles[file].forEach(function(f) {
// replace @ref
var match = f.match(/^\@(.*)/);
if (match) {
var deps = angularFiles[match[1]];
files = files.concat(deps);
} else {
if (!/jstd|jasmine/.test(f)) { //TODO(i): remove once we don't have jstd/jasmine in repo
files.push(f);
}
}
});
}
});
return files;
};
}
}
-11
View File
@@ -1,11 +0,0 @@
{
"root": true,
"extends": "../.eslintrc-browser.json",
"globals": {
"benchmarkSteps": false,
// Benchmarks are not run in IE 9 so we're fine.
"console": false
}
}
-6
View File
@@ -1,6 +0,0 @@
Instructions for using benchpress (how to create benchmarks, how to run, how to configure) can be
found at: https://github.com/angular/benchpress/blob/master/README.md.
In this project, there is a configured grunt task for building the benchmarks,
`grunt bp_build`, which places the runnable benchmarks in "/build/benchmarks/".
The existing `grunt webserver` task can be used to serve the built benchmarks at `localhost:8000/build/benchmarks/<benchmark-name>`
-44
View File
@@ -1,44 +0,0 @@
'use strict';
angular
.module('animationBenchmark', ['ngAnimate'], config)
.controller('BenchmarkController', BenchmarkController);
// Functions - Definitions
function config($compileProvider) {
$compileProvider
.commentDirectivesEnabled(false)
.cssClassDirectivesEnabled(false)
.debugInfoEnabled(false);
}
function BenchmarkController($scope) {
var self = this;
var itemCount = 1000;
var items = (new Array(itemCount + 1)).join('.').split('');
benchmarkSteps.push({
name: 'create',
fn: function() {
$scope.$apply(function() {
self.items = items;
});
}
});
benchmarkSteps.push({
name: '$digest',
fn: function() {
$scope.$root.$digest();
}
});
benchmarkSteps.push({
name: 'destroy',
fn: function() {
$scope.$apply(function() {
self.items = [];
});
}
});
}
-22
View File
@@ -1,22 +0,0 @@
/* eslint-env node */
'use strict';
module.exports = function(config) {
config.set({
scripts: [
{
id: 'jquery',
src: 'jquery-noop.js'
}, {
id: 'angular',
src: '/build/angular.js'
}, {
id: 'angular-animate',
src: '/build/angular-animate.js'
}, {
src: 'app.js'
}
]
});
};
-1
View File
@@ -1 +0,0 @@
// Override me with ?jquery=/node_modules/jquery/dist/jquery.js
-28
View File
@@ -1,28 +0,0 @@
<style>
[ng-cloak] { display: none !important; }
.animation-container .ng-enter,
.animation-container .ng-leave {
transition: all 0.1s;
}
.animation-container .ng-enter,
.animation-container .ng-leave.ng-leave-active {
opacity: 0;
}
.animation-container .ng-enter.ng-enter-active,
.animation-container .ng-leave {
opacity: 1;
}
</style>
<div ng-app="animationBenchmark" ng-cloak ng-controller="BenchmarkController as bm">
<div class="container-fluid">
<h2>Large collection of elements animated in and out with ngAnimate</h2>
<div class="animation-container">
<div ng-repeat="i in bm.items track by $index">
Just a plain ol' element
</div>
</div>
</div>
</div>
-61
View File
@@ -1,61 +0,0 @@
'use strict';
var app = angular.module('boostrapCompileBenchmark', []);
var commentDirectivesEnabled;
var cssClassDirectivesEnabled;
app.config(function($compileProvider) {
$compileProvider.debugInfoEnabled(false);
commentDirectivesEnabled = window.location.toString().indexOf('comment=disabled') === -1;
cssClassDirectivesEnabled = window.location.toString().indexOf('css=disabled') === -1;
$compileProvider
.commentDirectivesEnabled(commentDirectivesEnabled)
.cssClassDirectivesEnabled(cssClassDirectivesEnabled);
})
.controller('DataController', function DataController($compile, $http, $rootScope) {
this.isEA = !commentDirectivesEnabled && !cssClassDirectivesEnabled;
this.isEAC = !commentDirectivesEnabled && cssClassDirectivesEnabled;
this.isEAM = commentDirectivesEnabled && !cssClassDirectivesEnabled;
this.isEACM = commentDirectivesEnabled && cssClassDirectivesEnabled;
this.repeats = 50;
this.templates = [
'bootstrap-carousel.tpl.html',
'bootstrap-theme.tpl.html'
];
this.html = null;
this.loadTemplate = function() {
this.html = null;
$http.get(window.location.pathname + this.selectedTemplate)
.then(function(response) { this.html = response.data; }.bind(this));
};
this.selectedTemplate = this.templates[0];
this.loadTemplate();
var linkers = [];
benchmarkSteps.push({
name: 'create',
fn: function() {
for (var i = 0; i < this.repeats; i++) {
var linker = $compile(this.html);
linkers.push(linker);
}
}.bind(this)
});
benchmarkSteps.push({
name: 'destroy',
fn: function() {
linkers.length = 0;
}
});
});
@@ -1,172 +0,0 @@
<!-- code from http://getbootstrap.com/examples/carousel -->
<div class="navbar-wrapper">
<div class="container">
<nav class="navbar navbar-inverse navbar-static-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Project name</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li class="active"><a href="#">Home</a></li>
<li><a href="#about">About</a></li>
<li><a href="#contact">Contact</a></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="#">Action</a></li>
<li><a href="#">Another action</a></li>
<li><a href="#">Something else here</a></li>
<li role="separator" class="divider"></li>
<li class="dropdown-header">Nav header</li>
<li><a href="#">Separated link</a></li>
<li><a href="#">One more separated link</a></li>
</ul>
</li>
</ul>
</div>
</div>
</nav>
</div>
</div>
<!-- Carousel
================================================== -->
<div id="myCarousel" class="carousel slide" data-ride="carousel">
<!-- Indicators -->
<ol class="carousel-indicators">
<li data-target="#myCarousel" data-slide-to="0" class="active"></li>
<li data-target="#myCarousel" data-slide-to="1"></li>
<li data-target="#myCarousel" data-slide-to="2"></li>
</ol>
<div class="carousel-inner" role="listbox">
<div class="item active">
<img class="first-slide" src="data:image/gif;base64,R0lGODlhAQABAIAAAHd3dwAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==" alt="First slide">
<div class="container">
<div class="carousel-caption">
<h1>Example headline.</h1>
<p>Note: If you're viewing this page via a <code>file://</code> URL, the "next" and "previous" Glyphicon buttons on the left and right might not load/display properly due to web browser security rules.</p>
<p><a class="btn btn-lg btn-primary" href="#" role="button">Sign up today</a></p>
</div>
</div>
</div>
<div class="item">
<img class="second-slide" src="data:image/gif;base64,R0lGODlhAQABAIAAAHd3dwAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==" alt="Second slide">
<div class="container">
<div class="carousel-caption">
<h1>Another example headline.</h1>
<p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ultricies vehicula ut id elit.</p>
<p><a class="btn btn-lg btn-primary" href="#" role="button">Learn more</a></p>
</div>
</div>
</div>
<div class="item">
<img class="third-slide" src="data:image/gif;base64,R0lGODlhAQABAIAAAHd3dwAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==" alt="Third slide">
<div class="container">
<div class="carousel-caption">
<h1>One more for good measure.</h1>
<p>Cras justo odio, dapibus ac facilisis in, egestas eget quam. Donec id elit non mi porta gravida at eget metus. Nullam id dolor id nibh ultricies vehicula ut id elit.</p>
<p><a class="btn btn-lg btn-primary" href="#" role="button">Browse gallery</a></p>
</div>
</div>
</div>
</div>
<a class="left carousel-control" href="#myCarousel" role="button" data-slide="prev">
<span class="glyphicon glyphicon-chevron-left" aria-hidden="true"></span>
<span class="sr-only">Previous</span>
</a>
<a class="right carousel-control" href="#myCarousel" role="button" data-slide="next">
<span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span>
<span class="sr-only">Next</span>
</a>
</div><!-- /.carousel -->
<!-- Marketing messaging and featurettes
================================================== -->
<!-- Wrap the rest of the page in another container to center all the content. -->
<div class="container marketing">
<!-- Three columns of text below the carousel -->
<div class="row">
<div class="col-lg-4">
<img class="img-circle" src="data:image/gif;base64,R0lGODlhAQABAIAAAHd3dwAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==" alt="Generic placeholder image" width="140" height="140">
<h2>Heading</h2>
<p>Donec sed odio dui. Etiam porta sem malesuada magna mollis euismod. Nullam id dolor id nibh ultricies vehicula ut id elit. Morbi leo risus, porta ac consectetur ac, vestibulum at eros. Praesent commodo cursus magna.</p>
<p><a class="btn btn-default" href="#" role="button">View details &raquo;</a></p>
</div><!-- /.col-lg-4 -->
<div class="col-lg-4">
<img class="img-circle" src="data:image/gif;base64,R0lGODlhAQABAIAAAHd3dwAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==" alt="Generic placeholder image" width="140" height="140">
<h2>Heading</h2>
<p>Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Cras mattis consectetur purus sit amet fermentum. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh.</p>
<p><a class="btn btn-default" href="#" role="button">View details &raquo;</a></p>
</div><!-- /.col-lg-4 -->
<div class="col-lg-4">
<img class="img-circle" src="data:image/gif;base64,R0lGODlhAQABAIAAAHd3dwAAACH5BAAAAAAALAAAAAABAAEAAAICRAEAOw==" alt="Generic placeholder image" width="140" height="140">
<h2>Heading</h2>
<p>Donec sed odio dui. Cras justo odio, dapibus ac facilisis in, egestas eget quam. Vestibulum id ligula porta felis euismod semper. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus.</p>
<p><a class="btn btn-default" href="#" role="button">View details &raquo;</a></p>
</div><!-- /.col-lg-4 -->
</div><!-- /.row -->
<!-- START THE FEATURETTES -->
<hr class="featurette-divider">
<div class="row featurette">
<div class="col-md-7">
<h2 class="featurette-heading">First featurette heading. <span class="text-muted">It'll blow your mind.</span></h2>
<p class="lead">Donec ullamcorper nulla non metus auctor fringilla. Vestibulum id ligula porta felis euismod semper. Praesent commodo cursus magna, vel scelerisque nisl consectetur. Fusce dapibus, tellus ac cursus commodo.</p>
</div>
<div class="col-md-5">
<img class="featurette-image img-responsive center-block" data-src="holder.js/500x500/auto" alt="Generic placeholder image">
</div>
</div>
<hr class="featurette-divider">
<div class="row featurette">
<div class="col-md-7 col-md-push-5">
<h2 class="featurette-heading">Oh yeah, it's that good. <span class="text-muted">See for yourself.</span></h2>
<p class="lead">Donec ullamcorper nulla non metus auctor fringilla. Vestibulum id ligula porta felis euismod semper. Praesent commodo cursus magna, vel scelerisque nisl consectetur. Fusce dapibus, tellus ac cursus commodo.</p>
</div>
<div class="col-md-5 col-md-pull-7">
<img class="featurette-image img-responsive center-block" data-src="holder.js/500x500/auto" alt="Generic placeholder image">
</div>
</div>
<hr class="featurette-divider">
<div class="row featurette">
<div class="col-md-7">
<h2 class="featurette-heading">And lastly, this one. <span class="text-muted">Checkmate.</span></h2>
<p class="lead">Donec ullamcorper nulla non metus auctor fringilla. Vestibulum id ligula porta felis euismod semper. Praesent commodo cursus magna, vel scelerisque nisl consectetur. Fusce dapibus, tellus ac cursus commodo.</p>
</div>
<div class="col-md-5">
<img class="featurette-image img-responsive center-block" data-src="holder.js/500x500/auto" alt="Generic placeholder image">
</div>
</div>
<hr class="featurette-divider">
<!-- /END THE FEATURETTES -->
<!-- FOOTER -->
<footer>
<p class="pull-right"><a href="#">Back to top</a></p>
<p>&copy; 2016 Company, Inc. &middot; <a href="#">Privacy</a> &middot; <a href="#">Terms</a></p>
</footer>
</div><!-- /.container -->
@@ -1,595 +0,0 @@
<!-- Fixed navbar -->
<nav class="navbar navbar-inverse navbar-fixed-top">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#navbar" aria-expanded="false" aria-controls="navbar">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Bootstrap theme</a>
</div>
<div id="navbar" class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li class="active"><a href="#">Home</a></li>
<li><a href="#about">About</a></li>
<li><a href="#contact">Contact</a></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="#">Action</a></li>
<li><a href="#">Another action</a></li>
<li><a href="#">Something else here</a></li>
<li role="separator" class="divider"></li>
<li class="dropdown-header">Nav header</li>
<li><a href="#">Separated link</a></li>
<li><a href="#">One more separated link</a></li>
</ul>
</li>
</ul>
</div><!--/.nav-collapse -->
</div>
</nav>
<div class="container theme-showcase" role="main">
<!-- Main jumbotron for a primary marketing message or call to action -->
<div class="jumbotron">
<h1>Theme example</h1>
<p>This is a template showcasing the optional theme stylesheet included in Bootstrap. Use it as a starting point to create something more unique by building on or modifying it.</p>
</div>
<div class="page-header">
<h1>Buttons</h1>
</div>
<p>
<button type="button" class="btn btn-lg btn-default">Default</button>
<button type="button" class="btn btn-lg btn-primary">Primary</button>
<button type="button" class="btn btn-lg btn-success">Success</button>
<button type="button" class="btn btn-lg btn-info">Info</button>
<button type="button" class="btn btn-lg btn-warning">Warning</button>
<button type="button" class="btn btn-lg btn-danger">Danger</button>
<button type="button" class="btn btn-lg btn-link">Link</button>
</p>
<p>
<button type="button" class="btn btn-default">Default</button>
<button type="button" class="btn btn-primary">Primary</button>
<button type="button" class="btn btn-success">Success</button>
<button type="button" class="btn btn-info">Info</button>
<button type="button" class="btn btn-warning">Warning</button>
<button type="button" class="btn btn-danger">Danger</button>
<button type="button" class="btn btn-link">Link</button>
</p>
<p>
<button type="button" class="btn btn-sm btn-default">Default</button>
<button type="button" class="btn btn-sm btn-primary">Primary</button>
<button type="button" class="btn btn-sm btn-success">Success</button>
<button type="button" class="btn btn-sm btn-info">Info</button>
<button type="button" class="btn btn-sm btn-warning">Warning</button>
<button type="button" class="btn btn-sm btn-danger">Danger</button>
<button type="button" class="btn btn-sm btn-link">Link</button>
</p>
<p>
<button type="button" class="btn btn-xs btn-default">Default</button>
<button type="button" class="btn btn-xs btn-primary">Primary</button>
<button type="button" class="btn btn-xs btn-success">Success</button>
<button type="button" class="btn btn-xs btn-info">Info</button>
<button type="button" class="btn btn-xs btn-warning">Warning</button>
<button type="button" class="btn btn-xs btn-danger">Danger</button>
<button type="button" class="btn btn-xs btn-link">Link</button>
</p>
<div class="page-header">
<h1>Tables</h1>
</div>
<div class="row">
<div class="col-md-6">
<table class="table">
<thead>
<tr>
<th>#</th>
<th>First Name</th>
<th>Last Name</th>
<th>Username</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Mark</td>
<td>Otto</td>
<td>@mdo</td>
</tr>
<tr>
<td>2</td>
<td>Jacob</td>
<td>Thornton</td>
<td>@fat</td>
</tr>
<tr>
<td>3</td>
<td>Larry</td>
<td>the Bird</td>
<td>@twitter</td>
</tr>
</tbody>
</table>
</div>
<div class="col-md-6">
<table class="table table-striped">
<thead>
<tr>
<th>#</th>
<th>First Name</th>
<th>Last Name</th>
<th>Username</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Mark</td>
<td>Otto</td>
<td>@mdo</td>
</tr>
<tr>
<td>2</td>
<td>Jacob</td>
<td>Thornton</td>
<td>@fat</td>
</tr>
<tr>
<td>3</td>
<td>Larry</td>
<td>the Bird</td>
<td>@twitter</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="row">
<div class="col-md-6">
<table class="table table-bordered">
<thead>
<tr>
<th>#</th>
<th>First Name</th>
<th>Last Name</th>
<th>Username</th>
</tr>
</thead>
<tbody>
<tr>
<td rowspan="2">1</td>
<td>Mark</td>
<td>Otto</td>
<td>@mdo</td>
</tr>
<tr>
<td>Mark</td>
<td>Otto</td>
<td>@TwBootstrap</td>
</tr>
<tr>
<td>2</td>
<td>Jacob</td>
<td>Thornton</td>
<td>@fat</td>
</tr>
<tr>
<td>3</td>
<td colspan="2">Larry the Bird</td>
<td>@twitter</td>
</tr>
</tbody>
</table>
</div>
<div class="col-md-6">
<table class="table table-condensed">
<thead>
<tr>
<th>#</th>
<th>First Name</th>
<th>Last Name</th>
<th>Username</th>
</tr>
</thead>
<tbody>
<tr>
<td>1</td>
<td>Mark</td>
<td>Otto</td>
<td>@mdo</td>
</tr>
<tr>
<td>2</td>
<td>Jacob</td>
<td>Thornton</td>
<td>@fat</td>
</tr>
<tr>
<td>3</td>
<td colspan="2">Larry the Bird</td>
<td>@twitter</td>
</tr>
</tbody>
</table>
</div>
</div>
<div class="page-header">
<h1>Thumbnails</h1>
</div>
<img data-src="holder.js/200x200" class="img-thumbnail" alt="200x200" src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9InllcyI/PjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB3aWR0aD0iMjAwIiBoZWlnaHQ9IjIwMCIgdmlld0JveD0iMCAwIDIwMCAyMDAiIHByZXNlcnZlQXNwZWN0UmF0aW89Im5vbmUiPjwhLS0KU291cmNlIFVSTDogaG9sZGVyLmpzLzIwMHgyMDAKQ3JlYXRlZCB3aXRoIEhvbGRlci5qcyAyLjYuMC4KTGVhcm4gbW9yZSBhdCBodHRwOi8vaG9sZGVyanMuY29tCihjKSAyMDEyLTIwMTUgSXZhbiBNYWxvcGluc2t5IC0gaHR0cDovL2ltc2t5LmNvCi0tPjxkZWZzPjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+PCFbQ0RBVEFbI2hvbGRlcl8xNTYyY2ExYjA3YiB0ZXh0IHsgZmlsbDojQUFBQUFBO2ZvbnQtd2VpZ2h0OmJvbGQ7Zm9udC1mYW1pbHk6QXJpYWwsIEhlbHZldGljYSwgT3BlbiBTYW5zLCBzYW5zLXNlcmlmLCBtb25vc3BhY2U7Zm9udC1zaXplOjEwcHQgfSBdXT48L3N0eWxlPjwvZGVmcz48ZyBpZD0iaG9sZGVyXzE1NjJjYTFiMDdiIj48cmVjdCB3aWR0aD0iMjAwIiBoZWlnaHQ9IjIwMCIgZmlsbD0iI0VFRUVFRSIvPjxnPjx0ZXh0IHg9Ijc0LjY5NTMxMjUiIHk9IjEwNC41Ij4yMDB4MjAwPC90ZXh0PjwvZz48L2c+PC9zdmc+" data-holder-rendered="true" style="width: 200px; height: 200px;">
<div class="page-header">
<h1>Labels</h1>
</div>
<h1>
<span class="label label-default">Default</span>
<span class="label label-primary">Primary</span>
<span class="label label-success">Success</span>
<span class="label label-info">Info</span>
<span class="label label-warning">Warning</span>
<span class="label label-danger">Danger</span>
</h1>
<h2>
<span class="label label-default">Default</span>
<span class="label label-primary">Primary</span>
<span class="label label-success">Success</span>
<span class="label label-info">Info</span>
<span class="label label-warning">Warning</span>
<span class="label label-danger">Danger</span>
</h2>
<h3>
<span class="label label-default">Default</span>
<span class="label label-primary">Primary</span>
<span class="label label-success">Success</span>
<span class="label label-info">Info</span>
<span class="label label-warning">Warning</span>
<span class="label label-danger">Danger</span>
</h3>
<h4>
<span class="label label-default">Default</span>
<span class="label label-primary">Primary</span>
<span class="label label-success">Success</span>
<span class="label label-info">Info</span>
<span class="label label-warning">Warning</span>
<span class="label label-danger">Danger</span>
</h4>
<h5>
<span class="label label-default">Default</span>
<span class="label label-primary">Primary</span>
<span class="label label-success">Success</span>
<span class="label label-info">Info</span>
<span class="label label-warning">Warning</span>
<span class="label label-danger">Danger</span>
</h5>
<h6>
<span class="label label-default">Default</span>
<span class="label label-primary">Primary</span>
<span class="label label-success">Success</span>
<span class="label label-info">Info</span>
<span class="label label-warning">Warning</span>
<span class="label label-danger">Danger</span>
</h6>
<p>
<span class="label label-default">Default</span>
<span class="label label-primary">Primary</span>
<span class="label label-success">Success</span>
<span class="label label-info">Info</span>
<span class="label label-warning">Warning</span>
<span class="label label-danger">Danger</span>
</p>
<div class="page-header">
<h1>Badges</h1>
</div>
<p>
<a href="#">Inbox <span class="badge">42</span></a>
</p>
<ul class="nav nav-pills" role="tablist">
<li role="presentation" class="active"><a href="#">Home <span class="badge">42</span></a></li>
<li role="presentation"><a href="#">Profile</a></li>
<li role="presentation"><a href="#">Messages <span class="badge">3</span></a></li>
</ul>
<div class="page-header">
<h1>Dropdown menus</h1>
</div>
<div class="dropdown theme-dropdown clearfix">
<a id="dropdownMenu1" href="#" class="sr-only dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a>
<ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
<li class="active"><a href="#">Action</a></li>
<li><a href="#">Another action</a></li>
<li><a href="#">Something else here</a></li>
<li role="separator" class="divider"></li>
<li><a href="#">Separated link</a></li>
</ul>
</div>
<div class="page-header">
<h1>Navs</h1>
</div>
<ul class="nav nav-tabs" role="tablist">
<li role="presentation" class="active"><a href="#">Home</a></li>
<li role="presentation"><a href="#">Profile</a></li>
<li role="presentation"><a href="#">Messages</a></li>
</ul>
<ul class="nav nav-pills" role="tablist">
<li role="presentation" class="active"><a href="#">Home</a></li>
<li role="presentation"><a href="#">Profile</a></li>
<li role="presentation"><a href="#">Messages</a></li>
</ul>
<div class="page-header">
<h1>Navbars</h1>
</div>
<nav class="navbar navbar-default">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Project name</a>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li class="active"><a href="#">Home</a></li>
<li><a href="#about">About</a></li>
<li><a href="#contact">Contact</a></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="#">Action</a></li>
<li><a href="#">Another action</a></li>
<li><a href="#">Something else here</a></li>
<li role="separator" class="divider"></li>
<li class="dropdown-header">Nav header</li>
<li><a href="#">Separated link</a></li>
<li><a href="#">One more separated link</a></li>
</ul>
</li>
</ul>
</div><!--/.nav-collapse -->
</div>
</nav>
<nav class="navbar navbar-inverse">
<div class="container">
<div class="navbar-header">
<button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
<a class="navbar-brand" href="#">Project name</a>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li class="active"><a href="#">Home</a></li>
<li><a href="#about">About</a></li>
<li><a href="#contact">Contact</a></li>
<li class="dropdown">
<a href="#" class="dropdown-toggle" data-toggle="dropdown" role="button" aria-haspopup="true" aria-expanded="false">Dropdown <span class="caret"></span></a>
<ul class="dropdown-menu">
<li><a href="#">Action</a></li>
<li><a href="#">Another action</a></li>
<li><a href="#">Something else here</a></li>
<li role="separator" class="divider"></li>
<li class="dropdown-header">Nav header</li>
<li><a href="#">Separated link</a></li>
<li><a href="#">One more separated link</a></li>
</ul>
</li>
</ul>
</div><!--/.nav-collapse -->
</div>
</nav>
<div class="page-header">
<h1>Alerts</h1>
</div>
<div class="alert alert-success" role="alert">
<strong>Well done!</strong> You successfully read this important alert message.
</div>
<div class="alert alert-info" role="alert">
<strong>Heads up!</strong> This alert needs your attention, but it's not super important.
</div>
<div class="alert alert-warning" role="alert">
<strong>Warning!</strong> Best check yo self, you're not looking too good.
</div>
<div class="alert alert-danger" role="alert">
<strong>Oh snap!</strong> Change a few things up and try submitting again.
</div>
<div class="page-header">
<h1>Progress bars</h1>
</div>
<div class="progress">
<div class="progress-bar" role="progressbar" aria-valuenow="60" aria-valuemin="0" aria-valuemax="100" style="width: 60%;"><span class="sr-only">60% Complete</span></div>
</div>
<div class="progress">
<div class="progress-bar progress-bar-success" role="progressbar" aria-valuenow="40" aria-valuemin="0" aria-valuemax="100" style="width: 40%"><span class="sr-only">40% Complete (success)</span></div>
</div>
<div class="progress">
<div class="progress-bar progress-bar-info" role="progressbar" aria-valuenow="20" aria-valuemin="0" aria-valuemax="100" style="width: 20%"><span class="sr-only">20% Complete</span></div>
</div>
<div class="progress">
<div class="progress-bar progress-bar-warning" role="progressbar" aria-valuenow="60" aria-valuemin="0" aria-valuemax="100" style="width: 60%"><span class="sr-only">60% Complete (warning)</span></div>
</div>
<div class="progress">
<div class="progress-bar progress-bar-danger" role="progressbar" aria-valuenow="80" aria-valuemin="0" aria-valuemax="100" style="width: 80%"><span class="sr-only">80% Complete (danger)</span></div>
</div>
<div class="progress">
<div class="progress-bar progress-bar-striped" role="progressbar" aria-valuenow="60" aria-valuemin="0" aria-valuemax="100" style="width: 60%"><span class="sr-only">60% Complete</span></div>
</div>
<div class="progress">
<div class="progress-bar progress-bar-success" style="width: 35%"><span class="sr-only">35% Complete (success)</span></div>
<div class="progress-bar progress-bar-warning" style="width: 20%"><span class="sr-only">20% Complete (warning)</span></div>
<div class="progress-bar progress-bar-danger" style="width: 10%"><span class="sr-only">10% Complete (danger)</span></div>
</div>
<div class="page-header">
<h1>List groups</h1>
</div>
<div class="row">
<div class="col-sm-4">
<ul class="list-group">
<li class="list-group-item">Cras justo odio</li>
<li class="list-group-item">Dapibus ac facilisis in</li>
<li class="list-group-item">Morbi leo risus</li>
<li class="list-group-item">Porta ac consectetur ac</li>
<li class="list-group-item">Vestibulum at eros</li>
</ul>
</div><!-- /.col-sm-4 -->
<div class="col-sm-4">
<div class="list-group">
<a href="#" class="list-group-item active">
Cras justo odio
</a>
<a href="#" class="list-group-item">Dapibus ac facilisis in</a>
<a href="#" class="list-group-item">Morbi leo risus</a>
<a href="#" class="list-group-item">Porta ac consectetur ac</a>
<a href="#" class="list-group-item">Vestibulum at eros</a>
</div>
</div><!-- /.col-sm-4 -->
<div class="col-sm-4">
<div class="list-group">
<a href="#" class="list-group-item active">
<h4 class="list-group-item-heading">List group item heading</h4>
<p class="list-group-item-text">Donec id elit non mi porta gravida at eget metus. Maecenas sed diam eget risus varius blandit.</p>
</a>
<a href="#" class="list-group-item">
<h4 class="list-group-item-heading">List group item heading</h4>
<p class="list-group-item-text">Donec id elit non mi porta gravida at eget metus. Maecenas sed diam eget risus varius blandit.</p>
</a>
<a href="#" class="list-group-item">
<h4 class="list-group-item-heading">List group item heading</h4>
<p class="list-group-item-text">Donec id elit non mi porta gravida at eget metus. Maecenas sed diam eget risus varius blandit.</p>
</a>
</div>
</div><!-- /.col-sm-4 -->
</div>
<div class="page-header">
<h1>Panels</h1>
</div>
<div class="row">
<div class="col-sm-4">
<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">Panel title</h3>
</div>
<div class="panel-body">
Panel content
</div>
</div>
<div class="panel panel-primary">
<div class="panel-heading">
<h3 class="panel-title">Panel title</h3>
</div>
<div class="panel-body">
Panel content
</div>
</div>
</div><!-- /.col-sm-4 -->
<div class="col-sm-4">
<div class="panel panel-success">
<div class="panel-heading">
<h3 class="panel-title">Panel title</h3>
</div>
<div class="panel-body">
Panel content
</div>
</div>
<div class="panel panel-info">
<div class="panel-heading">
<h3 class="panel-title">Panel title</h3>
</div>
<div class="panel-body">
Panel content
</div>
</div>
</div><!-- /.col-sm-4 -->
<div class="col-sm-4">
<div class="panel panel-warning">
<div class="panel-heading">
<h3 class="panel-title">Panel title</h3>
</div>
<div class="panel-body">
Panel content
</div>
</div>
<div class="panel panel-danger">
<div class="panel-heading">
<h3 class="panel-title">Panel title</h3>
</div>
<div class="panel-body">
Panel content
</div>
</div>
</div><!-- /.col-sm-4 -->
</div>
<div class="page-header">
<h1>Wells</h1>
</div>
<div class="well">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit. Maecenas sed diam eget risus varius blandit sit amet non magna. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Praesent commodo cursus magna, vel scelerisque nisl consectetur et. Cras mattis consectetur purus sit amet fermentum. Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Aenean lacinia bibendum nulla sed consectetur.</p>
</div>
<div class="page-header">
<h1>Carousel</h1>
</div>
<div id="carousel-example-generic" class="carousel slide" data-ride="carousel">
<ol class="carousel-indicators">
<li data-target="#carousel-example-generic" data-slide-to="0" class=""></li>
<li data-target="#carousel-example-generic" data-slide-to="1" class=""></li>
<li data-target="#carousel-example-generic" data-slide-to="2" class="active"></li>
</ol>
<div class="carousel-inner" role="listbox">
<div class="item">
<img data-src="holder.js/1140x500/auto/#777:#555/text:First slide" alt="First slide [1140x500]" src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9InllcyI/PjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB3aWR0aD0iMTE0MCIgaGVpZ2h0PSI1MDAiIHZpZXdCb3g9IjAgMCAxMTQwIDUwMCIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+PCEtLQpTb3VyY2UgVVJMOiBob2xkZXIuanMvMTE0MHg1MDAvYXV0by8jNzc3OiM1NTUvdGV4dDpGaXJzdCBzbGlkZQpDcmVhdGVkIHdpdGggSG9sZGVyLmpzIDIuNi4wLgpMZWFybiBtb3JlIGF0IGh0dHA6Ly9ob2xkZXJqcy5jb20KKGMpIDIwMTItMjAxNSBJdmFuIE1hbG9waW5za3kgLSBodHRwOi8vaW1za3kuY28KLS0+PGRlZnM+PHN0eWxlIHR5cGU9InRleHQvY3NzIj48IVtDREFUQVsjaG9sZGVyXzE1NjJjYTIxYzRkIHRleHQgeyBmaWxsOiM1NTU7Zm9udC13ZWlnaHQ6Ym9sZDtmb250LWZhbWlseTpBcmlhbCwgSGVsdmV0aWNhLCBPcGVuIFNhbnMsIHNhbnMtc2VyaWYsIG1vbm9zcGFjZTtmb250LXNpemU6NTdwdCB9IF1dPjwvc3R5bGU+PC9kZWZzPjxnIGlkPSJob2xkZXJfMTU2MmNhMjFjNGQiPjxyZWN0IHdpZHRoPSIxMTQwIiBoZWlnaHQ9IjUwMCIgZmlsbD0iIzc3NyIvPjxnPjx0ZXh0IHg9IjM5MC41MDc4MTI1IiB5PSIyNzUuNSI+Rmlyc3Qgc2xpZGU8L3RleHQ+PC9nPjwvZz48L3N2Zz4=" data-holder-rendered="true">
</div>
<div class="item active left">
<img data-src="holder.js/1140x500/auto/#666:#444/text:Second slide" alt="Second slide [1140x500]" src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9InllcyI/PjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB3aWR0aD0iMTE0MCIgaGVpZ2h0PSI1MDAiIHZpZXdCb3g9IjAgMCAxMTQwIDUwMCIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+PCEtLQpTb3VyY2UgVVJMOiBob2xkZXIuanMvMTE0MHg1MDAvYXV0by8jNjY2OiM0NDQvdGV4dDpTZWNvbmQgc2xpZGUKQ3JlYXRlZCB3aXRoIEhvbGRlci5qcyAyLjYuMC4KTGVhcm4gbW9yZSBhdCBodHRwOi8vaG9sZGVyanMuY29tCihjKSAyMDEyLTIwMTUgSXZhbiBNYWxvcGluc2t5IC0gaHR0cDovL2ltc2t5LmNvCi0tPjxkZWZzPjxzdHlsZSB0eXBlPSJ0ZXh0L2NzcyI+PCFbQ0RBVEFbI2hvbGRlcl8xNTYyY2ExZTY3NCB0ZXh0IHsgZmlsbDojNDQ0O2ZvbnQtd2VpZ2h0OmJvbGQ7Zm9udC1mYW1pbHk6QXJpYWwsIEhlbHZldGljYSwgT3BlbiBTYW5zLCBzYW5zLXNlcmlmLCBtb25vc3BhY2U7Zm9udC1zaXplOjU3cHQgfSBdXT48L3N0eWxlPjwvZGVmcz48ZyBpZD0iaG9sZGVyXzE1NjJjYTFlNjc0Ij48cmVjdCB3aWR0aD0iMTE0MCIgaGVpZ2h0PSI1MDAiIGZpbGw9IiM2NjYiLz48Zz48dGV4dCB4PSIzMzUuNjAxNTYyNSIgeT0iMjc1LjUiPlNlY29uZCBzbGlkZTwvdGV4dD48L2c+PC9nPjwvc3ZnPg==" data-holder-rendered="true">
</div>
<div class="item next left">
<img data-src="holder.js/1140x500/auto/#555:#333/text:Third slide" alt="Third slide [1140x500]" src="data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiIHN0YW5kYWxvbmU9InllcyI/PjxzdmcgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB3aWR0aD0iMTE0MCIgaGVpZ2h0PSI1MDAiIHZpZXdCb3g9IjAgMCAxMTQwIDUwMCIgcHJlc2VydmVBc3BlY3RSYXRpbz0ibm9uZSI+PCEtLQpTb3VyY2UgVVJMOiBob2xkZXIuanMvMTE0MHg1MDAvYXV0by8jNTU1OiMzMzMvdGV4dDpUaGlyZCBzbGlkZQpDcmVhdGVkIHdpdGggSG9sZGVyLmpzIDIuNi4wLgpMZWFybiBtb3JlIGF0IGh0dHA6Ly9ob2xkZXJqcy5jb20KKGMpIDIwMTItMjAxNSBJdmFuIE1hbG9waW5za3kgLSBodHRwOi8vaW1za3kuY28KLS0+PGRlZnM+PHN0eWxlIHR5cGU9InRleHQvY3NzIj48IVtDREFUQVsjaG9sZGVyXzE1NjJjYTFiNTg5IHRleHQgeyBmaWxsOiMzMzM7Zm9udC13ZWlnaHQ6Ym9sZDtmb250LWZhbWlseTpBcmlhbCwgSGVsdmV0aWNhLCBPcGVuIFNhbnMsIHNhbnMtc2VyaWYsIG1vbm9zcGFjZTtmb250LXNpemU6NTdwdCB9IF1dPjwvc3R5bGU+PC9kZWZzPjxnIGlkPSJob2xkZXJfMTU2MmNhMWI1ODkiPjxyZWN0IHdpZHRoPSIxMTQwIiBoZWlnaHQ9IjUwMCIgZmlsbD0iIzU1NSIvPjxnPjx0ZXh0IHg9IjM3Ny44NjcxODc1IiB5PSIyNzUuNSI+VGhpcmQgc2xpZGU8L3RleHQ+PC9nPjwvZz48L3N2Zz4=" data-holder-rendered="true">
</div>
</div>
<a class="left carousel-control" href="#carousel-example-generic" role="button" data-slide="prev">
<span class="glyphicon glyphicon-chevron-left" aria-hidden="true"></span>
<span class="sr-only">Previous</span>
</a>
<a class="right carousel-control" href="#carousel-example-generic" role="button" data-slide="next">
<span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span>
<span class="sr-only">Next</span>
</a>
</div>
</div> <!-- /container -->
@@ -1,15 +0,0 @@
/* eslint-env node */
'use strict';
module.exports = function(config) {
config.set({
scripts: [{
id: 'angular',
src: '/build/angular.js'
},
{
src: 'app.js'
}]
});
};
-40
View File
@@ -1,40 +0,0 @@
<div ng-app="boostrapCompileBenchmark" ng-cloak>
<div ng-controller="DataController as config">
<p>Please, select which configuration you want to use:</p>
<ul>
<li>
<a href="?comment=disabled&css=disabled">Only EA</a>
<span ng-show="config.isEA">(active)</span>
</li>
<li>
<a href="?comment=disabled">Active EA and classes directives</a>
<span ng-show="config.isEAC">(active)</span>
</li>
<li>
<a href="?css=disabled">Active EA and comment directives</a>
<span ng-show="config.isEAM">(active)</span>
</li>
<li>
<a href="?">Active all directives</a>
<span ng-show="config.isEACM">(active)</span>
</li>
</ul>
<hr>
<p>How many repetitions do you want to do?</p>
<input type="number" ng-model="config.repeats">
<hr>
<p>Template to $compile:</p>
<select
ng-options="template for template in config.templates"
ng-model="config.selectedTemplate"
ng-change="config.loadTemplate()"></select>
<p>The benchmark is
<span ng-show="config.html">Ready!</span>
<span ng-hide="config.html">LOADING!</span>
</p>
</div>
</div>
-58
View File
@@ -1,58 +0,0 @@
'use strict';
var app = angular.module('eventDelegationBenchmark', []);
app.directive('noopDir', function() {
return {
compile: function($element, $attrs) {
return function($scope, $element) {
return 1;
};
}
};
});
app.directive('nativeClick', ['$parse', function($parse) {
return {
compile: function($element, $attrs) {
$parse($attrs.tstEvent);
return function($scope, $element) {
$element[0].addEventListener('click', function() {
console.log('clicked');
}, false);
};
}
};
}]);
app.directive('dlgtClick', function() {
return {
compile: function($element, $attrs) {
// We don't setup the global event listeners as the costs are small and one time only...
}
};
});
app.controller('DataController', function DataController($rootScope) {
this.ngRepeatCount = 1000;
this.rows = [];
var self = this;
benchmarkSteps.push({
name: '$apply',
fn: function() {
var oldRows = self.rows;
$rootScope.$apply(function() {
self.rows = [];
});
self.rows = oldRows;
if (self.rows.length !== self.ngRepeatCount) {
self.rows = [];
for (var i = 0; i < self.ngRepeatCount; i++) {
self.rows.push('row' + i);
}
}
$rootScope.$apply();
}
});
});
-14
View File
@@ -1,14 +0,0 @@
/* eslint-env node */
'use strict';
module.exports = function(config) {
config.set({
scripts: [{
id: 'angular',
src: '/build/angular.js'
}, {
src: 'app.js'
}]
});
};
-139
View File
@@ -1,139 +0,0 @@
<div ng-app="eventDelegationBenchmark">
<div ng-controller="DataController as ctrl">
<div class="container-fluid">
<p>
Impact of event delegation.
</p>
<p>
<label>
Number of ngRepeats:
<input type="number" ng-model="ctrl.ngRepeatCount">
</label>
</p>
<p>
<div class="radio"><label><input type=radio ng-model="benchmarkType" value="ngClick">ngClick</label></div>
<div class="radio"><label><input type=radio ng-model="benchmarkType" value="ngClickNoJqLite">ngClick without jqLite</label></div>
<div class="radio"><label><input type=radio ng-model="benchmarkType" value="ngShow">baseline: ng-show</label></div>
<div class="radio"><label><input type=radio ng-model="benchmarkType" value="textInterpolation">baseline: text interpolation</label></div>
<div class="radio"><label><input type=radio ng-model="benchmarkType" value="dlgtClick">delegate event directive (only compile)</label></div>
<div class="radio"><label><input type=radio ng-model="benchmarkType" value="noopDir">baseline: noop directive (compile and link)</label></div>
<div class="radio"><label><input type=radio ng-model="benchmarkType" value="noop">baseline: no directive</label></div>
</p>
<p>
How to read the results:
<ul>
<li>The benchmark measures how long it takes to instantiate a given number of directives</li>
<li>ngClick is compared against ngShow and text interpolation as baseline. The results show
how expensive ngClick is compared to other very simple directives that touch the DOM.
</li>
<li>To measure the impact of jqLite.on vs element.addEventListener there is also a benchmark
that as a modified version of ngClick that uses element.addEventListener.
</li>
<li>The delegate event directive is compared against a noop directive with a compile and link function and the case with no directives.
The result shows how expensive it is to add a link function to a directive, as the delegate event directive has none.
</li>
</ul>
</p>
<p>
Results as of 7/31/2014:
<ul>
<li>ngClick is very close to ngShow and text interpolation, especially when looking at a version of ngClick that does not use jqLite.on but element.addEventListener instead.</li>
<li>A delegate event directive that has no link function has the same speed as a directive with link function. I.e. ngClick is slower compared to the delegate event directive only because ngClick touches
the DOM for every element</li>
<li>A delegate event directive could be about 50% faster than ngClick. However, the overall performance
benefit depends on how many (and which) other directives are used on the same element
and what other things are part of the measures use case.
E.g. rows of a table with ngRepeat that use ngClick will probably also contain text interpolation.
</li>
</ul>
</p>
Debug output:
<ng-switch on="benchmarkType">
<div ng-switch-when="ngClick">
<div>
<span ng-repeat="row in ctrl.rows">
<span ng-click="a()">1</span>
<span ng-click="a()">1</span>
<span ng-click="a()">1</span>
<span ng-click="a()">1</span>
</span>
</div>
</div>
<div ng-switch-when="ngClickNoJqLite">
<div>
<span ng-repeat="row in ctrl.rows">
<span native-click="a()">1</span>
<span native-click="a()">1</span>
<span native-click="a()">1</span>
<span native-click="a()">1</span>
<span native-click="a()">1</span>
</span>
</div>
</div>
<div ng-switch-when="ngShow">
<div>
<span ng-repeat="row in ctrl.rows">
<span ng-show="true">1</span>
<span ng-show="true">1</span>
<span ng-show="true">1</span>
<span ng-show="true">1</span>
<span ng-show="true">1</span>
</span>
</div>
</div>
<div ng-switch-when="textInterpolation">
<div>
<span ng-repeat="row in ctrl.rows">
<span>{{row}}</span>
<span>{{row}}</span>
<span>{{row}}</span>
<span>{{row}}</span>
<span>{{row}}</span>
</span>
</div>
</div>
<div ng-switch-when="dlgtClick">
<div>
<span ng-repeat="row in ctrl.rows">
<span dlgt-click="a()">1</span>
<span dlgt-click="a()">1</span>
<span dlgt-click="a()">1</span>
<span dlgt-click="a()">1</span>
<span dlgt-click="a()">1</span>
</span>
</div>
</div>
<div ng-switch-when="noopDir">
<div>
<span ng-repeat="row in ctrl.rows">
<span noop-dir>1</span>
<span noop-dir>1</span>
<span noop-dir>1</span>
<span noop-dir>1</span>
<span noop-dir>1</span>
</span>
</div>
</div>
<div ng-switch-when="noop">
<div>
<span ng-repeat="row in ctrl.rows">
<span>1</span>
<span>1</span>
<span>1</span>
<span>1</span>
<span>1</span>
</span>
</div>
</div>
</ng-switch>
</div>
</div>
</div>
-187
View File
@@ -1,187 +0,0 @@
'use strict';
var app = angular.module('largetableBenchmark', []);
app.config(function($compileProvider) {
if ($compileProvider.debugInfoEnabled) {
$compileProvider.debugInfoEnabled(false);
}
});
app.filter('noop', function() {
return function(input) {
return input;
};
});
app.controller('DataController', function DataController($scope, $rootScope) {
var totalRows = 1000;
var totalColumns = 20;
var data = $scope.data = [];
$scope.digestDuration = '?';
$scope.numberOfBindings = totalRows * totalColumns * 2 + totalRows + 1;
$scope.numberOfWatches = '?';
/** @this */
function iGetter() { return this.i; }
/** @this */
function jGetter() { return this.j; }
for (var i = 0; i < totalRows; i++) {
data[i] = [];
for (var j = 0; j < totalColumns; j++) {
data[i][j] = {
i: i, j: j,
iFn: iGetter,
jFn: jGetter
};
}
}
var previousType;
benchmarkSteps.push({
name: 'destroy',
fn: function() {
$scope.$apply(function() {
previousType = $scope.benchmarkType;
$scope.benchmarkType = 'none';
});
}
});
benchmarkSteps.push({
name: 'create',
fn: function() {
$scope.$apply(function() {
$scope.benchmarkType = previousType;
});
}
});
benchmarkSteps.push({
name: '$apply',
fn: function() {
$rootScope.$apply();
}
});
});
app.directive('baselineBindingTable', function() {
return {
restrict: 'E',
link: function($scope, $element) {
var i, j, row, cell, comment;
var document = window.document;
var template = document.createElement('span');
template.setAttribute('ng-repeat', 'foo in foos');
template.classList.add('ng-scope');
template.appendChild(document.createElement('span'));
template.appendChild(document.createTextNode(':'));
template.appendChild(document.createElement('span'));
template.appendChild(document.createTextNode('|'));
for (i = 0; i < 1000; i++) {
row = document.createElement('div');
$element[0].appendChild(row);
for (j = 0; j < 20; j++) {
cell = template.cloneNode(true);
row.appendChild(cell);
cell.childNodes[0].textContent = i;
cell.childNodes[2].textContent = j;
cell.ng3992 = 'xxx';
comment = document.createComment('ngRepeat end: bar in foo');
row.appendChild(comment);
}
comment = document.createComment('ngRepeat end: foo in foos');
$element[0].appendChild(comment);
}
}
};
});
app.directive('baselineInterpolationTable', function() {
return {
restrict: 'E',
link: function($scope, $element) {
var i, j, row, cell, comment;
var document = window.document;
var template = document.createElement('span');
template.setAttribute('ng-repeat', 'foo in foos');
template.classList.add('ng-scope');
for (i = 0; i < 1000; i++) {
row = document.createElement('div');
$element[0].appendChild(row);
for (j = 0; j < 20; j++) {
cell = template.cloneNode(true);
row.appendChild(cell);
cell.textContent = '' + i + ':' + j + '|';
cell.ng3992 = 'xxx';
comment = document.createComment('ngRepeat end: bar in foo');
row.appendChild(comment);
}
comment = document.createComment('ngRepeat end: foo in foos');
$element[0].appendChild(comment);
}
}
};
});
/*
the fastest
240/44
app.directive('baselineTable', function() {
return function($scope, $element) {
var i, j, row, cell;
for (i = 0; i < 1000; i++) {
row = document.createElement('div');
for (j = 0; j < 20; j++) {
cell = document.createElement('span');
cell.textContent = '' + i + ':' + j;
row.appendChild(cell);
}
$element[0].appendChild(row);
}
};
});
*/
/*
with comments and expando
232/90
app.directive('baselineTable', function() {
return function($scope, $element) {
var i, j, row, cell, comment;
for (i = 0; i < 1000; i++) {
row = document.createElement('div');
$element[0].appendChild(row);
for (j = 0; j < 20; j++) {
cell = document.createElement('span');
row.appendChild(cell);
cell.textContent = '' + i + ':' + j;
cell.ng3992 = 'xxx';
comment = document.createComment('ngRepeat end: bar in foo');
row.appendChild(comment);
}
comment = document.createComment('ngRepeat end: foo in foos');
$element[0].appendChild(comment);
}
};
});
*/
-19
View File
@@ -1,19 +0,0 @@
/* eslint-env node */
'use strict';
module.exports = function(config) {
config.set({
scripts: [{
id: 'jquery',
src: 'jquery-noop.js'
},
{
id: 'angular',
src: '/build/angular.js'
},
{
src: 'app.js'
}]
});
};
-1
View File
@@ -1 +0,0 @@
// Override me with ?jquery=/node_modules/jquery/dist/jquery.js
-106
View File
@@ -1,106 +0,0 @@
<style>
[ng-cloak] { display: none; }
</style>
<div ng-app="largetableBenchmark" ng-cloak>
<div ng-controller="DataController">
<div class="container-fluid">
<p>
Large table rendered with AngularJS
</p>
<div><label><input type="radio" ng-model="benchmarkType" value="none">none: </label></div>
<div><label><input type="radio" ng-model="benchmarkType" value="baselineBinding">baseline binding: </label></div>
<div><label><input type="radio" ng-model="benchmarkType" value="baselineInterpolation">baseline interpolation: </label></div>
<div><label><input type="radio" ng-model="benchmarkType" value="ngBind">ngBind: </label></div>
<div><label><input type="radio" ng-model="benchmarkType" value="ngBindOnce">ngBindOnce: </label></div>
<div><label><input type="radio" ng-model="benchmarkType" value="interpolation">interpolation: </label></div>
<div><label><input type="radio" ng-model="benchmarkType" value="bindOnceInterpolation">interpolation + bind-once: </label></div>
<div><label><input type="radio" ng-model="benchmarkType" value="interpolationAttr">attribute interpolation: </label></div>
<div><label><input type="radio" ng-model="benchmarkType" value="ngBindFn">ngBind + fnInvocation: </label></div>
<div><label><input type="radio" ng-model="benchmarkType" value="interpolationFn">interpolation + fnInvocation: </label></div>
<div><label><input type="radio" ng-model="benchmarkType" value="ngBindFilter">ngBind + filter: </label></div>
<div><label><input type="radio" ng-model="benchmarkType" value="interpolationFilter">interpolation + filter: </label></div>
<div><label><input type="radio" ng-model="benchmarkType" value="ngModelConstName">ngModel (const name): </label></div>
<div><label><input type="radio" ng-model="benchmarkType" value="ngModelInterpName">ngModel (interp name): </label></div>
<ng-switch on="benchmarkType">
<baseline-binding-table ng-switch-when="baselineBinding">
</baseline-binding-table>
<baseline-interpolation-table ng-switch-when="baselineInterpolation">
</baseline-interpolation-table>
<div ng-switch-when="ngBind">
<h2>baseline binding</h2>
<div ng-repeat="row in data">
<span ng-repeat="column in row">
<span ng-bind="column.i"></span>:<span ng-bind="column.j"></span>|
</span>
</div>
</div>
<div ng-switch-when="ngBindOnce">
<h2>baseline binding once</h2>
<div ng-repeat="row in ::data">
<span ng-repeat="column in ::row">
<span ng-bind="::column.i"></span>:<span ng-bind="::column.j"></span>|
</span>
</div>
</div>
<div ng-switch-when="interpolation">
<h2>baseline interpolation</h2>
<div ng-repeat="row in data">
<span ng-repeat="column in row">{{column.i}}:{{column.j}}|</span>
</div>
</div>
<div ng-switch-when="bindOnceInterpolation">
<h2>baseline one-time interpolation</h2>
<div ng-repeat="row in ::data">
<span ng-repeat="column in ::row">{{::column.i}}:{{::column.j}}|</span>
</div>
</div>
<div ng-switch-when="interpolationAttr">
<h2>attribute interpolation</h2>
<div ng-repeat="row in data">
<span ng-repeat="column in row" i="{{column.i}}" j="{{column.j}}">i,j attrs</span>
</div>
</div>
<div ng-switch-when="ngBindFn">
<h2>bindings with functions</h2>
<div ng-repeat="row in data">
<span ng-repeat="column in row"><span ng-bind="column.iFn()"></span>:<span ng-bind="column.jFn()"></span>|</span>
</div>
</div>
<div ng-switch-when="interpolationFn">
<h2>interpolation with functions</h2>
<div ng-repeat="row in data">
<span ng-repeat="column in row">{{column.iFn()}}:{{column.jFn()}}|</span>
</div>
</div>
<div ng-switch-when="ngBindFilter">
<h2>bindings with filter</h2>
<div ng-repeat="row in data">
<span ng-repeat="column in row"><span ng-bind="column.i | noop"></span>:<span ng-bind="column.j | noop"></span>|</span>
</div>
</div>
<div ng-switch-when="interpolationFilter">
<h2>interpolation with filter</h2>
<div ng-repeat="row in data">
<span ng-repeat="column in row">{{column.i | noop}}:{{column.j | noop}}|</span>
</div>
</div>
<div ng-switch-when="ngModelConstName">
<h2>ngModel (const name)</h2>
<div ng-repeat="row in data">
<input type="text" ng-model="row.i" name="constName" />
<input type="text" ng-model="row.j" />
</div>
</div>
<div ng-switch-when="ngModelInterpName">
<h2>ngModel (interp name)</h2>
<div ng-repeat="(rowIdx, row) in data">
<input type="text" ng-model="row.i" name="input-{{rowIdx}}" />
<input type="text" ng-model="row.j" name="input2-{{rowIdx}}" />
</div>
</div>
</ng-switch>
</div>
</div>
</div>
-108
View File
@@ -1,108 +0,0 @@
'use strict';
var app = angular.module('ngClassBenchmark', []);
app.controller('DataController', function DataController($scope) {
this.init = function() {
this.numberOfTodos = 1000;
this.implementation = 'tableOptimized';
this.completedPeriodicity = 3;
this.importantPeriodicity = 13;
this.urgentPeriodicity = 29;
this.createTodos(100);
this.setTodosValuesWithSeed(0);
};
this.clearTodos = function() {
this.todos = null;
};
this.createTodos = function(count) {
var i;
this.todos = [];
for (i = 0; i < count; i++) {
this.todos.push({
id: i + 1,
completed: false,
important: false,
urgent: false
});
}
};
this.setTodosValuesWithSeed = function(offset) {
var i, todo;
for (i = 0; i < this.todos.length; i++) {
todo = this.todos[i];
todo.completed = 0 === (i + offset) % this.completedPeriodicity;
todo.important = 0 === (i + offset) % this.importantPeriodicity;
todo.urgent = 0 === (i + offset) % this.urgentPeriodicity;
}
};
this.init();
benchmarkSteps.push({
name: 'setup',
fn: function() {
$scope.$apply();
this.clearTodos();
this.createTodos(this.numberOfTodos);
}.bind(this)
});
benchmarkSteps.push({
name: 'create',
fn: function() {
// initialize data for first time that will construct the DOM
this.setTodosValuesWithSeed(0);
$scope.$apply();
}.bind(this)
});
benchmarkSteps.push({
name: '$apply',
fn: function() {
$scope.$apply();
}
});
benchmarkSteps.push({
name: 'update',
fn: function() {
// move everything but completed
this.setTodosValuesWithSeed(3);
$scope.$apply();
}.bind(this)
});
benchmarkSteps.push({
name: 'unclass',
fn: function() {
// remove all classes
this.setTodosValuesWithSeed(NaN);
$scope.$apply();
}.bind(this)
});
benchmarkSteps.push({
name: 'class',
fn: function() {
// add all classes as the initial state
this.setTodosValuesWithSeed(0);
$scope.$apply();
}.bind(this)
});
benchmarkSteps.push({
name: 'destroy',
fn: function() {
this.clearTodos();
$scope.$apply();
}.bind(this)
});
});
-15
View File
@@ -1,15 +0,0 @@
/* eslint-env node */
'use strict';
module.exports = function(config) {
config.set({
scripts: [{
id: 'angular',
src: '/build/angular.js'
},
{
src: 'app.js'
}]
});
};
-177
View File
@@ -1,177 +0,0 @@
<style>
.gold {
background: gold;
}
.silver {
background: silver;
}
.table tbody tr > td.success {
background-color: #dff0d8;
}
.table tbody tr > td.error {
background-color: #f2dede;
}
.table tbody tr > td.warning {
background-color: #fcf8e3;
}
.table tbody tr > td.info {
background-color: #d9edf7;
}
.completed {
text-decoration: line-through;
}
.important {
font-weight: bold;
}
.urgent {
color: red;
}
</style>
<div ng-app="ngClassBenchmark" ng-cloak class="container-fluid">
<div ng-controller="DataController as benchmark" class="row">
<div class="col-lg-12">
<div class="well">
<h3>Parameters</h3>
<br>
<p>
<label>Number of todos</label><br>
<input type="number" ng-model="benchmark.numberOfTodos">
</p>
<br>
<p>
<label>Implementation</label><br>
<div class="radio">
<label>
<input ng-model="benchmark.implementation" value="tableOptimized"
type="radio" name="implementation">
Table optimized <br>
<code>ng-class="todo.completed && 'success'"</code>
</label>
</div>
<div class="radio">
<label>
<input ng-model="benchmark.implementation" value="table"
type="radio" name="implementation">
Table <br>
<code>ng-class="{success: todo.completed}"</code>
</label>
</div>
<div class="radio">
<label>
<input ng-model="benchmark.implementation" value="list"
type="radio" name="implementation">
List <br>
<code>ng-class="{completed: todo.completed, urgent: todo.urgent, important: todo.important"}</code>
</label>
</div>
<div class="radio">
<label>
<input ng-model="benchmark.implementation" value="singleOptimized"
type="radio" name="implementation">
Single ngClass optimized <br>
<code>
ng-class="{'panel-success': !!benchmark.todos, 'panel-danger': !benchmark.todos}"
</code>
</label>
</div>
<div class="radio">
<label>
<input ng-model="benchmark.implementation" value="single"
type="radio" name="implementation">
Single ngClass <br>
<code>
ng-class="{'panel-success': benchmark.todos, 'panel-danger': !benchmark.todos}"
</code>
</label>
</div>
</p>
</div>
<br>
<h3>Example</h3>
<div ng-switch="benchmark.implementation">
<table ng-switch-when="tableOptimized" class="table">
<thead>
<tr>
<th>todo #id</th>
<th>completed?</th>
<th>urgent?</th>
<th>important?</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="todo in benchmark.todos track by todo.id"
ng-class="todo.completed && 'active'"
ng-class-even="todo.completed && todo.important && 'gold'"
ng-class-odd="todo.completed && todo.important && 'silver'"
>
<td>#{{todo.id}}</td>
<td>{{todo.completed}}</td>
<td ng-class="todo.urgent && 'danger'">{{todo.urgent}}</td>
<td ng-class="todo.important && 'success'">{{todo.important}}</td>
</tr>
</tbody>
</table>
<table ng-switch-when="table" class="table">
<thead>
<tr>
<th>todo #id</th>
<th>completed?</th>
<th>urgent?</th>
<th>important?</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="todo in benchmark.todos track by todo.id"
ng-class="{active: todo.completed}"
ng-class-even="{gold: todo.completed && todo.important}"
ng-class-odd="{silver: todo.completed && todo.important}"
>
<td>#{{todo.id}}</td>
<td>{{todo.completed}}</td>
<td ng-class="{danger: todo.urgent}">{{todo.urgent}}</td>
<td ng-class="{success: todo.important}">{{todo.important}}</td>
</tr>
</tbody>
</table>
<ul ng-switch-when="list">
<li ng-repeat="todo in benchmark.todos track by todo.id"
ng-class="{
completed: todo.completed,
urgent: todo.urgent,
important: todo.important
}">#{{todo.id}}</li>
</ul>
<div ng-switch-when="singleOptimized"
class="panel"
ng-class="{'panel-success': !!benchmark.todos, 'panel-danger': !benchmark.todos}">
<div class="panel-heading">
<h3 class="panel-title">Information</h3>
</div>
<div class="panel-body"> The title is green because there are todos... </div>
</div>
<div ng-switch-when="single"
class="panel"
ng-class="{'panel-success': benchmark.todos, 'panel-danger': !benchmark.todos}">
<div class="panel-heading">
<h3 class="panel-title">Information</h3>
</div>
<div class="panel-body"> The title is green because there are todos... </div>
</div>
</div>
</div>
</div>
</div>
<br><br><br>
-95
View File
@@ -1,95 +0,0 @@
'use strict';
/* globals angular, benchmarkSteps */
var app = angular.module('ngOptionsBenchmark', []);
app.config(function($compileProvider) {
if ($compileProvider.debugInfoEnabled) {
$compileProvider.debugInfoEnabled(false);
}
});
app.controller('DataController', function($scope, $element) {
$scope.items = [];
$scope.count = 10000;
function changeOptions() {
$scope.items = [];
for (var i = 0; i < $scope.count; ++i) {
$scope.items.push({
id: i,
label: 'item-' + i,
group: 'group-' + i % 100
});
}
}
var selectElement = $element.find('select');
console.log(selectElement);
benchmarkSteps.push({
name: 'add-options',
fn: function() {
$scope.$apply(function() {
$scope.count = 10000;
changeOptions();
});
}
});
benchmarkSteps.push({
name: 'set-model-1',
fn: function() {
$scope.$apply(function() {
$scope.x = $scope.items[1000];
});
}
});
benchmarkSteps.push({
name: 'set-model-2',
fn: function() {
$scope.$apply(function() {
$scope.x = $scope.items[10];
});
}
});
benchmarkSteps.push({
name: 'remove-options',
fn: function() {
$scope.count = 100;
changeOptions();
}
});
benchmarkSteps.push({
name: 'add-options',
fn: function() {
$scope.$apply(function() {
$scope.count = 10000;
changeOptions();
});
}
});
benchmarkSteps.push({
name: 'set-view-1',
fn: function() {
selectElement.val('2000');
selectElement.triggerHandler('change');
}
});
benchmarkSteps.push({
name: 'set-view-2',
fn: function() {
selectElement.val('1000');
selectElement.triggerHandler('change');
}
});
});
-15
View File
@@ -1,15 +0,0 @@
/* eslint-env node */
'use strict';
module.exports = function(config) {
config.set({
scripts: [{
id: 'angular',
src: '/build/angular.js'
},
{
src: 'app.js'
}]
});
};
-10
View File
@@ -1,10 +0,0 @@
<div ng-app="ngOptionsBenchmark" ng-cloak>
<div ng-controller="DataController">
<div class="container-fluid">
<p>
Tests the execution of ng-options for rendering during model and option updates.
</p>
<select ng-model="x" ng-options="a as a.label group by a.group for a in items track by a.id"></select>
</div>
</div>
</div>
-50
View File
@@ -1,50 +0,0 @@
'use strict';
var app = angular.module('orderByBenchmark', []);
app.controller('DataController', function DataController($rootScope, $scope) {
this.ngRepeatCount = 5000;
this.rows = [];
var self = this;
$scope.benchmarkType = 'baseline';
$scope.rawProperty = function(key) {
return function(item) {
return item[key];
};
};
// Returns a random integer between min (included) and max (excluded)
function getRandomInt(min, max) {
return Math.floor(Math.random() * (max - min)) + min;
}
benchmarkSteps.push({
name: 'setup',
description: 'Set rows to empty array and apply, then push new rows to be applied in next step',
fn: function() {
var oldRows = self.rows;
$rootScope.$apply(function() {
self.rows = [];
});
self.rows = oldRows;
if (self.rows.length !== self.ngRepeatCount) {
self.rows = [];
for (var i = 0; i < self.ngRepeatCount; i++) {
self.rows.push({
'name': getRandomInt(i, (i + 40)),
'index': i
});
}
}
}
});
benchmarkSteps.push({
name: '$apply',
fn: function() {
$rootScope.$apply();
}
});
});
-18
View File
@@ -1,18 +0,0 @@
/* eslint-env node */
'use strict';
module.exports = function(config) {
config.set({
scripts: [
{
'id': 'jquery',
'src': 'jquery-noop.js'
}, {
id: 'angular',
src: '/build/angular.js'
}, {
src: 'app.js'
}]
});
};
-1
View File
@@ -1 +0,0 @@
// Override me with ?jquery=/node_modules/jquery/dist/jquery.js
-82
View File
@@ -1,82 +0,0 @@
<div class="container-fluid" ng-app="orderByBenchmark">
<div class="row" ng-controller="DataController as ctrl">
<div class="col-lg-8">
<p>Filters</p>
<p>
<label>Number of ngRepeats:</label>
<input type="number" ng-model="ctrl.ngRepeatCount">
</p>
<p>
<div class="radio">
<label>
<input type="radio" ng-model="benchmarkType" value="baseline">baseline
</label>
</div>
<pre><code>ng-repeat="row in ctrl.rows"</code></pre>
<br />
<div class="radio">
<label>
<input type="radio" ng-model="benchmarkType" value="orderBy">orderBy
</label>
</div>
<pre><code>ng-repeat="row in ctrl.rows | orderBy:'name'"</code></pre>
<br />
<div class="radio">
<label>
<input type="radio" ng-model="benchmarkType" value="orderByArray">orderBy array expression
</label>
</div>
<pre><code>ng-repeat="row in ctrl.rows | orderBy:['name', 'index']"</code></pre>
<br />
<div class="radio">
<label>
<input type="radio" ng-model="benchmarkType"
value="orderByFunction">orderBy function expression
</label>
</div>
<pre><code>ng-repeat="row in ctrl.rows | orderBy:rawProperty('name')"</code></pre>
<br />
<div class="radio">
<label>
<input type="radio" ng-model="benchmarkType"
value="orderByArrayFunction">orderBy array function expression
</label>
</div>
<pre><code>ng-repeat="row in ctrl.rows | orderBy:[rawProperty('name'), rawProperty('index')]"</code></pre>
</p>
Debug output:
<ng-switch on="benchmarkType">
<div ng-switch-when="baseline">
<span ng-repeat="row in ctrl.rows">
<span ng-bind="row.name"></span>,
</span>
</div>
<div ng-switch-when="orderBy">
<span ng-repeat="row in ctrl.rows | orderBy:'name'">
<span ng-bind="row.name"></span>,
</span>
</div>
<div ng-switch-when="orderByArray">
<span ng-repeat="row in ctrl.rows | orderBy:['name', 'index']">
<span ng-bind="row.name"></span>,
</span>
</div>
<div ng-switch-when="orderByFunction">
<span ng-repeat="row in ctrl.rows | orderBy:rawProperty('name')">
<span ng-bind="row.name"></span>,
</span>
</div>
<div ng-switch-when="orderByArrayFunction">
<span ng-repeat="row in ctrl.rows | orderBy:[rawProperty('name'), rawProperty('index')]">
<span ng-bind="row.name"></span>,
</span>
</div>
</ng-switch>
</div>
</div>
</div>
-84
View File
@@ -1,84 +0,0 @@
'use strict';
var app = angular.module('parsedExpressionBenchmark', []);
app.config(function($compileProvider) {
if ($compileProvider.debugInfoEnabled) {
$compileProvider.debugInfoEnabled(false);
}
});
app.filter('noop', function() {
return function(input) {
return input;
};
});
//Executes the specified expression as a watcher
app.directive('bmPeWatch', function() {
return {
restrict: 'A',
compile: function($element, $attrs) {
$element.text($attrs.bmPeWatch);
return function($scope, $element, $attrs) {
$scope.$watch($attrs.bmPeWatch, function(val) {
$element.text(val);
});
};
}
};
});
//Executes the specified expression as a collection watcher
app.directive('bmPeWatchCollection', function() {
return {
restrict: 'A',
compile: function($element, $attrs) {
$element.text($attrs.bmPeWatchCollection);
return function($scope, $element, $attrs) {
$scope.$watchCollection($attrs.bmPeWatchCollection, function(val) {
$element.text(val);
});
};
}
};
});
app.controller('DataController', function($scope, $rootScope) {
var totalRows = 10000;
var data = $scope.data = [];
var star = '*';
$scope.func = function() { return star; };
for (var i = 0; i < totalRows; i++) {
data.push({
index: i,
odd: i % 2 === 0,
even: i % 2 === 1,
str0: 'foo-' + Math.random() * Date.now(),
str1: 'bar-' + Math.random() * Date.now(),
str2: 'baz-' + Math.random() * Date.now(),
num0: Math.random() * Date.now(),
num1: Math.random() * Date.now(),
num2: Math.random() * Date.now(),
date0: new Date(Math.random() * Date.now()),
date1: new Date(Math.random() * Date.now()),
date2: new Date(Math.random() * Date.now()),
func: function() { return star; },
obj: data[i - 1],
keys: data[i - 1] && (data[i - 1].keys || Object.keys(data[i - 1]))
});
}
benchmarkSteps.push({
name: '$apply',
fn: function() {
for (var i = 0; i < 50; i++) {
$rootScope.$digest();
}
}
});
});
@@ -1,15 +0,0 @@
/* eslint-env node */
'use strict';
module.exports = function(config) {
config.set({
scripts: [{
id: 'angular',
src: '/build/angular.js'
},
{
src: 'app.js'
}]
});
};
-253
View File
@@ -1,253 +0,0 @@
<div ng-app="parsedExpressionBenchmark" ng-cloak>
<div ng-controller="DataController">
<div class="container-fluid">
<p>
Tests the execution of $parse()ed expressions. Each test tries to isolate specific expression types. Expressions should (probably) not be constant so they get evaluated per digest.
</p>
<ul style="list-style:none">
<li>
<input type="radio" ng-model="expressionType" value="simplePath" id="simplePath">
<label for="simplePath">Simple Paths</label>
</li>
<li>
<input type="radio" ng-model="expressionType" value="complexPath" id="complexPath">
<label for="complexPath">Complex Paths</label>
</li>
<li>
<input type="radio" ng-model="expressionType" value="fieldAccess" id="fieldAccess">
<label for="fieldAccess">Field Accessors</label>
</li>
<li>
<input type="radio" ng-model="expressionType" value="fieldIndex" id="fieldIndex">
<label for="fieldIndex">Field Indexes</label>
</li>
<li>
<input type="radio" ng-model="expressionType" value="operators" id="operators">
<label for="operators">Binary/Unary operators</label>
</li>
<li>
<input type="radio" ng-model="expressionType" value="shortCircuitingOperators" id="shortCircuitingOperators">
<label for="shortCircuitingOperators">AND/OR short-circuiting operators</label>
</li>
<li>
<input type="radio" ng-model="expressionType" value="filters" id="filters">
<label for="filters">Filters</label>
</li>
<li>
<input type="radio" ng-model="expressionType" value="functionCalls" id="functionCalls">
<label for="functionCalls">Function calls</label>
</li>
<li>
<input type="radio" ng-model="expressionType" value="assignment" id="assignment">
<label for="assignment">Assignment</label>
</li>
<li>
<input type="radio" ng-model="expressionType" value="objectLiterals" id="objectLiterals">
<label for="objectLiterals">Object Literals</label>
</li>
<li>
<input type="radio" ng-model="expressionType" value="arrayLiterals" id="arrayLiterals">
<label for="arrayLiterals">Array Literals</label>
</li>
<li>
<input type="radio" ng-model="expressionType" value="watchCollection" id="watchCollection">
<label for="watchCollection">$watchCollection</label>
</li>
<li>
<input type="radio" ng-model="expressionType" value="watchCollectionLiterals" id="watchCollectionLiterals">
<label for="watchCollectionLiterals">$watchCollection Literals</label>
</li>
</ul>
<!--
NOTES:
- ensure each tested expression has at least one variable in it to avoid constant expressions
-->
<ul ng-switch="expressionType">
<li ng-switch-when="simplePath" ng-repeat="(rowIdx, row) in ::data">
<span bm-pe-watch="rowIdx"></span>
<span bm-pe-watch="row.index"></span>
<span bm-pe-watch="row.num0"></span>
<span bm-pe-watch="row.num1"></span>
<span bm-pe-watch="row.num2"></span>
<span bm-pe-watch="row.str0"></span>
<span bm-pe-watch="row.str1"></span>
<span bm-pe-watch="row.str2"></span>
<span bm-pe-watch="row.date0"></span>
<span bm-pe-watch="row.obj"></span>
<span bm-pe-watch="row.keys"></span>
</li>
<li ng-switch-when="complexPath" ng-repeat="(rowIdx, row) in ::data">
<span bm-pe-watch="row.index"></span>
<span bm-pe-watch="row.num0"></span>
<span bm-pe-watch="row.num1"></span>
<span bm-pe-watch="row.str0"></span>
<span bm-pe-watch="row.str1"></span>
<span bm-pe-watch="row.obj.index"></span>
<span bm-pe-watch="row.obj.index"></span>
<span bm-pe-watch="row.obj.index"></span>
<span bm-pe-watch="row.obj.obj.index"></span>
<span bm-pe-watch="row.obj.obj.index"></span>
<span bm-pe-watch="row.obj.obj.obj.index"></span>
<span bm-pe-watch="row.obj.obj.obj.index"></span>
</li>
<li ng-switch-when="fieldAccess" ng-repeat="(rowIdx, row) in ::data">
<span bm-pe-watch="data[rowIdx].index"></span>
<span bm-pe-watch="data[rowIdx].num0"></span>
<span bm-pe-watch="data[rowIdx].num1"></span>
<span bm-pe-watch="data[rowIdx].str0"></span>
<span bm-pe-watch="data[rowIdx].str1"></span>
<span bm-pe-watch="data[rowIdx].obj.index"></span>
<span bm-pe-watch="data[rowIdx].obj.index"></span>
<span bm-pe-watch="data[rowIdx].obj.index"></span>
<span bm-pe-watch="data[rowIdx].obj.obj.index"></span>
<span bm-pe-watch="data[rowIdx].obj.obj.index"></span>
<span bm-pe-watch="data[rowIdx].obj.obj.obj.index"></span>
<span bm-pe-watch="data[rowIdx].obj.obj.obj.index"></span>
</li>
<li ng-switch-when="fieldIndex" ng-repeat="(rowIdx, row) in ::data">
<span bm-pe-watch="data[rowIdx]"></span>
<span bm-pe-watch="row['str0']"></span>
<span bm-pe-watch="row['str1']"></span>
<span bm-pe-watch="data[row['index']]['index']"></span>
<span bm-pe-watch="data[rowIdx]['obj']"></span>
<span bm-pe-watch="data[rowIdx]['obj']['obj']"></span>
<span bm-pe-watch="row[row['keys'][0]]"></span>
<span bm-pe-watch="row[row['keys'][1]]"></span>
<span bm-pe-watch="row[row['keys'][2]]"></span>
<span bm-pe-watch="row[row['keys'][3]]"></span>
<span bm-pe-watch="row[row['keys'][4]]"></span>
<span bm-pe-watch="row[row['keys'][5]]"></span>
</li>
<li ng-switch-when="operators" ng-repeat="(rowIdx, row) in ::data">
<span bm-pe-watch="+rowIdx"></span>
<span bm-pe-watch="-rowIdx"></span>
<span bm-pe-watch="rowIdx + 1"></span>
<span bm-pe-watch="rowIdx - 1"></span>
<span bm-pe-watch="rowIdx * 2"></span>
<span bm-pe-watch="rowIdx + -1"></span>
<span bm-pe-watch="rowIdx - -1"></span>
<span bm-pe-watch="-rowIdx * 2 + 1"></span>
<span bm-pe-watch="rowIdx % 2"></span>
<span bm-pe-watch="rowIdx % 2 === 1"></span>
<span bm-pe-watch="rowIdx % 2 === 0"></span>
<span bm-pe-watch="rowIdx / 1"></span>
<span bm-pe-watch="-rowIdx * 2 * rowIdx + rowIdx / rowIdx + 1"></span>
</li>
<li ng-switch-when="shortCircuitingOperators" ng-repeat="(rowIdx, row) in ::data">
<span bm-pe-watch="rowIdx && row.odd"></span>
<span bm-pe-watch="row.odd && row.even"></span>
<span bm-pe-watch="row.odd && !row.even"></span>
<span bm-pe-watch="row.odd || row.even"></span>
<span bm-pe-watch="row.odd || row.even || row.index"></span>
<span bm-pe-watch="row.index === 1 || row.index === 2"></span>
<span bm-pe-watch="row.num0 < row.num1 && row.num1 < row.num2"></span>
<span bm-pe-watch="row.num0 < row.num1 || row.num1 < row.num2"></span>
</li>
<li ng-switch-when="filters" ng-repeat="(rowIdx, row) in ::data">
<span bm-pe-watch="rowIdx | noop"></span>
<span bm-pe-watch="rowIdx | noop"></span>
<span bm-pe-watch="rowIdx | noop"></span>
<span bm-pe-watch="rowIdx | noop:1"></span>
<span bm-pe-watch="rowIdx | noop:rowIdx"></span>
<span bm-pe-watch="rowIdx | noop:1:2:3:4:5"></span>
<span bm-pe-watch="rowIdx | noop:rowIdx:rowIdx:rowIdx"></span>
<span bm-pe-watch="rowIdx | noop | noop"></span>
<span bm-pe-watch="rowIdx | noop:1 | noop"></span>
<span bm-pe-watch="rowIdx | noop | noop:null:undefined:0"></span>
<span bm-pe-watch="rowIdx | noop | noop | noop"></span>
<span bm-pe-watch="rowIdx | noop:1 | noop:2 | noop:3"></span>
</li>
<li ng-switch-when="functionCalls" ng-repeat="(rowIdx, row) in ::data">
<span bm-pe-watch="func()"></span>
<span bm-pe-watch="func(1)"></span>
<span bm-pe-watch="func(1, 2)"></span>
<span bm-pe-watch="func(1, 2, 3)"></span>
<span bm-pe-watch="row.func()"></span>
<span bm-pe-watch="row.func(1)"></span>
<span bm-pe-watch="row.func(1, 2)"></span>
<span bm-pe-watch="row.func(1, 2, 3)"></span>
<span bm-pe-watch="func(func())"></span>
<span bm-pe-watch="func(func(), func())"></span>
<span bm-pe-watch="row.func(row.func())"></span>
<span bm-pe-watch="row.func(row.func(), row.func())"></span>
</li>
<li ng-switch-when="assignment" ng-repeat="(rowIdx, row) in ::data">
<span bm-pe-watch="row.foo = row.str0"></span>
<span bm-pe-watch="row.obj.foo = row.str1"></span>
<span bm-pe-watch="row.obj.obj.foo = row.str2"></span>
<span bm-pe-watch="row['bar'] = row.num0"></span>
<span bm-pe-watch="row.obj['bar'] = row.num1"></span>
<span bm-pe-watch="row.obj.obj['bar'] = row.num2"></span>
<span bm-pe-watch="row[0] = row.date0"></span>
<span bm-pe-watch="row.obj[0] = row.date1"></span>
<span bm-pe-watch="row.obj.obj[0] = row.date2"></span>
</li>
<li ng-switch-when="objectLiterals" ng-repeat="(rowIdx, row) in ::data">
<span bm-pe-watch="{foo: rowIdx}"></span>
<span bm-pe-watch="{foo: row, bar: rowIdx}"></span>
<span bm-pe-watch="{0: row, 1: rowIdx, 2: 3}"></span>
<span bm-pe-watch="{str: 'foo', num: rowIdx, b: true}"></span>
<span bm-pe-watch="{a: {b: {c: {d: {e: {f: rowIdx}}}}}}"></span>
<span bm-pe-watch="{a: rowIdx, b: 1, c: 2, d: 3, e: 4, f: 5, g: rowIdx, h: 6, i: 7, j: 8, k: rowIdx}"></span>
</li>
<li ng-switch-when="arrayLiterals" ng-repeat="(rowIdx, row) in ::data">
<span bm-pe-watch="[rowIdx]"></span>
<span bm-pe-watch="[rowIdx, 0]"></span>
<span bm-pe-watch="[rowIdx, 0, 1]"></span>
<span bm-pe-watch="[rowIdx, 0, 1, 2]"></span>
<span bm-pe-watch="[rowIdx, 0, 1, 2, 3]"></span>
<span bm-pe-watch="[[], [rowIdx], [], [], [3], [[[]]]]"></span>
<span bm-pe-watch="[rowIdx, undefined, null, true, false]"></span>
<span bm-pe-watch="[[][0], [0][0], [][rowIdx]]"></span>
<span bm-pe-watch="[0, rowIdx]"></span>
<span bm-pe-watch="[0, 1, rowIdx]"></span>
<span bm-pe-watch="[0, 1, 2, rowIdx]"></span>
<span bm-pe-watch="[0, 1, 2, 3, rowIdx]"></span>
</li>
<li ng-switch-when="watchCollection" ng-repeat="(rowIdx, row) in data">
<span bm-pe-watch-collection="data"></span>
<span bm-pe-watch-collection="row.keys"></span>
<span bm-pe-watch-collection="thisProbablyDoesntHaveAValue"></span>
</li>
<li ng-switch-when="watchCollectionLiterals" ng-repeat="(rowIdx, row) in ::data">
<span bm-pe-watch-collection="[rowIdx, row]"></span>
<span bm-pe-watch-collection="[rowIdx, row, num0, str0, date0, obj, g, h, i, j, k, l, m, n, o, p]"></span>
<span bm-pe-watch-collection="{a: rowIdx, b: row, c: num0, d: str0, e: date0, f: obj, g: g, h: h, i: i, j: j, k: k, l: l, m: m, n: n, o: o, p: p}"></span>
<!-- primitive/valueOf-compatible -->
<span bm-pe-watch-collection="[rowIdx, row]"></span>
<span bm-pe-watch-collection="[rowIdx, num0, str0, date0, date1, h, i, j, k, l, m, n, o, p]"></span>
<span bm-pe-watch-collection="{a: rowIdx, c: num0, d: str0, e: date0, g: date1, h: h, i: i, j: j, k: k, l: l, m: m, n: n, o: o, p: p}"></span>
</li>
</ul>
</div>
</div>
</div>
@@ -1,9 +0,0 @@
'use strict';
angular.module('repeatAnimateBenchmark', ['ngAnimate'])
.config(function($animateProvider) {
$animateProvider.classNameFilter(/animate-/);
})
.run(function($rootScope) {
$rootScope.fileType = 'classfilter';
});
@@ -1,6 +0,0 @@
'use strict';
angular.module('repeatAnimateBenchmark', [])
.run(function($rootScope) {
$rootScope.fileType = 'noanimate';
});
-7
View File
@@ -1,7 +0,0 @@
'use strict';
angular.module('repeatAnimateBenchmark', ['ngAnimate'])
.run(function($rootScope) {
$rootScope.fileType = 'default';
});
-24
View File
@@ -1,24 +0,0 @@
/* eslint-env node */
'use strict';
module.exports = function(config) {
config.set({
scripts: [
{
id: 'angular',
src: '/build/angular.js'
},
{
id: 'angular-animate',
src: '/build/angular-animate.js'
},
{
id: 'app',
src: 'app.js'
},
{
src: 'common.js'
}]
});
};
-120
View File
@@ -1,120 +0,0 @@
'use strict';
(function() {
var app = angular.module('repeatAnimateBenchmark');
app.config(function($compileProvider, $animateProvider) {
if ($compileProvider.debugInfoEnabled) {
$compileProvider.debugInfoEnabled(false);
}
});
app.run(function($animate) {
if ($animate.enabled) {
$animate.enabled(true);
}
});
app.controller('DataController', function($scope, $rootScope, $animate) {
var totalRows = 500;
var totalColumns = 20;
var data = $scope.data = [];
function fillData() {
if ($animate.enabled) {
$animate.enabled($scope.benchmarkType !== 'globallyDisabled');
}
for (var i = 0; i < totalRows; i++) {
data[i] = [];
for (var j = 0; j < totalColumns; j++) {
data[i][j] = {
i: i
};
}
}
}
benchmarkSteps.push({
name: 'enter',
fn: function() {
$scope.$apply(function() {
fillData();
});
}
});
benchmarkSteps.push({
name: 'leave',
fn: function() {
$scope.$apply(function() {
data = $scope.data = [];
});
}
});
});
app.directive('disableAnimations', function($animate) {
return {
link: {
pre: function(s, e) {
$animate.enabled(e, false);
}
}
};
});
app.directive('noop', function($animate) {
return {
link: {
pre: angular.noop
}
};
});
app.directive('baseline', function($document) {
return {
restrict: 'E',
link: function($scope, $element) {
var document = $document[0];
var i, j, row, cell, comment;
var template = document.createElement('span');
template.setAttribute('ng-repeat', 'foo in foos');
template.classList.add('ng-scope');
template.appendChild(document.createElement('span'));
template.appendChild(document.createTextNode(':'));
function createList() {
for (i = 0; i < $scope.data.length; i++) {
row = document.createElement('div');
$element[0].appendChild(row);
for (j = 0; j < $scope.data[i].length; j++) {
cell = template.cloneNode(true);
row.appendChild(cell);
cell.childNodes[0].textContent = i;
cell.ng339 = 'xxx';
comment = document.createComment('ngRepeat end: bar in foo');
row.appendChild(comment);
}
comment = document.createComment('ngRepeat end: foo in foos');
$element[0].appendChild(comment);
}
}
$scope.$watch('data.length', function(newVal) {
if (newVal === 0) {
while ($element[0].firstChild) {
$element[0].removeChild($element[0].firstChild);
}
} else {
createList();
}
});
}
};
});
})();
-70
View File
@@ -1,70 +0,0 @@
<div ng-app="repeatAnimateBenchmark" ng-cloak>
<div ng-controller="DataController">
<div class="container-fluid">
<p>
Tests rendering of an ngRepeat with 500 elements.<br>
Animations can be enabled / disabled in different ways.<br>
Two tests require reloading the app with different module / app configurations.
</p>
<div><label><input type="radio" ng-model="benchmarkType" value="none">none: </label></div>
<div><label><input type="radio" ng-model="benchmarkType" value="baseline">baseline (vanilla Javascript): </label></div>
<div><label><input type="radio" ng-model="benchmarkType" ng-disabled="fileType !== 'default'" value="enabled">enabled : </label> (requires <a href="./">app.js</a>)</div>
<div><label><input type="radio" ng-model="benchmarkType" ng-disabled="fileType !== 'default' && fileType !== 'classfilter'" value="globallyDisabled">globally disabled:</label> (requires <a href="./">app.js</a> or <a href="?app=app-classfilter.js">app-classfilter.js</a>)</div>
<div><label><input type="radio" ng-model="benchmarkType" ng-disabled="fileType !== 'default'" value="disabledParentElement">disabled by $animate.enabled() on parent element: </label> (requires <a href="./">app.js</a>)</div>
<div><label><input type="radio" ng-model="benchmarkType" ng-disabled="fileType !== 'noanimate'" value="noanimate">Without ngAnimate:</label> (requires <a href="?app=app-noanimate.js">app-noanimate.js</a>)</div>
<div><label><input type="radio" ng-model="benchmarkType" ng-disabled="fileType !== 'classfilter'" value="disabledClassFilter">disabled by classNameFilter on element:</label> (requires <a href="?app=app-classfilter.js">app-classfilter.js</a>)</div>
<ng-switch on="benchmarkType">
<baseline ng-switch-when="baseline">
</baseline>
<div ng-switch-when="noanimate">
<div noop>
<div ng-repeat="row in data">
<span ng-repeat="column in row">
<span>{{column.i}}</span>
</span>
</div>
</div>
</div>
<div ng-switch-when="enabled">
<div noop>
<div ng-repeat="row in data">
<span ng-repeat="column in row">
<span>{{column.i}}</span>
</span>
</div>
</div>
</div>
<div ng-switch-when="globallyDisabled">
<div noop>
<div ng-repeat="row in data">
<span ng-repeat="column in row">
<span>{{column.i}}</span>
</span>
</div>
</div>
</div>
<div ng-switch-when="disabledClassFilter">
<div noop>
<div ng-repeat="row in data">
<span class="disable-animations" ng-repeat="column in row">
<span>{{column.i}}</span>
</span>
</div>
</div>
</div>
<div ng-switch-when="disabledParentElement">
<div disable-animations>
<div ng-repeat="row in data">
<span ng-repeat="column in row">
<span>{{column.i}}</span>
</span>
</div>
</div>
</div>
</ng-switch>
</div>
</div>
</div>
-104
View File
@@ -1,104 +0,0 @@
'use strict';
/* globals angular, benchmarkSteps */
var app = angular.module('selectBenchmark', []);
app.config(function($compileProvider) {
if ($compileProvider.debugInfoEnabled) {
$compileProvider.debugInfoEnabled(false);
}
});
app.controller('DataController', function($scope, $element) {
$scope.groups = [];
$scope.count = 10000;
function changeOptions() {
$scope.groups = [];
var i = 0;
var group;
while (i < $scope.count) {
if (i % 100 === 0) {
group = {
name: 'group-' + $scope.groups.length,
items: []
};
$scope.groups.push(group);
}
group.items.push({
id: i,
label: 'item-' + i
});
i++;
}
}
var selectElement = $element.find('select');
console.log(selectElement);
benchmarkSteps.push({
name: 'add-options',
fn: function() {
$scope.$apply(function() {
$scope.count = 10000;
changeOptions();
});
}
});
benchmarkSteps.push({
name: 'set-model-1',
fn: function() {
$scope.$apply(function() {
$scope.x = $scope.groups[10].items[0];
});
}
});
benchmarkSteps.push({
name: 'set-model-2',
fn: function() {
$scope.$apply(function() {
$scope.x = $scope.groups[0].items[10];
});
}
});
benchmarkSteps.push({
name: 'remove-options',
fn: function() {
$scope.count = 100;
changeOptions();
}
});
benchmarkSteps.push({
name: 'add-options',
fn: function() {
$scope.$apply(function() {
$scope.count = 10000;
changeOptions();
});
}
});
benchmarkSteps.push({
name: 'set-view-1',
fn: function() {
selectElement.val('2000');
selectElement.triggerHandler('change');
}
});
benchmarkSteps.push({
name: 'set-view-2',
fn: function() {
selectElement.val('1000');
selectElement.triggerHandler('change');
}
});
});
-15
View File
@@ -1,15 +0,0 @@
/* eslint-env node */
'use strict';
module.exports = function(config) {
config.set({
scripts: [{
id: 'angular',
src: '/build/angular.js'
},
{
src: 'app.js'
}]
});
};
-15
View File
@@ -1,15 +0,0 @@
<div ng-app="selectBenchmark" ng-cloak>
<div ng-controller="DataController">
<div class="container-fluid">
<p>
Tests the execution of a select with ngRepeat'ed options with ngValue for rendering during model
and option updates.
</p>
<select ng-model="x">
<optgroup ng-repeat="g in groups track by g.name" label="{{g.name}}">
<option ng-repeat="a in g.items track by a.id" ng-value="a">{{a.label}}</option>
</optgroup>
</select>
</div>
</div>
</div>
Executable
+210
View File
@@ -0,0 +1,210 @@
#!/usr/bin/env node
// TODO(vojta): pre-commit hook for validating messages
// TODO(vojta): report errors, currently Q silence everything which really sucks
var child = require('child_process');
var fs = require('fs');
var util = require('util');
var q = require('qq');
var GIT_LOG_CMD = 'git log --grep="%s" -E --format=%s %s..HEAD';
var GIT_TAG_CMD = 'git describe --tags --abbrev=0';
var HEADER_TPL = '<a name="%s"></a>\n# %s (%s)\n\n';
var LINK_ISSUE = '[#%s](https://github.com/angular/angular.js/issues/%s)';
var LINK_COMMIT = '[%s](https://github.com/angular/angular.js/commit/%s)';
var EMPTY_COMPONENT = '$$';
var MAX_SUBJECT_LENGTH = 80;
var warn = function() {
console.log('WARNING:', util.format.apply(null, arguments));
};
var parseRawCommit = function(raw) {
if (!raw) return null;
var lines = raw.split('\n');
var msg = {}, match;
msg.hash = lines.shift();
msg.subject = lines.shift();
msg.closes = [];
msg.breaks = [];
lines.forEach(function(line) {
match = line.match(/(?:Closes|Fixes)\s#(\d+)/);
if (match) msg.closes.push(parseInt(match[1]));
});
match = raw.match(/BREAKING CHANGE:([\s\S]*)/);
if (match) {
msg.breaking = match[1];
}
msg.body = lines.join('\n');
match = msg.subject.match(/^(.*)\((.*)\)\:\s(.*)$/);
if (!match || !match[1] || !match[3]) {
warn('Incorrect message: %s %s', msg.hash, msg.subject);
return null;
}
if (match[3].length > MAX_SUBJECT_LENGTH) {
warn('Too long subject: %s %s', msg.hash, msg.subject);
match[3] = match[3].substr(0, MAX_SUBJECT_LENGTH);
}
msg.type = match[1];
msg.component = match[2];
msg.subject = match[3];
return msg;
};
var linkToIssue = function(issue) {
return util.format(LINK_ISSUE, issue, issue);
};
var linkToCommit = function(hash) {
return util.format(LINK_COMMIT, hash.substr(0, 8), hash);
};
var currentDate = function() {
var now = new Date();
var pad = function(i) {
return ('0' + i).substr(-2);
};
return util.format('%d-%s-%s', now.getFullYear(), pad(now.getMonth() + 1), pad(now.getDate()));
};
var printSection = function(stream, title, section, printCommitLinks) {
printCommitLinks = printCommitLinks === undefined ? true : printCommitLinks;
var components = Object.getOwnPropertyNames(section).sort();
if (!components.length) return;
stream.write(util.format('\n## %s\n\n', title));
components.forEach(function(name) {
var prefix = '-';
var nested = section[name].length > 1;
if (name !== EMPTY_COMPONENT) {
if (nested) {
stream.write(util.format('- **%s:**\n', name));
prefix = ' -';
} else {
prefix = util.format('- **%s:**', name);
}
}
section[name].forEach(function(commit) {
if (printCommitLinks) {
stream.write(util.format('%s %s\n (%s', prefix, commit.subject, linkToCommit(commit.hash)));
if (commit.closes.length) {
stream.write(',\n ' + commit.closes.map(linkToIssue).join(', '));
}
stream.write(')\n');
} else {
stream.write(util.format('%s %s', prefix, commit.subject));
}
});
});
stream.write('\n');
};
var readGitLog = function(grep, from) {
var deferred = q.defer();
// TODO(vojta): if it's slow, use spawn and stream it instead
child.exec(util.format(GIT_LOG_CMD, grep, '%H%n%s%n%b%n==END==', from), function(code, stdout, stderr) {
var commits = [];
stdout.split('\n==END==\n').forEach(function(rawCommit) {
var commit = parseRawCommit(rawCommit);
if (commit) commits.push(commit);
});
deferred.resolve(commits);
});
return deferred.promise;
};
var writeChangelog = function(stream, commits, version) {
var sections = {
fix: {},
feat: {},
breaks: {}
};
sections.breaks[EMPTY_COMPONENT] = [];
commits.forEach(function(commit) {
var section = sections[commit.type];
var component = commit.component || EMPTY_COMPONENT;
if (section) {
section[component] = section[component] || [];
section[component].push(commit);
}
if (commit.breaking) {
sections.breaks[component] = sections.breaks[component] || [];
sections.breaks[component].push({
subject: util.format("due to %s,\n %s", linkToCommit(commit.hash), commit.breaking),
hash: commit.hash,
closes: []
});
};
});
stream.write(util.format(HEADER_TPL, version, version, currentDate()));
printSection(stream, 'Bug Fixes', sections.fix);
printSection(stream, 'Features', sections.feat);
printSection(stream, 'Breaking Changes', sections.breaks, false);
}
var getPreviousTag = function() {
var deferred = q.defer();
child.exec(GIT_TAG_CMD, function(code, stdout, stderr) {
if (code) deferred.reject('Cannot get the previous tag.');
else deferred.resolve(stdout.replace('\n', ''));
});
return deferred.promise;
};
var generate = function(version, file) {
getPreviousTag().then(function(tag) {
console.log('Reading git log since', tag);
readGitLog('^fix|^feat|Breaks', tag).then(function(commits) {
console.log('Parsed', commits.length, 'commits');
console.log('Generating changelog to', file || 'stdout', '(', version, ')');
writeChangelog(file ? fs.createWriteStream(file) : process.stdout, commits, version);
});
});
};
// publish for testing
exports.parseRawCommit = parseRawCommit;
// hacky start if not run by jasmine :-D
if (process.argv.join('').indexOf('jasmine-node') === -1) {
generate(process.argv[2], process.argv[3]);
}
+43
View File
@@ -0,0 +1,43 @@
describe('changelog.js', function() {
var ch = require('./changelog');
describe('parseRawCommit', function() {
it('should parse raw commit', function() {
var msg = ch.parseRawCommit(
'9b1aff905b638aa274a5fc8f88662df446d374bd\n' +
'feat(scope): broadcast $destroy event on scope destruction\n' +
'perf testing shows that in chrome this change adds 5-15% overhead\n' +
'when destroying 10k nested scopes where each scope has a $destroy listener\n');
expect(msg.type).toBe('feat');
expect(msg.hash).toBe('9b1aff905b638aa274a5fc8f88662df446d374bd');
expect(msg.subject).toBe('broadcast $destroy event on scope destruction');
expect(msg.body).toBe('perf testing shows that in chrome this change adds 5-15% overhead\n' +
'when destroying 10k nested scopes where each scope has a $destroy listener\n')
expect(msg.component).toBe('scope');
});
it('should parse closed issues', function() {
var msg = ch.parseRawCommit(
'13f31602f396bc269076ab4d389cfd8ca94b20ba\n' +
'feat(ng-list): Allow custom separator\n' +
'bla bla bla\n\n' +
'Closes #123\nCloses #25\n');
expect(msg.closes).toEqual([123, 25]);
});
it('should parse breaking changes', function() {
var msg = ch.parseRawCommit(
'13f31602f396bc269076ab4d389cfd8ca94b20ba\n' +
'feat(ng-list): Allow custom separator\n' +
'bla bla bla\n\n' +
'BREAKING CHANGE: first breaking change\nsomething else\n' +
'another line with more info\n');
expect(msg.breaking).toEqual(' first breaking change\nsomething else\nanother line with more info\n');
});
});
});
+80
View File
@@ -0,0 +1,80 @@
<a name="v1.0.0rc3"></a>
# v1.0.0rc3 (2012-03-27)
## Bug Fixes
- **$compile:**
- create new (isolate) scopes for directives on root elements ([5390fb37](https://github.com/angular/angular.js/commit/5390fb37d2c01937922613fc57df4986af521787), closes [#817](https://github.com/angular/angular.js/issues/817))
- don't touch static element attributes ([9cb2195e](https://github.com/angular/angular.js/commit/9cb2195e61a78e99020ec19d687a221ca88b5900))
- Merge interpolated css class when replacing an element ([f49eaf8b](https://github.com/angular/angular.js/commit/f49eaf8bf2df5f4e0e82d6c89e849a4f82c8d414))
- **$http:**
- don't send Content-Type header when no data ([1a5bebd9](https://github.com/angular/angular.js/commit/1a5bebd927ecd22f9c34617642fdf58fe3f62efb), closes [#749](https://github.com/angular/angular.js/issues/749))
- **$log:**
- avoid console.log.apply calls in IE ([15213ec2](https://github.com/angular/angular.js/commit/15213ec212769837cb2b7e781ffc5bfd598d27ca), closes [#805](https://github.com/angular/angular.js/issues/805))
- **$resource:**
- support escaping of ':' in resource url ([6d6f8753](https://github.com/angular/angular.js/commit/6d6f875345e01f2c6c63ef95164f6f39e923da15))
- **compiler:**
- allow transclusion of root elements ([9918b748](https://github.com/angular/angular.js/commit/9918b748be01266eb10db39d51b4d3098d54ab66))
- **e2e runner:**
- fix typo that caused errors on IE8 ([ee5a5352](https://github.com/angular/angular.js/commit/ee5a5352fd4b94cedee6ef20d4bf2d43ce77e00b), closes [#806](https://github.com/angular/angular.js/issues/806))
- **forEach:**
- should ignore prototypically inherited properties ([8d7e6948](https://github.com/angular/angular.js/commit/8d7e6948496ff26ef1da8854ba02fcb8eebfed61), closes [#813](https://github.com/angular/angular.js/issues/813))
- **forms:**
- Remove double registering of form ([1faafa31](https://github.com/angular/angular.js/commit/1faafa31582c4e9413f48dc7d12f5b681f9fe9fd))
- Set ng-valid/ng-invalid correctly ([08bfea18](https://github.com/angular/angular.js/commit/08bfea183a850b29da270eac47f80b598cbe600f))
- **init:**
- use jQuery#ready for init if available ([cb2ad9ab](https://github.com/angular/angular.js/commit/cb2ad9abf24e6f855cc749efe3155bd7987ece9d), closes [#818](https://github.com/angular/angular.js/issues/818))
- **json:**
- added support for iso8061 timezone ([5ac14f63](https://github.com/angular/angular.js/commit/5ac14f633a69f49973b5512780c6ec7752405967))
- **matchers.toHaveClass:**
- Correct reference to angular.mock.dump ([f701ce08](https://github.com/angular/angular.js/commit/f701ce08f9d63be05fc3b92f57ad473e1e749b2d))
- **ng-switch:**
- properly destroy child scopes ([2315d9b3](https://github.com/angular/angular.js/commit/2315d9b3610994b36c44e4a97fb1427d59471ce8))
- **ngDocSpec:**
- fix broken tests ([53b6f522](https://github.com/angular/angular.js/commit/53b6f522a56eea314cbd084816e08f24b2c7879f))
- **ngForm:**
- alias name||ngForm ([823adb23](https://github.com/angular/angular.js/commit/823adb231995e917bc060bfa49453e2a96bac2b6))
- **ngRepeat:**
- correct variable reference in error message ([935c1018](https://github.com/angular/angular.js/commit/935c1018da05dbf3124b2dd33619c4a3c82d7a2a))
- **ngView:**
- controller not published ([21e74c2d](https://github.com/angular/angular.js/commit/21e74c2d2e8e985b23711785287feb59965cbd90))
- **q:**
- resolve all of nothing to nothing ([ac75079e](https://github.com/angular/angular.js/commit/ac75079e2113949d5d64adbcf23d56f3cf295d41))
- **select:**
- multiselect failes to update view on selection insert ([6ecac8e7](https://github.com/angular/angular.js/commit/6ecac8e71a84792a434d21db2c245b3648c55f18))
## Features
- **$compile:**
- do not interpolate boolean attributes, rather evaluate them ([a08cbc02](https://github.com/angular/angular.js/commit/a08cbc02e78e789a66e9af771c410e8ad1646e25))
- **$controller:**
- support controller registration via $controllerProvider ([d54dfecb](https://github.com/angular/angular.js/commit/d54dfecb00fba41455536c5ddd55310592fdaf84))
- **$route:**
- when matching consider trailing slash as optional ([a4fe51da](https://github.com/angular/angular.js/commit/a4fe51da3ba0dc297ecd389e230d6664f250c9a6), closes [#784](https://github.com/angular/angular.js/issues/784))
- **assertArgFn:**
- should support array annotated fns ([4b8d9260](https://github.com/angular/angular.js/commit/4b8d926062eb4d4483555bdbdec4656f585ab40b))
- **http:**
- added params parameter ([73c85930](https://github.com/angular/angular.js/commit/73c8593077155a9f2e8ef42efd4c497eba0bef4f))
- **injector:**
- infer _foo_ as foo ([f13dd339](https://github.com/angular/angular.js/commit/f13dd3393dfb7a33565c9360342c193bc0bddcb6))
- **input.radio:**
- Allow value attribute to be interpolated ([ade6c452](https://github.com/angular/angular.js/commit/ade6c452753145c84884d17027a7865bf4b34b0c))
- **jqLite:**
- make injector() and scope() work with the document object ([5fdab52d](https://github.com/angular/angular.js/commit/5fdab52dd7c269f99839f4fa6b5854d9548269fa))
- add .controller() method ([6c5a05ad](https://github.com/angular/angular.js/commit/6c5a05ad49a1e083570c3dfe331403398f899dbe))
- **ngValue:**
- allow radio inputs to have non string values ([09e175f0](https://github.com/angular/angular.js/commit/09e175f02cca0f4a295fd0c9b980cd8f432e722b), closes [#816](https://github.com/angular/angular.js/issues/816))
- **scope:**
- broadcast $destroy event on scope destruction ([9b1aff90](https://github.com/angular/angular.js/commit/9b1aff905b638aa274a5fc8f88662df446d374bd))
- **scope.$eval:**
- Allow passing locals to the expression ([192ff61f](https://github.com/angular/angular.js/commit/192ff61f5d61899e667c6dbce4d3e6e399429d8b))
## Breaking Changes
- boolean attrs are evaluated rather than interpolated ([a08cbc02](https://github.com/angular/angular.js/commit/a08cbc02e78e789a66e9af771c410e8ad1646e25))
- ng-bind-attr directive removed ([55027132](https://github.com/angular/angular.js/commit/55027132f3d57e5dcf94683e6e6bd7b0aae0087d))
- any app that depends on this service and its fallback to Modernizr, please ([aaedefb9](https://github.com/angular/angular.js/commit/aaedefb92e6bec6626e173e5155072c91471596a))
+1 -1
View File
@@ -1,5 +1,5 @@
#!/bin/bash
grunt minify
rake minify
gzip -c < build/angular.min.js > build/angular.min.js.gzip
ls -l build/angular.min.*
+1 -2
View File
@@ -13,8 +13,7 @@ body {
text-align: center;
}
#json,
#xml {
#json, #xml {
display: none;
}
+3 -16
View File
@@ -1,23 +1,10 @@
@charset "UTF-8";
[ng\:cloak],
[ng-cloak],
[data-ng-cloak],
[x-ng-cloak],
.ng-cloak,
.x-ng-cloak,
.ng-hide:not(.ng-hide-animate) {
display: none !important;
[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak],
.ng-cloak, .x-ng-cloak {
display: none;
}
ng\:form {
display: block;
}
.ng-animate-shim {
visibility:hidden;
}
.ng-anchor {
position:absolute;
}
-11
View File
@@ -1,11 +0,0 @@
<h1>Oops!</h1>
<p>The page you requested does not exist. Perhaps you were looking for something else...</p>
<div ng-controller="Error404SearchCtrl">
<dl ng-repeat="(key, value) in results" ng-show="value.length" style="float: left; margin-right:20px">
<dt>{{ key }}</dt>
<dd ng-repeat="item in value"><a ng-href="{{ item.path }}">{{ item.name }}</a></dd>
</dl>
</div>
-1
View File
@@ -1 +0,0 @@
.visible-phone{display:none}.visible-desktop{display:block}.navbar{display:block}.navbar .container{padding:0 16px;width:auto}.navbar .brand{float:left;margin:8px 80px 0 8px;padding:0}.navbar .brand a{display:block;height:30px;margin:6px 0 5px 0;overflow:hidden;padding:0;width:117px}.navbar .nav{float:right}.navbar .nav .dropdown-toggle{color:rgba(255,255,255,0.87);font-size:16px;font-weight:300;line-height:56px;padding:0 24px;text-transform:uppercase;transition:all .3s}.navbar .nav .dropdown-toggle:hover,.navbar .nav .dropdown-toggle:active,.navbar .nav .dropdown-toggle:focus{background:#37474F;color:#fff}.navbar .nav .dropdown-menu{background:#37474F;border:none;border-radius:0;box-shadow:0 0 16px rgba(0,0,0,0.12),0 16px 16px rgba(0,0,0,0.24);color:#fff;left:auto;margin:0;padding:0;right:0}.navbar .nav .dropdown-menu:after,.navbar .nav .dropdown-menu:before{display:none}.navbar .nav .dropdown-menu li{border-bottom:1px solid rgba(38,50,56,0.56);box-sizing:border-box;line-height:48px}.navbar .nav .dropdown-menu li:last-child{border:none}.navbar .nav .dropdown-menu a{background:#37474F;color:#fff;font-weight:300;line-height:48px;padding:0 16px;transition:all .2s}.navbar .nav .dropdown-menu a:hover,.navbar .nav .dropdown-menu a:focus{background:#455A64}.navbar .navbar-search{left:200px;margin:0;position:absolute;right:440px;top:8px;width:auto}.navbar .navbar-search i{color:#546E7A;font-size:16px;left:12px;position:absolute;top:11px}.navbar .navbar-search .search-query{background:#37474F;border:none;border-radius:2px;box-shadow:none;box-sizing:border-box;color:#546E7A;font-size:14px;height:40px;width:100%;padding:0 16px 0 32px;text-shadow:none;transition:all .3s}.navbar .navbar-search .search-query:-webkit-autofill,.navbar .navbar-search .search-query:-webkit-autofill:hover,.navbar .navbar-search .search-query:-webkit-autofill:focus{background-color:#fff;transition:background-color 5000s ease-in-out 0s;-webkit-text-fill-color:#455A64}.navbar .navbar-search .search-query:hover,.navbar .navbar-search .search-query:active,.navbar .navbar-search .search-query:focus{background:#fff;box-shadow:inset 0 2px 4px rgba(0,0,0,0.24);color:#2196F3}.navbar .navbar-search .search-query::-webkit-input-placeholder{color:#546E7A}.navbar .navbar-search .search-query::-moz-placeholder{color:#546E7A}.navbar .navbar-search .search-query:-ms-input-placeholder{color:#546E7A}.navbar .navbar-search .search-query:-moz-placeholder{color:#546E7A}#navbar-main .navbar-inner{background:#263238;height:56px}#navbar-notice{z-index:1029;top:56px}#navbar-notice .navbar-inner{background:#ECEFF1;box-shadow:0 0 3px rgba(0,0,0,0.12),0 3px 3px rgba(0,0,0,0.24);height:auto}.site-notice{padding:4px 0;text-align:center;font-size:13px;margin:0}@media handheld and (max-width: 800px), screen and (max-device-width: 800px), screen and (max-width: 800px){.visible-phone{display:block}.visible-desktop{display:none}}@media handheld and (max-width: 800px), screen and (max-device-width: 800px), screen and (max-width: 800px){.homepage .container{padding:16px;width:auto}.homepage .span1{width:auto}.homepage .span2{width:auto}.homepage .span3{width:auto}.homepage .span4{width:auto}.homepage .span5{width:auto}.homepage .span6{width:auto}.homepage .span7{width:auto}.homepage .span8{width:auto}.homepage .span9{width:auto}.homepage .span10{width:auto}.homepage .navbar .container{padding:0 8px}.homepage #navbar-main .navbar-inner{height:40px}.homepage #navbar-main .brand{margin:6px 0 0 0}.homepage #navbar-main .brand a{margin:0}.homepage #navbar-main .nav{margin:0}.homepage #navbar-main .nav .dropdown-toggle{font-size:12px;line-height:40px;padding:0 8px}.homepage #navbar-main .dropdown-menu a{padding:0 8px}.homepage #navbar-main .navbar-search{background:#263238;border-bottom:1px solid #263238;left:0;right:0;top:100%}.homepage #navbar-main .navbar-search i{left:12px;top:7px}.homepage #navbar-main .navbar-search .search-query{border-radius:0;height:32px}.homepage #navbar-notice{top:40px}.homepage #navbar-notice .site-notice{font-size:11px}.homepage .hero{padding:80px 32px 32px 32px}.homepage .hero h2{background-size:230px 60px;height:60px;width:230px}}
-991
View File
@@ -1,991 +0,0 @@
@font-face {
font-family: 'Open Sans';
src: url("../components/open-sans-fontface-1.4.0/fonts/Regular/OpenSans-Regular.eot?v=1.1.0");
src: url("../components/open-sans-fontface-1.4.0/fonts/Regular/OpenSans-Regular.eot?#iefix&v=1.1.0") format("embedded-opentype"),
url("../components/open-sans-fontface-1.4.0/fonts/Regular/OpenSans-Regular.woff?v=1.1.0") format("woff"),
url("../components/open-sans-fontface-1.4.0/fonts/Regular/OpenSans-Regular.ttf?v=1.1.0") format("truetype"),
url("../components/open-sans-fontface-1.4.0/fonts/Regular/OpenSans-Regular.svg?v=1.1.0#OpenSansBold") format("svg");
font-weight: normal;
font-style: normal;
}
@font-face {
font-family: 'Open Sans';
src: url("../components/open-sans-fontface-1.4.0/fonts/Semibold/OpenSans-Semibold.eot?v=1.1.0");
src: url("../components/open-sans-fontface-1.4.0/fonts/Semibold/OpenSans-Semibold.eot?#iefix&v=1.1.0") format("embedded-opentype"),
url("../components/open-sans-fontface-1.4.0/fonts/Semibold/OpenSans-Semibold.woff?v=1.1.0") format("woff"),
url("../components/open-sans-fontface-1.4.0/fonts/Semibold/OpenSans-Semibold.ttf?v=1.1.0") format("truetype"),
url("../components/open-sans-fontface-1.4.0/fonts/Semibold/OpenSans-Semibold.svg?v=1.1.0#OpenSansBold") format("svg");
font-weight: 600;
font-style: normal;
}
@font-face {
font-family: 'Open Sans';
src: url("../components/open-sans-fontface-1.4.0/fonts/Bold/OpenSans-Bold.eot?v=1.1.0");
src: url("../components/open-sans-fontface-1.4.0/fonts/Bold/OpenSans-Bold.eot?#iefix&v=1.1.0") format("embedded-opentype"),
url("../components/open-sans-fontface-1.4.0/fonts/Bold/OpenSans-Bold.woff?v=1.1.0") format("woff"),
url("../components/open-sans-fontface-1.4.0/fonts/Bold/OpenSans-Bold.ttf?v=1.1.0") format("truetype"),
url("../components/open-sans-fontface-1.4.0/fonts/Bold/OpenSans-Bold.svg?v=1.1.0#OpenSansBold") format("svg");
font-weight: bold;
font-style: normal;
}
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-bottom: 0px;
}
.header .brand img {
margin-top: 0;
height: auto;
vertical-align: top;
}
.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;
}
.navbar .navbar-search i {
top: 13px;
font-size: 12px;
}
.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-index-group .nav-index-listing.current a {
color: #B52E31;
}
.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 {
white-space: pre-wrap;
word-break: normal;
}
.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;
}
ul + p {
margin-top: 10px;
}
.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;
-moz-appearance: none;
text-indent: 0.01px;
text-overflow: '';
}
.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 {
position: relative;
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-group .search-results {
padding: 0 5px 0;
list-style-type: none;
}
.search-results-frame > .search-results-group:first-child > .search-results {
border-right: 1px solid #222;
}
.search-results-group.col-group-api {
width: 30%;
}
.search-results-group.col-group-guide,
.search-results-group.col-group-tutorial {
width: 20%;
}
.search-results-group.col-group-misc,
.search-results-group.col-group-error {
width: 15%;
float: right;
}
@supports ((column-count: 2) or (-moz-column-count: 2) or (-ms-column-count: 2) or (-webkit-column-count: 2)) {
.search-results-group.col-group-api .search-results {
-moz-column-count: 2;
-ms-column-count: 2;
-webkit-column-count: 2;
column-count: 2;
/* Prevent bullets in the second column from being hidden in Chrome and IE */
-webkit-column-gap: 2em;
-ms-column-gap: 2em;
column-gap: 2em;
}
}
.search-results-group .search-result {
word-wrap: break-word;
-webkit-hyphens: auto;
-moz-hyphens: auto;
-ms-hyphens: auto;
hyphens: auto;
-ms-column-break-inside: avoid;
-webkit-column-break-inside: avoid;
-moz-column-break-inside: avoid; /* Unsupported */
column-break-inside: avoid;
text-indent: -0.65em; /* Make sure line wrapped words are aligned vertically */
}
@supports (-moz-column-count: 2) {
.search-results-group .search-result {
/* Prevents column breaks inside words in FF, but has adverse effects in IE11 and Chrome */
overflow: hidden;
padding-left: 1em; /* In FF the list item bullet is otherwise hidden */
margin-left: -1em; /* offset the padding left */
}
}
.search-result:before {
content: "\002D\00A0"; /* Dash and non-breaking space as List item type */
position: relative;
}
.search-results-group.col-group-api .search-result {
width: 48%;
display: inline-block;
padding-left: 12px;
}
@supports ((column-count: 2) or (-moz-column-count: 2) or (-ms-column-count: 2) or (-webkit-column-count: 2)) {
.search-results-group.col-group-api .search-result {
width: auto;
display: list-item;
}
}
.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;
}
#navbar-sub {
padding-top: 10px;
padding-bottom: 5px;
background: rgba(245,245,245,1);
box-shadow: 0 0 2px #999;
z-index: 1028;
top: 57px;
}
.main-body-grid {
margin-top: 144px;
position: relative;
}
.main-body-grid > .grid-left,
.main-body-grid > .grid-right {
padding: 20px 0;
}
.main-body-grid > .grid-left {
position: fixed;
top: 144px;
bottom: 0;
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;
padding-bottom: 120px;
}
.main-body-grid .side-navigation.ng-hide {
display: block!important;
}
.variables-matrix td {
vertical-align: top;
padding: 5px;
}
.type-hint {
display: inline-block;
background: gray;
}
.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);
}
.type-hint-regexp {
background: rgb(90, 84, 189);
}
.type-hint-domelement {
background: rgb(95, 158, 160);
}
.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;
}
.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, .btn:focus {
color: black !important;
border: 1px solid #ddd !important;
background: white !important;
}
.view-source, .improve-docs {
position: relative;
z-index: 100;
}
.view-source {
margin-right: 10px;
}
.improve-docs {
float: right;
}
.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;
}
.definition-table td {
padding: 8px;
border: 1px solid #eee;
vertical-align: top;
}
.table > tbody > tr.head > td,
.table > tbody > tr.head > th {
border-bottom: 2px solid #ddd;
padding-top: 50px;
}
.diagram {
margin-bottom: 10px;
margin-top: 30px;
max-width: 100%;
}
.deprecation {
margin-top: 15px;
}
.deprecation .title {
float: left;
margin-right: 5px;
}
@media only screen and (min-width: 768px) {
[ng-include="partialPath"].ng-hide {
display: block !important;
visibility: hidden;
}
}
@media only screen and (min-width: 768px) and (max-width: 991px) {
.main-body-grid {
margin-top: 160px;
}
.main-body-grid > .grid-left {
top: 160px;
}
}
@media only screen and (max-width: 767px) {
.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;
padding-bottom: 50px;
}
.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):after {
padding-right: 5px;
margin-left: -3px;
content: ", ";
}
.nav-index-group .nav-index-listing:last-child:after {
content: "";
display: inline-block;
}
.nav-index-group .nav-index-section {
display: block;
}
.toc-toggle {
margin-bottom: 20px;
}
.toc-close {
position: absolute;
bottom: 5px;
left: 50%;
margin-left: -50%;
text-align: center;
padding: 5px;
background: #eee;
border-radius: 5px;
width: 100%;
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-frame > .search-results-group:first-child > .search-results {
border-right: none;
}
.search-results-group {
float: none !important;
display: block !important;
width: auto !important;
border: 0! important;
padding: 0! important;
}
@supports ((column-count: 2) or (-moz-column-count: 2) or (-ms-column-count: 2) or (-webkit-column-count: 2)) {
.search-results-group .search-results {
-moz-column-count: 2;
-ms-column-count: 2;
-webkit-column-count: 2;
column-count: 2;
}
}
.search-results-group .search-result {
display: inline-block !important;
padding: 0 5px;
width: auto !important;
text-indent: initial;
margin-left: 0;
}
.search-results-group .search-result:after {
content: ", ";
}
.search-results-group .search-result:before {
content: "";
}
@supports ((column-count: 2) or (-moz-column-count: 2) or (-ms-column-count: 2) or (-webkit-column-count: 2)) {
.search-results-group .search-result {
display: list-item !important;
}
.search-results-group .search-result:after {
content: "";
}
}
#wrapper {
padding-bottom: 0px;
}
}
iframe[name="example-anchoringExample"] {
height: 400px;
}
/*
angular-topnav.css and bootstrap overrides
*/
.navbar .navbar-inner .container {
padding: 0 16px;
width: auto;
height: auto;
}
.navbar .nav > li {
float: left;
}
.navbar-nav .open .dropdown-menu {
position: absolute;
float: left;
}
.navbar-nav .open .dropdown-menu > li > a {
line-height: 48px;
}
#navbar-main .navbar-inner, #navbar-notice .navbar-inner {
box-shadow: none;
}
#navbar-sub .container {
max-width: 970px;
}
.nav .open > a, .nav .open > a:hover, .nav .open > a:focus {
background-color: inherit;
}
toc-container {
display: block;
margin: 15px 10px;
}
toc-container b {
text-transform: uppercase;
}
toc-container .btn {
padding: 3px 6px;
font-size: 13px;
margin-left: 5px;
}
toc-container > div > toc-tree ul {
list-style: none;
padding-left: 15px;
padding-bottom: 2px;
}
toc-container > div > toc-tree > ul {
padding-left: 0;
}
toc-container > div > toc-tree > ul > li > toc-tree > ul > li toc-tree > ul li {
font-size: 13px;
}
.dev-status span {
padding: 2px 8px;
border-radius: 5px;
}
.security span { background-color: orange; }
.stable span { background-color: green; color: white; }
.current span { background-color: blue; color: white; }
@media handheld and (max-width:800px), screen and (max-device-width:800px), screen and (max-width:800px) {
.navbar {
min-height: auto;
}
.search-results-container {
top: 32px;
overflow: auto;
max-height: 85vh;
padding-bottom: 0;
position: static;
}
.search-close {
right: 1px;
margin-left: 0;
top: 41px;
padding: 5px 10px;
border-top-right-radius: 0;
border-top-left-radius: 0;
box-shadow: none;
width: auto;
bottom: auto;
left: auto;
}
.navbar-nav .open .dropdown-menu > li > a, .navbar-nav .open .dropdown-menu .dropdown-header {
padding: 0 8px;
}
.homepage #navbar-notice {
top: 72px;
}
#navbar-notice .navbar-inner {
box-shadow: 0 0 3px rgba(0, 0, 0, .12), 0 3px 3px rgba(0, 0, 0, .24)
}
#navbar-sub {
position: relative;
top: 0;
margin-top: 80px;
padding-bottom: 0;
margin-bottom: 0;
}
}
-142
View File
@@ -1,142 +0,0 @@
/* 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;
}
.lang-text * {
color: #333333!important;
}
.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 {
/* */
}
-51
View File
@@ -1,51 +0,0 @@
.pln { color: #000 } /* plain text */
@media screen {
.str { color: #080 } /* string content */
.kwd { color: #008 } /* a keyword */
.com { color: #800 } /* a comment */
.typ { color: #606 } /* a type name */
.lit { color: #066 } /* a literal value */
/* punctuation, lisp open bracket, lisp close bracket */
.pun, .opn, .clo { color: #660 }
.tag { color: #008 } /* a markup tag name */
.atn { color: #606 } /* a markup attribute name */
.atv { color: #080 } /* a markup attribute value */
.dec, .var { color: #606 } /* a declaration; a variable name */
.fun { color: red } /* a function name */
}
/* Use higher contrast and text-weight for printable form. */
@media print, projection {
.str { color: #060 }
.kwd { color: #006; font-weight: bold }
.com { color: #600; font-style: italic }
.typ { color: #404; font-weight: bold }
.lit { color: #044 }
.pun, .opn, .clo { color: #440 }
.tag { color: #006; font-weight: bold }
.atn { color: #404 }
.atv { color: #060 }
}
pre.prettyprint {
padding: 8px;
background-color: #f7f7f9;
border: 1px solid #e1e1e8;
}
pre.prettyprint.linenums {
-webkit-box-shadow: inset 40px 0 0 #fbfbfc, inset 41px 0 0 #ececf0;
-moz-box-shadow: inset 40px 0 0 #fbfbfc, inset 41px 0 0 #ececf0;
box-shadow: inset 40px 0 0 #fbfbfc, inset 41px 0 0 #ececf0;
}
ol.linenums {
margin: 0 0 0 33px; /* IE indents via margin-left */
}
ol.linenums li {
padding-left: 12px;
font-size:12px;
color: #bebec5;
line-height: 18px;
text-shadow: 0 1px 0 #fff;
list-style-type:decimal!important;
}
Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.0 KiB

@@ -1,41 +0,0 @@
<?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>

Before

Width:  |  Height:  |  Size: 3.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 183 B

-147
View File
@@ -1,147 +0,0 @@
/* 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.on('click', closeDropdown);
$document.on('keydown', escapeKeyBind);
}
if ( openScope && openScope !== dropdownScope ) {
openScope.isOpen = false;
}
openScope = dropdownScope;
};
this.close = function( dropdownScope ) {
if ( openScope === dropdownScope ) {
openScope = null;
$document.off('click', closeDropdown);
$document.off('keydown', escapeKeyBind);
}
};
var closeDropdown = function(evt) {
if (evt && evt.which === 3) return;
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.on('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);
});
}
};
});
-45
View File
@@ -1,45 +0,0 @@
'use strict';
/* eslint-env worker */
/* global importScripts, lunr */
// Load up the lunr library
importScripts('../components/lunr-0.7.2/lunr.min.js');
// Create the lunr index - the docs should be an array of object, each object containing
// the path and search terms for a page
var index = lunr(/** @this */function() {
this.ref('path');
this.field('titleWords', {boost: 50});
this.field('members', {boost: 40});
this.field('keywords', {boost: 20});
});
// Retrieve the searchData which contains the information about each page to be indexed
var searchData = {};
var searchDataRequest = new XMLHttpRequest();
searchDataRequest.onload = function() {
// Store the pages data to be used in mapping query results back to pages
searchData = JSON.parse(this.responseText);
// Add search terms from each page to the search index
searchData.forEach(function(page) {
index.add(page);
});
self.postMessage({e: 'index-ready'});
};
searchDataRequest.open('GET', 'search-data.json');
searchDataRequest.send();
// The worker receives a message everytime the web app wants to query the index
self.onmessage = function(oEvent) {
var q = oEvent.data.q;
var hits = index.search(q);
var results = [];
// Only return the array of paths to pages
hits.forEach(function(hit) {
results.push(hit.ref);
});
// The results of the query are sent back to the web app via a new message
self.postMessage({e: 'query-ready', q: q, d: results});
};
-4
View File
@@ -1,4 +0,0 @@
User-agent: *
# The map files are not required by the app
Disallow: /*.map$
-29
View File
@@ -1,29 +0,0 @@
{
"root": true,
"extends": "../../../.eslintrc-node.json",
"env": {
"jasmine": true,
"protractor": true
},
"globals": {
"angular": false,
/* testabilityPatch / matchers */
"inject": false,
"module": false,
"dealoc": false,
"_jQuery": false,
"_jqLiteMode": false,
"sortedHtml": false,
"childrenTagsOf": false,
"assertHidden": false,
"assertVisible": false,
"provideLog": false,
"spyOnlyCallsWithArgs": false,
"createMockStyleSheet": false,
"browserTrigger": false,
"jqLiteCacheSize": false
}
}
@@ -1,48 +0,0 @@
'use strict';
describe('API pages', function() {
it('should display links to code on GitHub', function() {
browser.get('build/docs/index.html#!/api/ng/service/$http');
expect(element(by.css('.improve-docs')).getAttribute('href')).toMatch(/https?:\/\/github\.com\/angular\/angular\.js\/edit\/.+\/src\/ng\/http\.js/);
browser.get('build/docs/index.html#!/api/ng/service/$http');
expect(element(by.css('.view-source')).getAttribute('href')).toMatch(/https?:\/\/github\.com\/angular\/angular\.js\/tree\/.+\/src\/ng\/http\.js#L\d+/);
});
it('should change the page content when clicking a link to a service', function() {
browser.get('build/docs/index.html');
var ngBindLink = element(by.css('.definition-table td a[href="api/ng/directive/ngClick"]'));
ngBindLink.click();
var mainHeader = element(by.css('.main-body h1 '));
expect(mainHeader.getText()).toEqual('ngClick');
});
it('should show the functioning input directive example', function() {
browser.get('build/docs/index.html#!/api/ng/directive/input');
// Ensure that the page is loaded before trying to switch frames.
browser.waitForAngular();
browser.switchTo().frame('example-input-directive');
var nameInput = element(by.model('user.name'));
nameInput.sendKeys('!!!');
var code = element.all(by.css('tt')).first();
expect(code.getText()).toContain('guest!!!');
});
it('should trim indentation from code blocks', function() {
browser.get('build/docs/index.html#!/api/ng/type/$rootScope.Scope');
var codeBlocks = element.all(by.css('pre > code.lang-js'));
codeBlocks.each(function(codeBlock) {
var firstSpan = codeBlock.all(by.css('span')).first();
expect(firstSpan.getText()).not.toMatch(/^\W+$/);
});
});
});
@@ -1,58 +0,0 @@
'use strict';
describe('directives', function() {
describe('parameter section', function() {
it('should show the directive name only if it is a param (attribute) with a value', function() {
browser.get('build/docs/index.html#!/api/ng/directive/ngInclude');
expect(getParamNames().getText()).toContain('ngInclude | src');
browser.get('build/docs/index.html#!/api/ngRoute/directive/ngView');
expect(getParamNames().getText()).not.toContain('ngView');
});
});
describe('usage section', function() {
it('should show the directive name if it is a param (attribute) with a value', function() {
browser.get('build/docs/index.html#!/api/ng/directive/ngInclude');
expect(getUsageAs('element', 'ng-include').isPresent()).toBe(true);
expect(getUsageAs('attribute', 'ng-include').isPresent()).toBe(true);
expect(getUsageAs('CSS class', 'ng-include').isPresent()).toBe(true);
});
it('should show the directive name if it is a void param (attribute)', function() {
browser.get('build/docs/index.html#!/api/ngRoute/directive/ngView');
expect(getUsageAs('element', 'ng-view').isPresent()).toBe(true);
expect(getUsageAs('attribute', 'ng-view').isPresent()).toBe(true);
expect(getUsageAs('CSS class', 'ng-view').isPresent()).toBe(true);
});
});
});
function getParamNames() {
var argsSection = element(by.className('input-arguments'));
var paramNames = argsSection.all(by.css('tr td:nth-child(1)'));
return paramNames;
}
// Based on the type of directive usage, the directive name will show up in the code block
// with a specific class
var typeClassMap = {
element: 'tag',
attribute: 'atn',
'CSS class': 'atv'
};
function getUsageAs(type, directiveName) {
var usage = element(by.className('usage'));
var as = usage.element(by.cssContainingText('li', 'as ' + type));
return as.element(by.cssContainingText('span.' + typeClassMap[type], directiveName));
}
@@ -1,12 +0,0 @@
'use strict';
describe('provider pages', function() {
it('should show the related service', function() {
browser.get('build/docs/index.html#!/api/ng/provider/$compileProvider');
var serviceLink = element.all(by.css('ol.api-profile-header-structure li a')).first();
expect(serviceLink.getText()).toEqual('- $compile');
expect(serviceLink.getAttribute('href')).toMatch(/api\/ng\/service\/\$compile/);
});
});
@@ -1,22 +0,0 @@
'use strict';
describe('service pages', function() {
it('should show the related provider if there is one', function() {
browser.get('build/docs/index.html#!/api/ng/service/$compile');
var providerLink = element.all(by.css('ol.api-profile-header-structure li a')).first();
expect(providerLink.getText()).toEqual('- $compileProvider');
expect(providerLink.getAttribute('href')).toMatch(/api\/ng\/provider\/\$compileProvider/);
browser.get('build/docs/index.html#!/api/ng/service/$q');
providerLink = element.all(by.css('ol.api-profile-header-structure li a')).first();
expect(providerLink.getText()).not.toEqual('- $compileProvider');
expect(providerLink.getAttribute('href')).not.toMatch(/api\/ng\/provider\/\$compileProvider/);
});
it('should show parameter defaults', function() {
browser.get('build/docs/index.html#!/api/ng/service/$timeout');
expect(element.all(by.css('.input-arguments p em')).first().getText()).toContain('(default: 0)');
});
});
-170
View File
@@ -1,170 +0,0 @@
'use strict';
var webdriver = require('selenium-webdriver');
describe('docs.angularjs.org', function() {
beforeEach(function() {
// read and clear logs from previous tests
browser.manage().logs().get('browser');
});
afterEach(function() {
// verify that there were no console errors in the browser
browser.manage().logs().get('browser').then(function(browserLog) {
var filteredLog = browserLog.filter(function(logEntry) {
return logEntry.level.value > webdriver.logging.Level.WARNING.value;
});
expect(filteredLog.length).toEqual(0);
if (filteredLog.length) {
console.log('browser console errors: ' + require('util').inspect(filteredLog));
}
});
browser.ignoreSynchronization = false;
browser.clearMockModules();
});
describe('App', function() {
// it('should filter the module list when searching', function () {
// browser.get();
// browser.waitForAngular();
// var search = element(by.model('q'));
// search.clear();
// search.sendKeys('ngBind');
// var firstModule = element(by.css('.search-results a'));
// expect(firstModule.getText()).toEqual('ngBind');
// });
it('should change the page content when clicking a link to a service', function() {
browser.get('build/docs/index-production.html');
var ngBindLink = element(by.css('.definition-table td a[href="api/ng/directive/ngClick"]'));
ngBindLink.click();
var mainHeader = element(by.css('.main-body h1 '));
expect(mainHeader.getText()).toEqual('ngClick');
});
it('should include the files for the embedded examples from the same domain', function() {
browser.get('build/docs/index-production.html#!api/ng/directive/ngClick');
var origin = browser.executeScript('return document.location.origin;');
var exampleIFrame = element(by.name('example-ng-click'));
// This is technically an implementation detail, but if this changes, then there's a good
// chance the deployment process changed
expect(exampleIFrame.getAttribute('src')).toContain('examples/example-ng-click/index.html');
browser.switchTo().frame('example-ng-click');
var scriptEl = element(by.tagName('script'));
// Ensure the included file is from the same domain
expect(scriptEl.getAttribute('src')).toContain(origin);
});
it('should be resilient to trailing slashes', function() {
browser.get('build/docs/index-production.html#!/api/ng/function/angular.noop/');
var mainHeader = element(by.css('.main-body h1 '));
expect(mainHeader.getText()).toEqual('angular.noop');
});
it('should be resilient to trailing "index"', function() {
browser.get('build/docs/index-production.html#!/api/ng/function/angular.noop/index');
var mainHeader = element(by.css('.main-body h1 '));
expect(mainHeader.getText()).toEqual('angular.noop');
});
it('should be resilient to trailing "index/"', function() {
browser.get('build/docs/index-production.html#!/api/ng/function/angular.noop/index/');
var mainHeader = element(by.css('.main-body h1 '));
expect(mainHeader.getText()).toEqual('angular.noop');
});
it('should display formatted error messages on error doc pages', function() {
browser.get('build/docs/index-production.html#!error/ng/areq?p0=Missing&p1=not%20a%20function,%20got%20undefined');
expect(element(by.css('.minerr-errmsg')).getText()).toEqual('Argument \'Missing\' is not a function, got undefined');
});
it('should display an error if the page does not exist', function() {
browser.get('build/docs/index-production.html#!/api/does/not/exist');
var mainHeader = element(by.css('.main-body h1 '));
expect(mainHeader.getText()).toEqual('Oops!');
});
it('should set "noindex" if the page does not exist', function() {
browser.get('build/docs/index-production.html#!/api/does/not/exist');
var robots = element(by.css('meta[name="robots"][content="noindex"]'));
var googleBot = element(by.css('meta[name="googlebot"][content="noindex"]'));
expect(robots.isPresent()).toBe(true);
expect(googleBot.isPresent()).toBe(true);
});
it('should remove "noindex" if the page exists', function() {
browser.get('build/docs/index-production.html#!/api');
var robots = element(by.css('meta[name="robots"][content="noindex"]'));
var googleBot = element(by.css('meta[name="googlebot"][content="noindex"]'));
expect(robots.isPresent()).toBe(false);
expect(googleBot.isPresent()).toBe(false);
});
describe('template request error', function() {
beforeEach(function() {
browser.addMockModule('httpMocker', function() {
angular.module('httpMocker', ['ngMock'])
.run(['$httpBackend', function($httpBackend) {
$httpBackend.whenGET('localhost:8000/build/docs/partials/api.html').respond(500, '');
}]);
});
});
it('should set "noindex" for robots if the request fails', function() {
// index-test includes ngMock
browser.get('build/docs/index-test.html#!/api');
var robots = element(by.css('meta[name="robots"][content="noindex"]'));
var googleBot = element(by.css('meta[name="googlebot"][content="noindex"]'));
expect(robots.isPresent()).toBe(true);
expect(googleBot.isPresent()).toBe(true);
});
});
describe('page bootstrap error', function() {
beforeEach(function() {
browser.addMockModule('httpMocker', function() {
// Require a module that does not exist to break the bootstrapping
angular.module('httpMocker', ['doesNotExist']);
});
});
it('should have "noindex" for robots if bootstrapping fails', function() {
browser.get('build/docs/index.html#!/api').catch(function() {
// get() will fail on AngularJS bootstrap, but if we continue here, protractor
// will assume the app is ready
browser.ignoreSynchronization = true;
var robots = element(by.css('meta[name="robots"][content="noindex"]'));
var googleBot = element(by.css('meta[name="googlebot"][content="noindex"]'));
expect(robots.isPresent()).toBe(true);
expect(googleBot.isPresent()).toBe(true);
});
});
});
});
});
-130
View File
@@ -1,130 +0,0 @@
'use strict';
/**
* This scenario checks the presence of the table of contents for a sample of pages - API and guide.
* The expectations are kept vague so that they can be easily adjusted when the docs change.
*/
describe('table of contents', function() {
it('on provider pages', function() {
browser.get('build/docs/index.html#!/api/ng/provider/$controllerProvider');
var toc = element.all(by.css('toc-container > div > toc-tree'));
toc.getText().then(function(text) {
expect(text.join('')).toContain('Overview');
expect(text.join('')).toContain('Methods');
});
var tocFirstLevel = element.all(by.css('toc-container > div > toc-tree > ul > li'));
tocFirstLevel.then(function(match) {
expect(match.length).toBe(2);
expect(match[1].all(by.css('li')).count()).toBe(2);
});
});
it('on service pages', function() {
browser.get('build/docs/index.html#!/api/ng/service/$controller');
var toc = element.all(by.css('toc-container > div > toc-tree'));
toc.getText().then(function(text) {
expect(text.join('')).toContain('Overview');
expect(text.join('')).toContain('Usage');
});
var tocFirstLevel = element.all(by.css('toc-container > div > toc-tree > ul > li'));
tocFirstLevel.then(function(match) {
expect(match.length).toBe(3);
expect(match[2].all(by.css('li')).count()).toBe(2);
});
});
it('on directive pages', function() {
browser.get('build/docs/index.html#!/api/ng/directive/input');
var toc = element.all(by.css('toc-container > div > toc-tree'));
toc.getText().then(function(text) {
expect(text.join('')).toContain('Overview');
expect(text.join('')).toContain('Usage');
expect(text.join('')).toContain('Directive Info');
});
var tocFirstLevel = element.all(by.css('toc-container > div > toc-tree > ul > li'));
tocFirstLevel.then(function(match) {
expect(match.length).toBe(4);
expect(match[2].all(by.css('li')).count()).toBe(1);
});
});
it('on function pages', function() {
browser.get('build/docs/index.html#!/api/ng/function/angular.bind');
var toc = element.all(by.css('toc-container > div > toc-tree'));
toc.getText().then(function(text) {
expect(text.join('')).toContain('Overview');
expect(text.join('')).toContain('Usage');
});
var tocFirstLevel = element.all(by.css('toc-container > div > toc-tree > ul > li'));
tocFirstLevel.then(function(match) {
expect(match.length).toBe(2);
expect(match[1].all(by.css('li')).count()).toBe(2);
});
});
it('on type pages', function() {
browser.get('build/docs/index.html#!/api/ng/type/ModelOptions');
var toc = element.all(by.css('toc-container > div > toc-tree'));
toc.getText().then(function(text) {
expect(text.join('')).toContain('Overview');
expect(text.join('')).toContain('Methods');
});
var tocFirstLevel = element.all(by.css('toc-container > div > toc-tree > ul > li'));
tocFirstLevel.then(function(match) {
expect(match.length).toBe(2);
expect(match[1].all(by.css('li')).count()).toBe(2);
});
});
it('on filter pages', function() {
browser.get('build/docs/index.html#!/api/ng/filter/date');
var toc = element.all(by.css('toc-container > div > toc-tree'));
toc.getText().then(function(text) {
expect(text.join('')).toContain('Overview');
expect(text.join('')).toContain('Usage');
});
var tocFirstLevel = element.all(by.css('toc-container > div > toc-tree > ul > li'));
tocFirstLevel.then(function(match) {
expect(match.length).toBe(3);
expect(match[1].all(by.css('li')).count()).toBe(2);
});
});
it('on guide pages', function() {
browser.get('build/docs/index.html#!/guide/services');
var tocFirstLevel = element.all(by.css('toc-container > div > toc-tree > ul > li'));
tocFirstLevel.then(function(match) {
expect(match.length).toBe(5);
expect(match[1].all(by.css('li')).count()).toBe(3);
});
});
});
-8
View File
@@ -1,8 +0,0 @@
{
"root": true,
"extends": "../../../.eslintrc-browser.json",
"globals": {
"lunr": false
}
}
-22
View File
@@ -1,22 +0,0 @@
'use strict';
angular.module('docsApp', [
'ngRoute',
'ngCookies',
'ngSanitize',
'ngAnimate',
'DocsController',
'pagesData',
'navData',
'directives',
'errors',
'examples',
'search',
'tutorials',
'versions',
'ui.bootstrap.dropdown'
])
.config(['$locationProvider', function($locationProvider) {
$locationProvider.html5Mode(true).hashPrefix('!');
}]);
-183
View File
@@ -1,183 +0,0 @@
'use strict';
var directivesModule = angular.module('directives', []);
directivesModule
/**
* backToTop Directive
* @param {Function} $anchorScroll
*
* @description Ensure that the browser scrolls when the anchor is clicked
*/
.directive('backToTop', ['$anchorScroll', '$location', function($anchorScroll, $location) {
return function link(scope, element) {
element.on('click', function(event) {
$location.hash('');
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[0].className);
var lang = match && match[1];
var html = element.html();
element.html(window.prettyPrintOne(html, lang, linenums));
}
};
})
.directive('scrollYOffsetElement', ['$anchorScroll', function($anchorScroll) {
return function(scope, element) {
$anchorScroll.yOffset = element;
};
}])
.directive('table', function() {
return {
restrict: 'E',
link: function(scope, element, attrs) {
if (!attrs['class']) {
element.addClass('table table-bordered table-striped code-table');
}
}
};
})
.directive('tocCollector', ['$rootScope', function($rootScope) {
return {
controller: ['$element', function($element) {
/* eslint-disable no-invalid-this */
var ctrl = this;
$rootScope.$on('$includeContentRequested', function() {
ctrl.hs = [];
ctrl.root = [];
});
this.hs = [];
this.root = [];
this.element = $element;
this.register = function(h) {
var previousLevel;
for (var i = ctrl.hs.length - 1; i >= 0; i--) {
if (ctrl.hs[i].level === (h.level - 1)) {
previousLevel = ctrl.hs[i];
break;
}
}
if (previousLevel) {
previousLevel.children.push(h);
} else {
this.root.push(h);
}
ctrl.hs.push(h);
/* eslint-enable no-invalid-this */
};
}]
};
}])
.component('tocTree', {
template: '<ul>' +
'<li ng-repeat="item in $ctrl.items">' +
'<a ng-href="{{ $ctrl.path }}#{{item.fragment}}">{{item.title}}</a>' +
'<toc-tree ng-if="::item.children.length > 0" items="item.children"></toc-tree>' +
'</li>' +
'</ul>',
bindings: {
items: '<'
},
controller: ['$location', /** @this */ function($location) {
this.path = $location.path().replace(/^\/?(.+?)(\/index)?\/?$/, '$1');
}]
})
.directive('tocContainer', function() {
return {
scope: true,
restrict: 'E',
require: {
tocContainer: '',
tocCollector: '^^'
},
controller: function() {
this.showToc = true;
this.items = [];
},
controllerAs: '$ctrl',
link: function(scope, element, attrs, ctrls) {
ctrls.tocContainer.items = ctrls.tocCollector.root;
},
template: '<div ng-if="::$ctrl.items.length > 1">' +
'<b>Contents</b>' +
'<button class="btn" ng-click="$ctrl.showToc = !$ctrl.showToc">{{$ctrl.showToc ? \'Hide\' : \'Show\'}}</button><br>' +
'<toc-tree items="$ctrl.items" ng-show="$ctrl.showToc"></toc-tree>' +
'</div>'
};
})
.directive('header', function() {
return {
restrict: 'E',
controller: ['$element', function($element) {
// eslint-disable-next-line no-invalid-this
this.element = $element;
}]
};
})
.directive('h1', ['$compile', function($compile) {
return {
restrict: 'E',
require: {
tocCollector: '^^?',
header: '^^?'
},
link: function(scope, element, attrs, ctrls) {
if (!ctrls.tocCollector) return;
var tocContainer = angular.element('<toc-container></toc-container>');
var containerElement = ctrls.header ? ctrls.header.element : element;
containerElement.after(tocContainer);
$compile(tocContainer)(scope);
}
};
}]);
for (var i = 2; i <= 5; i++) {
registerHDirective(i);
}
function registerHDirective(i) {
directivesModule.directive('h' + i, function() {
return {
restrict: 'E',
require: {
'tocCollector': '^^?'
},
link: function(scope, element, attrs, ctrls) {
var toc = ctrls.tocCollector;
if (!toc || !attrs.id) return;
toc.register({
level: i,
fragment: attrs.id,
title: element.text(),
children: []
});
}
};
});
}
-77
View File
@@ -1,77 +0,0 @@
'use strict';
angular.module('DocsController', ['currentVersionData'])
.controller('DocsController', [
'$scope', '$rootScope', '$location', '$window', '$cookies',
'NG_PAGES', 'NG_NAVIGATION', 'CURRENT_NG_VERSION',
function($scope, $rootScope, $location, $window, $cookies,
NG_PAGES, NG_NAVIGATION, CURRENT_NG_VERSION) {
var errorPartialPath = 'Error404.html';
$scope.navClass = function(navItem) {
return {
active: navItem.href && this.currentPage && this.currentPage.path,
current: this.currentPage && this.currentPage.path === navItem.href,
'nav-index-section': navItem.type === 'section'
};
};
$scope.$on('$includeContentLoaded', function() {
var pagePath = $scope.currentPage ? $scope.currentPage.path : $location.path();
$window._gaq.push(['_trackPageview', pagePath]);
$scope.loading = false;
});
$scope.$on('$includeContentError', function() {
$scope.loading = false;
$scope.loadingError = true;
});
$scope.$watch(function docsPathWatch() {return $location.path(); }, function docsPathWatchAction(path) {
path = path.replace(/^\/?(.+?)(\/index)?\/?$/, '$1');
var currentPage = $scope.currentPage = NG_PAGES[path];
$scope.loading = true;
$scope.loadingError = false;
if (currentPage) {
$scope.partialPath = 'partials/' + path + '.html';
$scope.currentArea = 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 = NG_NAVIGATION['api'];
$scope.breadcrumb = [];
$scope.partialPath = errorPartialPath;
}
});
$scope.hasError = function() {
return $scope.partialPath === errorPartialPath || $scope.loadingError;
};
/**********************************
Initialize
***********************************/
$scope.versionNumber = CURRENT_NG_VERSION.full;
$scope.version = CURRENT_NG_VERSION.full + ' ' + CURRENT_NG_VERSION.codeName;
$scope.loading = false;
$scope.loadingError = false;
var INDEX_PATH = /^(\/|\/index[^.]*.html)$/;
if (!$location.path() || INDEX_PATH.test($location.path())) {
$location.path('/api').replace();
}
}]);
-71
View File
@@ -1,71 +0,0 @@
'use strict';
angular.module('errors', ['ngSanitize'])
.filter('errorLink', ['$sanitize', function($sanitize) {
var LINKY_URL_REGEXP = /((ftp|https?):\/\/|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s.;,(){}<>]/g,
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) {
if (!text) return text;
var targetHtml = target ? ' target="' + target + '"' : '';
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 encodeAngleBrackets = function(text) {
return text.replace(/</g, '&lt;').replace(/>/g, '&gt;');
};
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],
formattedText,
i;
for (i = 0; angular.isDefined(search['p' + i]); i++) {
formatArgs.push(search['p' + i]);
}
formattedText = encodeAngleBrackets(interpolate.apply(null, formatArgs));
element.html(errorLinkFilter(formattedText, '_blank'));
}
};
}]);

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