Compare commits

...

1317 Commits

Author SHA1 Message Date
Vojta Jina 1faafa3158 fix(forms): Remove double registering of form 2012-03-16 12:06:29 -07:00
Vojta Jina 08bfea183a fix(forms): Set ng-valid/ng-invalid correctly 2012-03-16 12:06:29 -07:00
Igor Minar f13dd3393d feat(injector): infer _foo_ as foo
this is to enable nicer tests:

 describe('fooSvc', function() {
   var fooSvc;

   beforeEach(inject(function(_fooSvc_) {
     fooSvc = _fooSvc_;
   }));

   it('should do this thing', function() {
     //test fooSvc
   });
 });
2012-03-16 10:52:40 -07:00
Igor Minar bca96e7c7c style(ngViewSpec): pretify some tests with $destroy events 2012-03-16 10:52:40 -07:00
Igor Minar 9b1aff905b feat(scope): broadcast $destroy event on scope destruction
perf testing shows that in chrome this change adds 5-15% overhead
when destroying 10k nested scopes where each scope has a $destroy listener
2012-03-16 09:41:05 -07:00
Igor Minar 252d4548f9 style(ngSwitchSpec): fix typo 2012-03-15 15:23:49 -07:00
Igor Minar 6abafcb424 docs(changelog): fix broken links
Closes #793
2012-03-15 10:19:44 -07:00
Igor Minar 2315d9b361 fix(ng-switch): properly destroy child scopes 2012-03-14 14:33:20 -07:00
Igor Minar 8fd1b74872 chore(release): start the 1.0.0rc2 silence-absorption iteration 2012-03-14 13:45:44 -07:00
alkis 02091b2c1e style(changelog): Fix some typos 2012-03-14 10:13:03 -07:00
Igor Minar 25cd774abf chore(release): cutting 1.0.0rc1 moiré-vision 2012-03-14 01:00:46 -07:00
Igor Minar c70ead0aa1 fix(Rakefile): version.dot extractor should ignore 'rc1' 2012-03-13 23:24:17 -07:00
Igor Minar 716b5fd3e2 docs(*): fixing various docs 2012-03-13 23:17:43 -07:00
Misko Hevery 8b8fdddc0b docs(links): corrected borken links 2012-03-13 19:36:09 -07:00
Igor Minar ce4b630524 fix(docs): properly close the optional ] in directive signatures 2012-03-13 17:51:05 -07:00
Vojta Jina 13f31602f3 feat(ng-list): Allow custom separator 2012-03-13 17:51:05 -07:00
Daniel Zen 7b52586f7c docs(guide): fix non-working example + add docs for implicit DI 2012-03-13 17:14:50 -07:00
Misko Hevery e9e3ee012b feat(compile): allow ngForm on attribute and class
#feature
- ngForm directive can now be used with element, class, and attributes
2012-03-13 16:59:10 -07:00
Misko Hevery de9464c143 f(compile): boolean attributes too agresive
- compiler would rewrite boolean attributes on all elements. This is too aggressive and interferes with some third-party frameworks
2012-03-13 16:59:03 -07:00
Misko Hevery 31cd580310 fix(ng-non-bindable): increase priority to 1000
- increase ng-non-bindable prioirity to 1000 so that it prevents attribute interpolation on same level.
2012-03-13 16:58:36 -07:00
Misko Hevery d34f3bc7a6 feat(form): publish validationErrorKeys as CSS
- The validationErrorKeys are now published as CSS for easy styling. The errorKeys should be in
 camelCase and the CSS will be in snake-case
2012-03-13 16:57:36 -07:00
Misko Hevery 027801a00a doc(search): include method names in corpus 2012-03-13 16:32:15 -07:00
Vojta Jina 66e6c1ce2c docs(forms): Change validation tokens to lowercase 2012-03-13 16:18:14 -07:00
Igor Minar 4806d28a29 fix(forms): remove control.$form and use nullFormCtrl 2012-03-13 16:05:52 -07:00
Igor Minar 089c0f8b0e fix(forms): fix nesting issues and add tests 2012-03-13 16:05:52 -07:00
Igor Minar b6ae6e52f9 fix(indexOf): use native impl if available 2012-03-13 14:13:53 -07:00
Igor Minar 9277d12fc0 fix(forms): lowercase all validation error keys 2012-03-13 14:13:53 -07:00
Igor Minar ac5151a469 fix(scope): remove scope $destroy event 2012-03-13 14:13:53 -07:00
Vojta Jina 63be222326 docs(input): Fix some broken links, add missing $, use ng- in examples 2012-03-13 13:52:57 -07:00
Vojta Jina a29c2cf70c doc(form): updated to reflect the latest changes 2012-03-13 13:36:28 -07:00
Igor Minar afe617a647 docs(*): renaming incorrect widget references to control or directive 2012-03-12 23:04:12 -07:00
Igor Minar f59e4b11f1 fix(forms): prefix all form and control properties with $ 2012-03-12 23:04:11 -07:00
Igor Minar 5e6ba25201 fix(forms): remove the need for extra form scope
the forms/controls code refactored not to depend on events which forced
us to create new scope for each form element.
2012-03-12 23:04:11 -07:00
Igor Minar 9134f5ce5a style(ng-include): remove unused args 2012-03-12 23:04:11 -07:00
Igor Minar 4e6b065a2f test(ng-include): add ng-include=src test 2012-03-12 23:04:11 -07:00
Igor Minar 5e3db61b1d docs(release): release notes for 1.0.0rc1 2012-03-12 23:04:11 -07:00
Igor Minar a9ed5745a0 docs(directive): add more docs for the directive api 2012-03-12 23:04:10 -07:00
Misko Hevery 48096048cf fix(svg): normalize class access for SVG 2012-03-12 21:59:50 -07:00
Vojta Jina 317adb36a4 docs(guide.forms): Update forms guide 2012-03-12 01:40:12 -07:00
Vojta Jina 1b9277bf6f fix(forms): Propagate change from model even if it's undefined 2012-03-12 01:40:12 -07:00
Misko Hevery cce31d4c93 chore(ng-include): update to work in ng-include|src mode 2012-03-11 22:36:29 -07:00
Misko Hevery 3e5377f4f3 doc(fixes): to better support ng-directive notation 2012-03-11 21:31:35 -07:00
Misko Hevery 488a03631e Mostly Revert "fix(docs): directive events + cleanup"
This reverts commit 8fb34f008e.
2012-03-11 21:31:34 -07:00
Vojta Jina 716dd5f3f9 refactor(forms): Remove touch() method 2012-03-09 17:33:22 -08:00
Vojta Jina 83314913e7 refactor(forms): Rename read() -> setViewValue() 2012-03-09 17:33:22 -08:00
Igor Minar e0cc84ad7b docs(directives): set directive param name to directive name
so that we can render better usage examples in docs
2012-03-09 16:27:12 -08:00
Igor Minar 4a94bb9b34 fix(startTag): fix tagname extraction
the original code magically worked for ng:foo but for nothing else
2012-03-09 16:27:12 -08:00
Igor Minar 53aacb35fa chore(shiv): remove obsolete shiv code
we can't provide this functionality because the directives are lazy
loaded when the module loads, which is too late for the shiv to do
anything useful.
2012-03-09 16:14:26 -08:00
Igor Minar f4d338d393 chore(*): refactor all ng: to ng- 2012-03-09 16:14:26 -08:00
Vojta Jina 0bfaa579c0 feat($provide.service): Add $provide.service() for registering a class 2012-03-09 10:10:29 -08:00
Vojta Jina 00d4427388 refactor($provide) Rename service -> provider
It registers a provider class, so this makes more sense.

Breaks Rename $provide.service -> $provide.provider
2012-03-09 10:10:28 -08:00
Vojta Jina e0c9551fd7 refactor(forms): remove registerWidget and use event instead
Each widget (ng-model directive) emits $newFormControl event instead of getting hold of parent form
and calling form.registerWidget(this);
2012-03-09 10:10:28 -08:00
Igor Minar fae84463e4 docs(css): allow headers to wrap with blue background 2012-03-08 22:29:35 -08:00
Igor Minar 8fb34f008e fix(docs): directive events + cleanup 2012-03-08 22:29:35 -08:00
Igor Minar 5d09a1efd3 fix(ng-view, ng-include): onload and $contentLoaded
- change custom onload directive to special arguments recongnized by both
  ng-view and ng-include
- rename $contentLoaded event to $viewContentLoaded and $includeContentLoaded
- add event docs
2012-03-08 22:29:35 -08:00
Igor Minar f54db2ccda chore(directives,widgets): reorg the code under directive/ dir 2012-03-08 22:29:34 -08:00
Misko Hevery dd7b0f56fc fix(ng-cloak): work with class 2012-03-08 16:30:39 -08:00
Vojta Jina b3750103cc fix($parse): Allow property names that collide with native object properties
I.e. constructor, toString, or watch on FF
(https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Object/watch)

+ optimize parser a bit to not create getter function for operators
2012-03-08 11:39:03 -08:00
Vojta Jina b348347dad refactor(fromJson): Remove error() and just throw
It's more likely you are using angular.fromJson() inside Angular world, which means you get proper
exception handling by $exceptionHandler.

There is no point to explicitly push it to console and it causes memory leaks on most browsers 
(tried Chrome stable/canary, Safari, FF).
2012-03-08 11:38:14 -08:00
Igor Minar 512db03cc0 docs(ng-list): update the ng-list directive docs 2012-03-08 11:06:15 -08:00
Igor Minar ee7209fe26 fix(tests): fix name collisions between various tests 2012-03-08 11:06:15 -08:00
Igor Minar 772ddb983b docs(directive, module): add various missing docs and fix existing docs 2012-03-08 11:06:14 -08:00
Igor Minar 7f6c1093f5 docs(ng-view): improve the ng-view docs 2012-03-08 11:06:14 -08:00
Igor Minar 1b4289ce76 fix(docs): add a header for the directive info section 2012-03-08 11:06:14 -08:00
Igor Minar af21233820 fix(test): rename an it so that it doesn't colide with the test above 2012-03-08 11:06:14 -08:00
Igor Minar 08ad4b6a46 docs(jqlite): add docs for wrap() 2012-03-08 11:06:14 -08:00
Igor Minar 2acd60df4d fix(docs): remove undefined from examples with jsfiddle=false 2012-03-08 11:06:14 -08:00
Igor Minar e0ace15cd3 docs($rootScope): rename ttl to digestTtl + docs 2012-03-08 11:01:22 -08:00
Misko Hevery 6a98c52c84 chore(compiler): change default restriction to attribute only for directives 2012-03-08 10:07:49 -08:00
Vojta Jina 6aa3cfc31b docs($compileProvider.directive): Update iAttrs docs 2012-03-07 14:04:14 -08:00
Vojta Jina 64912069ca docs(mock.inject): Fix the example
And explicitly say that you need to load your application modules that you wanna test.
2012-03-05 19:28:03 -08:00
Vojta Jina b49ddf9848 docs($route, ng:view): Fix the examples to work on jsfiddle, update docs 2012-03-05 19:15:18 -08:00
Vojta Jina 1084ccf7ef fix(docs): Add $locationProvider methods to the docs example provider
- $locationProvider.html5Mode
- $locationProvider.hashPrefix

Docs example is basically a different application on the same page, but we don't want to instantiate multiple instances of $browser or $location service, so we are overriding these providers to return the instances from parent app.

Overriding the service with $provide.value caused a provider to be auto-generated without the necessary hashPrefix and html5Mode apis.
2012-03-05 19:09:43 -08:00
Vojta Jina c2989f6cc6 fix(ng-include): Compile only content 2012-03-05 10:41:59 -08:00
Vojta Jina 4f797fe5f3 refactor(testabilityPatch): Change JSTD fail to more general throw
"fail" is a JSTD specific API, so it's not defined when testing without JSTD (eg SlimJim).
2012-03-05 10:41:51 -08:00
Vojta Jina bbd3a3fd76 chore: Update slim-jim 2012-03-05 09:59:29 -08:00
Stephane Bisson e86bafecd2 fix(mock.TzDate): getDay() takes into account the timezone offset 2012-02-29 15:53:51 -08:00
Marcello Nuccio e68c02c537 docs($cacheFactory): Correct method's description 2012-02-29 15:48:37 -08:00
Marcello Nuccio 25d207c48c docs($injector): Correct provider suffix to "Provider" 2012-02-29 15:46:55 -08:00
Vojta Jina 4370d756e4 refactor(directive.ngModel): rename emitValidity -> setValidity 2012-02-28 18:22:41 -08:00
Vojta Jina 4e83399570 fix(ng:model-instant): defer only keydown, throttle setTimeouts 2012-02-28 18:22:41 -08:00
Vojta Jina e7d6106811 fix(input): Render 0 (number) as 0 (not empty string) 2012-02-28 18:22:41 -08:00
Vojta Jina c4c60c25b4 reafactor: Rename ng:bind-immediate -> ng:model-instant 2012-02-28 18:22:41 -08:00
Vojta Jina 139e1b09a9 docs(forms): Update API docs for forms
- API forms (ng:model + controller, form + controller)
- fix some broken links
- ng:change, ng:model-instant
2012-02-28 18:22:35 -08:00
Vojta Jina 60743fc52a feat(ng:include) Fire $contentLoaded event
+ refactor unload to listen on this event -> we can use unload with ng:view as well

Closes #743
2012-02-28 17:48:07 -08:00
Vojta Jina 9486590e1b refactor(ng:view) Make $route scope agnostic, add $contentLoaded event
Problems:

- controller was instantiated immediately on $afterRouteChange (even if no content), that's
different compare to ng:controller, which instantiates controllers after compiling
- route listened on current scope ($afterRouteChange), so if you were listening on $rootScope
($afterRouteChange), you get called first and current.scope === undefined, which is flaky
- route handles scope destroying, but scope is created by ng:view
- route fires after/before route change even if there is no route (when no otherwise specified)

Solution:

- route has no idea about scope, whole scope business moved to ng:view (creating/destroying)
- scope is created (and controller instantiated) AFTER compiling the content
- that means on $afterRouteChange - there is no scope yet (current.scope === undefined)
- added $contentLoaded event fired by ng:view, after linking the content
2012-02-28 17:46:58 -08:00
Misko Hevery e31d1c287d refactor($route): remove .parent(); ng:view scope creation 2012-02-28 17:46:58 -08:00
Misko Hevery f16bd2f747 refactor($route): move when/otherwise to provider 2012-02-28 17:46:58 -08:00
Misko Hevery ef7346ff70 docs(scope): correct formatting 2012-02-28 17:46:58 -08:00
Misko Hevery f6fb31e8ad chore(ng:view): simplify, by taking advantage of new compiler features 2012-02-28 17:46:58 -08:00
Vojta Jina 21c725f1a1 refactor(forms): Even better forms
- remove $formFactory completely
- remove parallel scope hierarchy (forms, widgets)
- use new compiler features (widgets, forms are controllers)
- any directive can add formatter/parser (validators, convertors)

Breaks no custom input types
Breaks removed integer input type
Breaks remove list input type (ng-list directive instead)
Breaks inputs bind only blur event by default (added ng:bind-change directive)
2012-02-28 17:46:58 -08:00
Vojta Jina e23fa768aa docs(directive.script): Subtle update to API docs 2012-02-28 17:41:37 -08:00
Vojta Jina d656d11489 feat(directive.style): Do not compile content of style element 2012-02-28 17:41:30 -08:00
Vojta Jina b37e8a2b14 docs(directive.script): Add simple example of inlined template 2012-02-28 14:15:44 -08:00
Vojta Jina 4c1c50fd9b fix(directive.script): Do not compile content of script tags 2012-02-28 14:15:44 -08:00
Vojta Jina d1558d7924 docs: evaluate only scripts with type text/javascript 2012-02-28 14:15:39 -08:00
Vojta Jina 5b0d068358 fix($http): Do not serialize File object 2012-02-25 18:49:54 -08:00
Vojta Jina 230f29d0a7 fix(jqLite): set event's monkey patched methods to null (on IE7) 2012-02-23 23:41:41 -08:00
Vojta Jina 3171f21591 fix($httpBackend): Set current url, if not defined or empty string
Reason to fix this was the fact that with undefined url, it ended up with weird exception
(Cannot call method 'replace' of undefined), which was more confusing than helpful.

jQuery.ajax() does request to current url, if url is not specified, so I decided for this solution.
2012-02-23 22:50:02 -08:00
Misko Hevery d6e3e1baab feta(scope): watch object refference or equality
Breaks: Must set $watch equality to true for the old behavior
2012-02-23 15:01:08 -08:00
Misko Hevery ffa8441886 bug(equals): incorect comparison of dates 2012-02-23 13:57:28 -08:00
Misko Hevery 5d8528cc2e docs(module): Describe module loading 2012-02-23 09:53:14 -08:00
Misko Hevery 80edcadb1d feat($provide): added constant 2012-02-22 13:28:42 -08:00
Misko Hevery c27a56f4da docs(scope): show which directives create scopes 2012-02-22 12:59:23 -08:00
Misko Hevery fbcb7fdd14 fix($injector): circular dependency instatiation 2012-02-22 11:32:09 -08:00
Vojta Jina fa69d10122 docs(ng:app): Move to other directives namespace 2012-02-22 11:09:33 -08:00
Vojta Jina dd321c5f4d docs(scope): update $emit/$broadcast docs 2012-02-22 10:24:40 -08:00
Misko Hevery 656a495e50 refactor(directive): use attrs.$observe 2012-02-21 22:46:01 -08:00
Vojta Jina 6d0ca95fa0 feat($compiler): Allow attr.$observe() interpolated attrs 2012-02-21 22:46:01 -08:00
Misko Hevery 3df7b8e57f fix(ng:repeat): use transclusion 2012-02-21 22:46:01 -08:00
Misko Hevery 7bd69d0f5b chore(ng:switch): rewritten with transclusion API
BREAKING CHANGE: the change event fires on scope of switch not on scope of case.
2012-02-21 22:46:01 -08:00
Misko Hevery 3773323e46 docs($compile): transclude documentation 2012-02-21 22:46:01 -08:00
Misko Hevery 78656fe0df feat($compile) add locals, isolate scope, transclusion 2012-02-21 22:46:00 -08:00
Misko Hevery cb10ccc44f feat($compile): mark scope creation with ng-scope class 2012-02-21 22:46:00 -08:00
Misko Hevery 4a051efb89 feat($compile): support compiling text nodes by wrapping them in <span> 2012-02-21 22:46:00 -08:00
Misko Hevery 1752c8c44a feat(directive): event now accessible as $event
Closes 259
2012-02-21 22:46:00 -08:00
Misko Hevery 6216dc0465 chore(select): remove inherit, replace with expression locals 2012-02-21 22:45:59 -08:00
Misko Hevery 761b2ed85a feat(parse): add support for local vars in expressions 2012-02-21 22:45:59 -08:00
Misko Hevery c8ee631c19 feat(mouseenter/mouseleave): emulating ie events 2012-02-21 22:45:59 -08:00
Misko Hevery cae9ad4ba9 docs(decorator): add missing decorate docs 2012-02-21 22:45:59 -08:00
Misko Hevery 85b2084f57 fix(select): double array issue with multislect and jQuery 2012-02-21 22:45:59 -08:00
Misko Hevery 13b21aaf5a fix(doc): example was referring to non existent CSS 2012-02-21 22:45:59 -08:00
Misko Hevery 22c1db1744 fix(ngdoc): extract keywords from properties/methods. 2012-02-21 22:45:58 -08:00
Misko Hevery 292a5dae07 chore(slim-jim) add configuration 2012-02-21 22:45:58 -08:00
Vojta Jina 6e635012fb feat(scope): scope.$emit/$broadcast return the event object, add cancelled property 2012-02-21 10:58:48 -08:00
Misko Hevery eb92735c9e fix(injector) .instantiate([Type]) produced wrong result 2012-02-16 14:32:52 -08:00
Vojta Jina 776739299b fix($injector): instantiate returns instance, if non-object value returned from constructor 2012-02-08 16:12:11 -08:00
Vojta Jina 3173d8603d fix(jqLite): fix memory leaking in IE8 (remove monkey patched methods on Event)
These methods cause IE8 holds the whole jqLite in the memory, even when page is reloaded.
jqLite's cache keeps element's data (event handlers, attached scopes, injector, etc…), so almost all used memory is never released in IE8.

jQuery creates its own Event object (wrapper around native Event) instead.
2012-02-05 00:09:02 -08:00
Vojta Jina 6c4f1391bc refactor(test): remove odd inject from describe 2012-01-30 11:44:19 -08:00
Vojta Jina 58d6da556a refactor(binder): replace jested assertions with jasmine 2012-01-29 21:59:35 -08:00
Vojta Jina b6f61a89cf docs($compileProvider.directive): fix some typos 2012-01-26 09:13:08 -08:00
Igor Minar 8b32900d72 fix($parse): simplify getterFn 2012-01-25 16:52:39 -08:00
Igor Minar 18a1e860a3 fix($parse): small fixes
- typos
- dead code removal
- remove unneeded variable
2012-01-25 16:17:44 -08:00
Igor Minar 39b3297fc3 fix($parse): get rid of $unboundFn
Closes #731
2012-01-25 16:17:43 -08:00
Misko Hevery 1268fc1a44 cleanup($scope): remove $$scope ref. 2012-01-25 11:54:00 -08:00
Misko Hevery 4804c83b7d docs(compiler): update the compiler docs 2012-01-25 11:53:59 -08:00
Misko Hevery e2b1d9e994 feat(scriptTemplateLoader): provide template inlining
populates $templateCache with content of ng-template scripts
2012-01-25 11:50:37 -08:00
Misko Hevery 9ee2cdff44 refactor(directives): connect new compiler
- turn everything into a directive
2012-01-25 11:50:37 -08:00
Misko Hevery 8af4fde182 add($compile): add compiler v2.0 - not connected 2012-01-25 11:46:36 -08:00
Misko Hevery 5001c1a121 refactor($interpolate): improve interpolation service add documentation 2012-01-25 11:46:36 -08:00
Misko Hevery 0f6b2ef982 refactor(sanitizer): turn sanitizer into a service 2012-01-25 11:46:35 -08:00
Misko Hevery 1e258d11d0 feat(test): support it('should', pending); 2012-01-25 11:46:35 -08:00
Misko Hevery 81a6601e05 fix(docs): improper rendering of JSON 2012-01-25 11:46:35 -08:00
Igor Minar 1e96d0af8c fix(injector): small perf improvement & code cleanup 2012-01-25 11:46:35 -08:00
Misko Hevery 97dae0d0a0 feat(jqLite): add contents() 2012-01-25 11:46:35 -08:00
Misko Hevery 84823b2eff feature($exceptionHandler): $exceptionHandler now supports var_args 2012-01-25 11:46:34 -08:00
Misko Hevery 517811764d cleanup(tests): remove unused variables 2012-01-25 11:46:34 -08:00
Misko Hevery 1354718365 chore(jasmine-adapter): upgrade 2012-01-25 11:46:34 -08:00
Kai Groner 56bcc04c54 feat(ng:class): support using map of classnames and conditions
enables <div ng:class="{'hide': !visible, 'warning': isAlert()}"...
2012-01-24 10:28:29 -08:00
Igor Minar b2052d08a1 fix($parse): fixing typos in JS_KEYWORDS 2012-01-23 22:33:28 -08:00
Igor Minar 7da2bdb82a fix(scope): support watching functions
currently we run into infinite digest if a function is being
watched as an expression. This is because we generate bound
function wrapper when the watch is processed via parser.

I'm not too keen on the solution because it relies on the unbound
fn that is being exposed for other reasons, but I can't think
of a better way to deal with this right now
2012-01-23 22:33:28 -08:00
Igor Minar ed78f0d830 chore(log): generic test log service with custom toEquals matcher
- any test that needs a logger can just inject provideLog
- logger has susict api that makes tests more readable
- custom toEquals matcher allows for pretty expectations
2012-01-23 22:33:28 -08:00
Vojta Jina dbffbefb7c refactor($controller): Add $controller service for instantiating controllers
So that we can allow user to override this service and use BC hack:
https://gist.github.com/1649788
2012-01-23 13:11:12 -08:00
Vojta Jina 0196411dbe refactor(scope.$watch): rearrange arguments passed into watcher (newValue, oldValue, scope)
As scopes are injected into controllers now, you have the reference anyway, so having scope as first argument makes no sense…

Breaks $watcher gets arguments in different order (newValue, oldValue, scope)
2012-01-23 11:11:27 -08:00
Vojta Jina 992c790f07 refactor(scope): separate controller from scope
Controller is standalone object, created using "new" operator, not messed up with scope anymore.
Instead, related scope is injected as $scope.

See design proposal: https://docs.google.com/document/pub?id=1SsgVj17ec6tnZEX3ugsvg0rVVR11wTso5Md-RdEmC0k

Closes #321
Closes #425

Breaks controller methods are not exported to scope automatically
Breaks Scope#$new() does not take controller as argument anymore
2012-01-23 11:05:36 -08:00
alkis f5343c9fd3 docs($http): fix missing quote 2012-01-22 00:30:39 -08:00
Igor Minar 0470ff04b4 docs(changelog): clarified breaking changes for 0.10.6 2012-01-19 15:47:55 -08:00
Igor Minar efe33a5e21 docs($http): doc fixes suggested by Gina 2012-01-19 12:39:05 -08:00
Igor Minar 7046d6053d chore(jstd): upgrade JSTD to 1.3.3d 2012-01-19 10:38:26 -08:00
Vojta Jina afc241bd28 docs(inputType): fix small typo 2012-01-19 00:27:32 -08:00
ludicast a507fb7bb3 docs(guide): update angular version in an example 2012-01-18 17:16:27 -08:00
Igor Minar 0ce139c42d chore(release): preparing the 0.10.7 moiré-vision iteration 2012-01-18 17:12:21 -08:00
Igor Minar b00262fffe chore(release): cutting the 0.10.6 bubblewrap-cape release 2012-01-17 13:54:18 -08:00
Igor Minar 3f98d6ac99 docs(*): more docs 2012-01-17 12:19:26 -08:00
Igor Minar 22309c312f fix(docs): disable appcache - causing too much trouble 2012-01-17 12:13:29 -08:00
Igor Minar fcf95a47d1 docs(*): more fixes 2012-01-17 11:23:56 -08:00
Konstantin Stepanov e1e7aca9a6 fix($locationProvider) hashPrefix's getter returned html5Mode + doc fix 2012-01-17 11:21:20 -08:00
Vojta Jina 039041e3ae docs: syntax highlight auto bootstrap code example 2012-01-17 11:00:25 -08:00
Igor Minar 3da441b580 docs(release-notes): 0.10.6 bubblewrap-cape release 2012-01-17 09:49:40 -08:00
Igor Minar f9502d2ad3 fix(docs): temp hack to get appcache properly invalidated 2012-01-17 09:49:39 -08:00
Igor Minar 0356c90af8 chore(jquery): make the license header closure friendly 2012-01-17 09:49:39 -08:00
Igor Minar 0d4def452e fix(Rakefile): rewrite version number for mocks.js 2012-01-17 09:49:39 -08:00
Vojta Jina 897d0f1424 docs(guide): update the diagram 2012-01-17 09:49:38 -08:00
Igor Minar 92af30ce6e docs(*): various doc fixes 2012-01-17 09:49:37 -08:00
Igor Minar 54581d36df fix(e2e $httpBackend): use browser.defer instead of $defer
this is necessary to avoid $apply from within $apply situations
2012-01-16 23:26:44 -08:00
Igor Minar b587091b6e feat(jqLite): added injector() helper method 2012-01-16 02:17:27 -08:00
Vojta Jina c49b8a2db5 fix($location): do not $digest if browser's url change fired within $apply/$digest
Chrome (probably other browsers as well) fires 'hashchange' event synchronously, so if you change raw location from within $apply/$digest, we don't want to $apply twice. (It would throw an exception)
2012-01-14 11:23:12 -08:00
Misko Hevery 5cdfe45aa3 feat(module): add runtime block 2012-01-13 14:28:43 -08:00
Igor Minar 16a40c626f style(*): small fixes 2012-01-13 14:28:21 -08:00
Igor Minar b7f4d8c3c3 fix($http): anonnymous response interceptors should be treated as factories 2012-01-13 14:28:20 -08:00
Igor Minar 939c8e8fac docs($http, $httpBackend): docs docs docs 2012-01-13 14:28:20 -08:00
Igor Minar d2ba4c5170 fix(ngdocs): add '=' to type signatures with optional arguments 2012-01-13 13:53:07 -08:00
Igor Minar 46691c2721 fix($http): remove support for PATCH + better whenXXX, expectXXX api
- there are too many unknowns about PATCH, so I'm dropping its support until we know that this is actually useful
- expectGET, expectHEAD and expectJSON (and the same for whenXXX) should not require response data to be specified
2012-01-13 13:53:07 -08:00
Vojta Jina e7a23e4b65 fix(docs): generate correct ids on h elements to get scrolling working 2012-01-13 01:07:17 -08:00
Vojta Jina 15fd735793 refactor($autoScroll): rename to $anchorScroll and allow disabling auto scrolling (links)
Now, that we have autoscroll attribute on ng:include, there is no reason to disable the service completely, so $anchorScrollProvider.disableAutoScrolling() means it won't be scrolling when $location.hash() changes.

And then, it's not $autoScroll at all, it actually scrolls to anchor when it's called, so I renamed
it to $anchorScroll.
2012-01-13 01:07:12 -08:00
Vojta Jina 985d3d7558 refactor($autoScroll): rename method in test + use $apply instead of $digest 2012-01-13 01:05:24 -08:00
Vojta Jina 249c89c091 fix($autoScroll): scroll even if $location is in html5 mode
+ use autoscroll in docs (ng:include)
2012-01-13 01:01:26 -08:00
Vojta Jina 5164ae545b style(mocks): remove console.log 2012-01-13 00:37:16 -08:00
Misko Hevery e1e0ddb910 docs(inject/module): add documentation 2012-01-12 17:10:48 -08:00
Misko Hevery d648d709f3 refactor(module): strict separation between module-config / app-runtime 2012-01-12 13:40:07 -08:00
Vojta Jina 9a8dbfef51 style(mock): make jslint and igor happier 2012-01-11 22:11:06 -08:00
Vojta Jina 28114de8dc refactor(mock.$httpBackend): split (e2e/unit testing version of $httpBackend mock) 2012-01-11 22:11:01 -08:00
Vojta Jina c6ea1be053 fix(mock.$httpBackend): resetExpectations should not create new array 2012-01-11 11:48:03 -08:00
Misko Hevery 5143e7bf06 feat(module): new module loader 2012-01-10 22:27:00 -08:00
Misko Hevery afd25446d2 feat(ngdocs): support for interface documentation 2012-01-10 22:21:54 -08:00
Misko Hevery 3c3e6980b3 chore(specs.js): remove unused dependency 2012-01-10 22:21:54 -08:00
Misko Hevery e0b4b107ee chore(license): update year 2012-01-10 22:21:54 -08:00
Igor Minar 614fd3d55a fix(ng:repeat): support repeating over array with null
typeof null == 'object', but it doesn't behave like an object
because its properties can't be dereferenced, so we need
to special-case it.

Closes #702
2012-01-10 22:21:53 -08:00
Igor Minar 7146f70636 fix($httpBackend): fix for jsonp requests 2012-01-09 14:38:32 -08:00
Igor Minar 11cb9423a7 chore(docs): disable disqus for localhost
it's just slowing down the test runs and debugging
2012-01-09 13:17:49 -08:00
Igor Minar c76a120bfe fix(nodeserver): add dummy favicon.ico to silence 404s 2012-01-09 13:17:49 -08:00
Igor Minar b8960c3710 chore($http): small $http fixes 2012-01-09 13:17:48 -08:00
Igor Minar 67338ce061 feat($http): turn mock backend into a decorator + e2e testing support
- provider -> decorator
- autoflush + passThrough mode
- fix noop -> angular.noop
2012-01-09 13:17:48 -08:00
Igor Minar 23f8da7cbb feat($http): expose req/resp headers to transform fns 2012-01-09 13:17:48 -08:00
Igor Minar b911e303ec feat($httpBackend): add expect/when shortcut methods 2012-01-09 13:17:48 -08:00
Igor Minar a13b5ed3bc fix($http): fix and cleanup $http and friends
$http:
- use promises internally
- get rid of XhrFuture that was previously used internally
- get rid of $browser.defer calls for async stuff (serving from cache),
  promises will take care of asynchronicity
- fix transformation bugs (when caching requested + multiple request
  pending + error is returned)
- get rid of native header parsing and instead just lazily parse the
  header string

$httpBackend:
- don't return raw/mock XMLHttpRequest object (we don't use it for
  anything anymore)
- call the callback with response headers string

mock $httpBackend:
- unify response api for expect and when
- call the callback with response headers string
- changed the expect/when failure error message so that EXPECTED and GOT
  values are aligned

Conflicts:

	src/service/http.js
	test/service/compilerSpec.js
	test/service/httpSpec.js
2012-01-09 13:17:48 -08:00
Igor Minar 63cca9afbc feat(browser.defer): flush should throw exception when queue is empty 2012-01-09 13:17:48 -08:00
Vojta Jina d47ec772c3 docs(fix): select widget name -> ng:model 2012-01-08 15:06:12 -08:00
Vojta Jina 5c19766063 feat(ng:include): enable/disable scrolling through autoscroll attribute 2012-01-07 00:18:22 -08:00
Vojta Jina f2119c7524 fix($httpBackend): respond 200/404 when on file protocol (fix protocol parsing) 2012-01-06 19:20:29 -08:00
Dhruv Manek 08029c7b72 fix(angular.copy): throw Error if source and destination are identical
Closes #693
2012-01-06 12:19:39 -08:00
Igor Minar 0bf611087b feat(scope): throw exception when recursive $apply 2012-01-06 12:19:39 -08:00
Igor Minar acb4338b70 style(widgetsSpec): ws, unused variables, etc 2012-01-06 12:19:39 -08:00
Igor Minar cd9a7b9608 fix(ng:repeat): support repeating over array with null
typeof null == 'object', but it doesn't behave like an object
because its properties can't be dereferenced, so we need
to special-case it.

Closes #702
2012-01-06 12:19:39 -08:00
Vojta Jina 1dccaaaaa2 chore(readme): add some links and update test commands 2012-01-05 19:54:42 -08:00
Igor Minar 9632f5c1c7 style(q): rename src/Deferred.js to src/service/q.js 2012-01-03 17:48:09 -08:00
Igor Minar bb3be87606 style(q): reorganize the file + drop fallback dependencies 2012-01-03 17:48:09 -08:00
Igor Minar 174952e443 docs(q): documentation for all $q apis 2012-01-03 17:31:23 -08:00
Vojta Jina 6f91ffeb91 style: prefer single quotes + some whitespaces 2012-01-03 15:09:00 -08:00
Vojta Jina c594f75b4c refactor: remove old JSTD assertions
So that we can run the tests even without JSTD :-D
2012-01-03 15:09:00 -08:00
Mark Hansen 50eb7f15b8 docs(scope): fix typo $digest -> $watch 2012-01-03 15:01:34 -08:00
Sean Gilligan 212a6ff29a docs(resource): fix params for non-get actions 2012-01-03 14:57:38 -08:00
Igor Minar 871252ab4c docs(guide): fix $xhr -> $http links 2011-12-07 16:59:06 -08:00
bartes 0c534644bc fix(input): bind inputs to the 'input' event
The input event is fired on all non-ie browsers whenever the contents of an input
field changes. This means that we now support cut&paste via mouse which
was previously unsupported.

IE8 and older don't support this events and IE9 has a problematic
support for it, so we can't rely solely on this event and drop keydown
and change events.
2011-12-07 13:07:20 -08:00
Igor Minar c28662d28d fix(filter): remove the $ prefix from filter service ids 2011-12-07 13:07:19 -08:00
Igor Minar b97c6e5f74 style(scopeSpec): clean up scopeSpec.js 2011-12-07 09:41:09 -08:00
Igor Minar 4e3c05b99e feat(injector): add $provide.decorator 2011-12-07 09:41:08 -08:00
Igor Minar 5e4d59adf0 style(injector): cleanup of InjectorSpec.js 2011-12-07 09:41:07 -08:00
Igor Minar fd38655e6c fix(): use angular.callbacks namespace for jsonp callbacks
Previously we used to put callbacks on the window object, but that
causes problems on IE8 where it is not possible to delete properties
from the window object
2011-12-07 07:54:09 -08:00
Vojta Jina b9001e9147 fix(route): $destroy scope after update and reload
When we update route (changing only search param, no route reload) and then reload (change to different
route), it did not $destroy last scope.
2011-12-06 13:35:05 -08:00
Igor Minar d1e7a5394a docs(form): add docs about form submission 2011-12-06 13:32:49 -08:00
Vojta Jina 2090136dd8 docs(ng:submit): update docs example to not add empty items 2011-12-06 13:07:27 -08:00
Vojta Jina c9f2b1eec5 feat(form): do not prevent submission if action attribute present 2011-12-06 13:07:26 -08:00
Igor Minar 163e05ed36 feat($http): allow interceptors to be services 2011-12-05 23:53:26 -08:00
Igor Minar 2986a09c0d fix(jqLite): JQLiteHasClass should work even when minified
closure compiler is smarter than we expected and drops the unused fn
argument - this breaks the meta-programing logic of jqLite.

The fix special cases JQLiteHasClass since its the only fn that needs
this treatment in a way that is minification-proof.
2011-12-05 14:12:00 -08:00
Igor Minar bb2e7488fa fix($httpBackend mock): getResponseHeader should be case insensitive 2011-12-01 18:21:45 -05:00
Igor Minar 44b2f44f93 fix($resource): forwardport exposing headers from 0.9.19 2011-12-01 16:20:08 -05:00
Igor Minar 1d14760c6d fix(ng:include): prevent race conditions by ignoring stale http callbacks
This fix is similar to what I've done in ng:view, if a new template has been requested before the
callback for the previous template returned, ignore it. Otherwise weird race conditions happen
and users might end up getting the content for the previous include rendered instead of the most
recent one.
2011-11-30 14:49:36 -05:00
Igor Minar baa7af0df0 docs($location): add docs for the $location.search setter 2011-11-30 14:49:36 -05:00
Igor Minar f43c226c67 fix(copy,equals): prevent browser crashes with Scope or Window
Scope and Window instances are special and when copied can crash browser. For this reason
it makes sense to compare them only by identity.
2011-11-30 14:49:36 -05:00
Misko Hevery 0e1fa2aefe feat($interpolate): string interpolation function 2011-11-30 14:49:36 -05:00
Igor Minar 3d0ce0ebe9 feat($location): name the watch function to ease debugging 2011-11-30 14:49:36 -05:00
Igor Minar b00da987a9 scope($digest): add new&old val to the infinite $digest log 2011-11-30 14:49:35 -05:00
Igor Minar 188bdf7768 feat($http): add response interceptors 2011-11-30 14:49:35 -05:00
Igor Minar dbd880cc0a feat($http): add promise support
quite messy, some tests are missing, contains an experimental jasmine DI support)
2011-11-30 14:49:35 -05:00
Igor Minar bf8e0540f8 feat(dump): add support for arrays, functions, errors 2011-11-30 14:49:35 -05:00
Igor Minar 78b6e8a446 feat($parse): add support for transparent evaluation of Promises
Parser now builds expressions that can detect promises and transparently
evaluate them to undefined or the promise value.

If promiseA is resolved with value 'A', then {{promiseA}} evals to 'A';
If promiseA is unresolved, then {{promiseA}} evals to undefined;

Following invocations are supported:

- {{promise}}
- {{promise.futureProp}}
- {{[promise][0]}}
- {{object.promise}}
- {{object[promise]}}
- {{array[promise]}}
- {{fn(promise)}}
- combinations of the above
2011-11-30 14:49:35 -05:00
Igor Minar b656552d68 fix(angular-boostrap): add missing jQuery/jqLite binding 2011-11-30 14:49:35 -05:00
Igor Minar 1cdfa3b960 feat(deferreds/promises): Q-like deferred/promise implementation with a ton of specs 2011-11-30 14:49:03 -05:00
Vojta Jina 16363d8000 refactor(ng:view, ng:include): pass cache instance into $http
Instead of doing all the stuff in these widgets (checking cache, etc..) we can rely on $http now...
2011-11-30 14:49:03 -05:00
Vojta Jina 92995bbce9 fix($http): default json transformation should not crash on angular template
The way we determine whether it's json is lame anyway. We need to change that.
We should probably check the content type header...
2011-11-30 11:17:25 -05:00
Vojta Jina b9707d910e style(): get rid off some jsl warnings 2011-11-30 11:17:25 -05:00
Vojta Jina 5bbd64ac65 feat($http): allow passing custom cache instance per request
You can still use cache: true, which will use $http's default cache.
2011-11-30 11:17:25 -05:00
Vojta Jina caeb1bf899 feat($httpBackend): fix 0 status code when "file" protocol
Browsers return always 0 status code for "file" protocol, so we convert them into 200/404.
2011-11-30 11:17:24 -05:00
Vojta Jina 9b4efa73f9 feat(mock.$httpBackend): say which request was expected when unexpected request error 2011-11-30 11:17:24 -05:00
Vojta Jina 4aaa2f7f6b feat(mock.$httpBackend): verify expectations after flush() 2011-11-30 11:17:24 -05:00
Vojta Jina 6290bd4587 refactor(mock.$httpBackend): rename when().then() to when().respond() 2011-11-30 11:17:24 -05:00
Vojta Jina e9f81b6631 fix(mock.$httpBackend): flush() even requests sent during callbacks 2011-11-30 11:17:23 -05:00
Vojta Jina afbe073121 feat(mock.$httpBackend): add verifyNoOutstandingRequest method
+ rename verifyExpectations to verifyNoOutstandingExpectation
2011-11-30 11:17:23 -05:00
Vojta Jina 7b705df2b7 feat($http): broadcast $http.request event 2011-11-30 11:17:23 -05:00
Vojta Jina a4c8ac7126 feat(mock.$httpBackend): throw when nothing to flush, dump data/headers when expected different 2011-11-30 11:17:23 -05:00
Vojta Jina e3e2e4436e fix($http): add .send() alias for .retry() to get better stack trace on error 2011-11-30 11:17:22 -05:00
Vojta Jina 972c3e9be0 refactor($http): change callback matching mechanism 2011-11-30 11:17:22 -05:00
Vojta Jina feacf608ee fix($resource): to work with $http, $httpBackend services
Breaks Disabling $resource caching for the moment.
2011-11-30 11:17:22 -05:00
Vojta Jina fe633dd0cf fix($http): allow multiple json vulnerability prefixes
We strip out both:
)]}',
)]}'
2011-11-30 11:17:22 -05:00
Vojta Jina fdcc2dbfd3 feat($http): expose pendingRequests and configuration object
- $http.pendingRequests is now an array of pending requests
- each request (its future object) has public property configuration
2011-11-30 11:17:22 -05:00
Vojta Jina 5ad0c7d0e4 feat($httpBackend): extract $browser.xhr into separate service
- remove whole $browser.xhr stuff
- remove whole mock $browser.xhr stuff
- add $httpBackend service + migrate unit tests from $browser
- add temporary API to access $browser's outstandingRequests count
2011-11-30 11:17:22 -05:00
Vojta Jina 540701a8d8 feat(mocks.$browser): add simple addJs() method into $browser mock 2011-11-30 11:17:22 -05:00
Vojta Jina 4d2d70e7fb feat($templateCache): add $templateCache - shared by ng:include, ng:view 2011-11-30 11:17:21 -05:00
Vojta Jina cd28a2e952 feat(mocks.$httpBackend): add $httpBackend mock
$httpBackend mock allows:
- expecting (asserting) requests
- stubbing (responding without asserting)

Add empty $httpBackend service (currently just wrapper for $browser.xhr)
2011-11-30 11:12:14 -05:00
Vojta Jina 59adadca08 feat($http): new $http service, removing $xhr.*
Features:
- aborting requests
- more flexible callbacks (per status code)
- custom request headers (per request)
- access to response headers
- custom transform functions (both request, response)
- caching
- shortcut methods (get, head, post, put, delete, patch, jsonp)
- exposing pendingCount()
- setting timeout
Breaks Renaming $xhr to $http
Breaks Takes one parameter now - configuration object
Breaks $xhr.cache removed - use configuration cache: true instead
Breaks $xhr.error, $xhr.bulk removed
Breaks Callback functions get parameters: response, status, headers
Closes #38
Closes #80
Closes #180
Closes #299
Closes #342
Closes #395
Closes #413
Closes #414
Closes #507
2011-11-30 11:12:14 -05:00
Igor Minar 497839f583 feat($cacheFactory): add general purpose $cacheFactory service 2011-11-30 11:03:42 -05:00
Vojta Jina 5487bdb3d1 feat($browser.xhr): add timeout option to abort request
Timeouted request responds internal status code -1, which should be normalized
into 0 by $xhr.
2011-11-30 11:03:42 -05:00
Vojta Jina 3ae3ccf3da fix($browser.xhr): fix IE6, IE7 bug - sync xhr when serving from cache
IE6, IE7 is sync when serving content from cache.
We want consistent api, so we have to use setTimeout to make it async.
2011-11-30 11:03:42 -05:00
Vojta Jina e9b57f9df8 fix($browser.xhr): respond with internal -2 status on jsonp error
If jsonp is not successfull, we return internal status -2.
This internal status should by normalized by $xhr into 0,
but $xhr needs to distinguish between jsonp-error/abort/timeout (all status 0).
2011-11-30 11:03:42 -05:00
Vojta Jina 45f47ff6cd fix($browser.xhr): change method "JSON" to "JSONP"
Breaks "JSON" xhr method is now called "JSONP"
2011-11-30 11:03:41 -05:00
Vojta Jina 0c8b35681e feat($browser): xhr returns raw request object 2011-11-30 11:03:41 -05:00
Igor Minar a035e88397 docs(guide): fix directives guide docs 2011-11-28 18:04:01 -05:00
Vojta Jina 3548fe3139 feat(service.$autoScroll): scroll to hash fragment
- whenever hash part of the url changes
- after ng:view / ng:include load
2011-11-21 17:49:49 -08:00
Codier 29f9e2665d fix(scope): $watch (and angular.equals) should support NaN values
- since NaN !== NaN in javascript digest can get into an infinite loop
  when model value is set to NaN
- angular.equals(NaN, NaN) should return true since that's what we
  expect when comparing primitives or objects containing NaN values

Previously NaN because of its special === properties was used as the
initial value for watches, but that results in issues when NaN is used
as model value.

In order to allow for model to be anything incuding undefined and NaN we
need to mark the initial value differently in a way that would avoid
these issues, allow us to run digest without major perf penalties and
allow for clients to determine if the listener is being called because
the watcher is being initialized or because the model changed. This
implementation covers all of these scenarios.

BREAKING CHANGE: previously to detect if the listener was called because
the watcher was being initialized, it was suggested that clients check
if old value is NaN. With this change, the check should be if the newVal
equals the oldVal.

Closes #657
2011-11-21 15:43:12 -08:00
Igor Minar 8d1944851d fix(docs): specify disqus_url 2011-11-19 15:42:17 -08:00
TEHEK Firefox 3e1a6688c3 chore(browser): rename Browser.js -> browser.js, BrowserSpec.js -> browserSpec.js
And move them to proper service subfolder...
2011-11-18 12:05:55 -08:00
Misko Hevery aba9bb2a24 fix(input): treat all not number model as blank 2011-11-15 11:47:23 -08:00
Misko Hevery 5857c44e0c fix(radio): fix binding to value={{exp}} 2011-11-15 11:44:36 -08:00
Misko Hevery 8adae2fdf2 refactor(injector): removed loadModule/ng:module
- added module property to doc:example
2011-11-14 20:31:21 -08:00
Misko Hevery 955551141d style(angularPublic): move public export definition to AnuglarPublic.js 2011-11-14 20:31:21 -08:00
Misko Hevery 94e1a07b28 doc(rename): NG_LOCALE -> ngLocale 2011-11-14 20:31:20 -08:00
Misko Hevery ac73e8877e add(doc): added missing angular.module.ng namespace 2011-11-14 20:31:19 -08:00
Misko Hevery e88dfb734a refactor(injector): $injector is no longer a function.
- $injector('abc') -> $injector.get('abc');
- $injector(fn) -> $injector.invoke(null, fn);
2011-11-14 20:31:19 -08:00
Misko Hevery 8d6dc0b9a7 del($eager): removed the support for $eager services 2011-11-14 20:31:19 -08:00
Vojta Jina acbd7cdf32 style(docs): make jslint happy - fix some warnings 2011-11-14 20:31:19 -08:00
Misko Hevery 035c751076 fix(doc) cleanup all dev guide doc link warnings 2011-11-14 20:31:18 -08:00
Misko Hevery 186a840cd3 feat(bootstrap): added angular.bootstrap method 2011-11-14 20:31:18 -08:00
Misko Hevery b09595a3c1 fix(doc) cleanup all api doc link warnings 2011-11-14 20:31:18 -08:00
Misko Hevery f6d98f1472 fix(doc): make output less noisy 2011-11-14 20:31:17 -08:00
Vojta Jina 5279de0e70 fix($location): links without path segment should not change the path
Closes #648
2011-11-14 20:31:17 -08:00
Misko Hevery 8fe77b69e8 refactor(docs): improved the visual rendering of the documentation pages 2011-11-14 20:31:17 -08:00
Misko Hevery 1cc6bee4ce docs(browser): moved and migrate browser removed unneeded files. 2011-11-14 20:31:17 -08:00
Misko Hevery a8aa193c6b doc($rootScope): scope documentation changes 2011-11-14 20:31:17 -08:00
Misko Hevery e45b013143 doc(locale): migrate docs to new format 2011-11-14 20:31:16 -08:00
Misko Hevery ea18f4548d doc($formFactory): migrated the $formFactory documentation 2011-11-14 20:31:16 -08:00
Misko Hevery 57c37a21d1 doc(service): update docs for the moved services 2011-11-14 20:31:16 -08:00
Misko Hevery 74fac45f48 doc($filter): added $filter documentation 2011-11-14 20:31:16 -08:00
Misko Hevery f0fa5e6376 doc(AUTO, NG_MOCK): Documenting the AUTO and NG_MOCK module 2011-11-14 20:31:16 -08:00
Misko Hevery c283bf6035 refactor($location): merged $locationConfig service into $locationProvider 2011-11-14 20:31:15 -08:00
Misko Hevery b3c17f3fdc chore(scope): remove $service 2011-11-14 20:31:15 -08:00
Misko Hevery 9c06394376 chore(scenario tests): make scenario tests pass again 2011-11-14 20:31:15 -08:00
Misko Hevery 085e3c611f new(directive): added ng:module directive for loading modules 2011-11-14 20:31:15 -08:00
Misko Hevery 4b35a59c6a refactor(scenario): fix scenario bootstrap & publish injector for inspection 2011-11-14 20:31:14 -08:00
Misko Hevery 7cb03c5ab9 chore(angular): clean up unused constants 2011-11-14 20:31:14 -08:00
Misko Hevery 78c7066422 refactor(angular): isDate / isArray test iframe independent fix 2011-11-14 20:31:14 -08:00
Misko Hevery 923da410bd fix(i18n): updated the way locale is being registered 2011-11-14 20:31:14 -08:00
Misko Hevery a87f2fb9e4 refactor(mock): moved mocks into its own module 2011-11-14 20:31:14 -08:00
Misko Hevery c27aba4354 refactor(api): remove type augmentation
BREAK:
  - remove angular.[Object/Array/String/Function]
  - in templates [].$filter(predicate) and friends need to change to [] | filter:predicate
2011-11-14 20:31:14 -08:00
Misko Hevery dd9151e522 refacter(filters): convert filter/limitTo/orderBy from type augmentation to filters 2011-11-14 20:31:13 -08:00
Misko Hevery 3972d2a89b refactor(json): break dependence on api.js 2011-11-14 20:31:13 -08:00
Misko Hevery cb6f832f38 refactor(filter): filters are now injectable and services
BREAK:
 - removed CSS support from filters
2011-11-14 20:31:09 -08:00
Misko Hevery 6022f3df39 move(filters): appease the History God 2011-11-14 16:39:34 -08:00
Misko Hevery 7c11531902 refactor(parser): turn parser into a service (keep compatibility hack) 2011-11-14 16:39:33 -08:00
Misko Hevery c6d2549a52 fix(JSON): json date parsing same native/ngular parser 2011-11-14 16:39:33 -08:00
Misko Hevery bee6060e4b move(parser): appease the History God 2011-11-14 16:39:33 -08:00
Misko Hevery 16597e8b52 refactor($service): removed almost all references to scope.$service
- still need to remove from factory
2011-11-14 16:39:33 -08:00
Misko Hevery f684f20c99 cleanup(parser): removed unused method 2011-11-14 16:39:33 -08:00
Misko Hevery bd04316a89 refactor(services): migrate angular.service -> module 2011-11-14 16:39:33 -08:00
Misko Hevery ed36b9da3b refactor(injector): switch to injector 2.0 introduce modules 2011-11-14 16:39:32 -08:00
Misko Hevery c925f8a657 new(injector): new injector v2.0
- not connected to keep the CL small
2011-11-14 16:39:32 -08:00
Misko Hevery 4c10d33eb4 refactor(api): cleaned up the externalization of angular API methods 2011-11-14 16:39:32 -08:00
Misko Hevery 9062996a0e feat(injector): support $inject(fn($service){}) function invocation 2011-11-14 16:39:32 -08:00
Misko Hevery 411c1ae77e feat(injector): support ['$service', function($service){}] annotations for function invocation. 2011-11-14 16:39:32 -08:00
Misko Hevery d12df0d360 refactor(compiler) turn compiler into a service
BREAK
- remove angular.compile() since the compile method is now a service and needs to be injected
2011-11-14 16:39:32 -08:00
Misko Hevery d9b58f23f6 move(compiler): appease the History God
-	renamed:    src/Compiler.js -> src/service/compiler.js
-	renamed:    test/CompilerSpec.js -> test/service/compilerSpec.js
2011-11-14 16:39:32 -08:00
Misko Hevery 03dd8c4f4c feat(injector): Service look up failures include dependency path 2011-11-14 16:39:32 -08:00
Misko Hevery 48697a2b86 refactor(injector): turn scope into a service
- turn scope into a $rootScope service.
- injector is now a starting point for creating angular application.
- added inject() method which wraps jasmine its/beforeEach/afterEach,
  and which allows configuration and injection of services.
- refactor tests to use inject() where possible

BREAK:
- removed angular.scope() method
2011-11-14 16:39:31 -08:00
Misko Hevery 93b777c916 move(scope): appease the History God
-	renamed:    src/Scope.js -> src/service/scope.js
-	renamed:    test/ScopeSpec.js -> test/service/scopeSpec.js
2011-11-14 16:39:31 -08:00
Vojta Jina 5c70ff72e2 style(docs): make jslint happy - fix some warnings 2011-11-13 16:40:31 -08:00
Vojta Jina 5e663c3dc7 fix(docs.guide): fix $location example 2011-11-13 16:40:31 -08:00
Vojta Jina 260725efcd feat(docs): allow examples with hidden source code 2011-11-13 16:40:31 -08:00
Vojta Jina 4afad1da29 feat(docs): allow custom attributes on <doc:source>
Allow any attributes, not only jsfiddle...
2011-11-13 16:40:31 -08:00
Dhruv Manek eb01fe593d feat(jquery): upgrade to jQuery 1.7
no breaking changes AFAICT
2011-11-13 16:30:21 -08:00
Misko Hevery fc7834f9ac cleanup(parser): remove unused method 2011-11-11 13:04:26 -08:00
Misko Hevery e4303a1f3a chore(test): remove stale bit-rotten code
- deleted:    test/manual.html
2011-11-09 08:54:04 -08:00
Igor Minar 1e00db8daa fix(directives): make directive names case-insensitive
+ tests
+ added docs for angular.directive
2011-11-08 21:44:46 -08:00
Igor Minar aaa0179758 chore(release): preparing the 0.10.6 bubblewrap-cape iteration 2011-11-08 16:39:19 -08:00
Igor Minar f5ef3724ce chore(release): cutting the 0.10.5 steel-fist release 2011-11-08 04:29:07 -08:00
Igor Minar e60601be4f docs(changelog): release notes for 0.10.5 steel-fist 2011-11-08 04:29:07 -08:00
Dhruv Manek e2663f62b0 feat(ng:style): compatibility + perf improvements
- better compatibility with 3rd party code - we clober 3rd party
  style only if it direcrtly collides with 3rd party styles
- better perf since it doesn't execute stuff on every digest
- lots of tests
2011-11-08 02:25:22 -08:00
Igor Minar 9f9ed4c5ff docs(ng:bind-attr): improve examples 2011-11-08 02:23:51 -08:00
Igor Minar 66fc268aeb docs(css): fixing positioning of disqus comments
float:left causes the comments to shift to the left when content is longer
than the sidebar
2011-11-05 22:30:50 -07:00
Vojta Jina 1d966f8a65 style(angularFiles): just missing semi-colon and extra comma 2011-11-01 14:14:52 -07:00
Vojta Jina ddf6f1143f test(mocks): test mocks with compiled angular
Unfortunately, there people in our team (me), who are not able to use angular.* namespace prefix
when writing angular-mocks code, so we need to test it...
2011-10-31 18:22:38 -07:00
Vojta Jina 2636105c5e feat(matchers): extract jasmine matchers into separate file for future reuse
Prefix all used functions with angular.* so that they can be used with compiled angular as well...
2011-10-31 18:22:21 -07:00
Igor Minar c0b557a96c test(scope): infinite digest test should pass on all browsers
Different browsers print function body differently, and best of all IE doesn't have
function.name property.
2011-10-31 12:46:12 -07:00
Igor Minar 84873e7f4e fix(angular-bootstrap): fix boostrap scripts that broke w\ 5a2dcb9a
Commit 5a2dcb9a doesn't properly modify angular-boostrap.js.

This fix resolves issues and makes both the regular and scenario
version of angular-boostrap.js functional.
2011-10-31 11:34:25 -07:00
Igor Minar 95fdb1231f chore(watchr): watchr scripts should output logs to terminal
Having the extra level of indirection by using logs/*.log file
only makes it more difficult to use these scripts. After this
change it will be enough to just start the watchr and watch the
terminal it was started in.
2011-10-31 11:34:25 -07:00
Igor Minar ef875ad0cf feat(scope): better logging of infinite digest error
Feedback team has often problems debugging inifinite digest errors, this change
should reveal info about what watchers are causing the infinite loop
2011-10-31 11:34:25 -07:00
Igor Minar 615841a5d3 style(widgets): fix typo in a spec comment 2011-10-31 07:19:33 -07:00
Vojta Jina 7d0c256ecd docs(jqlite): add missing methods 2011-10-30 22:31:03 -07:00
Igor Minar 6cbe096dbf feat(docs): remove the Report Issue link - duplication of disqus 2011-10-30 22:27:25 -07:00
Igor Minar 21602b5cd6 fix(docs): special case url generation for index pages 2011-10-30 22:27:25 -07:00
Igor Minar 4ae671ac88 fix(docs): increment load counter only when a valid page is requested 2011-10-30 22:27:25 -07:00
dandoyon 28ed5ba465 feat(docs): disqus integration
- add style for disqus threads in css
- add loadDisqus method to be called afterPartialLoaded
- add div container for disqus threads
2011-10-30 22:27:25 -07:00
Igor Minar 02dc81bae0 fix(css): ng:form should always be a block element 2011-10-30 22:26:32 -07:00
Igor Minar 445680f601 fix(nodeserver): properly escape all, not just first char 2011-10-27 08:44:14 -07:00
Vojta Jina bf729d550b feat(docs): Add scenario runner into dev guide
And update the link in the tutorial as well...
2011-10-26 15:58:59 -07:00
Vojta Jina dc8ffa51b7 fix(scenario.dsl): Fix dsl for $location
New $location does not have hashSearch, hashPath.
The old dsl was mixing $location / window.location so this solves the problem as well...
2011-10-26 15:58:59 -07:00
Igor Minar d7ba5bc83b feat(bootstrap): drop angular.js file name restrictions for autobind
The last script element in the dom is always us if the script that
contains angular is loaded synchronously.

For async loading manual bootstrap needs to be performed.

Close #621
2011-10-26 12:57:15 -07:00
Igor Minar 950d02b4d4 fix(docs): remove unused $browser dependency 2011-10-26 12:57:14 -07:00
Igor Minar 578e38e0af fix(example): fixes for personalLog e2e tests
Looks like this got broken with scope rewrite.
2011-10-26 12:57:14 -07:00
Igor Minar af7c51ee1d style(Angular.js): various code style fixes 2011-10-26 12:57:14 -07:00
Igor Minar 25d1822bd8 style(HashQueueMap): fixing a typo in the comment 2011-10-26 12:54:00 -07:00
Igor Minar 3945f884c5 fix(ng:repeat) with array ignore properties not representing array elements
Along the way I also changed the repeater impl to use for loop instead
of for in loop.

Iteration over objects is handled by creating an array of keys, which is
sorted and this array then determines the order of iteration over an
element. This makes repeating over objects deterministic and
cross-browser compatible.
2011-10-26 12:54:00 -07:00
Igor Minar d5ccabce60 fix(ng:view): ignore stale xhr callbacks
A lot of badness happens when we don't ignore stale xhrs. These
raceconditions are only apparent when user clicks through the app very
quckly without waiting for routes to fully load.

Closes #619
2011-10-26 12:15:07 -07:00
Igor Minar bb948176aa test(ng:view): spec cleanup
- remove optional controller definition from specs
- remove extranious digest calls
2011-10-26 12:02:30 -07:00
Dhruv Manek 163c799eff fix(angular.widget): Allow widgets to be styled in IE8 and below
Closes #584
2011-10-24 23:28:36 -07:00
Vojta Jina 7da70af1ae fix(scenario): Change title to "AngularJS" 2011-10-24 14:03:50 -07:00
Igor Minar 836e4c1428 chore(release): preparing the 0.10.5 steel-fist iteration 2011-10-24 09:16:33 -07:00
Igor Minar eabedba34d chore(release): cutting the 0.10.4 human-torch release 2011-10-22 21:39:39 -07:00
Igor Minar b4add97c17 docs(changelog): update changelog with 0.10.4 release notes 2011-10-22 21:39:39 -07:00
Igor Minar bacc31bea9 fix(defer.cancel): should return false instead of undefined 2011-10-22 21:32:48 -07:00
Igor Minar ad90c3574f feat($defer): add $defer.cancel
This functionality was previously available only as obscure $browser.defer.cancel.

I also added docs and tests and fixed an issue in .defer.cancel mock.
2011-10-22 21:32:48 -07:00
Igor Minar e28171d5e4 fix(docs): key-binding used old scope apis 2011-10-22 21:32:48 -07:00
Igor Minar ce73ed091b feat(docs): add "Loading..." notification 2011-10-22 21:32:47 -07:00
Igor Minar 90ac8d57b0 fix(docs): update page title only when content loads 2011-10-22 21:32:47 -07:00
Igor Minar 6eb1179505 style(docs): change "this" to "scope" in the controller 2011-10-22 21:32:47 -07:00
Vojta Jina 9b85757102 fix($location): rewrite links with nested elements
For example:
<a href="some/link">inner <span>text</span></a>

If you click on "text", then the span element is event.target, so we need to traverse the DOM.
2011-10-22 15:35:18 -07:00
Igor Minar c6c3949b14 feat(filter.date): use mediumDate as default
Breaking change!

Previously the default was fullDate.
2011-10-20 16:51:28 -07:00
Igor Minar e175db37c6 fix(date filter): default to fullDate format
The browser's behave inconsistently, so we should just stick to one format
when the format is not specified by the developer

Closes #605
2011-10-20 16:51:28 -07:00
Igor Minar f38010d3a2 fix(compiler): revert 8611ebe6 - calling \$digest after linking
Change introduced by me in 8611ebe6 results in considerable inefficiencies when the compiler
and linker is used from within a widget, in which case, we call $digest unnecessary since it
will be called by the $apply which called the directive/widget in the first place.

There are only two places when the extra $digest call can be useful - when manually bootstrapping
the app or in tests. However even in tests this behavior can result in unwanted results (especially
when ng:controller is involved). So it is better to leave it for the developer to call $digest
when it is really needed.
2011-10-20 15:51:14 -07:00
Misko Hevery 7fc18b263d fix(radio): allows data-binding on value property. Closes#316 2011-10-20 11:30:40 -07:00
Igor Minar fabc9f77a3 feat(sanitizer): add html5 elements to the whitelist
Closes #89
2011-10-20 09:44:52 -07:00
Igor Minar c17c731fdc style(select): cleaning up select.js 2011-10-19 22:52:14 -07:00
TEHEK Firefox 3692885810 fix(ng:options): compile null/blank option tag
Fixes #562
2011-10-19 22:52:14 -07:00
Igor Minar 5d43439dbe fix(ng:pattern): correctly parse out inlined regexp 2011-10-19 21:52:20 -07:00
Igor Minar a46f2a0db3 docs(textarea): add docs for angular.widget.textarea 2011-10-19 16:49:34 -07:00
Igor Minar 3217a249e1 style(input): fix style violations in the input.js file 2011-10-19 16:49:34 -07:00
Konstantin Stepanov 78f394fd17 feat(input): add ng:minlength and ng:maxlength validation
notes(igor): I also e2e tests and refactorred the e2e test example to be
more clear about what is a variable and what is an html/framework api.
2011-10-19 16:49:20 -07:00
Konstantin Stepanov e82e64d57b fix(input): recognize 'password' as an html input type 2011-10-19 10:36:36 -07:00
Vojta Jina 8978e066b5 fix(gen-docs): require files without touching PATH
So that it works on latest revision of node...
New version of Node (v0.5.x) does not support require.paths.push().
2011-10-18 22:23:52 -07:00
Igor Minar 833eb3c844 fix(ng:repeat): repeater should ignore $ and $$ properties 2011-10-18 17:27:43 -07:00
Igor Minar 07926ff1ef chore(version.yaml): add missing snapshot version suffix 2011-10-18 17:25:10 -07:00
Igor Minar e801faba2e chore(jstd adapter): switch to our version with backported fixes
sha of the version: da92db714142b49f9cf61db664e782bb0ccad80b
2011-10-18 16:21:52 -07:00
TEHEK Firefox ee6af9a978 fix(ng:options): select correct element when '?'-option was previously selected
Closes #599
2011-10-18 14:02:54 -07:00
Igor Minar 74379df6c4 chore(release): preparing the 0.10.4 human-torch iteration 2011-10-14 15:29:17 -07:00
Igor Minar fe65dd926c chore(release): cutting the 0.10.3 shattering-heartbeat release 2011-10-14 08:31:39 -07:00
Igor Minar 669b53ede2 fix(docs): fix jsfiddle integration
this got accidentally messed up during the forms refactoring and mass renaming
2011-10-14 08:31:00 -07:00
Igor Minar b0c3f28e8f docs(forms): fix devguide forms example code 2011-10-14 08:30:02 -07:00
Igor Minar 9810dc0993 docs(cookbook): disable jsfiddle for deeplinking example
it uses extra resources, so it won't work on fiddle
2011-10-14 08:29:33 -07:00
Vojta Jina ab5df20dfa chore(libs): update libs (jasmine, jstd, jasmine-jstd adapter) 2011-10-13 17:36:11 -07:00
Igor Minar d83a92c121 fix(checkbox): prefix true-value & false-value with ng: 2011-10-13 17:35:00 -07:00
Igor Minar d0425de29e chore(release): preparing release notes for 0.10.3 2011-10-13 16:54:30 -07:00
Igor Minar ad5e42cf82 docs($location): Html5 -> HTML5 2011-10-13 14:42:49 -07:00
Igor Minar 9ed1126adb docs($location): update replace() docs 2011-10-13 14:37:37 -07:00
Igor Minar 7a19eb84aa docs($location): fix $config -> $locationConfig in docs 2011-10-13 14:07:48 -07:00
Igor Minar 718741acab chore(logo): add hi-res ng logo 2011-10-13 13:44:38 -07:00
Vojta Jina ec8bb675b4 fix(docs): set proper base href when hashbang url requested 2011-10-13 11:10:20 -07:00
Vojta Jina 8e32f3fd35 fix(nodeserver): docs rewriting
There can be url /api which does not end with / and we want to rewrite this url as well...
2011-10-13 11:10:20 -07:00
Vojta Jina 02332107e5 feat(nodeserver): if index.html exists, serve it instead of directory listing 2011-10-13 11:10:20 -07:00
Vojta Jina afc81b554e fix($location): do not rewrite link when meta key pressed 2011-10-13 11:10:19 -07:00
Vojta Jina 26e8ab3693 feat(scenario): allow key pressing when triggering browser event
Add parameter to our browserTriger function to allow specifying which keys are pressed.

Note, this does not work on IE<9 !
2011-10-13 11:10:19 -07:00
Igor Minar 28ccc76aa1 docs(dev_guide.bootstrap.auto_bootstrap): fixing a typo 2011-10-12 23:04:48 -07:00
Igor Minar b3c4cb7cff docs(*): remove @workInProgress from everywhere
it's not useful any more and it only makes the docs look ugly
2011-10-12 23:04:48 -07:00
Misko Hevery 4af4378b11 fix(forms): broken tests on jQuery and ie8&9 2011-10-12 23:04:48 -07:00
Igor Minar 8611ebe6a0 fix(compiler): linking function should call $digest
The linked scope should be $digest-ed but only if a $digest isn't
already running on it.
2011-10-12 23:04:48 -07:00
Igor Minar 8f46a3c9ac fix(jqLite): attr for boolean attribute should lowercase value 2011-10-12 23:04:47 -07:00
Igor Minar 66fdb36ecb refactor(ng:bind-attr): simplify impl by leveraging jquery 2011-10-12 23:04:47 -07:00
Igor Minar f0f5ffa9aa test(jstd-config): add widget specs to jsTestDriver-jquery.conf 2011-10-12 23:04:47 -07:00
Igor Minar 2bc7afd3ba fix(ng:class): ignore undefined or NaN classnames 2011-10-12 23:04:47 -07:00
Igor Minar a4b45397e0 docs(forms): add ng:change docs and other fixes 2011-10-12 11:49:42 -07:00
Igor Minar de4e06ed73 test(checkbox): add test for ng:change 2011-10-12 11:11:10 -07:00
Misko Hevery fd822bdaf9 chore(formating): clean code to be function() { 2011-10-11 11:01:46 -07:00
Misko Hevery 4f78fd692c feat(forms): new and improved forms 2011-10-11 11:01:45 -07:00
Misko Hevery df6d2ba326 style(examples): clean up dead examples 2011-10-11 10:53:07 -07:00
Misko Hevery ccda436f94 style(.gitignore) added IDEA 2011-10-11 10:53:07 -07:00
Misko Hevery e86c435349 refactor(bindings): remove the decoration of the DOM with errors.
Only $exceptionHandler gets notified now.
2011-10-11 10:53:07 -07:00
Misko Hevery 1942861472 refactor(hover): delete hover service 2011-10-11 10:53:06 -07:00
Misko Hevery b96e978178 fix(jqlite): removeClass would clobber class names 2011-10-11 10:53:06 -07:00
Misko Hevery bda2bba2be feat(jqlite): added .inheritedData method and $destroy event.
- refactored .scope() to use .inheritedData() instead.
- .bind('$destroy', callback) will call when the DOM element is removed
2011-10-11 10:53:05 -07:00
Misko Hevery ca08c004c8 feat(jqlite): support required as a no-value attribute 2011-10-11 10:53:05 -07:00
Misko Hevery 25a62b58db refactor(injection) infer injection args in ng:controller only
Because only controllers don't have currying, we can infer its arguments, all other APIs needing currying, automatic inference complicates the matters unecessary.
2011-10-11 10:53:04 -07:00
Misko Hevery 97e3ec4d1b style(gitignore): added xproject to ignore list 2011-10-11 10:53:04 -07:00
Misko Hevery 75f11f1fc4 feat(ng:repeat) collection items and DOM elements affinity / stability 2011-10-11 10:53:04 -07:00
Misko Hevery e134a8335f fix(filter): make json filter ignore private properties 2011-10-11 10:53:03 -07:00
Igor Minar 8ee32a75f0 chore(release): prepare the 0.10.3 shattering-heartbeat iteration 2011-10-10 11:23:08 -07:00
Igor Minar f6a8ad87ee chore(release): cutting the 0.10.2 sneaky-seagull release 2011-10-08 09:18:19 -07:00
Igor Minar 7e6ff401b8 docs(changelog): release notes for 0.10.2 sneaky-seagull 2011-10-08 09:15:10 -07:00
Dhruv Manek 7aeb6a24f7 fix(docs): rename doc dev_guide.templates.css to dev_guide.templates.css-styling
Closes #580
2011-10-07 18:20:20 -07:00
Dhruv Manek e1ecc34edd fix(parser): Fix short circuit of logical AND and OR operators
Closes #433
2011-10-07 16:01:09 -07:00
Misko Hevery 29d36e94e1 feat(gdocs): better error handling 2011-10-05 14:19:33 -07:00
dandoyon 091c173632 docs(started): fixing pluralization 2011-10-05 13:47:43 -07:00
TEHEK Firefox c115fa9924 fix($limitTo): properly handle excessive limits
`angular.Array.limitTo`'s  result should not exceed original input array size

Closes #571
2011-10-05 11:01:32 -07:00
Igor Minar b7a7fc7065 doc($log): fix the $log service example
is no longer auto-published on the root scope, so we need to publish
it via a controller
2011-09-29 03:21:24 +02:00
Igor Minar 21b2a5bd21 chore(directives): add a todo for ng:style 2011-09-28 23:57:01 +02:00
Igor Minar ca1e45beaf fix(jqLite): css should convert dash-separated properties to camelCase
this fix is needed for Firefox or other browsers that strictly follow
dom/css spec which states that element.style should make properties
available in camelCased form.

Closes #569
2011-09-28 23:57:00 +02:00
Igor Minar 084b83ffa9 test(matchers): add toBeOneOf matcher 2011-09-27 21:48:47 +02:00
Marcello Nuccio bf5e5f7bc9 fix($resource): action defaults should override resource defaults
defaults definned per action should take precedence over defaults
defined for the whole resource.

This is potentialy a BREAKING CHANGE in case someone relied on the buggy
behavior.
2011-09-27 00:44:10 +02:00
Igor Minar 2e9fed7b6c fix(e2e): add index-nocache.html to run e2e tests without cache
using appcache while running e2e tests was causing the following
problems:
- Safari would occasionally reload the app (as a result of the appcache
  refresh) during the angular.validator.asychronous test, which would
  result in test failure and false positivy.
- Firefox6 would run the tests very slowly, disabling the cache resolved
  the latency issues
- Sometimes tests would run with stale code pulled from cache, which
  would result in flaky tests.
2011-09-26 23:51:55 +02:00
Igor Minar ea3228e311 fix(scenario): workaround for FF6 dispatchEvent issue #684208 2011-09-26 23:51:54 +02:00
Igor Minar 2eb49147d6 Revert "fix(scenario): temporary fix for FF6"
This reverts commit aac68bf2ba.
2011-09-26 23:51:54 +02:00
Vojta Jina 13f92de624 feat(docs): use html5 history api for all routing in the docs app
- Configure our docs app to use new $location with html5 history api!

- Update simple node web server to serve index.html for all links
  (rewritting).

- Update .htaccess file to serve index.html for all links (rewritting).

- At runtime determine the base href path and attach it to the DOM. We
  needed the absolute URL to get all browsers to work well.

- Because of the above, we also need to dynamically determine all needed
  js/css resources and add them to the DOM. This was needed because FF6
  would eagerly fetch resources with wrong URL since the base element is
  added to the dom at runtime.

- All content html files were moved to the partials directory, because
  with the new html5 urls it was impossible to tell if request for
  http://domain/api/angular.filter.html was an html5 url for the html
  filter doc page, or an xhr/appcache request for the content html file
  for the html filter.

f
2011-09-26 23:51:53 +02:00
Igor Minar 2bc39bb0b4 fix($route): fix regex escaping in route matcher 2011-09-21 13:47:17 +02:00
Igor Minar 62ae7fccbc fix(angular-mocks): fix .defer.cancel when i=0 2011-09-16 14:18:45 +02:00
Igor Minar 3ace81b92a fix(e2e tests): use prop() instead of attr() and quote attributes
Because of changes in jQuery, we need to use element().prop() instead of element().attr() to retrieve className and other element properties.

Additionally all attribute selectors (e.g. input[name=value]) must have value quoted if it contains dots (".").
2011-09-16 02:44:35 +02:00
Igor Minar 9acf45127e fix(scenarioRunner): navigateTo should use prop('contentWindow')
... instead of attr('contentWindow')
2011-09-16 02:44:35 +02:00
Igor Minar 6883e8c7a0 feat(scenarioRunner): adding support for element().prop()
since jQuery 1.6.4 attr() focuses only on work with element attributes and doesn't deal well with element properties, so adding prop() support is required for getting many e2e tests to pass after upgrading the runner to jQuery 1.6.4.
2011-09-16 02:44:34 +02:00
Igor Minar 7ae536d053 fix(specs): various fixes to get IE8+jquery unit tests green 2011-09-16 02:44:33 +02:00
Igor Minar 2170c06924 fix(specs): fix jQuery to jqLite binding on IE8
It appears that this whole time all IE8 unit tests ran only with jqLite. Due to a weird bug in IE[1], we never overwrote jqLite implementation with jQuery, so the tests ran with our jqLite instead.

This affected only IE8 (and likely older) and only in unit testing mode. angular.js - the built artifact binds to jQuery just find.

[1] https://plus.google.com/104744871076396904202/posts/Kqjuj6RSbbT
2011-09-16 02:44:33 +02:00
Igor Minar 0e5a24c584 fix(specs): jQuery now returns attr name instead of true/false for special attrs
for special attrs like 'checked' or 'multiple', jquery now returns the name or undedefined.

e.g. foo.attr('checked') => 'checked' || undefined

The solution is a combination of updating our tests as well as switching
over to prop() instead which properly returns true/false
2011-09-16 02:44:32 +02:00
Igor Minar 4e8f0d6e9f fix($location) $location specs must unbind document listener
link rewriting used in html5 mode on legacy browsers binds to document.onClick - we need to destroy this listener after each test to prevent test collisions (global state is evil).
2011-09-16 02:44:31 +02:00
Igor Minar f9b6b61468 fix(scenario dsl): jQuery getters must have no value
jQuery now requires getter methods to have no value at all -
they do arguments.length check to identify getters vs setters.
2011-09-16 02:44:31 +02:00
Igor Minar 555f415290 fix(ng:options): fix selecting options
Contains 3 fixes:

- the internal model was by mistake using "checked" property instead of
  "selected"
- use jqLite.prop() to set 'selected' property
- added inChangeEvent check - we should not interfere with the browser
  selecting elements when not necessary
2011-09-16 02:44:30 +02:00
Igor Minar 3800d17703 feat(jqLite): add prop() support
since jQuery 1.6.4 prop() became very important because attr() does't have access to certain properties any more (e.g. className), so I'm adding it to jqLite as well so that jqLite preserves the feature-set it had before the jQuery upgrade.
2011-09-16 02:44:30 +02:00
Igor Minar 009059dd1b fix(jqLite): make css() on IE8 behave the same way as jQuery 1.6.4 2011-09-16 02:44:29 +02:00
Igor Minar 6b7ddf414d feat(jqLite): add support for unbind()
supports these invocation types:

- foo.unbind();
- foo.unbind('eventType');
- foo.unbind('eventType', fn);

more info: http://api.jquery.com/unbind/
2011-09-16 02:44:29 +02:00
Igor Minar 8259f10138 fix(jqLite): make attr() compatible with jQuery 1.6.4
The behavior of attr() getter and setter changed in jQuery 1.6 and now they treat element properties and attributes as two different things, but in order to not break everyone there is a partial backwards compatibility for checking and updating element properties as well. see http://api.jquery.com/prop/ for more info.
2011-09-16 02:44:28 +02:00
Igor Minar ab407de54d fix(jqLiteSpec): jQuery's css() getter works only for valid rules
foo.css('bogus', 'value')
foo.css('bogus') => null

so I had to change all tests to use valid css rules
2011-09-16 02:44:28 +02:00
Igor Minar 0d7fe97aff fix(jqLite): attr() should not special-case 'class' attribute
since jQuery 1.6 'class' is not treated specially, so we have to revert this fix and use className in tests instead
2011-09-16 02:44:28 +02:00
Igor Minar a2a830e227 feat (jquery): upgrade everything to jQuery 1.6.4
Closes #556
2011-09-16 02:44:27 +02:00
Igor Minar 8336f3f0ba fix(angular-mocks): fix forEach -> angular.forEach in $browser.defer.cancel 2011-09-16 01:39:03 +02:00
Di Peng e14ac2c3b0 style(bootstrap): fix some missing spaces 2011-09-13 01:02:23 +02:00
Di Peng a13653c814 refactor(angular): externalize script load order into JSON
- move all script load order into angularFiles.js
- rakefile and angular-bootstrap.js use angularFiles.js to get script orders
- gen_jstd_configs.js uses angularFiles.js to generate various jstd config files
- run gen_jstd_configs.js whenever we run server.sh

Closes #470
2011-09-13 01:02:22 +02:00
Igor Minar 8017340cd1 chore(version): preparing the 0.10.2 sneaky-seagull iteration 2011-09-12 19:23:37 +02:00
Igor Minar 17d1aef66a chore(release): cutting the angular 0.10.1 inexorable-juggernaut release 2011-09-09 01:01:46 -07:00
Igor Minar 1856f62cb1 docs(changelog): release notes for angular 0.10.1 inexorable-juggernaut 2011-09-09 01:01:05 -07:00
Kai Groner 7e1f364177 fix($location): Use encodeUriQuery instead of escape
Closes #492
2011-09-08 23:00:59 +02:00
Vojta Jina aac68bf2ba fix(scenario): temporary fix for FF6
https://bugzilla.mozilla.org/show_bug.cgi?id=684208
2011-09-08 23:00:59 +02:00
Vojta Jina 4b4292edb8 style: fix some missing semi-colons and spaces, typos 2011-09-08 23:00:59 +02:00
Vojta Jina 292d5d1421 refactor($route): remove some odd code and rename allowReload to forceReload 2011-09-08 23:00:59 +02:00
Vojta Jina 66dec77555 fix(scenario): do not navigate if click event was cancelled
This is jQuery incompatible hack.
But we were doing monkey patching there anyway...

`$(...).trigger('click')` returns an array of return values, so that scenario
runner knows, whether the event default action was cancelled.

Without this fix, scenario runner was doing navigation even if JS code called
`event.preventDefault()`.

Note, this does not work in FF6
2011-09-08 23:00:59 +02:00
Vojta Jina 8fa79066e2 doc($location): $location docs + using $location guide 2011-09-08 23:00:59 +02:00
Vojta Jina 909415d5ed feat(scenario): browserTrigger returns false if preventDefault()
https://developer.mozilla.org/en/DOM/element.dispatchEvent
dispatchEvent method returns false if at least one of the event handlers called
preventDefault(), true otherwise.

It's helpful when browserTrigger method returns this value, as we can assert,
whether the default operation was cancelled or not.
2011-09-08 23:00:59 +02:00
Vojta Jina 4421f3d435 fix(docs): update docs to reflect new $location and fix e2e tests 2011-09-08 23:00:59 +02:00
Vojta Jina 22cb600280 fix($route): update $route to reflect $location changes
* update $route to reflect new $location
* add some more unit tests to $route
* fix some other failing unit tests
* redirect overrides the url now

Breaks $route custom redirect fn has only 3 params now
2011-09-08 23:00:59 +02:00
Vojta Jina 5ba227c7cd feat($location): $location service with html5 history api support
See documentation of $location for more info

Breaks $location has no properties, only get/set methods

Closes #168
Closes #146
Closes #281
Closes #234
2011-09-08 23:00:49 +02:00
Vojta Jina f37f0ea16e feat(jqLite): add event.isDefaultPrevented() as jQuery
Chrome's Event has defaultPrevented property, but other browsers haven't.
This is workaround for other browsers - same as jQuery.
2011-09-08 20:37:28 +02:00
Vojta Jina 91ccb4ba6e feat($browser): add $browser.baseHref()
This method abstracts <base href="" /> in document.head - returns the value.
If absolute href set, it converts the href to relative.
2011-09-08 20:37:28 +02:00
Vojta Jina d0f459c56f feat($sniffer): basic implementation of browser feature testing
This only extracts our 'hashchange' event and html5 history api detection from
$browser.

Closes #400
2011-09-08 20:37:28 +02:00
Vojta Jina cbedf55641 refactor($browser): extract MockWindow, use toHaveBeenCalledOnce 2011-09-08 20:36:33 +02:00
Vojta Jina 988ed451b5 feat($browser): jQuery style url method, onUrlChange event
This is just basic implementation of $browser.url, $browser.onUrlChange methods:

$browser.url() - returns current location.href

$browser.url('/new') - set url to /new
If supported, history.pushState is used, location.href property otherwise.

$browser.url('/new', true) - replace current url with /new
If supported, history.replaceState is used, location.replace otherwise.

$browser.onUrlChange is only fired when url is changed from the browser:
- user types into address bar
- user clicks on back/forward button
- user clicks on link

It's not fired when url is changed using $browser.url()

Breaks Removed $browser.setUrl(), $browser.getUrl(), use $browser.url()
Breaks Removed $browser.onHashChange(), use $browser.onUrlChange()
2011-09-08 20:36:33 +02:00
Vojta Jina fc2f188d4d style(filter): Couple of missing spaces, semi-colons, add empty lines 2011-09-08 17:59:52 +02:00
Vojta Jina 4b1913c5ec fix(filter.currency): Return empty string for non-numbers 2011-09-08 17:59:45 +02:00
Igor Minar 06534413d3 fix(ng:options): ng:change should be called after the new val is set
Closes #547
2011-09-07 23:37:37 -07:00
Igor Minar e54909f5ef fix(docs): use window.execScript instead of window.eval on IE
IE's window.eval doesn't execute in the global context, so we have to
use window.execScript instead which works like window.eval on normal
browsers. However execScript throws an exception when an empty string is
passed in, so I created a workaround with a workaround.
2011-09-06 14:57:37 -07:00
Vojta Jina 79f2512ba7 chore(config): Remove updateView from jstd config
This should have been part of 42062dab34
2011-09-06 17:36:53 +02:00
Vojta Jina b0eb831bce fix($browser.xhr): not convert 0 status to 200 2011-09-05 23:53:53 +02:00
Igor Minar 7f0b97e02c test(jsonp): fixing jsonp e2e tests
- buzz api keeps on throttling our requests which makes our build fail
  so I'm disabling the buzz demo e2e test
- the $xhr service jsonp test was modified to use jsonp on angularjs.org
  instead of buzz api for the same reason as mentioned above
2011-09-02 16:17:05 -07:00
Igor Minar fc7f1ef6a0 chore(version.yaml): preparing the 0.10.1 inexorable-juggernaut iteration 2011-09-02 15:41:41 -07:00
Igor Minar 8bae2a5ecb cutting the 0.10.0 chicken-hands release 2011-09-02 11:32:29 -07:00
Igor Minar 30e5f6274a docs(changelog): release notes for 0.10.0 chicken-hands 2011-09-02 10:53:41 -07:00
Igor Minar bc6e0cc954 docs(guide/tutorial/misc): sync with google docs 2011-09-02 10:44:19 -07:00
Igor Minar 8d11db0757 docs(ng:bind): fix example code 2011-09-01 16:37:08 -07:00
Igor Minar 2a8fe56997 fix(ng:class): make ng:class friendly towards other code adding/removing classes
ng:class as well as ng:class-odd and ng:class-even always reset the
class list to whatever it was before compilation, this makes it
impossible to create another directive which adds its own classes on the
element on which ng:class was applied.

the fix simply removes all classes that were added previously by
ng:class and add classes that the ng:class expression evaluates to.

we can now guarantee that we won't clobber stuff added before or after
compilation as long as all class names are unique.

in order to implement this I had to beef up jqLite#addClass and
jqLite#removeClass to be able to add/remove multiple classes without
creating duplicates.
2011-09-01 16:37:08 -07:00
Igor Minar 622c3ec974 fix(jqLite): addClass should ignore falsy values 2011-09-01 16:37:07 -07:00
Igor Minar db78aa1ce1 test(jqLite): add test for mass assignment to style 2011-09-01 16:37:07 -07:00
Igor Minar 986608fe76 fix(jqLite): special-case attr('class') because of IE9 bug 2011-09-01 16:37:06 -07:00
Igor Minar 31b8624121 feat(scope): add listener deregistration fn for $watch and $on
- both $watch and $on now return a function which when called
  deregisters the listener
- $removeListener was removed and replaced with the above
- added more tests for $watch and $on

Closes #542
2011-09-01 15:00:22 -07:00
Igor Minar a5607e3061 docs(API): various api doc fixes from Toni 2011-09-01 00:19:35 -07:00
Igor Minar ff2cb86d5d style(e2e tests): shorten jquery/jqlite describe 2011-08-31 23:03:58 -07:00
Igor Minar 825cbadf80 kill(merge): removing merge fn - dead buggy code with no specs 2011-08-31 22:32:27 -07:00
Igor Minar 93f96a16f6 fix(scope): fix edge case for $digest & $broadcast scope traversal
- fixed traversal originating on a scope with with a right sibling
- unified code for both $broadcast and $digest
2011-08-31 14:34:56 -07:00
Misko Hevery c763b009ac feat(gdocs.js): output usefull error messages when not logged in. 2011-08-31 14:34:56 -07:00
Misko Hevery e5da0c956b feat(jasmine-node): use the jasmine-node NPM to run our non-browser specs 2011-08-31 14:34:56 -07:00
Misko Hevery 3c80cf3df6 style(docs): improve the formatting of events in docs 2011-08-31 14:34:56 -07:00
Misko Hevery ad3cc16eef feat($route): add events before/after route change
BREAKING CHANGE
* removing `onChange`

FEATURE
* adding three events: $beforeRouteChange, $afterRouteChange, $routeReload
2011-08-31 14:31:23 -07:00
Misko Hevery 08d09ecbaa feat(docs): add support for events 2011-08-31 14:30:21 -07:00
Misko Hevery 456c7f62c5 bug($xhr.bulk): fix exceptions under some circumstances 2011-08-31 14:29:37 -07:00
Misko Hevery c9e7fb894b style(tests): correct indentation 2011-08-30 22:05:13 -07:00
Di Peng 4a9ccc0abc test(i18n): Update some i18n/e2e tests 2011-08-30 02:11:10 -07:00
Di Peng bceadd8e30 feat(i18n): locale specific files changed due to change in ClosureSlurper.js 2011-08-30 02:11:10 -07:00
Di Peng 545b31aa2e feat(closureSlurper): closureSlurper plural rules
- fetch plural rules from closure
- distribtue pluralization rules into each locale specific files
2011-08-30 02:11:09 -07:00
Di Peng e068addadb feat(widget): add ng:pluralize as an Angular widget 2011-08-30 02:11:09 -07:00
Di Peng 0da4902e9d feat(locale): add getPluralCat function 2011-08-30 02:11:08 -07:00
Igor Minar 3ba90003b4 fix(test): improve $cookie service test to work with Safari 5.1
the max size for safari cookies has changed sligtly so I had to adjust
the test to make cookie creation fail on this browser
2011-08-29 14:38:28 -07:00
Di Peng 5927b23ef3 fix(markup): Make special attrs such as ng:href work even without binding
- special attrs such as ng:href, ng:check did not work as intended when
their values do not contain bindings. And this commit is to fix that

Closes #534
2011-08-25 16:34:18 -07:00
Igor Minar 452607fc64 fix(events): fixing IE specific issues
IE doesn't have Array#indexOf and [].splice.call doesn't work there
either.
2011-08-24 18:36:38 -07:00
Di Peng 19401280ae feat(doc): generate both normal and debug version of index.html
- index.html has manifest file and angular.min.js
- index-jq.html has manifest file, angular.min.js and jquery.min.js
- index-debug.html has angular.js
- index-jq-debug.html has angular.js and jquery.min.js
2011-08-24 15:03:09 -07:00
Igor Minar 08a33e7bb3 feat(scope): support for events
- register listeners with $on
- remove listeners with $removeListener
- fire event that bubbles to root with $emit
- fire event that propagates to all child scopes with $broadcast
2011-08-24 15:01:50 -07:00
Igor Minar 30753cb131 feat(ng:cloak): add ng:cloak directive 2011-08-24 15:01:49 -07:00
Di Peng dbf8afcba0 fix(AngularPublic): expose missing angular public methods
- expose lowercase, uppercase and isDate to angular public api
- remove unnecessary extention of jqLite at an early stage
2011-08-24 08:00:33 -07:00
Toni Thompson 446f6b233f doc(API): various API documentation improvements 2011-08-24 11:06:55 +02:00
Igor Minar e3fad0feb3 fix(jqlite): correct the jqLite.removeClass method 2011-08-23 10:27:51 -07:00
Igor Minar 0f6e199d98 chore(ide): add pom.xml for IDEs that grok maven 2011-08-23 08:17:46 -07:00
Di Peng 15e6105779 fix(docs): remove more unecessary use of hide() and show() method
- tutorial section of docs fails to render properly as
doc:tutorial-instructions widget uses deprecated show and hide methods
of jQlite.
2011-08-21 09:40:53 -07:00
Igor Minar ee38918059 doc(changelog): add info about the memory leak in ng:options 2011-08-21 01:31:54 -07:00
Igor Minar 94e3b28d24 preparing the project for 0.10.0 chicken-hands iteration 2011-08-21 00:52:26 -07:00
Igor Minar 38e6d1e313 release notes of the 0.9.19 canine-psychokinesis 2011-08-21 00:50:58 -07:00
Igor Minar 607de75fa4 fix(docs): work around the lame ng:show directive 2011-08-21 00:46:58 -07:00
Igor Minar db04241beb fix(docs): change docs.css to avoid css clashes in buzz example 2011-08-21 00:46:46 -07:00
Di Peng 774db0aecb fix(sample): Fix for jsFiddle integration 2011-08-19 15:27:21 -07:00
Igor Minar dc0b0c77c7 feat($route): add reloadOnSearch route param to avoid reloads
In order to avoid unnecesary route reloads when just hashSearch part
of the url changes, it is now possible to disable this behavior by
setting reloadOnSearch param of the route declaration to false.

Closes #354
2011-08-19 03:55:47 -07:00
Karl Seamon 6114c8f504 fix($resource): properly call error callback when resource is called with two arguments 2011-08-18 15:07:04 -04:00
Vojta Jina b99b0a8072 feat(test): toHaveBeenCalledOnce jasmine matcher 2011-08-18 17:41:23 +02:00
dandoyon 431b748cac doc(sample): Add javascript sandbox integration (jsFiddle)
Change doc_widget.js to:

- render "edit in jsfiddle" button next to all examples
- make opt out certain examples by adding jsfiddle="false" attribute to
  doc:source element
2011-08-16 15:15:06 -07:00
Igor Minar de34ca0b64 fix(filters): fix lint warnings 2011-08-15 12:52:09 -07:00
Igor Minar 793ecb4817 refactor(jqLite): remove jqLite show/hide support
it turns out that even with our tricks, jqLite#show is not usable in
practice and definitely not on par with jQuery. so rather than
introducing half-baked apis which introduce issues, I'm removing them.

I also removed show/hide uses from docs, since they are not needed.

Breaks jqLite.hide/jqLite.show which are no longer available.
2011-08-15 12:51:41 -07:00
Igor Minar 1d45e65f4a chore(jasmine): disable 'Jasmine waiting for..' msg 2011-08-15 00:21:02 -07:00
Igor Minar 2bbef363e4 style(*): remove extra semicolons 2011-08-15 00:21:02 -07:00
Igor Minar 035ad72726 refactor(json): use angularString instead of angular.String 2011-08-15 00:21:02 -07:00
Igor Minar 9d808239b3 style(*): wrap all assignments in if statements
we commonly assign stuff in if statments like this:

if (variable = someFn()) {
  //do something with variable
}

This results in lint and IDE warnings (did you mean ==?).

It is better to be explicit about our intention and wrap the assignement
into parens:

if ((variable = someFn())) {
  //do something with variable
}

Doing so suppresses warnings + is easier to understand the intention.

I verified that the closure compiler strips the extra parens, so there
is no byte overhead for this safety practice.

We should use this style going forward...
2011-08-15 00:20:48 -07:00
Igor Minar ef01362e44 chore(.idea): remove all obsolete idea files 2011-08-15 00:15:07 -07:00
Igor Minar 6c30601ad8 feat(i18n): add i18n/locale rule set files 2011-08-14 23:44:21 -07:00
Igor Minar 37b5c5cfe9 break(date): remove support for 'long', 'longtime' date formats and 'z' flag
The support for the 'z' formatting flag was removed becase the timezone
info can't be retrieved from the browser apis (except for en-US locale
on some but not all browsers). For this reason we don't want to support
this flag at all.

Related to this, since the 'long' and 'longtime' datetime formats require
the 'z' flag in the formatting string, we are removing support for this
format as well.
2011-08-14 23:44:21 -07:00
Di Peng 966cbd4cf8 feat(i18n): collect and convert locale info from closure
- add i18n/closure directory with closure i18n files and
  update-closure.sh script to update them
- generate.sh script runs node.js scripts that extract localization
  rules from the closure library, transform them to a more suitable
format and dumps them into i18n/locale directory as angular's $locale
services
- update Rakefile to copy i18n files to build/ and pkg/ dirs
- copy i18n stuff during rake build
- e2e tests for several locales
2011-08-14 23:44:20 -07:00
Di Peng 8534b7c7c0 refactor(date,curreny,number): inject and use $locale in filters
- filter.number, filter.currency and filter.date are injected with
$locale service so that we can just swap the service to localize these
- date filter was beefed up in order to support literal strings found in
  localization rules
2011-08-14 23:44:20 -07:00
Di Peng 6802a76007 feat($locale): add default locale service for en-US 2011-08-14 23:44:20 -07:00
Di Peng 7ec8a89362 fix(directives): make ng:class-even/odd work with ng:class
Closes #508
2011-08-14 22:46:51 -07:00
Misko Hevery 34f174066f refactor(scope): non-recursive $digest method 2011-08-14 21:32:15 -07:00
Misko Hevery 530dc412c4 refactor(scope): use double-linked-list for children
Much faster $destroy operations for large ng:repeat sets.
2011-08-14 21:32:13 -07:00
Misko Hevery 3f99cdbdc3 feat(scope): $evalAsync support 2011-08-12 16:18:41 -07:00
Misko Hevery 13e7df68a6 perf(scope): re-enable statement cacheing 2011-08-12 15:48:12 -07:00
Misko Hevery 42062dab34 refactor(scope): remove $flush/$observe ng:eval/ng:eval-order 2011-08-12 15:47:47 -07:00
Misko Hevery 1c9fc1e1de fix(scope): rerun $digest from root, rather then per scope. 2011-08-12 15:47:44 -07:00
Misko Hevery 8bc7beacd8 fix(bootstrap): missing var failed strict mode boot 2011-08-12 10:19:28 -07:00
Vojta Jina 842741ee99 doc($browser): remove duplication of $browser to docs
This was causing to show up the "$browser" twice in the menu.
2011-08-10 11:51:24 +02:00
Vojta Jina 40ad543d27 doc($browser): hide $browser.notifyWhenNoOustandingRequest method
Closes #506
2011-08-10 11:50:15 +02:00
Igor Minar 06835a462a style($function): replace $function with 'function' 2011-08-06 01:54:06 -07:00
Di Peng 142cffcf64 refactor(widgets): remove input[button, submit, reset, image] and button windgets
These widgets are useless and only trigger extra $updateViews.

The only reason we had them was to support ng:change on these widgets,
but since there are no bindings present in these cases it doesn't make
sense to support ng:change here. It's likely just a leftover from
getangular.com

Breaking change: ng:change for input[button], input[submit], input[reset], input[image]
and button widgets is not supported any more
2011-08-06 01:54:05 -07:00
Di Peng 862d78c1d9 doc(xhr): add e2e test for JSONP error handling
- add e2e tests
- refactor the example by removing clear button and simplifying the code
2011-08-06 01:54:05 -07:00
Di Peng 6f8904e027 feat($browser): JSONP error handling
since we don't know if the error was due to a client error (4xx) or
server error (5xx), we leave the status code as undefined.
2011-08-06 01:54:05 -07:00
Igor Minar 4dc9e6416a doc(tutorial): updates needed for 0.9.18 rebase 2011-08-04 10:48:17 -07:00
DiPeng 4f6e947e49 fix(docs): fix qfs.read() encoding issue
- must use binary reading when using read function in q-fs module
otherwise some unicode character may be garbled.

Closes #497
2011-08-03 16:50:25 -07:00
Vojta Jina 15efbbdc1f fix($xhr.error): fix docs and add missed breaking change
$xhr.error's first argument (request) has no callback property anymore,
it's called success now...

This breaking change was introduced by b5594a773a
2011-08-02 19:01:36 +02:00
DiPeng 67a3315e1d refactor(angular): remove unnecessary parameter for slice function
- the end index for slice, if not specified, is default to the
end of the array it operates on.
2011-08-02 07:11:47 -07:00
Misko Hevery 8f0dcbab80 feat(scope): new and improved scope implementation
- Speed improvements (about 4x on flush phase)
- Memory improvements (uses no function closures)
- Break $eval into $apply, $dispatch, $flush
- Introduced $watch and $observe

Breaks angular.equals() use === instead of ==
Breaks angular.scope() does not take parent as first argument
Breaks scope.$watch() takes scope as first argument
Breaks scope.$set(), scope.$get are removed
Breaks scope.$config is removed
Breaks $route.onChange callback has not "this" bounded
2011-08-02 01:00:03 +02:00
dandoyon 1f4b417184 doc(typos): fix couple of typos in the docs
Minor documentation fixes. Should not be any code changes.
One test changed due to dependency on text in documentation.
2011-07-30 16:41:42 +02:00
Igor Minar 2d8d5aef29 prepare the 0.9.19 canine-psychokinesis iteration 2011-07-29 20:06:32 -07:00
Igor Minar eb758bc605 fix(Rakefile): index-jq.html needs to be rewritten like index.html 2011-07-29 19:35:27 -07:00
Igor Minar 761997e082 doc(release notes): small fixes for the 0.9.18 release 2011-07-29 19:34:22 -07:00
Igor Minar aacd5b672e cutting the 0.9.18 jiggling-armfat release 2011-07-29 16:30:24 -07:00
Igor Minar 8d64793717 doc(release notes): release notes for the 0.9.18 jiggling-armfat release 2011-07-29 15:27:15 -07:00
Igor Minar 908f59a5df doc(date filter): fix dashes in api docs 2011-07-29 15:00:00 -07:00
Igor Minar a45d383da2 doc(contribute): add npm & q dependencies to setup instructions 2011-07-29 13:59:36 -07:00
Igor Minar c1a681d6f4 doc(index.html): change the order of elements in the navbar
Users often don't see Tutorial and go straight to crappy Dev Guide,
changing the order should help find them right content in the right
order.
2011-07-29 13:44:55 -07:00
Igor Minar f4df421b44 doc(css): make all navbar links bold 2011-07-29 13:43:51 -07:00
Igor Minar bdef462ccc doc(started): fixing up the doc and adding link to the tutorial 2011-07-29 12:56:50 -07:00
Igor Minar a79231dea6 doc(guide): various fixes and improvements 2011-07-29 12:46:54 -07:00
Igor Minar 3e54a1b18a doc(tutorial): fixes and improvements from Toni and Ben 2011-07-29 12:40:27 -07:00
Igor Minar 4b90f65614 feat(tutorial): add an arrow to 'Workspace Reset Instructions' links
The arrow is a hint that user won't navigate to a new page, but instead
the instructions will be displayed inline.
2011-07-29 11:43:17 -07:00
Karl Seamon b5594a773a feat($xhr): add custom error callback to $xhr, $xhr.cache, $xhr.bulk, $resource
Closes #408
2011-07-27 15:21:31 -07:00
Vojta Jina f39420e7d7 style(): fix couple of missing semi-colons 2011-07-27 22:24:07 +02:00
Vojta Jina 72e46548b8 test(filter.date): fix e2e test to pass on different time zones 2011-07-27 22:18:51 +02:00
Di Peng 9dea9de449 feat(docs): add full offline support 2011-07-26 16:35:42 -07:00
Di Peng bee78a8492 feat(docs): add a changelog link to the footer 2011-07-26 14:21:13 -07:00
Di Peng f3e04fbd6a fix(ng:show/ng:hide): use jqLite.show/jqLite.hide
The previous implementation didn't handle situation when in css
something was hidden with a cascaded display:none rule and then we
wanted to show it.

Unfortunatelly our test doesn't test this scenario because it's too
complicated. :-/
2011-07-26 14:21:13 -07:00
Vojta Jina 00ea08e0ab doc(tutorial): fix navigation widget to work without jQuery
jqLite doesn't support class selectors, can find only by tag name...
2011-07-26 14:20:24 -07:00
Di Peng 31b59efa96 feat(number/currency filter): format numbers and currency using pattern
both numbers and currency need to be formatted using a generic pattern
which can be replaced for a different pattern when angular is working in
a non en-US locale

for now only en-US locale is supported, but that will change in the
future
2011-07-26 14:16:57 -07:00
Igor Minar 17251372b1 style(ng:options): fix style and some docs 2011-07-26 10:11:40 -07:00
Misko Hevery f768954f38 fix(ng:options): add support for option groups
Closes# 450
2011-07-26 10:11:06 -07:00
Misko Hevery 3237f8b995 fix(directive): ng:options to support ng:change
Closes #463
2011-07-26 09:41:44 -07:00
Misko Hevery 7802c90e13 fix(directive): ng:options to support iterating over objects
Closes #448
2011-07-26 09:41:43 -07:00
Misko Hevery c348f2cad6 fix(directive): ng:options incorrectly re-grew options on datasource change
Closes #464
2011-07-26 09:41:42 -07:00
Misko Hevery f3456dc282 fix(directive): ng:options now support binding to expression
Closes #449
2011-07-26 09:41:41 -07:00
Misko Hevery ee04141a5a style(warnings): prevent the browser from making bogus GET requests during tests 2011-07-26 09:40:29 -07:00
Misko Hevery 66fec10dc3 style(warnings): added missing semi colons 2011-07-26 09:40:29 -07:00
Misko Hevery ae75c35746 chore(jqlite): clean up dead code 2011-07-26 09:40:29 -07:00
Misko Hevery 0cf5535333 doc(ng:view): fix broken template links in docs; add scenario test. 2011-07-26 09:40:29 -07:00
Igor Minar fdd5d9471f chore(license): update license headers + add version num
- fixed copyright overnship
- updated copyright years
- added @license tag so that closure compiler preserves the header
- added version number into headers (finally!)
2011-07-22 15:49:10 -07:00
Di Peng 0782422d1f feat(angular.version): add angular.version
- placeholders are replaced with actual angular versions when doing
rake compile
2011-07-22 15:34:55 -07:00
Di Peng 8fa066190a refactor(gen-docs): use q, qq, q-fs (node modules) to write gen-docs
- re-write gendocs.js, reader.js and writer.js
- all calls are asynchronous
2011-07-20 17:33:18 -07:00
Di Peng e90b741c94 feat(gen-docs): enable caching the whole site
Generate a manifest file automatically by reading the directories.
2011-07-20 17:09:40 -07:00
Di Peng 3af1e7ca2e feat(filter.date): add support for default datetime formats in en
- add support for full,long, medium, short datetime formats in en

Breaks MMMMM. now we don't support MMMMM anymore as old implementation differs
from Unicode Locale Data format we are following.

- removed support for fullDateTime and fullTime as it means too much
trouble with full timeZone names
- added docs for the new features
2011-07-20 17:06:56 -07:00
Di Peng 0fbaa2f12a feat(TzDate): add mock "toString" method to TzDate.
- If the third param of TzDate constructor is defined, toStirng will
just return this third parameter. Otherwise, toString will still
be treated as unimplemented method
2011-07-20 16:50:44 -07:00
Igor Minar ad3b8d7bcf chore(docs/.htaccess): bundle .htaccess with docs 2011-07-19 16:58:40 -07:00
Igor Minar 3ea2416f80 Revert "fix(ng:class): preserve classes added post compilation"
This reverts commit 2428907259.

We decided to revert this because it is not bullet proof. The issue is
that we can't reliably have both angular and non-angular code in charge
of the DOM. We could work around some issues here and there, but we
can't do it reliably, so it's better not to support DOM manipulation
that happens outside of angular. There is a good chance that once we
integrate with MDVs our possition will change, but until then our
position is that only angular or angular widgets/directives can change
change DOM that was compiled.
2011-07-19 16:07:25 -07:00
Igor Minar 9636160332 doc(.defer.cancel): temporarily disable the doc 2011-07-19 14:04:50 -07:00
Igor Minar 2b2df4754d feat($browser.$defer.cancel): support canceling defered tasks 2011-07-18 14:14:19 -07:00
Igor Minar 120701b9d9 fix($browser.setUrl): make browser.setUrl more efficient
- browser should remember the last value retrieved via browser.getUrl
- browser should update window.location only if the new value is
  different from the current window.location value
2011-07-18 14:14:19 -07:00
Igor Minar fe5240732d feat(strict mode): adding strict mode flag to all js files
the flag must be in all src and test files so that we get the benefit of
running in the strict mode even in jstd

the following script was used to modify all files:

for file in `find src test -name "*.js"`; do
  echo -e "'use strict';\n" > temp.txt
  cat $file >> temp.txt
  mv temp.txt $file
done
2011-07-18 12:12:55 -07:00
Igor Minar b98c23274b feat(strict mode): turn on ECMAScript 5 strict mode
- add 'use strict'; statement to the prefix file
- configure closure compiler to use the ES5 strict mode
- strip all file-specific strict mode flags after concatination

Closes #223
2011-07-18 12:12:55 -07:00
Igor Minar 4c6d26a38f fix(strict mode): fix all issues discovered by strict mode and unit/e2e tests 2011-07-18 12:12:54 -07:00
Igor Minar c43ce91b25 chore(closure-compiler): upgrading to v20110615 2011-07-18 12:12:54 -07:00
Igor Minar b7cf7f2a79 doc(angular.annotate): properly disable doc snippet to avoid compiler warnings 2011-07-18 12:12:54 -07:00
Igor Minar ef7cf60ebd doc(misc): fixing typos in docs 2011-07-18 00:04:38 -07:00
DiPeng 7974e7eb5f refactor($browser): hide startPoll and poll methods
Breaks $browser.poll() method is moved inline to $browser.startpoll()
Breaks $browser.startpoll() method is made private
Refactor tests to reflect updated browser API

Closes #387
2011-07-18 00:04:14 -07:00
Di Peng f9b4c9da64 refactor(docs): run e2e tests with and without jquery
- e2e tests will run index.html (without jquery) and with
index-jq.html(with jquery).
- many small changes to make e2e tests work withough JQuery as we
discover problems that were previously hidden by using real JQuery.
2011-07-17 22:19:08 -07:00
Di Peng 83ac1193f2 style(jqLiteSpec): add space 2011-07-17 22:19:08 -07:00
Di Peng 7a3fdda965 feat(jqlite): added show(),hide() and eq() methods to jqlite
- add those three methods to jqlite
2011-07-17 22:19:08 -07:00
Igor Minar b4f18fc295 style(injector): remove extra semicolon 2011-07-18 04:47:39 +00:00
Igor Minar da464683aa doc(ng:include): improve the doc example to avoid confusion 2011-07-16 22:01:19 -07:00
Igor Minar a0b35161a6 fix(doc): fix all broken links 2011-07-16 01:15:37 -07:00
Igor Minar a8f4d87be5 doc(css): add '#content-list .level-4' css 2011-07-16 01:12:29 -07:00
Igor Minar 57ea8156a1 doc(ngdoc): add 'this' and 'returns' section for methods 2011-07-16 01:12:29 -07:00
Igor Minar 6289d18e61 doc(ngdoc): fix usage format for functions bolted onto services 2011-07-16 01:12:29 -07:00
Igor Minar 9e37ebe635 test(ngdoc): add test for @ngdoc function 2011-07-16 01:12:29 -07:00
Igor Minar 345c01c81b test(ngdoc): fix a typo in the @deprecated spec 2011-07-16 01:12:29 -07:00
Igor Minar 975aef2ad2 test(ngdoc): fix failing tests 2011-07-16 01:12:28 -07:00
Di Peng c863514660 doc(angular.mock.service.$browser): add xhr docs 2011-07-16 01:12:28 -07:00
Vojta Jina 86a6cc7152 chore(configs): Add missing files to jstd config
Add jstd-scenario-adapter files into jstd configs (jquery, coverage).

Remove angular.prefix, sufifix from exclude, as they don't have to be there.
They are not included, because of *.js mask.
2011-07-14 10:59:30 +02:00
Vojta Jina 8f3276bbcd chore(scripts): add test-jquery.sh for running unit tests with jQuery 2011-07-14 10:59:25 +02:00
Di Peng 2428907259 fix(ng:class): preserve classes added post compilation
- make sure ng:class preserve classes added after compilation

Closes #355
2011-07-13 16:42:38 -07:00
Igor Minar 8a8a2cf462 refactor($browser.xhr): use $browser.addJs for JSONP
There is no reason why we shouldn't reuse $browser.addJs for JSONP
requests.
2011-07-13 16:21:08 -07:00
Igor Minar 47efe44a1d fix($browser.addJs): make addJs jQuery compatible
Change addJs implementation to avoid use of jQuery because of issues
that affect angular-ie-compat.js. See inlined comment for more info.
2011-07-13 16:21:08 -07:00
Igor Minar c52e749a6e fix($browser.xhr): properly delete jsonp callbacks 2011-07-13 16:21:08 -07:00
Igor Minar 4ab3596295 fix(ie-compat): escape \ in regexp 2011-07-13 16:21:07 -07:00
Igor Minar 106674ac1e style(ie-compat): improved generated ie compat code 2011-07-13 16:21:07 -07:00
Vojta Jina 330d1a870d fix(bootstrap): Fix bootstrap on IE<8
No reason for including ie-compat in bootstrap, it's included during angularInit.

Fix including ie-compat even for production.
2011-07-13 16:21:07 -07:00
Vojta Jina 7e2e7b07b6 doc($route): fix $route example and couple of typos
Rewrite $route example a bit, as it required $location and $route services
to be eager published in the root scope.

Fix small typos in formatter and ng:options docs.
2011-07-13 11:49:16 +02:00
Vojta Jina ce80576e0b fix:jqLite: Set event.target on IE<8
IE<8's Event has not target property - it has srcElement property.
Fix that to be consistent as jQuery.
2011-07-12 23:04:46 -07:00
Vojta Jina 10da625ed9 fix:jqLite: Normalize non-existing attributes to undefined as jQuery
jqLite was returning null, but jQuery returns undefined
2011-07-12 23:04:46 -07:00
Vojta Jina 9ee9ca13da fix:jqLite: Fix binding to more events separated by space
The var eventHandler was defined outside forEach loop, so registering more
events caused calling listeners registered by the last one.

Regression:
elm.bind('click keyup', callback1);
elm.bind('click', callback2);
elm.bind('keyup', callback3);

Firing click event would have executed callback1, callback3 !
2011-07-12 23:04:46 -07:00
Igor Minar bb39d34279 test(ng:repeat): add tests for $position for small arrays/objects 2011-07-12 22:49:12 -07:00
Igor Minar e09a78438f doc:widget: improve angular.widget docs 2011-07-11 12:19:42 -07:00
Vojta Jina 1e890863e5 docs:compile: Just fixing some typos in the docs 2011-07-10 19:29:46 +02:00
Igor Minar 76a500179d docs:template: rename <angular/> to AngularJS 2011-07-08 08:24:09 -07:00
Igor Minar 7b32c71386 docs:css: remove bullet points from tutorial sidebar 2011-07-08 08:24:09 -07:00
Igor Minar 28e84ca167 docs:css: fix indentation for pre element 2011-07-08 08:24:09 -07:00
Igor Minar 41250e9cf9 prepare the jiggling-armfat iteration 2011-07-08 08:23:30 -07:00
Mårten Dolk 77ba539f63 fix:injector: make injector compatible with Rhino (HtmlUnit) 2011-07-06 16:06:54 -07:00
Igor Minar 952225f020 doc:dependencies: add /api/ prefix to dependency links 2011-07-02 10:37:04 -07:00
Igor Minar 35f9f527d3 doc:changelog: small changelog fixes 2011-07-02 08:44:50 -07:00
Igor Minar 30bd04feaa fix:exceptionHandler mock: should not specify dependencies
also added a test for this mock service
2011-07-01 18:17:54 -07:00
Igor Minar 25a77c58c1 fix:jstd.conf: explicitly specify script load order
Originally we relied on a lot of globbing, which resulted in
angular-mocks being loaded before normal services, so we never overwrote
services like $exceptionHandler with mocks. Explict definition
guarantees that we don't fall into the loading order trap, but requires
us to remember to update the jsTestDriver.conf file every time we
add/rename/remove a js file.
2011-07-01 18:17:42 -07:00
Igor Minar 75721223b5 fix:$browser mock: defer.flush() should flush all fns 2011-07-01 17:03:50 -07:00
DiPeng f606ffed4b doc:markup: wrong spelling for Vojta, all DI's fault. 2011-06-30 20:24:17 -07:00
Igor Minar b49035a8c5 preparing the 0.9.18 jiggling-armfat iteration 2011-06-30 14:29:28 -07:00
Igor Minar 86ff9dee23 docs:include: improve docs 2011-06-30 11:33:36 -07:00
Igor Minar 6dc22fe575 feat:build: better build/pkg/ dir structure
rake package now produced directory structure that can be uploaded to
the ftp server as is without manual changes
2011-06-30 10:58:14 -07:00
Igor Minar 68ab0f9b02 docs:changelog: add release date for 0.9.17 2011-06-30 10:54:24 -07:00
Igor Minar d7e0915e62 cutting the 0.9.17 vegetable-reanimation relase 2011-06-30 09:10:59 -07:00
Igor Minar b3d5d2caa9 docs:changelog: updating release notes 2011-06-30 09:09:05 -07:00
Igor Minar c02ef92630 fix:docs: fix $orderBy example and e2e test 2011-06-30 01:07:08 -07:00
Igor Minar 1e8448b9e5 fix:docs: properly distinguish between being offline and 404 2011-06-30 00:49:44 -07:00
Igor Minar c5f3a413bc feat:$xhr: provide access to $xhr header defaults
$xhr header defaults are now exposed as $xhr.defaults.headers.common and
$xhr.default.headers.<httpmethod>. This allows applications to configure
their defaults as needed.

This commit doesn't allow headers to be set per request, only per
application. Per request change would require api change, which I tried
to avoid *for now*.
2011-06-30 00:34:50 -07:00
Igor Minar d3fb5b411e fix:tests: replace angular.annotate with annotate
forgot to fix tests in 6aee2938a7
2011-06-27 22:41:49 -07:00
Di Peng 75bc59ee4b test:ng#class: added a better unit test for ng:class 2011-06-27 22:31:29 -07:00
Igor Minar 6aee2938a7 fix:testabilityPatch: remove annotate since it's not public 2011-06-27 16:46:29 -07:00
Igor Minar 2043fd43fa docs:release notes: prepare for notes for 0.9.17 release 2011-06-27 16:46:01 -07:00
Igor Minar ce4f27aa7b fix:docs: css lint fixes 2011-06-27 15:05:38 -07:00
Vojta Jina 8e915f5545 fix:$browser: Use document.createElement to create JSONP script tag
Creating <script> tags would require a lot of extra work if we want all browsers
to load and execute these scripts. We decided to not implement that in jqLite.

See #369 for more information.

Closes #369
2011-06-27 19:04:40 +02:00
Di Peng 8e6e09a4bc fix:docs: Fix sitemap generator to use doc.id instead of doc.name
doc.id should be used instead of doc.name, otherwise links are wrongly
generated
2011-06-25 08:00:43 -07:00
Igor Minar f3323ec18e fix🔁 fix ending comment tag 2011-06-23 15:13:15 -07:00
Di Peng b5a510a343 feat:filter.date: add day/month string format support
Support new date format, specifically day of week/Month of year in string
e.g. {{ someDate | data:"EEE, MMM d, yyyy" }} -> "Wed, Jul 10, 2011"

Closes #396
2011-06-23 12:06:46 -07:00
Misko Hevery 9ec45ad5c4 fix:ng:repeater - fix $position when collection size changes 2011-06-23 08:12:01 -07:00
Misko Hevery 8e880fcb77 style:ApiSpecs - clean up test names to match jasmine conventions 2011-06-23 08:12:01 -07:00
Misko Hevery b74163dc1d fix:$orderBy - return unsorted array if no predicate
Closes #399
2011-06-23 08:12:01 -07:00
Di Peng bad62d87a1 fix:scope - reintroduce support for eager services
8cad231 broke $eager services

Problem is that the injector.eager function is not invoked when a new scope
is created. Added a test to make sure service is eagerly instantiated.

Closes #403
2011-06-23 08:06:24 -07:00
Di Peng 65b6e48742 test:angular.service - add tests for $inject 2011-06-23 07:56:58 -07:00
Vojta Jina fee3717892 Update fixed docs content (guide)
Couple of typos fixed:

* indentation
* batchLogbatchLog -> batchLog
* start periodic checking
* missing brace
2011-06-21 16:23:48 +02:00
Vojta Jina d0edc11704 Fix failing unit tests in IE7 (Binder, select widget)
The fix does not change any production code, we only need to ignore couple of attributes that IE7 should not display:
* value attribute for LI
* selected attribut for SELECT

Simplified condition in compiler test, this should have been part of f9f0905f4a
2011-06-17 22:48:22 +02:00
Vojta Jina f9f0905f4a Fix compiler test for IE9
Older IEs serialize html uppercased, but IE9 does not...
Would be better to expect case insensitive, unfortuntaly jasmine does not allow
to user regexps for throw expectations.

Closes #392
2011-06-17 19:48:49 +02:00
Vojta Jina 92ebf11b2a Remove obsolete scenario folder
* moved scenario e2e tests in test/scenario/e2e folder
* remove $location test
2011-06-17 19:13:49 +02:00
Di Peng e6ee994764 Added ng:disabled, ng:checked, ng:multiple, ng:readonly, ng:selected to markup.js.
Also added coresponding descriptions  live examples and tests for each directive to be displayed on the website.

Closes #351
2011-06-16 21:17:46 -07:00
Vojta Jina c8ee00cb2b Update docs from googledocs
* fixed typo in tutorial step-10
* revert cookbook/buzz example to use googlebuzz user
2011-06-16 16:27:46 +02:00
Vojta Jina 7460a7ef61 Fix test for scenario.Application - should remove old iframe
This behavior was changed by e83465c362
So this commit should have been part of e83465c362

Also removed hiding and navigating to about:blank as it makes no sense now...
2011-06-15 22:58:57 -07:00
Igor Minar 3c87611188 docs - various doc fixes 2011-06-15 22:32:24 -07:00
Igor Minar b842642b57 docs - stripping extra new lines 2011-06-15 22:31:40 -07:00
Di Peng d428c9910e Replaced double line break with single when text is fetched from Google Docs
Closes #384
2011-06-15 09:20:22 -07:00
Di Peng f8529672f6 Updated docs/cookbook/buzz from gdocs
With couple of fixes:

* indentation + code formatting
* use ng:href, ng:src
* change UserId to misko.hevery so it will work now
2011-06-15 01:33:56 +02:00
Misko Hevery e83465c362 Fix scenario runner on IE7, IE8
* add ng:disabled, ng:checked, ng:multiple, ng:readonly, ng:selected
* fetch fixed cookbook/advancedform (use ng:disabled)
* fire keydown instead of change on input
* remove frame when test finishes
2011-06-15 01:14:22 +02:00
Vojta Jina f370be85cb Fix small typo in docs widget (tutorial instructions) 2011-06-10 18:30:55 +02:00
Vojta Jina 5dbf0cc8a2 Fix changelog url (angularjs.com -> angularjs.org) 2011-06-08 15:58:00 -07:00
Di Peng e4a00626d8 Should have replaced all instances of element('input[name=something]').val() with input('name').val()
Closes #376
2011-06-08 15:54:57 -07:00
Misko Hevery 91a34a7027 remove ng:format=index 2011-06-08 15:21:33 -07:00
Misko Hevery af285dd370 Added ng:options directive
Closes #301
2011-06-08 15:21:33 -07:00
Misko Hevery 89e001b18a Added prepend() to jqLite 2011-06-08 15:21:33 -07:00
Misko Hevery 4f2f3c9cbf Added support for deferring callbacks in time 2011-06-08 15:21:33 -07:00
Misko Hevery c1abc03cf3 Fixed indentation error 2011-06-08 15:21:33 -07:00
Misko Hevery 04a62e83bc Throw error when compiling multiple roots
Closes #338
2011-06-08 15:21:33 -07:00
Misko Hevery f9f95879f0 Added support for properties in documentation 2011-06-08 15:21:33 -07:00
Misko Hevery 8cad231bd2 Refactor injector to have invoke method for speed reasons 2011-06-08 15:21:31 -07:00
Misko Hevery 0e17ade959 Cleanup parser code to expose smaller API 2011-06-08 15:01:32 -07:00
Misko Hevery bb67ee8d28 Added HashMap 2011-06-08 15:01:32 -07:00
Misko Hevery 2a12f7dcaa Added nextUid() function for unified way of generating IDs in angular 2011-06-08 15:01:32 -07:00
Misko Hevery 20ce797906 performance improvement of single statement in parser 2011-06-08 13:49:11 -07:00
Misko Hevery cc9f1fdf38 Proper handling of special attributes in jqlite 2011-06-08 13:49:11 -07:00
Misko Hevery f243c6aeda removed jqLite warning 2011-06-08 13:49:11 -07:00
Misko Hevery 26e651996a fix JSON to match native browser behavior 2011-06-08 13:49:11 -07:00
Misko Hevery f57536ddb6 cleanup old closure directives 2011-06-08 13:49:11 -07:00
Misko Hevery 73e3f4c10c better error reporting for exceptions 2011-06-08 13:49:11 -07:00
Misko Hevery ec6d106d4a code cleanup: missing ; and indentation 2011-06-08 13:49:11 -07:00
Misko Hevery fab4ada3c8 Created a performance test harness and reporter 2011-06-08 13:49:10 -07:00
Misko Hevery d6eba8f39f Number filter would return incorrect value when fractional part had leading zeros. 2011-06-08 13:49:09 -07:00
Misko Hevery 4295b3dded Allow disabling of shell scripts without changing eclipse configuration 2011-06-08 13:46:39 -07:00
Misko Hevery a23d15ad3a Remove stray console.log statemente 2011-06-08 11:52:12 -07:00
Misko Hevery 66f3317bef preparing the 0.9.17 vegetable-reanimation iteration 2011-06-08 11:24:55 -07:00
Igor Minar a4dd9ca769 fix comment stripping 2011-06-07 16:11:01 -07:00
Vojta Jina d6e4636618 Couple of missing semi-colons 2011-06-07 16:11:01 -07:00
Vojta Jina e0ee3a0726 Update latest docs content from gdocs 2011-06-07 16:11:00 -07:00
Vojta Jina e670a812fa Remove removing old comments from gdocs
There were two places where we were removing old comments from google docs:

* gdocs.js fetching script
* docs/src/reader.js
2011-06-07 14:56:56 -07:00
Vojta Jina 517ada2662 Fix couple of failing e2e tests
The reason was recent change in docs url
2011-06-07 14:56:56 -07:00
Igor Minar 88ae927857 release notes for angular 0.9.16 weather-control 2011-06-07 14:56:01 -07:00
Igor Minar bb7228e2d9 fix ngdocSpec tests 2011-06-07 14:56:01 -07:00
Igor Minar 25b3438fd7 add appcache for docs site - caches only css/js/img resources 2011-06-07 14:56:01 -07:00
Igor Minar f21b9214e6 remove $script loader because incompatibilities with e2e runner 2011-06-07 10:39:57 -07:00
Igor Minar 80ea329d5f fix css for api reference 2011-06-07 07:44:59 -07:00
Igor Minar 6e0ff5fa96 fixing the dev guide ordering 2011-06-07 07:44:49 -07:00
Vojta Jina 4cdce2d30b Docs: Error 404 page with simple suggestion for new links 2011-06-06 23:10:30 -07:00
Igor Minar 48e69ed4d1 moving the angular.mock docs down in the api list 2011-06-06 23:10:30 -07:00
Igor Minar c35b0a7907 yet another docs batch 2011-06-06 23:10:30 -07:00
Igor Minar 805bb5bb6e fixing broken docs links 2011-06-06 23:10:30 -07:00
Kenneth R. Culp 4224e8e371 images for guide 2011-06-06 23:10:29 -07:00
Kenneth R. Culp 6319ba2ed0 remove test img file 2011-06-06 23:10:29 -07:00
Igor Minar dd44e00ddd docs css fix for content-list indentation 2011-06-06 23:10:29 -07:00
Igor Minar 6e4a501127 another batch of doc fixes from ken 2011-06-06 23:10:29 -07:00
Igor Minar c7dbe4d98b di diagram change 2011-06-06 23:10:29 -07:00
Igor Minar 3069566073 api doc fixes from ken 2011-06-06 23:10:28 -07:00
Kenneth R. Culp bd9a7b9fd7 adding all omnigraffle files for tutorial and guide images 2011-06-06 23:10:28 -07:00
Igor Minar 759e6ea8ed docs css fixes 2011-06-06 23:10:28 -07:00
Igor Minar c4989d8979 add new version of api/angular doc 2011-06-06 23:10:28 -07:00
Igor Minar af710c3ac1 fix wrapping api links into code element 2011-06-06 23:10:27 -07:00
Igor Minar e89ef35d05 make *.angularjs.org analytics work on subdomains 2011-06-06 23:10:27 -07:00
Igor Minar 2ba3c3ee57 fix getting started docs 2011-06-06 23:10:27 -07:00
Igor Minar c6dbdde6dc fix hashpath prefix for docs/sitemap/etc 2011-06-06 23:10:27 -07:00
Igor Minar f8417b48be docs app css/js/html rewrite 2011-06-06 22:52:02 -07:00
Igor Minar 7f1e2e4846 new batch of docs 2011-06-06 22:52:02 -07:00
Igor Minar 5533e48dea work in progress 2011-06-06 22:52:02 -07:00
Vojta Jina 16d0354f93 Load GA script using $script loader 2011-06-06 22:52:02 -07:00
Vojta Jina 350ee31107 Google Analytics - basic page tracking for docs 2011-06-06 22:52:02 -07:00
Vojta Jina 2da07127e4 Add doc:tutorial-instructions widget 2011-06-06 22:52:01 -07:00
Vojta Jina d05e839920 Use node's vm module instead of deprecated process.compile
So that I don't have to watch the warning all the time :-D
2011-06-06 22:52:01 -07:00
Igor Minar 22dee3e278 gdocs.js - add docos style comment stripping 2011-06-06 22:52:01 -07:00
Igor Minar bc2ca384b1 move docs/content/intro to docs/content/misc 2011-06-06 22:52:01 -07:00
Vojta Jina 2380943106 Allow "section/" links pointing to "section/index" 2011-06-06 22:52:01 -07:00
Vojta Jina 297c9b5b89 Fix wrong links in source code 2011-06-06 22:52:01 -07:00
Vojta Jina 43b2cd45f0 Allow relative links in docs
So you can use links without section when they link within the section.
2011-06-06 22:52:01 -07:00
Vojta Jina e389911a35 Change warning to log place first and then link 2011-06-06 22:52:00 -07:00
Vojta Jina fd357b4cd2 Remove trailing ws 2011-06-06 22:52:00 -07:00
Igor Minar 924ffafc51 fixing broken links 2011-06-06 22:52:00 -07:00
Vojta Jina 3616716615 Indent the API reference list 2011-06-06 22:52:00 -07:00
Vojta Jina 76df0db598 Fixed docs search input with
And couple of missing semi-colons...
2011-06-06 22:52:00 -07:00
Vojta Jina e21a868524 Fix links in docs 2011-06-06 22:52:00 -07:00
Vojta Jina 7fe46e8d7e Bit of refactoring 2011-06-06 22:51:59 -07:00
Vojta Jina 864da8b553 Couple of todos 2011-06-06 22:51:59 -07:00
Vojta Jina d62b8407cf Fixed couple of failing tests in docs
These tests were failing because of rewriting urls into new 'section' format,
i.e. angular.scope -> api.angular.scope
2011-06-06 22:51:59 -07:00
Vojta Jina 8cb84eac68 Log warning for every non existing link instead of throwing exception
Guess we don't want to stop doc generating process because of non-existing link, so just log warning and continue...
2011-06-06 22:51:59 -07:00
Vojta Jina 2e0e732cad Check whether links do exist and throw exception 2011-06-06 22:51:59 -07:00
Vojta Jina 22f9354c21 Fix sitemap include (to work on case sensitive linux) 2011-06-06 22:51:59 -07:00
Igor Minar 0c75a96917 new version of the xhr service 2011-06-06 22:51:59 -07:00
Igor Minar 14407921c7 reorder docs main menu items 2011-06-06 22:51:58 -07:00
Igor Minar 8920381b44 fix docs css 2011-06-06 22:51:58 -07:00
Igor Minar 3751f172b3 add new batch of tutorial docs and images 2011-06-06 22:51:58 -07:00
Igor Minar 3776e08db0 new docs skin - WIP 2011-06-06 22:51:58 -07:00
Igor Minar c1debfb81d fix docs landing page redirection 2011-06-06 22:51:58 -07:00
Igor Minar 0fb37b08e7 add resource merging 2011-06-06 22:51:58 -07:00
Igor Minar 8fa598fa00 remove gdocs.js workaround for extra space issue in gdocs api 2011-06-06 22:28:40 -07:00
Igor Minar 91f9efed49 gdocs.js should store files under docs/content/[collection]/ 2011-06-06 22:28:39 -07:00
Igor Minar 2094bc8f61 make docs/writer.js copyDir recursive 2011-06-06 22:28:39 -07:00
Igor Minar 9701f0735b add the tutorial collection to gdocs.js 2011-06-06 22:28:39 -07:00
Igor Minar a1f3725c0f ignore non .ngdoc files 2011-06-06 22:28:39 -07:00
Kenneth R. Culp 4ac234833a Don't forget the_end... 2011-06-06 22:28:39 -07:00
Kenneth R. Culp 9d9117384f Latest greatest tutorial udpates. 2011-06-06 22:28:38 -07:00
Igor Minar 525e444a0f temporary hack to strip all the extra chars from google docs 2011-06-06 22:28:38 -07:00
Igor Minar fd112877f8 fix link to the tutorial page 2011-06-06 22:28:38 -07:00
Igor Minar 6181ca600d new batch of tutorial docs 2011-06-06 22:28:38 -07:00
Misko Hevery 11e9572b95 Move documentation under individual headings 2011-06-06 22:28:38 -07:00
Misko Hevery b6bc6c2ddf fix syntax highlighting on the javascript 2011-06-06 22:28:37 -07:00
Misko Hevery ea6b87c24b renamed tutorial so that it would sort properly 2011-06-06 22:28:37 -07:00
Kenneth R. Culp e205bd7137 Update tutorial docs. 2011-06-06 22:28:37 -07:00
Igor Minar bd7e68f12f process only tutorial files 2011-06-06 22:28:37 -07:00
Kenneth R. Culp 0a604bdb90 Tutorial files for your perusal. 2011-06-06 22:28:37 -07:00
Igor Minar 4738d49e1c new skin WIP 2011-06-06 22:28:36 -07:00
Di Peng 9fdb09ebf8 added input#val method
Closes #237
2011-06-06 12:49:46 -07:00
Di Peng 1eebb771e3 renamed $pause to $sleep AND $wait to $pause
Closes #207
2011-06-05 12:00:45 -07:00
Di Peng 9250fce19c fixed opera date.toISOString issue
Closes #365
2011-06-03 09:44:21 -07:00
Vojta Jina 9a69677551 Fix CSS tests on Opera
Opera translates name colors to numbers (red -> #ff0000)
Other browsers like FF or Chrome translate number to rgb (#ff0000 -> rgb(255, 0, 0)
So avoiding colors in tests is probably the easiest solution...
2011-06-02 12:51:12 -07:00
Vojta Jina b6db58c647 Fix formatError for FF4 and Opera
Other browsers prepend "Error: <Exception name>" to stack, but FF4 and Opera do not.
So when formatting error we prepend it by hand, when not present...
2011-06-02 12:51:12 -07:00
Vojta Jina 4b0f2dfe0c Fix IE bug - ng:href
ng:href was producing unclickable links, as the event propagation was stopped by 'a' widget

All links in regression/issue-352.html were tested in:

* Chrome 11
* Opera 11
* Firefox 4
* IE7, IE8

Closes #352
2011-06-02 11:15:41 -07:00
Vojta Jina dad2603752 Refactor $browser's lazy start polling
+ unit tests
2011-06-02 10:50:43 -07:00
Vojta Jina 50076b571d Fix hashchange event on IE8 compatibility mode
Stupid IE8 in compatibility mode or in IE7 mode returns true for `('onhashchange' in window)`, but does not support hashchange event.

Closes #353
2011-06-02 10:50:39 -07:00
Vojta Jina aa64d37a23 Fix unit test in IE7 2011-06-02 08:55:10 -07:00
Vojta Jina 2e5199997c Rename deprecated wasCalled() -> toHaveBeenCalled() in all specs
As well as wasNotCalled(), wasCalledWith(), wasNotCalledWith()
2011-05-31 10:32:54 +02:00
Vojta Jina b2f5299e0e Normalize IE XHR bug (status code 1223 to 204)
See http://bugs.jquery.com/ticket/1450
2011-05-31 10:23:30 +02:00
Vojta Jina 805e083c24 Remove trailing white spaces from all source files
find . -name "*.js" -print | xargs sed -Ei s/[[:space:]]*$//
2011-05-19 09:43:56 -07:00
Vojta Jina 1abdc097b2 JSTD adapter for running e2e tests
Couple of changes into angular.scenario runner:
 - add autotest config (runs tests when document ready)
 - update ObjectModel (forwards events)
 - use only one ObjectModel instance for all outputters
 - expose error msg and line number in ObjectModel.Spec and ObjectModel.Step
 - fix generating spec.ids
 - fix 'html' output so that it does not mutate ObjectModel

Couple of changes into docs / generator:
 - rename copy -> copyTpl
 - move docs/static into docs/examples (to avoid conflict with jstd proxy)

Running all docs e2e tests:
========================================================
1/ compile angular-scenario, jstd-scenario-adapter
>> rake compile

2/ build docs
>> rake docs

3/ start jstd server
>> ./server-scenario.sh

4/ capture some browser

5/ run node server to serve static content
>> node ../lib/nodeserver/server.js

6/ run tests
>> ./test-scenario.sh
2011-05-19 09:43:56 -07:00
Vojta Jina 9f56af9c15 XHR should add Content-type header only for POST
Sending Content-type header causes JSTD (Jetty) proxy to change GET methods into POST.
2011-05-19 09:43:56 -07:00
Vojta Jina c5f0342ad8 Don't check url (by HEAD request) before navigateTo
Removed angular.scenario.Application.checkUrlStatus_ method and these tests:
* should call error handler if status check fails
* should perform a HEAD request to verify file existence
* should call error handler if status code is less than 200
* should call error handler if status code is greater than 299
* should call error handler if status code is greater than 299
2011-05-19 09:43:56 -07:00
Igor Minar b85e95709d fix widget example code 2011-05-13 07:15:59 -07:00
Igor Minar cc5dfaf0ab fix broken link $xhr docs 2011-05-02 21:20:36 -07:00
Igor Minar 9272a1a472 fix url validator example 2011-04-26 22:51:13 -07:00
Vojta Jina f85c82acd6 Fix some typos, missing semi-colons, etc...
This is a combination of 4 commits:
* Fix some small typos, missing semi-colons, etc.
* Fix comment for angular.scenario.SpecRunner.run method
* Fixed some missing semi-colons in cookbook
* Fixed missing semi-colon in nodeserver/server.js
2011-04-25 08:17:17 -07:00
Igor Minar 35bb19856c fix typo in scenario jsdocs 2011-04-22 23:10:07 -07:00
Igor Minar 97bdf979a1 fix Cookbook link in getting started doc 2011-04-20 15:14:45 -07:00
Craig Tataryn 64938a2e81 Added a bit more documentation to ng:autobind to explain some of the semantics 2011-04-16 14:36:47 -07:00
Anthony Lieuallen e7c22e8153 spelling fix 2011-04-15 16:01:47 -04:00
Misko Hevery b2dc2ce0b5 Have iit have higher priority then ddesrcibe 2011-04-12 14:02:21 -07:00
Igor Minar 498ad0a3be preparing the 0.9.16 weather-control iteration 2011-04-12 13:58:19 -07:00
Igor Minar cfc18efd28 cutting the 0.9.15 lethal-stutter release 2011-04-11 14:23:26 -07:00
Igor Minar 97573c3930 release notes for 0.9.15 lethal-stutter release 2011-04-11 14:23:26 -07:00
Igor Minar 8bb9f12961 fix indentation in angular.filter.html examples 2011-04-11 14:23:26 -07:00
Igor Minar ce0fbc6a77 fix e2e runner's navigateTo when url contains # fragment 2011-04-11 10:20:42 -07:00
Igor Minar 3d388498e5 add test for ng:view sync cache regression
test for 9bd2c396
2011-04-11 08:04:16 -07:00
Kenneth R. Culp 3d787ab6f4 doc fix - ng:autobind, ng:controller and more 2011-04-11 07:20:30 -07:00
Igor Minar 81063a748c fix typo in angular.widget docs 2011-04-10 14:16:08 -07:00
Igor Minar 9462b556a3 fix build for IE9
all unit tests now pass under IE9
2011-04-09 00:16:44 -07:00
Igor Minar 8e6ecd98ae fix e2e runner tests 2011-04-08 10:16:56 -07:00
Igor Minar 1d7adac7a5 fix $location service docs and examples 2011-04-08 10:03:06 -07:00
Igor Minar 72ad726efa fix e2e runner's browser.location methods
when we stopped exposing $location service on the root scope
the scenario runner was not modified to access the $location
service via $service

The following apis were affected:

- browser().location().hashSearch()
- browser().location().hashPath()
- browser().location().search()
2011-04-08 09:51:08 -07:00
Igor Minar 0d2d7025e6 use special nodeName_ impl only for IE<9
apparently IE9 is one step closer to becoming a real browser by
treating xmlns-like ("foo:") prefixes in node names as part of the
node name.

fixes:
https://groups.google.com/forum/?lnk=srg#!topic/angular/TGdrV4GsL8U
2011-04-07 14:56:57 -07:00
Igor Minar d517bcad5b improve docs for angular.Object.copy 2011-04-07 12:48:14 -07:00
Igor Minar e5419db6c7 fix indentation regexp for doc:examples 2011-04-07 12:34:34 -07:00
Igor Minar 754d2541c4 correct $resource's success callback execution
succcess callbacks should be executed for status codes in the range
of <200,300).
2011-04-04 16:04:37 -07:00
Igor Minar 9bd2c3967b revert ng:view sync caching
sync caching in ng:view must be reverted becase ng:view uses
$route.onChange to listen for changes.

$route fires all onChange events before it calls $become(Controller)
which means that if the template being included via ng:view contains
ng:controller, ng:include or other widget that create new scopes,
these scopes will be created and initialized before the parent scope
is fully initialized (happens after $become is called).

For this reason ng:view must be async.

The new scope implemenetation will resolve this issue by providing
us with an api to register one-off tasks to be executed during the
flush phase. We'll be able to compile and link the included template
safely at this time.
2011-04-04 15:35:28 -07:00
Igor Minar 38ec6519a3 prepare for the angular 0.9.15 lethal-stutter iteration 2011-04-04 14:49:48 -07:00
Igor Minar 0b8cf8539d cutting the 0.9.14 key-maker release 2011-04-01 12:26:04 -07:00
Igor Minar f109604315 release notes for the 0.9.14 key-maker iteration 2011-04-01 12:26:00 -07:00
Igor Minar ac3dbae370 upgrade jstd to 1.3.2 + improve test-coverage.sh script 2011-04-01 09:59:42 -07:00
Igor Minar cf1d365f57 fix infinite loop in elementError when working with detached elements 2011-03-31 21:48:52 -07:00
Igor Minar 78a0f41058 encode query params correctly but not too agressively 2011-03-31 21:45:28 -07:00
Igor Minar eccd9bfbb3 add much needed whitespace to jqLiteSpec.js
can we agree to put more white space into our code?

I follow there rules for specs:

- 1 blank line between sections of nontrivial it block
- 2 blank lines between it blocks
- 2 blank lines between describe blocks
- 2 blank lines between beforeEach and afterEach
- no blank line between describe and the first child it
- no blank lines between two or more closing }); lines
2011-03-31 01:42:42 -07:00
Igor Minar 2d9dd1c172 add specs for jqLite wrapping/node creation
tests cover:
- creating comment tags from a string
- creating script tag from a string
- wrapping document fragment
2011-03-31 01:20:20 -07:00
Igor Minar a2c4271128 ignore jqLite#append for doc fragment
this is needed to be compatible with jqQuery 1.5.1
2011-03-31 01:19:07 -07:00
Igor Minar 56c00800c7 fix jqLite#parent to be compatible with jQuery
our original implementation doesn't work with
document fragments on IE

- tests were added to cover missing cases
2011-03-31 01:17:34 -07:00
Igor Minar 15ec78f5ef use document fragments to grow repeaters
- unless we are repeating OPTION elements, buffer new nodes in document
  fragment and append them to the DOM in one go at the end
- for OPTION elements we have to keep on using the old way
  because of how option widget communicates with select widget
  this should be change, but that change is out of scope of this CL
- modify jqLite to support wrapping of document fragments
- fix jqLite documentation typo

This change unintentionally avoids the following webkit bug that
that affects repeater growth:
https://bugs.webkit.org/show_bug.cgi?id=57059

However the following bug affecting shrining of repeaters is still
unresolved https://bugs.webkit.org/show_bug.cgi?id=57061
2011-03-30 15:24:03 -07:00
Igor Minar a4863d5244 correct size() impl for object's w/ 'length' prop
the original implementation returned incorrect value value for
objects with 'length' property.
2011-03-30 15:24:03 -07:00
Igor Minar 96a1df192a extend size() to take ownPropsOnly param
- extend size() to take size(obj, ownPropsOnly)
- add specs for size()
- update docs to mention string support
- use size() in ng:repeat

including the hasOwnProp check for all object doesn't create
significant perf penalty:
http://jsperf.com/dedicated-code-branch-for-hasownprop
2011-03-30 15:24:03 -07:00
Igor Minar 89c25fe713 call $eval in repeater only when needed
when growing children linker calls eval for new nodes, so we need
to call it only for reused nodes.
2011-03-30 15:24:03 -07:00
Igor Minar c06c5a36b1 make xhr.cache optionally synchronous
- add `sync` flag xhr.cache
- change ng:include to use the sync flag
- change ng:view to use the sync flag

The end result is that there are fewer repaints in the browser,
which means less "blinking" that user sees.
2011-03-30 15:22:22 -07:00
Igor Minar 9985104dc0 remove weird spaces from resource mutation test 2011-03-30 15:22:14 -07:00
Anthony Lieuallen 94514a91f8 Don't mutate resource if server responded with no body
If the server provides response with no body to a resource request,
resource should not mutate the resource model in the callback.
2011-03-29 00:25:22 -07:00
Pepper Lebeck-Jobe 4da65d0e8c Fixes some links and types in the DI docs. 2011-03-28 23:40:56 -07:00
Igor Minar e1d122a4b7 encode $resource query params using encodeURIComponent 2011-03-28 23:33:46 -07:00
Igor Minar 885c3ad5dd fixing lint warnings 2011-03-28 23:15:28 -07:00
Vojta Jina 9312bed472 Added missing semi-colons
So that my eclipse stops complaining...
2011-03-28 23:04:48 -07:00
Igor Minar faf29dd047 upgrade closure compiler to version 20110322
the new version minifies our js better:

              before   |  after  | diff
-----------------------------------------
min       |  62161     | 60868   | -2.1%
min+gzip  |  25176     | 24552   | -2.5%
2011-03-26 23:22:00 -07:00
Igor Minar 510b5f3d90 renaming lib/compiler-closure to lib/closure-compiler 2011-03-26 23:21:59 -07:00
Igor Minar 1e59822df7 remove _null and _undefined
they have no significant effect on minified and gziped size. in fact
they make things worse.

file        | before     | after removal
----------------------------------------
concat      | 325415     | 325297
min         | 62070      | 62161
min + gzip  | 25187      | 25176

The bottom line is that we are getting 0.05% decrease in size after
gzip without all of the hassle of using underscores everywhere.
2011-03-26 23:19:04 -07:00
Igor Minar d95a6925cd fix broken 'downloading' links 2011-03-23 15:25:05 -07:00
Pepper Lebeck-Jobe b4d680a921 Fixes two links on the conribute page. 2011-03-22 10:18:07 -07:00
Pepper Lebeck-Jobe ff4480be65 Fixes a typo xmlsn -> xmlns 2011-03-22 10:10:55 -07:00
Anthony Lieuallen cf0513dc6f Require 'yaml' in Rakefile. 2011-03-22 10:03:27 -07:00
Igor Minar dfba8fb2e7 fixing broken angular-mocks.js 2011-03-15 16:13:11 -07:00
Igor Minar a0af13f672 preparing the 0.9.14 key-maker iteration 2011-03-13 23:15:36 -07:00
Igor Minar 69e6379d19 cutting the 0.9.13 curdling-stare release 2011-03-13 22:48:26 -07:00
Igor Minar 1094b3471e preparing release notes for the 0.9.13 curdling stare release 2011-03-13 17:34:01 -07:00
Misko Hevery 3224862a9c Stop using document write, so that we are compatible with async script loader 2011-03-11 14:16:53 -08:00
Misko Hevery 0084cb5ca4 Remove the script tag after successful JSONP request 2011-03-11 14:16:53 -08:00
Misko Hevery c578f8c3ed Added XSRF prevention logic to $xhr service 2011-03-11 14:16:53 -08:00
Misko Hevery 5b05c0de03 @require in ngdoc now takes reason for dependency 2011-03-11 14:16:52 -08:00
Misko Hevery d19c0ac6d3 Changed the $browser.xhr parameter post from optional to required 2011-03-11 14:16:52 -08:00
Misko Hevery 5343deb3da Consider all 2xx responses as OK, not just 200 2011-03-11 14:16:52 -08:00
Misko Hevery 26bad2bf87 Fixed cookies which contained unescaped '=' would not show up in cookie service. 2011-03-11 14:16:52 -08:00
Igor Minar d304b0c3df fix failing autobind test on IE 2011-03-11 09:30:53 -08:00
Igor Minar 9d5c533791 ng:autobind now optionally takes element id
so it is possible to easily compile just a part of a document.

e.g.:

<html>
  <head>
    <title>partially compiled doc</title>
    <script src="angular.js" ng:autobind="compileThis"></script>
  </head>
  <body>
    this part won't be compiled: {{1+2}}
    <div id="compileThis" ng:init="i=0" ng:click="i = i+1">
      Click count: {{i}}
    </div>
  </body>
</html>
2011-03-11 08:45:43 -08:00
Igor Minar 7414e7b533 angularJsConfig now allows ng:autobind and #autobind value to be passed in 2011-03-11 08:45:16 -08:00
Misko Hevery 5432dd289a pass undefined through fn closure for better minification 2011-03-09 13:41:16 -08:00
Misko Hevery 194b2c1ea0 Fix IE: reffering to non existent var on window, must be prefixed by window 2011-03-09 13:40:47 -08:00
Misko Hevery f7a9ea6a41 fix ie7 regression in jqLite which prevented 2011-03-08 20:23:19 -08:00
Igor Minar 627eba2b7c upgrading jasmin-jstd-adapter to 1ade1ad7cad4caadb3a3 11-03-07 2011-03-07 00:07:02 -08:00
Igor Minar 73ee5fc008 jstd r899 2011-02-18 (post 1.3.1) + fix for jasmine adapter. 2011-03-07 00:07:01 -08:00
Misko Hevery 4c762bfe5c fix orberBy documentation error 2011-03-05 22:54:41 -08:00
Igor Minar 749b3e8763 preparing the 0.9.13 curdling-stare iteration 2011-03-03 23:14:43 -08:00
Igor Minar fd409bd2df cutting the 0.9.12 thought-implanter release 2011-03-03 23:14:43 -08:00
Igor Minar e80a64883d re-eagarizing the $hover service - mea culpa 2011-03-03 23:14:43 -08:00
Igor Minar 8b2753eee2 fixing left over .scope 2011-03-03 23:14:43 -08:00
Igor Minar 02aa7978d3 fixing link in thought-implanter release notes 2011-03-03 22:59:11 -08:00
Igor Minar 5bf7ff5a3e fixing broken e2e tests 2011-03-03 13:50:12 -08:00
Igor Minar a01aa7055c preparing release notes for the 0.9.12 though-implanter release 2011-03-03 00:45:20 -08:00
Igor Minar a01d888eec adding dependency injection docs 2011-03-03 00:16:20 -08:00
Igor Minar 28800a48ad renaming guide.contribute.ngdoc to contribute.ngdoc 2011-03-02 23:19:59 -08:00
Igor Minar dea72be0cc docs cleanup and improvements
- moving 'downloading' from devguide to "misc"
- syncing the latest version of 'downloading'
- getting rid of junk files
2011-03-02 23:14:13 -08:00
Igor Minar cd139f5767 $xhr service now autodetects and strips )]}',\n
")]}\',\n" is a commonly used security prefix added to json http
responses iat google and elsewhere in order to prevent certain
cross-site attacks

$xhr service now autodetects the prefix and strips it before
deserializing the json.

the implementation should be more flexible to allow for wider range
of prefixes, but we need this one right now and can address other
usecases later.
2011-03-02 22:56:14 -08:00
Igor Minar 10a7521f0b rename devguide collection in gdocs.js to guide 2011-03-02 17:40:48 -08:00
Igor Minar 887da5684b enhancing gdocs.js to work with nested collections 2011-03-01 22:36:48 -08:00
Igor Minar 95a29d7bde additional fixes for the angular.compile docs 2011-03-01 19:08:30 -08:00
Igor Minar 945056b166 linking function should return bound scope
angular.compile()() returns {scope:scope, view:view},
this isn't useful at all and only makes tests more verbose.
Instead, this change makes the linking function return scope directly
and if anyone needs the linked dom there are two ways to do it
documented in angular.compile.

other changes:
- moved angular.compile docs to the compiler so that they are closer to
  the compiler
- fixed some typos and updated angular.compile docs with the new return
  value
2011-03-01 17:09:25 -08:00
Luther Goh 128feb2674 On some linux systems, such as Ubuntu, /bin/sh symlinks to dash, which causes issues. Symlinking to bash may be more prudent 2011-03-01 10:02:57 +08:00
Igor Minar a709dc19b8 adding an extra injector spec
- added a spec for dependency graph resolution
- also simplyfying cache presence check
2011-02-27 16:19:21 -08:00
Igor Minar 65585a2d3c $cookie factory fn should not run $eval 2011-02-27 15:54:06 -08:00
Misko Hevery edbe9d8ca8 Added delay parameter to the $defer service 2011-02-25 11:30:22 -08:00
Misko Hevery 9e67da420b Corrected an issue where properties inherited from __proto__ show up in ng:repeat.
Closses #112
2011-02-25 09:23:30 -08:00
Igor Minar 5fc2b96b97 docs.css should not inline all pragraphs, only those in lists 2011-02-23 15:52:29 -08:00
Igor Minar a7ee4a8884 gdocs.js should add dropped leading space 2011-02-22 17:42:05 -08:00
Janet Davies eea0de6db4 Rewrite of the "Contributing" section of the DevGuide 2011-02-22 17:42:00 -08:00
Igor Minar d15165f207 fixing typo in guide.overview 2011-02-22 15:49:46 -08:00
Misko Hevery c7998f5f99 add class on any namespace elments 2011-02-22 15:23:08 -08:00
Igor Minar 08e3b1edbb gdocs.js should strip trailing whitespace in imported docs 2011-02-22 15:09:44 -08:00
Kenneth R. Culp fe743e31f8 Rewrite of the overview section of the dev guide 2011-02-22 15:09:44 -08:00
Misko Hevery 55ce859998 fix documentation for ie 2011-02-22 14:48:53 -08:00
Misko Hevery 5a3c9190dc correct hashchange event registration on window 2011-02-19 20:39:46 -08:00
Misko Hevery e160944bfa fix test which fails on CI build, because the image has size 2011-02-19 20:37:17 -08:00
Igor Minar 6f8940c5d0 add missing example files for temp.html 2011-02-18 23:02:13 -08:00
Misko Hevery 87cbf9f591 Remove ng:watch
Closes#143
2011-02-18 14:22:51 -08:00
Misko Hevery fd6e5e3f31 replace smart-quotes with regular quotes 2011-02-18 14:02:21 -08:00
Misko Hevery 7d4aee31bb Auto create $inject property form the argument names. Any arg starting with $ or _ will be injected 2011-02-18 13:14:07 -08:00
Misko Hevery 7a54d2791f script for dowlnoading docs from google docs 2011-02-18 11:52:57 -08:00
Misko Hevery 65243b7d60 corrected new lines in @link 2011-02-18 11:52:57 -08:00
Igor Minar 9e30baad3f resources should not over-encode chars in url path
- added encodeUriSegment that properly encodes only those chars
  that URI RFC requires us to encode
- modified Resource to use encodeUriSegment
2011-02-17 23:06:53 -08:00
Igor Minar a070ff5ad0 make all built-in services lazy
now that we require DI everywhere, we don't need any of these
services to be eager - they get initialized when and only when
they are requested.
2011-02-17 22:58:59 -08:00
Misko Hevery c90abf057b Changed the angular.compile(element)(scope[, cloneAttachNode]) 2011-02-16 08:59:57 -05:00
Misko Hevery cdc093a463 reformated multiline trinary expressions to have a leading ?/:. 2011-02-16 08:59:57 -05:00
Misko Hevery 00cc9eb32a rewrite of JQuery lite implementation, which now better supports selected sets 2011-02-16 08:59:42 -05:00
Misko Hevery ef4bb28be1 Change API angular.compile(element)([scope], [element/true]) 2011-02-16 01:03:12 -05:00
Misko Hevery 496e6bf901 refactored quickClone to cloneNode and exposed it on jQuery 2011-02-16 00:49:16 -05:00
Misko Hevery 23b255a8b7 remove $init on scope from applying compilation template
Closes #40
2011-02-16 00:49:15 -05:00
Misko Hevery e2154cbc0b remove dom manipulation API from compiler 2011-02-16 00:48:22 -05:00
Misko Hevery 0a5c00abf8 Add public API to retrieve scope from element. 2011-02-16 00:48:22 -05:00
Misko Hevery a004d487c4 allow jquery to be declared after angular in the script loading order 2011-02-16 00:48:22 -05:00
Misko Hevery 037f30a0c9 added missing semicolons 2011-02-16 00:48:21 -05:00
Igor Minar c37bb2dc28 improving the $document docs
Closes #276
2011-02-16 00:10:47 -05:00
Anthony Lieuallen 7cf70c587e Small spelling and grammar fixes in documentation. 2011-02-16 00:04:15 -05:00
Igor Minar 1777110958 split up services into individual files
- split up services into files under src/service
- split up specs into files under test/service
- rewrite all specs so that they don't depend on one global forEach
- get rid of obsolete code and tests in ng:switch
- rename mock $log spec from "$log" to "$log mock"
2011-02-15 11:01:53 -05:00
Igor Minar d2089a1633 docs - adding cross links from directives to guide.expression 2011-02-14 11:42:58 -05:00
Igor Minar e9ce22592a $resource should encode url params with encodeURIComponent 2011-02-10 17:57:42 -08:00
Igor Minar 4f6fe1d479 adding testimonials page to docs
this is just a temporary move so that the content doesn't get lost.
in the long term we want this to be part of the main site.
2011-02-10 15:40:38 -08:00
Misko Hevery 0f19cd3625 corrected missbehaved example 2011-02-09 20:11:34 -08:00
Janet Davies c1caf2560a Update Dev Guide Downloading content (to be moved to Contributing later). 2011-02-09 11:19:30 -08:00
Kenneth R. Culp b07cc0e392 Cleanup of the Getting Started guide 2011-02-09 11:01:54 -08:00
Misko Hevery a26f192e01 added omingrafle file for docs 2011-02-09 10:30:35 -08:00
Igor Minar f943180e34 renaming fag.ngdoc to faq.ngdoc 2011-02-08 20:42:32 -08:00
Igor Minar e6a6e32c72 preparing the 0.9.11 thought-implanter iteration 2011-02-08 19:25:15 -08:00
Igor Minar e1cfb99ae9 cutting the 0.9.11 snow-maker release 2011-02-08 17:47:31 -08:00
Igor Minar 1cdc050ce7 release notes for 0.9.11 snow-maker 2011-02-08 17:42:03 -08:00
Igor Minar d600c608e3 markdown pre-processor should strip all the extra indentation
- split trim into trim and indent
- merged my indentation code with trim
- cleaned up some small issues
2011-02-07 23:56:51 -08:00
Igor Minar 86321d1f57 add support for hashSearch redirection and custom redirection functions 2011-02-07 23:56:33 -08:00
Igor Minar 8724e97b7e $route redirection should interpolate variables 2011-02-07 23:56:33 -08:00
Igor Minar bf8013ad57 $location.updateHash should not preserve hashSearch when hashSearch is undefined 2011-02-07 23:56:32 -08:00
Igor Minar a6c45c3e66 add description for ng:controller example 2011-02-07 23:55:46 -08:00
Igor Minar e626f95469 $resource service docs 2011-02-07 23:55:42 -08:00
Igor Minar 2fab1a2da9 docs for $xhr, $xhr.error and $xhr.cache 2011-02-07 23:55:03 -08:00
Igor Minar f3a39a6418 docs should print usage for services that are functions 2011-02-07 23:55:02 -08:00
Igor Minar f00b157841 @property should require type and description should be markdownified 2011-02-07 23:55:02 -08:00
Igor Minar ae20f0c1b3 adding docs for angular.markup and angular.attrMarkup 2011-02-07 23:55:02 -08:00
Igor Minar 9f6c5db2a6 fix script name in watchr-docs.rb 2011-02-07 23:55:02 -08:00
Igor Minar ea9ca651d2 fix how redirection is handled and tested 2011-02-06 09:35:14 -08:00
Igor Minar d6db4b1749 fix typo in $browser mock
Closes #260
2011-02-04 14:23:51 -08:00
Vojta Jina 9798f5e35f mock $log: fixed bug, added some tests
I extracted mock $log factory into stand alone function, so we can access it and test, because this service is rewritten by real service during testing, so we can't access it through angular.$service('$log')...
2011-02-04 14:18:28 -08:00
Igor Minar 94bf24e3b6 fix angular.js file path detection in docs 2011-02-04 14:11:53 -08:00
Igor Minar fbc7f1b454 ng:view should be nestable in ng:include 2011-02-04 14:11:53 -08:00
Igor Minar bf7c9d9900 $route.onChange should return the registered fn 2011-02-04 14:11:52 -08:00
Igor Minar 568574b915 mock's .xhr.flush() should throw exception when there is nothing to flush 2011-02-04 14:11:52 -08:00
Misko Hevery 46d690ff01 smarter normalization of value on option, and htmlParser fixes 2011-02-04 13:44:22 -08:00
Misko Hevery 882f412d57 Added remainder of the cookbook 2011-02-03 20:03:38 -08:00
Misko Hevery 0d4def68ae added more cookbook: work in progress 2011-02-03 20:03:38 -08:00
Misko Hevery d35c1ac8b0 Fixed notifyWhenNoOutstandingRequests() when using JSONP 2011-02-03 20:03:32 -08:00
Misko Hevery 2a9f7b7287 changed order of auto test runner so that JS errors show up last 2011-02-03 13:26:48 -08:00
Misko Hevery 245b60d69a addded cookbook 2011-02-03 13:26:48 -08:00
Misko Hevery b6a01bd27d fixed population of value attribute on option
The value attribute must be populated manually, since different
browsers default to different value of option when not explicitly
defined.
2011-02-03 13:25:01 -08:00
Misko Hevery aaaad298ac corrected typo in the dump function which was preventig serialization of objects 2011-02-03 12:25:43 -08:00
Misko Hevery ba6b68b6ae changed the documentation @example to use <doc:example> 2011-02-01 10:00:09 -08:00
Misko Hevery ed768ebc53 Developer guide documentation 2011-02-01 09:58:37 -08:00
Igor Minar 9fd3dfe49d add support for $route.reload()
Closes 254
2011-02-01 09:35:19 -08:00
Igor Minar d7686a429c add $route.parent for setting parentScope 2011-02-01 09:35:19 -08:00
Igor Minar 6c0cf17404 add redirection support to $route
Closes #217
2011-02-01 09:35:19 -08:00
Igor Minar c648fee5c2 fix $location to handle updates to empty hash well 2011-02-01 09:35:18 -08:00
Igor Minar 9462c78fbf $browser poller should notify $location only once per url change 2011-02-01 09:35:18 -08:00
Igor Minar c4497d60bc fix docs for $window service 2011-02-01 09:35:18 -08:00
Igor Minar 5690627766 upgrading jstd to r845 2011-02-01 09:35:18 -08:00
Igor Minar 2389c71238 fixing $exceptionHandler docs 2011-02-01 09:33:59 -08:00
Igor Minar ce7ab3d1ee add support for 404 handling via $route.otherwise
Closes #217
2011-02-01 09:33:59 -08:00
Igor Minar 7db3b54c1f adding spec for controller-less $route definitions 2011-02-01 09:33:59 -08:00
Igor Minar 21ad176246 fixing $route docs 2011-02-01 09:33:58 -08:00
Igor Minar df1d222dd0 fix older release notes 2011-02-01 09:33:58 -08:00
Igor Minar 7eea26323b upgrading jstd to r844 2011-01-31 2011-01-31 12:46:31 -08:00
Igor Minar f0fb4a3928 jqlite should not generate exceptions when accessing attributes on Document 2011-01-30 14:43:53 -08:00
Igor Minar 0144fa1ca9 fixing angular.Scope. docs 2011-01-30 14:43:03 -08:00
Igor Minar b612826158 preparing the 0.9.11 snow-maker iteration 2011-01-30 14:40:48 -08:00
Misko Hevery e5a3acacad corrected sitemap.xml format 2011-01-27 09:53:20 -08:00
Igor Minar 9f947e5b8b cutting the 0.9.10 flea-whisperer release 2011-01-26 23:51:06 -08:00
Igor Minar 75de7395bb validator doc example should not be escaped 2011-01-26 23:44:21 -08:00
Igor Minar 9f73b1f290 updating release notes for the 0.9.10 release 2011-01-26 23:36:41 -08:00
Misko Hevery bd33f60276 Added part of guide documentation and supporting changes to doc generator 2011-01-26 23:31:15 -08:00
Igor Minar 8682befc72 fix for stupid IE handling of named functions in mocks 2011-01-26 22:30:09 -08:00
Igor Minar 3f0a37f380 add missing test/mocks.js 2011-01-26 20:12:23 -08:00
Igor Minar f5d08963b0 split mocks and create $log and $exceptionHandler mocks
- split mocks between angular-mocks.js and mocks.js
- src/angular-mocks.js now contains only mocks that we want to ship
- test/mocks.js contains mocks that we use internally for testing
  angular
- created angular.mock namespace
- created public $exceptionHandler mock rethrows errors
- created public $log mock stores all logs messages in an array that can
  be accessed to make assertions
- internally we now have factory to create $exceptionHandler
  that we can assert on
- internally we also keep track of all messages logged and
  fail tests if messages were not expected and cleaned up (checked
  via global beforeEach and afterEach)
- updated RakeFile and docs reader.js to point to the new
  angular-mocks.js location
- made real $exceptionHandler and $log factories accessible from tests
  and simplified their specs
- fixed typos in several spec descriptions
- added log assertions throughout the test suite
2011-01-26 15:46:05 -08:00
Igor Minar 7a48ee6aa9 fix deprication typo in the doc generator 2011-01-26 15:37:22 -08:00
Igor Minar 6512a736ac adding jsdoc for angular namespace 2011-01-26 15:37:22 -08:00
Igor Minar 9e0fa5b7c8 compile but don't bind option elements nested in a nameless select
otherwise an exception is thrown unexpectidly
2011-01-25 20:49:25 -08:00
Igor Minar 9368ea3814 Scope should retrieve $log and $exceptionHandler via $service
- fix $log and $exceptionHandler retrieval
- remove reference to non-existent `error` handler
- update tests
2011-01-25 20:49:25 -08:00
Misko Hevery a6a4c18ecd added any edit perf to make sure no trailing whitespace 2011-01-24 14:23:51 -08:00
Misko Hevery d8acfe7389 add @this and @exampleDescription tags
(also removed markdownNoP, now done through CSS)
2011-01-24 14:23:51 -08:00
Misko Hevery b036c0bc58 enable docs tests 2011-01-24 14:23:51 -08:00
Misko Hevery bf03eb007c Added SiteMap generation to the documentation 2011-01-24 14:23:51 -08:00
Misko Hevery c2f2587a79 fixed example rendering, add tests for it. 2011-01-24 14:23:51 -08:00
Misko Hevery 5d0d34ae72 remove trailing whitespace 2011-01-24 14:23:51 -08:00
Misko Hevery 70c74a9c4e add @this and @exampleDescription tags
(also removed markdownNoP, now done through CSS)
2011-01-24 14:23:51 -08:00
Misko Hevery 22c5b7059b updated doc styling for methods/properties 2011-01-24 14:23:50 -08:00
Misko Hevery 190498efd7 remove jasmine stack traces from the test output 2011-01-24 14:23:50 -08:00
Igor Minar a5990050d4 ng:view should propagate evals to the current child scope
- this change is needed because of previously reverted $route changes
  that used to propagate evals automatically.
- also added docs to highlight how the eval propagation works
2011-01-24 14:03:43 -08:00
Igor Minar 8d507df8c9 Revert "$route should create child scope via $new"
This reverts commit a5eb3ed107.

See 9ca2facb for reasoning.
2011-01-24 14:03:42 -08:00
Igor Minar 567f33823b Revert "fix ng:include issue introduced by a5eb3ed1"
This reverts commit 17ee0f031a.

this and a5eb3ed1 introduced scope leakage that can't be resolved
until we fix up scope relationships and eval propagation.
I'm reverting both this and a5eb3ed1 until we can properly address
the issue.
2011-01-24 14:03:42 -08:00
Igor Minar 5340d1e0b1 fix for infinite loop in retrieveScope with jQuery + specs
- retrieveScope run into infinite loop if called on DOM tree
  that doesn't contain scope reference (happens only with jQuery)
- added missing specs for retrieveScope function
2011-01-24 14:03:42 -08:00
Igor Minar 8d91ec4173 improve angular.Scope.$eval docs 2011-01-24 14:03:42 -08:00
Igor Minar 746e7a9768 update example/temp.html template 2011-01-24 14:03:42 -08:00
Igor Minar 94737cd017 $cookies service should not call $eval during $eval
- added comment
- removed $eval call
- changed the code to not require $eval
- updated specs
2011-01-24 14:03:41 -08:00
Igor Minar c8bb044be1 fix clobber test in angular-bootstrap.js for FF 2011-01-24 14:03:17 -08:00
Igor Minar 4a569560d8 null and other falsy values should not be rendered in the view
Closes #242
2011-01-20 12:55:03 -08:00
Igor Minar 17ee0f031a fix ng:include issue introduced by a5eb3ed1 2011-01-19 21:47:14 -08:00
Igor Minar 10646c9f6f add ng:view widget 2011-01-19 15:53:59 -08:00
Igor Minar 964e394555 fix argument variables in compiler 2011-01-19 15:53:59 -08:00
Igor Minar 2c0f7ffe3a ngdoc should escape content of pre in markdown 2011-01-19 15:53:58 -08:00
Igor Minar a5eb3ed107 $route should create child scope via $new 2011-01-19 15:52:27 -08:00
Igor Minar 63690d1892 angular internals should not call methods via angular namespace 2011-01-19 15:52:27 -08:00
Misko Hevery 050e5d773f verify that issue# 162 was fixed with doc rewrite 2011-01-18 15:32:46 -08:00
Igor Minar da4b8a74c3 fix spec title for angular.formatter.index 2011-01-18 15:15:33 -08:00
Misko Hevery 5be92f7b9c fix broken build for IE. Read option.type==select-multiple rather then check presence of multiple attribute 2011-01-18 15:02:51 -08:00
Misko Hevery 459a01e582 improved dump function to atomatically render HTML 2011-01-18 15:02:51 -08:00
Igor Minar 72e554ffeb doc widgets examples should display angular src as CAO instead of DAO 2011-01-18 14:42:23 -08:00
Igor Minar 3bd96609e9 remove script.type attribute from example widgets since its optional in html5 2011-01-18 14:42:23 -08:00
Igor Minar d73635d573 @returns type in docs should be wrapped in curlies 2011-01-18 14:42:22 -08:00
Igor Minar ad3b811b8b fixes, examples and tests for angular.Object.* docs 2011-01-18 14:42:18 -08:00
Igor Minar d3f7bd699e various doc fixes for angular.Array.* apis + example and spec limitTo 2011-01-18 11:15:36 -08:00
Igor Minar 1c55123f9c rewrite of several major portions of angular.service docs 2011-01-17 22:16:15 -08:00
Misko Hevery 1d7b9d5626 support compilation in HTML widgets 2011-01-14 10:30:05 -08:00
Misko Hevery 347be5ae9a fixed select with ng:format
select (one/multiple) could not chose from a list of objects, since DOM requires string ids.
Solved by adding index formatter, which exposed incorrect handling of formatters in select
widgets.
2011-01-14 10:30:00 -08:00
Igor Minar 934f44f69e preparing the 0.9.10 flea-whisperer iteration 2011-01-14 10:22:10 -08:00
Igor Minar d3d2a3a374 cutting the 0.9.9 time-shift release 2011-01-13 22:08:27 -08:00
Igor Minar 527d0a1600 updating release notes 2011-01-13 22:06:28 -08:00
Igor Minar 23875cb330 significant rewrite of the $location service
- don't update browser before and after eval instead
  - sync location properties before eval
  - sync location properties and update browser after eval
- added tests
- symplified the code
- removed $location.toString() because it was not idempotent and useless

This resolves the issue with issuing two $route.onHashChange calls
when the $location was updated with a hashPath that needs to be encoded
2011-01-13 16:58:35 -08:00
Igor Minar b0be87f663 fix for angular.Object.equals to handle equals({},null) 2011-01-13 07:55:31 -08:00
Igor Minar 9ccd2f0412 adding a fallthrough comment 2011-01-11 17:48:30 -08:00
Igor Minar 99004b0aed fixing missing dependency 2011-01-10 23:28:47 -08:00
Igor Minar ab040254f0 tabbing and keyboard shortcut for docs
- first tab goes to the search box, following tabs iterate results
- ctrl+s (FF on mac) or ctrl+alt+s (Chrome on mac) move focus to the
  search box
2011-01-10 21:23:22 -08:00
Igor Minar 4f5d5029c2 offline docs
- freezing syntaxhighlighter and jquery under docs/src/templates/
- for jquery I just used a symlink to lib/jquery not an ideal solution
  but writer.js is not very flexible and I didn't want to mess with it
- changed docs' index.html to point to the local resources
2011-01-10 21:03:50 -08:00
Misko Hevery f534def0c6 removed unnedded files; switch rake to new doc build script 2011-01-10 14:48:13 -08:00
Misko Hevery c3e32f1a51 fix broken e2e test due to $window no longer published 2011-01-10 13:55:08 -08:00
Misko Hevery 4f22d6866c complete rewrite of documentation generation
- romeved mustache.js
- unified templates
- improved testability of the code
2011-01-10 11:50:11 -08:00
Vojta Jina aab3df7aea Fixed filter.date, so it parses format ending with non-replaced string
Closes #159
2011-01-10 10:37:37 -08:00
Igor Minar 0a6cf70deb Rename angular.foreach to angular.forEach to make the api consistent.
camelcase is used for other angular functions and forEach is also
used by EcmaScript standard.

- rename the internal as well as the external function name
- tweak the implementation of the function so that it doesn't
  clober it self when we extend the angular object with an
  object that has a forEach property equal to this forEach function

Closes #85
2011-01-10 10:26:55 -08:00
Igor Minar c79aba92f6 bootstrap angular on "document ready" instead of window.onload
- use jqLite api to bootstrap angular
- when jQuery is present DOMContentLoaded or hacks for IE are used
- when jqLite is present DOMContentLoaded is used for modern browsers
  and IE9 and window.onload is used for other browsers.
- test html for comparing DOMContentLoaded with window.onload

Closes #224
2011-01-10 10:24:12 -08:00
Igor Minar 84dedb81e7 jqLite should recognize window as an element even in IE
in IE window object has length property which makes it look like a
collection to jqLite. This commit makes jqLite properly identify
window as an element even in IE.

IE6 doesn't have Window type, so we need to check against window
object and only then do a more general check against Window. This
is not perfect, but I say screw IE6.
2011-01-10 10:24:12 -08:00
Igor Minar e999740044 fix addEventLister detection for IE9
IE9 added support for addEventListener and it looks like some
new events (e.g. DOMContentLoaded) can't be registered via attachEvent,
only addEventListener correctly registeres these. So to make sure
we are using the latest and greatest we need to look for addEventListener
instead of attachEvent in the jqLite feature detection code.
2011-01-10 10:24:12 -08:00
Igor Minar 0ad39dde4f fix onhashchange tests for IE 2011-01-10 10:24:12 -08:00
Misko Hevery 4c71824a69 fix for IE free function weirdness 2011-01-10 10:22:24 -08:00
Misko Hevery 47c454a315 change to keydown from keyup; add delayed $updateView
- There was a perceived lag when typing do to the fact that we were
   listening on the keyup event instead of keydown. The issue with
   keydown is that we can not read the value of the input field. To
   solve this we schedule a defer call and perform the model update
   then.

 - To prevent calling $eval on root scope too many times as well as to
   prevent drowning the browser with too many updates we now call the
   $eval only after 25ms and any additional requests get ignored. The
   new update service is called $updateView
2011-01-07 14:39:46 -08:00
Igor Minar 16086aa37c $location service should utilize onhashchange events instead of polling 2011-01-07 14:39:41 -08:00
Igor Minar c0a26b1853 jasmine adapter with better stack traces 2011-01-07 12:02:46 -08:00
Igor Minar 9db2170dcf add personalLog files to jsTestDriver-jquery.conf 2011-01-07 12:02:46 -08:00
Igor Minar b28dee7fd5 use toMatch in widgetSpec 2011-01-07 12:02:46 -08:00
Igor Minar 142a985f33 Revert "Issue #51: Update extensionMap()"
This reverts commit 00ca67e4be.

Now that we don't have published services, we don't need to worryi
about this any more and in fact this behavior is confusing because
to override a service that has dependencies with a services with
no dependencies one must specify $inject:[] or else the old
dependencies will be injected.

Conflicts:

	src/Angular.js
	test/AngularSpec.js
2011-01-07 12:02:45 -08:00
Igor Minar bd5ec7c32a rename nodeName due to conflicts with jquery 2011-01-07 12:02:45 -08:00
Igor Minar bdc251c5a5 add global namespace clobbering check to angular-bootstrap 2011-01-07 12:02:45 -08:00
Igor Minar ad9537cdf6 remove unused jquery ui lib 2011-01-07 12:02:45 -08:00
Misko Hevery 807d8c92b3 removed dissabled tests which are now outdated 2011-01-06 14:51:44 -08:00
Misko Hevery 454626ad39 converted last of tests to specs 2011-01-06 14:34:21 -08:00
Misko Hevery 247c99a8a4 upgrade to latest jasmine adapter 2011-01-06 14:22:45 -08:00
Igor Minar da1d50fbe9 avoid namespace conflicts between jqLite and window when running in bootstrap mode 2011-01-04 18:04:01 -08:00
Igor Minar 67d064820c fixing up personalLog app 2011-01-04 18:04:01 -08:00
Igor Minar b2631f6170 rename scope.$inject to scope.$service
see changelog diff for more info
2011-01-04 18:04:00 -08:00
Igor Minar 1430c6d6b1 renaming service property $creation to $eager
see changelog diff for more info
2011-01-04 18:03:55 -08:00
Igor Minar 3ea5941f0e removing support for 'eager-published' services 2011-01-04 16:40:41 -08:00
Misko Hevery d0270d9256 Remove many eager-publish services, lazy polling
- Browser now starts the poller on first call to addPollFn()

- Many services ($location, $cookies, $router) are no longer eager-publish. The result is that
  unless someone needs the $cookies, they will not cause the Browser to start polling for them.
2011-01-04 16:40:40 -08:00
Misko Hevery 5f080193cb Added an extra security check to make sure that the parser can not execute anything while evaluting JSON. 2011-01-04 13:25:49 -08:00
Igor Minar cf891428bf upgrading JSTD to r788 2010-12-28 17:32:20 -08:00
Igor Minar 5b9967518e preparing the 0.9.9 time-shift iteration 2010-12-23 22:43:42 -08:00
Igor Minar 38f462d572 cutting the 0.9.8 astral-projection release 2010-12-23 22:42:11 -08:00
Igor Minar 56eeba0f3c release notes for the 0.9.8 release 2010-12-23 22:41:05 -08:00
Igor Minar 5a534235b6 fixing invalid json strings in ResourceSpec 2010-12-23 09:03:34 -08:00
Igor Minar e7a0fb250f fromJson delegation to native JSON parser if available
- native parser delegation
- $xhr change to use native parser
2010-12-22 14:16:36 -08:00
Igor Minar e3ddc2bcc4 simple perf testing harness with JSON parsing tests
- all tests should be under perf/
- all payloads should be under perf/data
- run tests with ./server.sh + ./test-perf.sh

We still lack a way to compare results against a baseline, but
this is better than nothing.
2010-12-22 14:16:36 -08:00
Igor Minar d11088eb43 Revert "Refactor lexer to use regular expressions"
We came across a major performance regression due to this change.
I'm reverting it until we find a better solution.

This reverts commit 23fc73081f.
2010-12-22 14:16:36 -08:00
Misko Hevery a5df1fc41f Stricter JSON parsing, for security 2010-12-11 10:07:10 -08:00
Misko Hevery ec4d446f89 Closes #153: input widgets without name are ignored 2010-12-11 08:28:11 -08:00
Misko Hevery b225083a21 Fire $eval only if the value has actually changed on input 2010-12-11 08:27:52 -08:00
Igor Minar e84d3334b0 preparing the 0.9.8 astral-projection iteration 2010-12-10 22:16:10 -08:00
Igor Minar 7989c7d24a cutting the 0.9.7 sonic-scream release 2010-12-10 17:08:52 -08:00
Igor Minar 5c36f466e1 fixing release notes 2010-12-10 17:08:10 -08:00
Igor Minar f8151afd90 improve doc app scrollbars 2010-12-10 17:04:56 -08:00
Igor Minar 74120eaa0f updating release notes 2010-12-10 13:49:03 -08:00
Igor Minar b370fac4fc $defer service should always call $eval after callback finished
Closes #189
2010-12-10 13:22:44 -08:00
Misko Hevery 23fc73081f Refactor lexer to use regular expressions 2010-12-08 14:39:22 -08:00
Misko Hevery e5e69d9b90 Remove RegExp parser
- RegExp parser is rearly used, feature, and one should not have RegExps
  in views anyways, so we are removing it

BACKWARD INCOMPATIBLE CHANGE!!!
2010-12-08 14:36:51 -08:00
Misko Hevery fa722447f8 Fixed failed assignments of form abj[0].name=value
Closes #169
2010-12-08 14:20:26 -08:00
Igor Minar 81d10e819e make the docs angular 'logo' link filename agnostic 2010-12-07 20:43:10 -08:00
Igor Minar 809ca94e1c @returns tag should allow the content to be split into multiple lines 2010-12-07 16:07:14 -08:00
Igor Minar 824eab9029 improving $resource docs 2010-12-07 16:06:31 -08:00
Igor Minar d503dfe99b preparations for the 0.9.7 sonic-scream iteration 2010-12-06 21:24:49 -08:00
Igor Minar e4d33917e3 cutting the 0.9.6 night-vision release 2010-12-06 21:11:10 -08:00
Igor Minar 6326e2028b fixing release notes 2010-12-06 21:10:38 -08:00
Igor Minar 8aed2047f0 fixing closure compiler warnings 2010-12-06 20:48:47 -08:00
Igor Minar f60b6b0938 fix the angular.Array.orderBy example + add docs 2010-12-06 20:32:37 -08:00
Igor Minar eea7113abe updating release notes for the 0.9.6 release 2010-12-06 20:23:06 -08:00
Igor Minar c8f34e7f6b fixing lint warnings in older code 2010-12-06 16:45:59 -08:00
Igor Minar 011fa39c2a add $browser.defer and $defer service and fix async xhr cache issue
- Closes #152 ($resource().query() sometimes calls callback before
  returning, and it shouldn't)
- add $browser.defer method
- add $defer service
- integrate $browser.defer with outstandingRequests counter in $browser
- fix all old tests that relied on buggy behavior
2010-12-06 16:45:59 -08:00
Misko Hevery 58d0e8945d allow documentation to be in external file
* Load templates once instead of per request
* show timing information
* load files ending in .ngdoc and process them
2010-12-06 15:48:40 -08:00
Misko Hevery 2bbced212e Fix sanitization issues as suggested by evn 2010-12-03 15:42:42 -08:00
Misko Hevery 5a8ad8fe32 Closes #170. Corrected the behavior of select when options are ng:repeated
- Delete $postEval method, as it was a hack
2010-12-02 22:45:57 -08:00
Misko Hevery 41d5938883 Fixed sanitization
* explicitly require full URLs (ftp|https?://...)
* list the URI attributes
* remove a lot of unneeded attributes
2010-11-29 21:55:32 -08:00
Igor Minar 5480d2a80b fix typo in searchbox placeholder 2010-11-29 16:47:21 -08:00
Igor Minar 95adf3a4d8 searchbar in docs should not scroll away 2010-11-29 16:47:20 -08:00
Igor Minar cc315ef4cc renaming #section to #main in docs html/css 2010-11-29 16:47:20 -08:00
Igor Minar 41c233ada1 getting rid of #page div in docs index.html 2010-11-29 16:47:19 -08:00
Igor Minar 46091f811b dual scrolling for docs with custom scrollbars 2010-11-29 16:47:13 -08:00
Igor Minar fde2ccb3f5 docs html/css cleanup 2010-11-29 11:25:38 -08:00
Igor Minar 1cc2ad2443 adding bash header to server.sh 2010-11-29 08:59:35 -08:00
Igor Minar 1aa46fac62 preparing the 0.9.6 night-vision iteration 2010-11-29 08:58:20 -08:00
Igor Minar 5bde02a8ca cutting the 0.9.5 turkey-blast release 2010-11-25 10:11:26 -08:00
Igor Minar d07e9f77f1 updating the release notes for 0.9.5 2010-11-25 10:10:54 -08:00
Igor Minar aa21c521eb more docs for angular.service. 2010-11-25 09:50:07 -08:00
Vojta Jina bd14a90610 Doc specs: added test for markdown
It should replace markdown between two <pre></pre>***<pre></pre>
2010-11-25 08:51:32 -08:00
Vojta Jina 9f1b9849d8 Small refactor in doc parser 2010-11-25 08:51:32 -08:00
Vojta Jina 47f159cdf3 Doc service: added example into service overview 2010-11-25 08:51:26 -08:00
Igor Minar 99eb123d79 docs for all angular.* type checking functions 2010-11-25 08:19:14 -08:00
Igor Minar 6515adc118 docs for angular.injector 2010-11-24 22:50:34 -08:00
Igor Minar b7aff92354 docs for angular.bind 2010-11-24 22:33:40 -08:00
Igor Minar 6b3b00e095 docs for angular.foreach 2010-11-24 21:13:58 -08:00
Igor Minar 921f7ce49e docs for angular.extend 2010-11-24 21:03:56 -08:00
Igor Minar 17eee57c52 fixing docs for angular.scope 2010-11-24 19:29:45 -08:00
Igor Minar 4fc3ee8040 docs for angular.compile 2010-11-24 19:14:34 -08:00
Igor Minar 39d3ae80d9 docs for angular.element 2010-11-24 19:03:06 -08:00
Igor Minar 480f2f33c1 docs for angular.noop and angular.identity 2010-11-24 18:23:21 -08:00
Igor Minar 9c9a89f7ff docs for angular.scope. and angular.scope. 2010-11-24 18:07:11 -08:00
Igor Minar 73194009a9 docs for angular.Object.copy 2010-11-24 17:32:04 -08:00
Igor Minar 162f41a1ab docs for angular.Object.size 2010-11-24 17:21:37 -08:00
Igor Minar 7c82c4f837 docs for angular.Object and angular.Object.equals 2010-11-24 16:55:44 -08:00
Igor Minar 97b1371199 adding Note section to angular.Array.* where it was missing 2010-11-24 16:32:03 -08:00
Igor Minar 95d1768c77 docs for angular.Array.sum 2010-11-24 16:28:17 -08:00
Igor Minar c3d99d68da docs for angular.Array.filter 2010-11-23 17:14:04 -08:00
Igor Minar 303a683081 docs for angular.Array.remove 2010-11-23 16:28:24 -08:00
Igor Minar a0e8c45880 docs for angular.Array.remove 2010-11-23 16:10:14 -08:00
Igor Minar 870547d185 docs for angular.Array.orderBy 2010-11-23 15:44:14 -08:00
Igor Minar 0d1f8a0532 docs for angular.Array.count 2010-11-23 14:10:10 -08:00
Igor Minar b94600d71e adding docs for angular.Array.add 2010-11-23 11:05:28 -08:00
Igor Minar 3e5a4ef86c placeholder docs for all angular.Array functions 2010-11-22 10:57:44 -08:00
Igor Minar efec0c358d Add angular.Array.limitTo and docs for angular.Array 2010-11-22 10:57:32 -08:00
Igor Minar 1f59de35c9 preparation for the 0.9.5 turkey-blast iteration 2010-11-18 23:42:57 -08:00
Igor Minar 9b53b25f15 cutting the 0.9.4 total-recall release 2010-11-18 22:40:01 -08:00
Igor Minar 3fbfa357ca updated release notes for the 0.9.4 total-recall release 2010-11-18 22:40:00 -08:00
Igor Minar 50ef1f8e35 don't escape $ in hashpath either 2010-11-18 22:40:00 -08:00
Igor Minar 66c0bfaa8e don't escape ! and : in hashPath
This is a temporary fix for Issue #158
2010-11-18 20:51:31 -08:00
Igor Minar 1719b0aca5 fix all closure compilation warnings due to invalid function types 2010-11-18 17:03:43 -08:00
Igor Minar 7ee102eecf add a feedback link to the doc pages 2010-11-18 16:53:11 -08:00
Igor Minar fc7f11d03b add @workInProgress tag and mark all @ngdocs as work in progress 2010-11-18 16:28:42 -08:00
Igor Minar 3c7874b07b don't encode page.name (hash) in docs.js
see discussion in https://github.com/angular/angular.js/pull/158"
2010-11-18 11:56:10 -08:00
Igor Minar 7f339a1782 escape code in ng:bind-attr jsdoc 2010-11-18 11:33:09 -08:00
Igor Minar 72a5f007d8 most of the documentation for angular.scope and friends 2010-11-18 02:35:30 -08:00
Igor Minar 63380bbbda title for index.html should not show raw binding while the app bootstraps 2010-11-18 02:35:30 -08:00
Igor Minar c635b69f5c fix docs and examples for ng:format, ng:required and ng:validate 2010-11-18 02:35:30 -08:00
Igor Minar 522ec1a9ec move attribute widgets to widgets.js file
- move @ng:repeat to widgets.js and its specs to widgetsSpecs.js
- move @ng:non-bindable to widgets.js and its specs to widgetsSpecs.js
- make widget.template suitable for attribute widgets
- fix up the js docs for attribute widgets
2010-11-18 02:35:29 -08:00
Igor Minar 9cb57772a4 fix docs for angular.directive and ng:autobind 2010-11-18 02:35:29 -08:00
Igor Minar d54f09ef29 add spec for incrementing headings 2010-11-18 02:35:29 -08:00
Igor Minar 65989c6f0d add support for {@link} tags within @description and remove implicit linking
use as:
- foo {@link bar}
- foo {@link bar desc}

I'm removing implicit linking because it unintentionally links stuff and
generally interferes with other conversions. We have to link stuff explicitely
from now on.
2010-11-18 02:35:29 -08:00
Igor Minar 4491bbdede docs linkifying regexp should not mess up links alreaded converete by markdown 2010-11-18 02:35:28 -08:00
Igor Minar a6978b201b make @param type and description non-optional 2010-11-18 02:35:28 -08:00
Igor Minar 28e72cbe6b CSS, Parameters, Returns template changes
- make css section optional
- make returns section optional
- change format of the parameters section
- properly format the Returns section
2010-11-18 02:34:55 -08:00
Igor Minar 916dadd8ec adjust spacing of headings in the main doc div 2010-11-18 02:34:54 -08:00
Igor Minar e509ec37f5 fixing angular.lowercase and angular.upppercase jsdocs + api 2010-11-18 02:34:54 -08:00
Igor Minar ee0e9a4452 adding support for @param.optional 2010-11-18 02:34:54 -08:00
Igor Minar 9d36368ff9 fixing angular.filter.number jsdocs 2010-11-18 02:34:54 -08:00
Igor Minar d4bcee0799 toJson and fromJson jsdocs 2010-11-18 02:34:54 -08:00
Igor Minar dd687e2bf5 @returns description should support markdown 2010-11-18 02:34:53 -08:00
Igor Minar 4c69d694d7 make @returns type non-optional 2010-11-18 02:34:53 -08:00
Igor Minar ff7c738c21 fix ng docs for angular, angular.lowercase and uppercase 2010-11-18 02:34:53 -08:00
Igor Minar 51a22cf435 group utility methods/objects while sorting stuff for the side bar 2010-11-18 02:34:53 -08:00
Igor Minar c2c60ab49a remove extra returns tag 2010-11-18 02:34:53 -08:00
Igor Minar 71c2f24fc6 remove extra toolbar directive and support multiple pre's in describe 2010-11-18 02:34:52 -08:00
Igor Minar fc78738cc6 scope docs + lowercase doc fix 2010-11-18 02:34:52 -08:00
Igor Minar c7052f098d add support for @deprecated ng:doc annotation + show warnings in templates 2010-11-18 02:34:31 -08:00
Igor Minar 7d6f5f986e add function.template 2010-11-18 02:34:30 -08:00
Igor Minar beeb5ff908 fix regexp for @param parsing in ng:docs
There is an extra + in the regexp which causes exponential increase in time
needed to parse a @param annotation when the length of default value increases
linearly.
2010-11-16 14:44:35 -08:00
Misko Hevery b2d63ac48b Changed error handling so that better stack traces are displayed in the ng-errors 2010-11-16 14:19:55 -08:00
Igor Minar 4af32de84a docs should use ng:include onload 2010-11-16 13:45:45 -08:00
Igor Minar a130bb899d add onload attribute to ng:include 2010-11-16 11:35:43 -08:00
Vojta Jina cc749760fd Added basic Services, which support @memberOf and @methodOf 2010-11-15 21:55:37 -08:00
Misko Hevery b467a50bc7 generate keyword for searches; improved layout of doc 2010-11-15 12:28:08 -08:00
Misko Hevery a1652057a5 changed to ! notation for indexable apps 2010-11-15 10:04:17 -08:00
Misko Hevery 7e6f999221 added remaining directives and search box. 2010-11-15 10:04:17 -08:00
Igor Minar 625cc7609c fix code name in the change log 2010-11-12 16:18:11 -08:00
Igor Minar c51273b1fb Add test coverage analysis.
- jstd upgrade to head from 2010-11-11
- coverage plugin from the same head as jstd
- test-coverage.sh and server-coverage.sh scripts
- jstd configuration

Generate html by installing lconv (brew or port) and run:

genhtml tmp/lcov/jsTestDriver.conf-coverage.dat

to generate html docs.
2010-11-12 16:13:53 -08:00
Igor Minar 0a8b3161b1 $watch should optionally skip listener exec
- if initRun param is set to false, listener doesn't execute
- the oldValue should equal newValue during the initial execution
- added docs
- added specs
2010-11-11 16:39:01 -08:00
Igor Minar ba554eeb1b preparations for 0.9.4 total-recall iteration 2010-11-11 16:38:23 -08:00
Igor Minar 5f0af2cd0e cutting the 0.9.3 cold-resistance release 2010-11-10 22:15:16 -08:00
Igor Minar 7411b24812 updating the release notes for 0.9.3 release 2010-11-10 22:14:16 -08:00
Igor Minar ae5f6f48b4 scenario repeater should match only visible stuff 2010-11-10 21:04:44 -08:00
Igor Minar c5b2bf083c Make ng:repeat expose $position.
- $position is a textual representation of the position of
  repeated item ('first', 'middle', 'last')
- added specs for $index
2010-11-10 21:04:44 -08:00
Misko Hevery 0499c47270 added ng:switch-when-default; changed $watch to always fire on init. (may be backward incompatible) 2010-11-10 21:01:17 -08:00
Misko Hevery 43a4ff4cdf Example snippets now have full html snippets 2010-11-10 21:01:05 -08:00
Misko Hevery 6b8ed42670 Added Directives 2010-11-10 12:02:49 -08:00
Elliott Sprehn c57df3dc77 Make the docs look a little nicer 2010-11-10 11:01:30 -08:00
Igor Minar 6d53808475 improve jsdocs
- improve json filter example
- improve filter overview doc
- improving validator overview jsdocs
- simplify number filter examples and make them live + add specs
- various doc fixes
2010-11-09 22:33:27 -08:00
Misko Hevery a7e8a503fd proper trimming of leading whitespace; url restriction to angular.* 2010-11-09 22:27:37 -08:00
Igor Minar 324694a58b Better example widget
- syntax highlighting
- tabless design
- rename widget to doc:example
- rename widget files (wiki_widget.* -> doc_widget.*)
- example section is now optional
2010-11-09 22:27:31 -08:00
Igor Minar effcd340e9 updating watchr-docs.rb 2010-11-09 21:44:51 -08:00
Igor Minar 264f960800 added spec for auto bootstrap with #autobind 2010-11-09 19:58:42 -08:00
Elliott Sprehn 257e97a65f Support substring matching of bindings with repeater(). Closes #123 2010-11-09 13:39:12 -08:00
Misko Hevery c048f0d8e8 Added formatter documentation. 2010-11-09 09:15:29 -08:00
Elliott Sprehn 96e37a0866 Add key/value jQuery methods in a loop. Support 'css' method.
Closes #134
2010-11-09 08:02:49 -08:00
Vojta Jina 5062d32621 Updated parser tests to use jasmine expects
And some formatting as well and a bit of rafactor...
2010-11-09 07:38:03 -08:00
Vojta Jina d458f31711 Updated filters tests to use jasmine expects
And some small formatting...
2010-11-09 07:38:03 -08:00
Igor Minar fc9ce9ec07 make angular.String.toDate consider all time fractions as optional 2010-11-08 22:49:30 -08:00
Igor Minar da17c61444 angular.Date.toString should use toISOString if available 2010-11-08 22:49:30 -08:00
Igor Minar e5c135ac50 Support ISO 8601 extended datetime format troughout angular.
Support ISO 8601 extended format datetime strings (YYYY-MM-DDTHH:mm:ss.SSSZ) as defined
  in EcmaScript 5 throughout angular. This means that the following apis switched from
  YYYY-MM-DDTHH:mm:ssZ to YYYY-MM-DDTHH:mm:ss.SSSZ (note the added millis) when representing dates:
  - angular.Date.toString
  - angular.String.toDate
  - JSON serialization and deserialization (used by json filter, $xhr and $resource)
2010-11-08 22:49:30 -08:00
Igor Minar 1a43f36e23 Add isDate method + fix old code 2010-11-08 22:49:29 -08:00
Igor Minar 1c305dc67a fixing spec description for the date filter 2010-11-08 22:46:41 -08:00
Igor Minar a397645537 date filter should accept ISO 8601 formatted string as input
Closes #125
2010-11-08 22:46:41 -08:00
Igor Minar f077649f48 TzDate should support various UTC methods 2010-11-08 22:46:41 -08:00
Vojta Jina f3ac2cd434 Update AngularSpec tests to use BDD style - jasmine expect 2010-11-07 14:42:04 -08:00
Vojta Jina 7779630989 Added tests for angular.service
- should allow to override a service
- should preserve angular properties on override
- should not preserve non-angular properties on override
2010-11-07 14:42:03 -08:00
Vojta Jina 00ca67e4be Issue #51: Update extensionMap()
If user override existing extension, angular properties ($) will be preserved.

This piece of logic could be refactored into separate method:
Something like we have extend(), addMissingProperties() - I can't find a name
for this method...

Closes #51
2010-11-07 14:42:03 -08:00
Misko Hevery 91b6c5f7ff Added documentation for validators.
BACKWARD INCOMPATIBLE: removed ssn validators, since it is unlikely that most people will need it and if they do, they can added it thorough RegExp
2010-11-07 13:06:55 -08:00
Vojta Jina 5be325a0c1 Refactored toJsonArray(), added isBoolean() function 2010-11-05 21:39:00 -07:00
Vojta Jina b7027b9d87 Updated toJson() to not serialize window/document objects.
The reason to void these to objects is that they cause all sorts
of problems like exceptions being thrown and infinite loops occuring
when we iterate over object properties.
2010-11-05 21:39:00 -07:00
Vojta Jina fe8353bc5e Changed toJson() to not ignore $ properties 2010-11-05 21:39:00 -07:00
Vojta Jina c780030c6e Json - corrected test descriptions and changed to BDD style expect() 2010-11-05 21:39:00 -07:00
Misko Hevery d5e9f38f3d fix error in json parser which did not allow 1.2E10 as number 2010-11-05 16:41:36 -07:00
Misko Hevery dc66687149 added tests for documentation 2010-11-05 15:05:24 -07:00
Misko Hevery 3d6a099d6e changed to showdown from markup. added validator overview 2010-11-05 13:32:37 -07:00
Misko Hevery 8767e766d1 eclipse settings for auto run of docs 2010-11-04 14:25:11 -07:00
Misko Hevery 47066e70e1 added documentation for ng:include and ng:widget and test for doc collector. 2010-11-04 14:24:31 -07:00
Misko Hevery c0d30aedfc added LICENSE to IDEA 2010-11-04 11:07:49 -07:00
Misko Hevery b246d6e2ab rename Index.js to index.js 2010-11-04 11:02:45 -07:00
Igor Minar 3b04b48b7c preparations for the 0.9.3 cold-resistance iteration 2010-11-03 13:09:52 -07:00
Igor Minar 0462422089 cutting the 0.9.2 faunal-mimicry release 2010-11-03 13:06:45 -07:00
Igor Minar bb460d6355 updating release notes 2010-11-03 13:05:12 -07:00
Igor Minar bbb19a4d16 fixing docs scenario runner template 2010-11-03 12:55:17 -07:00
Elliott Sprehn ee5e881b9e Fix JSON serialization breakage in WebKit browsers 2010-11-03 11:47:06 -07:00
Elliott Sprehn 690dfe000b Serialize RegExp to string in JSON. Closes #119. 2010-11-03 11:10:51 -07:00
Igor Minar 91c835dc0e fix dslSpec for IE 2010-11-03 10:41:37 -07:00
Igor Minar dfa8baf59a hide example for angular.filter 2010-11-03 10:02:20 -07:00
Igor Minar a8efd43d25 doc parser should recognize the 'defaults' syntax for params 2010-11-03 09:47:23 -07:00
Igor Minar 96abeb1074 adding watchr-docs.rb 2010-11-03 09:47:22 -07:00
Misko Hevery 5159eb7635 fix the linky filter 2010-11-03 09:47:22 -07:00
Igor Minar 1ba8c2a33a more documentation for filters 2010-11-03 09:47:22 -07:00
Misko Hevery 659af29adb jsdoc parser + generator + viewer + scenario runner
- parse jsdocs from source code
- generate prerendered (markdown + mustache) partials
- generate json
- generate scenario runner for examples in docs
- basic angular doc viewer
2010-11-03 09:47:22 -07:00
Igor Minar 1fe7e3a130 add jsdocs for angular and filter namespaces + all filters 2010-11-03 09:47:21 -07:00
Igor Minar aec3c8478c binding() should return value for input/text area, innerHTML for the rest 2010-11-03 09:47:21 -07:00
Igor Minar 5c887ddb66 adding textarea() DSL for scenario runner 2010-11-03 09:47:21 -07:00
Igor Minar 0bd4a473a7 adding regular expressions support for binding() DSL 2010-11-03 09:44:54 -07:00
Elliott Sprehn dcf76e6816 Provide better sandbox error messages, and disallow running from file:// URLs 2010-11-02 11:27:54 -07:00
Elliott Sprehn 56a3d52f45 Make future names consistent and handle falsy values in jQuery generated methods properly 2010-11-02 11:20:41 -07:00
Elliott Sprehn faa7d81b67 Add browser().reload() to simulate a refresh from a user 2010-11-01 17:24:24 -07:00
Elliott Sprehn 6bb2cd6ee2 Provide browser DSL with location() to expect the iframe URL parts. Also move navigateTo() under the browser DSL. 2010-11-01 15:21:37 -07:00
Vojta Jina 2d61040fb0 Small refactor in $location service
Added new inner method updateLastLocation()
2010-10-31 21:37:54 -07:00
Vojta Jina 99f25050a3 Fixing issue #98 (infinite loop when location hash set empty)
Added tests and fixed the issue.

Closes #98
2010-10-31 21:37:33 -07:00
Misko Hevery ba5f8ee27f fix typo, and change a list to string for more efficient compression. 2010-10-31 15:04:30 -07:00
Elliott Sprehn 9a532002cf Auto generate all the jQuery get/set methods 2010-10-29 12:19:22 -07:00
Elliott Sprehn 5524d2b0fb Check if file exists (not a 404) and that document is accessible and not using file:// URLs in Application 2010-10-29 11:40:56 -07:00
Igor Minar d4839bac32 adding watchr config file watchr.rb 2010-10-29 10:47:51 -07:00
Igor Minar 602369c6a2 creating logs/ and tmp/ dirs 2010-10-29 10:47:06 -07:00
Andres Ornelas 34909520ae add optional label to dsl with selectors to improve test and output readability
e.g.
Before:
   code:   element('.actions ul li a').click();
   output: element .actions ul li a click
After
   code:   element('.actions ul li a', "'Configuration' link").click();
   output: element 'Configuration' link ( .actions ul li a ) click
2010-10-28 15:21:02 -07:00
Elliott Sprehn 92e31b556f Correctly fail tests if no binding matches and add better test cases for failure behavior. 2010-10-27 17:56:44 -07:00
Misko Hevery 62c0e5c460 Fix failing tests for ie, and mark elements as ng-widget, ng-directive, and ng-binding 2010-10-27 15:42:46 -07:00
Igor Minar c67af8a038 rename src/Parser.js to src/parser.js 2010-10-27 15:32:30 -07:00
Elliott Sprehn 2da1de5a6d Revert performance optimization of using setTimeout in SpecRunner every 10 steps. Breaks loading partials 2010-10-27 13:41:31 -07:00
Igor Minar ee8465bf10 updating version.yaml for the 0.9.2 iteration 2010-10-27 07:38:18 -07:00
Misko Hevery 9c6794a044 start new release 0.9.2 faunal-mimicry 2010-10-26 22:48:34 -07:00
Igor Minar 0ffb47bdb6 cutting the 0.9.1 repulsion-field release 2010-10-26 22:18:25 -07:00
Igor Minar ec885489a2 updating CHANGELOG.md for the 0.9.1 release 2010-10-26 22:17:37 -07:00
Igor Minar 01c52e92b1 Adding e2e tests for the PersonalLog app
- added scenario runner
- added scenario specs
- cookie cleaning DSL
- making rmLog independent on ordering in the view
2010-10-26 21:58:00 -07:00
Misko Hevery 943377a091 fix closure compile warnings 2010-10-26 21:06:24 -07:00
Igor Minar 72b7a1c531 adding missing angular-mocksSpec.js file 2010-10-26 16:44:59 -07:00
Misko Hevery 9c0225512c fixes IE related failures, and form submit event handling in ie 2010-10-26 16:33:59 -07:00
Elliott Sprehn 40d7e66f40 Lots of bug fixes in the scenario runner and a bunch of new features.
- By default the runner now creates multiple output formats as it runs. Nodes are created in the DOM with ids: json, xml, and html.

ex. $('#json').html() => json output of the runner
ex. $('#xml').html() => json output of the runner

$result is also an object tree result.

The permitted formats are html,json,xml,object.

If you don't want certain formats you can select specific ones with the new ng:scenario-output attribute on the script tag.

<script src="angular-scenario.js" ng:scenario-output="xml,json">

- Added element(...).count() that returns the number of matching elements for the selector.

- repeater(...).count() now returns 0 if no elements matched which can be used to check if a repeater is empty.

- Added toBe() matcher that does strict equality with ===

- Implement iit and ddescribe. If iit() is used instead of it() then only that test will run. If ddescribe() is used instead of describe() them only it() statements inside of it will run. Several iit/ddescribe() blocks can be used to run isolated tests.

- Implement new event based model for SpecRunner. You can now listen for events in the runner. This is useful for writing your own UI or connecting a remote process (ex. WebDriver). Event callbacks execute on the Runner instance.

Events, if fired, will always be in the below order. All events always happen
except for Failure and Error events which only happen in error conditions.

Events:
  RunnerBegin
  SpecBegin(spec)
  StepBegin(spec, step)
  StepError(spec, step, error)
  StepFailure(spec, step, error)
  StepEnd(spec, step)
  SpecError(spec, step, error)
  SpecEnd(spec)
  RunnerEnd

- Only allow the browser to repaint every 10 steps. Cuts 700ms off Firefox in benchmark, 200ms off Chrome.

- Bug Fix: Manually navigate anchors on click since trigger wont work in Firefox.
2010-10-26 15:17:57 -07:00
Misko Hevery 1d52349440 Reverted change 841013a4c4 which does not work on all browsers 2010-10-26 14:25:01 -07:00
Igor Minar 3eb0c8bc67 Simplify dateGetter() within the date filter. 2010-10-26 13:47:50 -07:00
Igor Minar 42855e4363 Simplify implementation of angular.String.toDate() 2010-10-26 13:47:50 -07:00
Igor Minar 4c61fc01f9 Add TzDate to angular-mocks.js
TzDate is a Date-like type that is independent from the timezone
settings of the machine on which TzDate instances are created.
This property makes it ideal for testing code that deals with
timezones in a manner that makes the code portable between timezones.

Closes #81
2010-10-26 13:47:50 -07:00
Misko Hevery 4fdab37659 create HTML sanitizer to allow inclusion of untrusted HTML in safe manner.
Sanitization works in two phases:
 1) We parse the HTML into sax-like events (start, end, chars).
    HTML parsing is very complex, and so it may very well be that what
    most browser consider valid HTML may not pares properly here,
    but we do best effort. We treat this parser as untrusted.
 2) We have safe sanitizeWriter which treats its input (start, end, chars)
    as untrusted content and escapes everything. It only allows elements
    in the whitelist and only allows attributes which are whitelisted.
    Any attribute value must not start with 'javascript:'. This check
    is performed after escaping for entity (&xAB; etc..) and ignoring
    any whitespace.

 - Correct linky filter to use safeHtmlWriter
 - Correct html filter to use safeHtmlWriter

Close #33; Close #34
2010-10-26 13:41:07 -07:00
Igor Minar 841013a4c4 Add millisecond support for date filter
Date filter should translate input which is a number (or number
string) into a date.
2010-10-25 10:44:03 -07:00
Igor Minar 4e9a2aa10e Revert "added support for treating numbers as date in miliseconds"
This reverts commit 1391f19fb4.
2010-10-23 18:26:47 -07:00
Igor Minar 4fc2141458 improving the PersonalLog app
- adding jsdocs and comments
- logs should be ordered in inverse order
2010-10-23 16:25:53 -07:00
Igor Minar 5b40e87ac6 personalLog demo - initial version with spec 2010-10-23 14:38:08 -07:00
Misko Hevery 1391f19fb4 added support for treating numbers as date in miliseconds 2010-10-23 14:38:08 -07:00
Igor Minar 04a4d8b061 adding ng:submit directive for use with forms
- allows for binding angular expressions to onsubmit events
- prevent default submit action (page reload)
2010-10-23 14:22:54 -07:00
Igor Minar bbd87c9425 simplifying ng:click spec 2010-10-23 14:22:54 -07:00
Elliott Sprehn 64063b5d41 Fix issue where directories don't have a slash on the end and allow specifying a different port 2010-10-23 14:22:54 -07:00
Igor Minar 833e0ae343 $cookieStore should not be a global service
you must use $inject to $inject it as any other non-global service
2010-10-23 14:22:30 -07:00
Misko Hevery d74ef497de Fix for getting into recursive $eval on scope. Close #59
It sort of worked since the browser would throw stack too deep
exception and the angular would then print the error to console.
So as long as you did not have console open you would not notice
this as an error.
2010-10-23 13:42:11 -07:00
Misko Hevery 6ddcf91861 Fix test which was causing the Chrome runner to fail. Upgraded JSTD to latest. Cleanup whitespace. 2010-10-23 13:12:45 -07:00
Misko Hevery 8a867cee22 Workaround for http://bugs.jquery.com/ticket/7292 2010-10-22 22:46:51 -07:00
Misko Hevery 68217d427c Horrible IE + jQuery hack to make the tests pass 2010-10-22 16:40:04 -07:00
Misko Hevery 1efef67b5f corrected buzz.html to use ng:src on images to prevent sporious browser requests/errors 2010-10-22 14:27:03 -07:00
Misko Hevery a6cfa43c19 fixed issue with ie .data() method failing tests 2010-10-22 14:26:18 -07:00
Elliott Sprehn b41bc98c54 Better nodeserver that implements an HTTP server more completely 2010-10-22 00:26:05 +08:00
Misko Hevery aaabeb8c5e fixed more ie test failures 2010-10-20 23:51:49 -07:00
Misko Hevery 05d4971abb fix some of the failing ie tests 2010-10-20 23:17:59 -07:00
Igor Minar c6107fe8ac Rakefile should create the build directory when it is needed and doesn't exist 2010-10-20 17:14:31 -07:00
Igor Minar 68f074c299 adding CHANGELOG.md with 0.9.0 release notes 2010-10-20 17:00:36 -07:00
Igor Minar c53a37ed91 preparing 0.9.1 repulsion-field iteration 2010-10-20 15:52:55 -07:00
663 changed files with 148974 additions and 17088 deletions
+2 -1
View File
@@ -1,6 +1,7 @@
<?xml version="1.0" encoding="UTF-8"?>
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="org.eclipse.ui.externaltools.ProgramBuilderLaunchConfigurationType">
<booleanAttribute key="org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND" value="false"/>
<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_BUILDER_ENABLED" value="true"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_BUILD_SCOPE" value="${working_set:&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&#10;&lt;launchConfigurationWorkingSet editPageId=&quot;org.eclipse.ui.resourceWorkingSetPage&quot; factoryID=&quot;org.eclipse.ui.internal.WorkingSetFactory&quot; id=&quot;1262905463390_2&quot; label=&quot;workingSet&quot; name=&quot;workingSet&quot;&gt;&#10;&lt;item factoryID=&quot;org.eclipse.ui.internal.model.ResourceFactory&quot; path=&quot;/angular.js/test&quot; type=&quot;2&quot;/&gt;&#10;&lt;item factoryID=&quot;org.eclipse.ui.internal.model.ResourceFactory&quot; path=&quot;/angular.js/src&quot; type=&quot;2&quot;/&gt;&#10;&lt;/launchConfigurationWorkingSet&gt;}"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:/angular.js}/test.sh"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_RUN_BUILD_KINDS" value="full,incremental,auto,"/>
+10
View File
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="org.eclipse.ui.externaltools.ProgramBuilderLaunchConfigurationType">
<booleanAttribute key="org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND" value="false"/>
<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_BUILDER_ENABLED" value="false"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_BUILD_SCOPE" value="${working_set:&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&#10;&lt;resources&gt;&#10;&lt;item path=&quot;/angular.js/perf&quot; type=&quot;2&quot;/&gt;&#10;&lt;item path=&quot;/angular.js/src&quot; type=&quot;2&quot;/&gt;&#10;&lt;/resources&gt;}"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:/angular.js/perf.sh}"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_RUN_BUILD_KINDS" value="full,incremental,auto,"/>
<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_TRIGGERS_CONFIGURED" value="true"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:/angular.js}"/>
</launchConfiguration>
+11
View File
@@ -0,0 +1,11 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="org.eclipse.ui.externaltools.ProgramBuilderLaunchConfigurationType">
<stringAttribute key="org.eclipse.debug.core.ATTR_REFRESH_SCOPE" value="${working_set:&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&#10;&lt;resources&gt;&#10;&lt;item path=&quot;/angular.js/build&quot; type=&quot;2&quot;/&gt;&#10;&lt;/resources&gt;}"/>
<booleanAttribute key="org.eclipse.debug.ui.ATTR_LAUNCH_IN_BACKGROUND" value="false"/>
<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_BUILDER_ENABLED" value="true"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_BUILD_SCOPE" value="${working_set:&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&#10;&lt;resources&gt;&#10;&lt;item path=&quot;/angular.js/docs&quot; type=&quot;2&quot;/&gt;&#10;&lt;item path=&quot;/angular.js/src&quot; type=&quot;2&quot;/&gt;&#10;&lt;/resources&gt;}"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:/angular.js/gen_docs.sh}"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_RUN_BUILD_KINDS" value="full,incremental,auto,"/>
<booleanAttribute key="org.eclipse.ui.externaltools.ATTR_TRIGGERS_CONFIGURED" value="true"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:/angular.js}"/>
</launchConfiguration>
+7
View File
@@ -0,0 +1,7 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<launchConfiguration type="org.eclipse.ui.externaltools.ProgramLaunchConfigurationType">
<stringAttribute key="org.eclipse.debug.core.ATTR_REFRESH_SCOPE" value="${working_set:&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot;?&gt;&#10;&lt;resources&gt;&#10;&lt;item path=&quot;/angular.js/docs&quot; type=&quot;2&quot;/&gt;&#10;&lt;/resources&gt;}"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LAUNCH_CONFIGURATION_BUILD_SCOPE" value="${none}"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_LOCATION" value="${workspace_loc:/angular.js/gen_docs.sh}"/>
<stringAttribute key="org.eclipse.ui.externaltools.ATTR_WORKING_DIRECTORY" value="${workspace_loc:/angular.js}"/>
</launchConfiguration>
+12
View File
@@ -1,3 +1,15 @@
build/
angularjs.netrc
jstd.log
.DS_Store
gen_docs.disable
test.disable
regression/temp*.html
performance/temp*.html
.idea/workspace.xml
*~
angular.js.tmproj
node_modules
jsTestDriver*.conf
angular.xcodeproj
.idea
-1
View File
@@ -1 +0,0 @@
workspace.xml
-7
View File
@@ -1,7 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Settings><!--This file was automatically generated by Ruby plugin.
You are allowed to:
1. Remove rake task
2. Add existing rake tasks
To add existing rake tasks automatically delete this file and reload the project.
--><RakeGroup description="" fullCmd="" taksId="rake"><RakeTask description="Compile JavaScript" fullCmd="compile" taksId="compile" /><RakeTask description="Generate Externs" fullCmd="compileexterns" taksId="compileexterns" /><RakeTask description="Lint" fullCmd="lint" taksId="lint" /><RakeGroup description="" fullCmd="" taksId="server"><RakeTask description="Run JsTestDriver Server" fullCmd="server:start" taksId="start" /><RakeTask description="Run JavaScript tests against the server" fullCmd="server:test" taksId="test" /></RakeGroup><RakeTask description="Run JavaScript tests" fullCmd="test" taksId="test" /><RakeTask description="" fullCmd="default" taksId="default" /></RakeGroup></Settings>
-5
View File
@@ -1,5 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="Encoding" useUTFGuessing="true" native2AsciiForPropertiesFiles="false" />
</project>
-9
View File
@@ -1,9 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<module type="RUBY_MODULE" version="4">
<component name="NewModuleRootManager">
<content url="file://$MODULE_DIR$" />
<orderEntry type="inheritedJdk" />
<orderEntry type="sourceFolder" forTests="false" />
</component>
</module>
-14
View File
@@ -1,14 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="DependencyValidationManager">
<option name="SKIP_IMPORT_STATEMENTS" value="false" />
</component>
<component name="ProjectDetails">
<option name="projectName" value="master" />
</component>
<component name="ProjectRootManager" version="2" project-jdk-name="Ruby SDK 1.8.7 (/usr/bin/ruby)" project-jdk-type="RUBY_SDK" />
<component name="SvnBranchConfigurationManager">
<option name="mySupportsUserInfoFilter" value="true" />
</component>
</project>
-9
View File
@@ -1,9 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="ProjectModuleManager">
<modules>
<module fileurl="file://$PROJECT_DIR$/.idea/master.iml" filepath="$PROJECT_DIR$/.idea/master.iml" />
</modules>
</component>
</project>
Generated
-8
View File
@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="VcsDirectoryMappings">
<mapping directory="" vcs="" />
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>
+20
View File
@@ -10,6 +10,16 @@
<arguments>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.ui.externaltools.ExternalToolBuilder</name>
<triggers>auto,full,incremental,</triggers>
<arguments>
<dictionary>
<key>LaunchConfigHandle</key>
<value>&lt;project&gt;/.externalToolBuilders/docs.launch</value>
</dictionary>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.ui.externaltools.ExternalToolBuilder</name>
<triggers>auto,full,incremental,</triggers>
@@ -20,6 +30,16 @@
</dictionary>
</arguments>
</buildCommand>
<buildCommand>
<name>org.eclipse.ui.externaltools.ExternalToolBuilder</name>
<triggers>auto,full,incremental,</triggers>
<arguments>
<dictionary>
<key>LaunchConfigHandle</key>
<value>&lt;project&gt;/.externalToolBuilders/JSTD_perf.launch</value>
</dictionary>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.wst.jsdt.core.jsNature</nature>
+2 -1
View File
@@ -1,9 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<classpath>
<classpathentry excluding="test/" kind="src" path="src"/>
<classpathentry kind="src" path="src/test"/>
<classpathentry excluding="docs-data.js|docs-scenario.js" kind="src" path="docs"/>
<classpathentry excluding="test/" kind="src" path="test"/>
<classpathentry kind="src" path="test/test"/>
<classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.JRE_CONTAINER"/>
<classpathentry kind="con" path="org.eclipse.wst.jsdt.launching.baseBrowserLibrary"/>
<classpathentry kind="output" path=""/>
</classpath>
@@ -0,0 +1,16 @@
#Mon Jan 24 10:31:47 PST 2011
activeContentFilterList=*.makefile,makefile,*.Makefile,Makefile,Makefile.*,*.mk,MANIFEST.MF
addNewLine=true
convertActionOnSaave=AnyEdit.CnvrtTabToSpaces
eclipse.preferences.version=1
inActiveContentFilterList=
javaTabWidthForJava=true
org.eclipse.jdt.ui.editor.tab.width=2
projectPropsEnabled=false
removeTrailingSpaces=true
replaceAllSpaces=false
replaceAllTabs=false
saveAndAddLine=true
saveAndConvert=true
saveAndTrim=true
useModulo4Tabs=false
+1371
View File
File diff suppressed because it is too large Load Diff
+11 -4
View File
@@ -1,5 +1,10 @@
Angular
======
AngularJS
=========
* Web site: http://angularjs.org
* Tutorial: http://docs.angularjs.org/#!/tutorial
* API Docs: http://docs.angularjs.org
* Developer Guide: http://docs.angularjs.org/#!/guide
Compiling
---------
@@ -7,6 +12,8 @@ Compiling
Running Tests
-------------
rake server:start
rake test
./server.sh # start the server
open http://localhost:9876/capture # capture browser
./test.sh # run all unit tests
+193 -107
View File
@@ -1,44 +1,30 @@
require 'yaml'
include FileUtils
ANGULAR = [
'src/Angular.js',
'src/JSON.js',
'src/Compiler.js',
'src/Scope.js',
'src/Injector.js',
'src/Parser.js',
'src/Resource.js',
'src/Browser.js',
'src/jqLite.js',
'src/apis.js',
'src/filters.js',
'src/formatters.js',
'src/validators.js',
'src/services.js',
'src/directives.js',
'src/markups.js',
'src/widgets.js',
'src/AngularPublic.js',
]
ANGULAR_SCENARIO = [
'src/scenario/Scenario.js',
'src/scenario/Application.js',
'src/scenario/Describe.js',
'src/scenario/Future.js',
'src/scenario/HtmlUI.js',
'src/scenario/Describe.js',
'src/scenario/Runner.js',
'src/scenario/SpecRunner.js',
'src/scenario/dsl.js',
'src/scenario/matchers.js',
]
content = File.open('angularFiles.js', 'r') {|f| f.read }
files = eval(content.gsub(/\};(\s|\S)*/, '}').gsub(/angularFiles = /, '').gsub(/:/, '=>'));
BUILD_DIR = 'build'
task :default => [:compile, :test]
desc 'Init the build workspace'
task :init do
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).
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'])
end
desc 'Clean Generated Files'
task :clean do
FileUtils.rm_r(BUILD_DIR, :force => true)
@@ -47,131 +33,231 @@ end
desc 'Compile Scenario'
task :compile_scenario do
task :compile_scenario => :init do
deps = [
'lib/jquery/jquery-1.4.2.js',
'lib/jquery/jquery.js',
'src/scenario/angular.prefix',
ANGULAR,
ANGULAR_SCENARIO,
files['angularSrc'],
files['angularScenario'],
'src/scenario/angular.suffix',
]
concat = 'cat ' + deps.flatten.join(' ')
File.open(path_to('angular-scenario.js'), 'w') do |f|
f.write(%x{#{concat}})
f.write(%x{#{concat}}.gsub('"NG_VERSION_FULL"', NG_VERSION.full))
f.write(gen_css('css/angular.css') + "\n")
f.write(gen_css('css/angular-scenario.css'))
end
end
desc 'Compile JSTD Scenario Adapter'
task :compile_jstd_scenario_adapter => :init do
deps = [
'src/jstd-scenario-adapter/angular.prefix',
'src/jstd-scenario-adapter/Adapter.js',
'src/jstd-scenario-adapter/angular.suffix',
]
concat = 'cat ' + deps.flatten.join(' ')
File.open(path_to('jstd-scenario-adapter.js'), 'w') do |f|
f.write(%x{#{concat}}.gsub('"NG_VERSION_FULL"', NG_VERSION.full))
end
desc 'Generate IE css js patch'
task :generate_ie_compat do
css = File.open('css/angular.css', 'r') {|f| f.read }
# finds all css rules that contain backround images and extracts the rule name(s), content type of
# the image and base64 encoded image data
r = /\n([^\{\n]+)\s*\{[^\}]*background-image:\s*url\("data:([^;]+);base64,([^"]+)"\);[^\}]*\}/
images = css.scan(r)
# create a js file with multipart header containing the extracted images. the entire file *must*
# be CRLF (\r\n) delimited
File.open(path_to('angular-ie-compat.js'), 'w') do |f|
f.write("/*\r\n" +
"Content-Type: multipart/related; boundary=\"_\"\r\n" +
"\r\n")
images.each_index do |idx|
f.write("--_\r\n" +
"Content-Location:img#{idx}\r\n" +
"Content-Transfer-Encoding:base64\r\n" +
"\r\n" +
images[idx][2] + "\r\n")
end
f.write("--_--\r\n" +
"*/\r\n")
# generate a css string containing *background-image rules for IE that point to the mime type
# images in the header
cssString = ''
images.each_index do |idx|
cssString += "#{images[idx][0]}{*background-image:url(\"mhtml:' + jsUri + '!img#{idx}\")}"
end
# generate a javascript closure that contains a function which will append the generated css
# string as a stylesheet to the current html document
jsString = "(function(){ \r\n" +
" var jsUri = document.location.href.replace(/\\/[^\/]+(#.*)?$/, '/') + " +
" document.getElementById('ng-ie-compat').src; \r\n" +
" var css = '#{cssString}' \r\n" +
" var s = document.createElement('style'); \r\n" +
" s.setAttribute('type', 'text/css'); \r\n" +
" if (s.styleSheet) { \r\n" +
" s.styleSheet.cssText = css; \r\n" +
" } else { \r\n" +
" s.appendChild(document.createTextNode(css)); \r\n" +
" } \r\n" +
" document.getElementsByTagName('head')[0].appendChild(s); \r\n" +
"})();\r\n"
f.write(jsString)
# 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 'Compile JavaScript'
task :compile => [:compile_scenario, :generate_ie_compat] do
task :compile => [:init, :compile_scenario, :compile_jstd_scenario_adapter] do
deps = [
'src/angular.prefix',
ANGULAR,
files['angularSrc'],
'src/angular.suffix',
]
File.open(path_to('angular.js'), 'w') do |f|
concat = 'cat ' + deps.flatten.join(' ')
f.write(%x{#{concat}})
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
gsub(/'USE STRICT'/, "'use strict'") # rename the placeholder in angular.prefix
f.write(content)
f.write(gen_css('css/angular.css', true))
end
%x(java -jar lib/compiler-closure/compiler.jar \
%x(java -jar lib/closure-compiler/compiler.jar \
--compilation_level SIMPLE_OPTIMIZATIONS \
--language_in ECMASCRIPT5_STRICT \
--js #{path_to('angular.js')} \
--js_output_file #{path_to('angular.min.js')})
FileUtils.cp_r 'i18n/locale', path_to('i18n')
File.open(path_to('angular-loader.js'), 'w') do |f|
concat = 'cat ' + [
'src/loader.prefix',
'src/loader.js',
'src/loader.suffix'].flatten.join(' ')
content = %x{#{concat}}.
gsub('"NG_VERSION_FULL"', NG_VERSION.full).
gsub(/^\s*['"]use strict['"];?\s*$/, '') # remove all file-specific strict mode flags
f.write(content)
end
%x(java -jar lib/closure-compiler/compiler.jar \
--compilation_level SIMPLE_OPTIMIZATIONS \
--language_in ECMASCRIPT5_STRICT \
--js #{path_to('angular-loader.js')} \
--js_output_file #{path_to('angular-loader.min.js')})
end
desc 'Generate docs'
task :docs => [:init] do
`node docs/src/gen-docs.js`
File.open(path_to('docs/.htaccess'), File::RDWR) do |f|
text = f.read
f.truncate 0
f.rewind
f.write text.sub('"NG_VERSION_FULL"', NG_VERSION.full)
end
end
desc 'Create angular distribution'
task :package => :compile do
v = YAML::load( File.open( 'version.yaml' ) )['version']
match = v.match(/^([^-]*)(-snapshot)?$/)
version = match[1] + (match[2] ? ('-' + %x(git rev-parse HEAD)[0..7]) : '')
task :package => [:clean, :compile, :docs] do
tarball = "angular-#{NG_VERSION.full}.tgz"
tarball = "angular-#{version}.tgz"
pkg_dir = path_to("pkg/angular-#{version}")
pkg_dir = path_to("pkg/angular-#{NG_VERSION.full}")
FileUtils.rm_r(path_to('pkg'), :force => true)
FileUtils.mkdir_p(pkg_dir)
['test/angular-mocks.js',
['src/angular-mocks.js',
path_to('angular.js'),
path_to('angular-loader.js'),
path_to('angular.min.js'),
path_to('angular-ie-compat.js'),
path_to('angular-scenario.js')
path_to('angular-loader.min.js'),
path_to('angular-scenario.js'),
path_to('jstd-scenario-adapter.js'),
path_to('jstd-scenario-adapter-config.js'),
].each do |src|
dest = src.gsub(/^[^\/]+\//, '').gsub(/((\.min)?\.js)$/, "-#{version}\\1")
dest = src.gsub(/^[^\/]+\//, '').gsub(/((\.min)?\.js)$/, "-#{NG_VERSION.full}\\1")
FileUtils.cp(src, pkg_dir + '/' + dest)
end
FileUtils.cp_r path_to('i18n'), "#{pkg_dir}/i18n-#{NG_VERSION.full}"
FileUtils.cp_r path_to('docs'), "#{pkg_dir}/docs-#{NG_VERSION.full}"
File.open("#{pkg_dir}/angular-mocks-#{NG_VERSION.full}.js", File::RDWR) do |f|
text = f.read
f.truncate 0
f.rewind
f.write text.sub('"NG_VERSION_FULL"', NG_VERSION.full)
end
File.open("#{pkg_dir}/docs-#{NG_VERSION.full}/index.html", File::RDWR) do |f|
text = f.read
f.truncate 0
f.rewind
f.write text.sub('angular.min.js', "angular-#{NG_VERSION.full}.min.js").
sub('/build/docs/', "/#{NG_VERSION.full}/docs-#{NG_VERSION.full}/")
end
File.open("#{pkg_dir}/docs-#{NG_VERSION.full}/index-jq.html", File::RDWR) do |f|
text = f.read
f.truncate 0
f.rewind
f.write text.sub('angular.min.js', "angular-#{NG_VERSION.full}.min.js").
sub('/build/docs/', "/#{NG_VERSION.full}/docs-#{NG_VERSION.full}/")
end
File.open("#{pkg_dir}/docs-#{NG_VERSION.full}/index-nocache.html", File::RDWR) do |f|
text = f.read
f.truncate 0
f.rewind
f.write text.sub('angular.min.js', "angular-#{NG_VERSION.full}.min.js").
sub('/build/docs/', "/#{NG_VERSION.full}/docs-#{NG_VERSION.full}/")
end
File.open("#{pkg_dir}/docs-#{NG_VERSION.full}/index-jq-nocache.html", File::RDWR) do |f|
text = f.read
f.truncate 0
f.rewind
f.write text.sub('angular.min.js', "angular-#{NG_VERSION.full}.min.js").
sub('/build/docs/', "/#{NG_VERSION.full}/docs-#{NG_VERSION.full}/")
end
File.open("#{pkg_dir}/docs-#{NG_VERSION.full}/index-debug.html", File::RDWR) do |f|
text = f.read
f.truncate 0
f.rewind
f.write text.sub('../angular.js', "../angular-#{NG_VERSION.full}.js").
sub('/build/docs/', "/#{NG_VERSION.full}/docs-#{NG_VERSION.full}/")
end
File.open("#{pkg_dir}/docs-#{NG_VERSION.full}/index-jq-debug.html", File::RDWR) do |f|
text = f.read
f.truncate 0
f.rewind
f.write text.sub('../angular.js', "../angular-#{NG_VERSION.full}.js").
sub('/build/docs/', "/#{NG_VERSION.full}/docs-#{NG_VERSION.full}/")
end
File.open("#{pkg_dir}/docs-#{NG_VERSION.full}/docs-scenario.html", File::RDWR) do |f|
text = f.read
f.truncate 0
f.rewind
f.write text.sub('angular-scenario.js', "angular-scenario-#{NG_VERSION.full}.js")
end
File.open("#{pkg_dir}/docs-#{NG_VERSION.full}/appcache.manifest", File::RDWR) do |f|
text = f.read
f.truncate 0
f.rewind
f.write text.sub('angular.min.js', "angular-#{NG_VERSION.full}.min.js").
sub('/build/docs/', "/#{NG_VERSION.full}/docs-#{NG_VERSION.full}/")
end
File.open("#{pkg_dir}/docs-#{NG_VERSION.full}/appcache-offline.manifest", File::RDWR) do |f|
text = f.read
f.truncate 0
f.rewind
f.write text.sub('angular.min.js', "angular-#{NG_VERSION.full}.min.js").
sub('/build/docs/', "/#{NG_VERSION.full}/docs-#{NG_VERSION.full}/")
end
%x(tar -czf #{path_to(tarball)} -C #{path_to('pkg')} .)
FileUtils.cp path_to(tarball), pkg_dir
FileUtils.mv pkg_dir, path_to(['pkg', NG_VERSION.full])
puts "Package created: #{path_to(tarball)}"
end
@@ -240,7 +326,7 @@ def gen_css(cssFile, minify = false)
css.gsub! /'/, "\\\\'"
css.gsub! /\n/, "\\n"
return %Q{document.write('<style type="text/css">#{css}</style>');}
return %Q{angular.element(document).find('head').append('<style type="text/css">#{css}</style>');}
end
@@ -248,5 +334,5 @@ end
# returns path to the file in the build directory
#
def path_to(filename)
return File.join(BUILD_DIR, filename)
return File.join(BUILD_DIR, *filename)
end
+191
View File
@@ -0,0 +1,191 @@
angularFiles = {
'angularSrc': [
'src/Angular.js',
'src/loader.js',
'src/AngularPublic.js',
'src/JSON.js',
'src/Injector.js',
'src/Resource.js',
'src/jqLite.js',
'src/apis.js',
'src/service/anchorScroll.js',
'src/service/browser.js',
'src/service/cacheFactory.js',
'src/service/compiler.js',
'src/service/controller.js',
'src/service/cookieStore.js',
'src/service/cookies.js',
'src/service/defer.js',
'src/service/document.js',
'src/service/exceptionHandler.js',
'src/service/filter.js',
'src/service/filter/filter.js',
'src/service/filter/filters.js',
'src/service/filter/limitTo.js',
'src/service/filter/orderBy.js',
'src/service/interpolate.js',
'src/service/location.js',
'src/service/log.js',
'src/service/resource.js',
'src/service/parse.js',
'src/service/q.js',
'src/service/route.js',
'src/service/routeParams.js',
'src/service/scope.js',
'src/service/sanitize.js',
'src/service/sniffer.js',
'src/service/window.js',
'src/service/http.js',
'src/service/httpBackend.js',
'src/service/locale.js',
'src/directive/directives.js',
'src/directive/a.js',
'src/directive/booleanAttrDirs.js',
'src/directive/form.js',
'src/directive/input.js',
'src/directive/ngBind.js',
'src/directive/ngClass.js',
'src/directive/ngCloak.js',
'src/directive/ngController.js',
'src/directive/ngEventDirs.js',
'src/directive/ngInclude.js',
'src/directive/ngInit.js',
'src/directive/ngNonBindable.js',
'src/directive/ngPluralize.js',
'src/directive/ngRepeat.js',
'src/directive/ngShowHide.js',
'src/directive/ngStyle.js',
'src/directive/ngSwitch.js',
'src/directive/ngTransclude.js',
'src/directive/ngView.js',
'src/directive/script.js',
'src/directive/select.js',
'src/directive/style.js'
],
'angularScenario': [
'src/scenario/Scenario.js',
'src/scenario/Application.js',
'src/scenario/Describe.js',
'src/scenario/Future.js',
'src/scenario/ObjectModel.js',
'src/scenario/Describe.js',
'src/scenario/Runner.js',
'src/scenario/SpecRunner.js',
'src/scenario/dsl.js',
'src/scenario/matchers.js',
'src/scenario/output/Html.js',
'src/scenario/output/Json.js',
'src/scenario/output/Xml.js',
'src/scenario/output/Object.js'
],
'jstd': [
'lib/jasmine/jasmine.js',
'lib/jasmine-jstd-adapter/JasmineAdapter.js',
'lib/jquery/jquery.js',
'test/jquery_remove.js',
'@angularSrc',
'example/personalLog/*.js',
'test/testabilityPatch.js',
'test/matchers.js',
'src/scenario/Scenario.js',
'src/scenario/output/*.js',
'src/jstd-scenario-adapter/*.js',
'src/scenario/*.js',
'src/angular-mocks.js',
'test/scenario/*.js',
'test/scenario/output/*.js',
'test/jstd-scenario-adapter/*.js',
'test/*.js',
'test/service/*.js',
'test/service/filter/*.js',
'test/directive/*.js',
'example/personalLog/test/*.js'
],
'jstdExclude': [
'test/jquery_alias.js',
'src/angular-bootstrap.js',
'src/scenario/angular-bootstrap.js'
],
'jstdScenario': [
'build/angular-scenario.js',
'build/jstd-scenario-adapter-config.js',
'build/jstd-scenario-adapter.js',
'build/docs/docs-scenario.js'
],
'jstdMocks': [
'lib/jasmine/jasmine.js',
'lib/jasmine-jstd-adapter/JasmineAdapter.js',
'build/angular.js',
'src/angular-mocks.js',
'test/matchers.js',
'test/angular-mocksSpec.js'
],
'jstdPerf': [
'lib/jasmine/jasmine.js',
'lib/jasmine-jstd-adapter/JasmineAdapter.js',
'angularSrc',
'src/angular-mocks.js',
'perf/data/*.js',
'perf/testUtils.js',
'perf/*.js'
],
'jstdPerfExclude': [
'src/angular-bootstrap.js',
'src/scenario/angular-bootstrap.js'
],
'jstdJquery': [
'lib/jasmine/jasmine.js',
'lib/jasmine-jstd-adapter/JasmineAdapter.js',
'lib/jquery/jquery.js',
'test/jquery_alias.js',
'@angularSrc',
'example/personalLog/*.js',
'test/testabilityPatch.js',
'test/matchers.js',
'src/scenario/Scenario.js',
'src/scenario/output/*.js',
'src/jstd-scenario-adapter/*.js',
'src/scenario/*.js',
'src/angular-mocks.js',
'test/scenario/*.js',
'test/scenario/output/*.js',
'test/jstd-scenario-adapter/*.js',
'test/*.js',
'test/service/*.js',
'test/directive/*.js',
'example/personalLog/test/*.js'
],
'jstdJqueryExclude': [
'src/angular-bootstrap.js',
'src/scenario/angular-bootstrap.js',
'test/jquery_remove.js'
]
};
// Execute only in slim-jim
if (typeof JASMINE_ADAPTER !== 'undefined') {
// SlimJim config
files = [JASMINE, JASMINE_ADAPTER];
angularFiles.jstd.forEach(function(pattern) {
// replace angular source
if (pattern === '@angularSrc') files = files.concat(angularFiles.angularSrc);
// ignore jstd and jasmine files
else if (!/jstd|jasmine/.test(pattern)) files.push(pattern);
});
exclude = angularFiles.jstdExclude;
autoWatch = true;
autoWatchInterval = 1;
logLevel = LOG_INFO;
logColors = true;
}
+21 -8
View File
@@ -8,6 +8,15 @@ body {
font-size: 14px;
}
#system-error {
font-size: 1.5em;
text-align: center;
}
#json, #xml {
display: none;
}
#header {
position: fixed;
width: 100%;
@@ -32,7 +41,7 @@ body {
height: 30px;
}
#frame h2,
#application h2,
#specs h2 {
margin: 0;
padding: 0.5em;
@@ -45,26 +54,26 @@ body {
}
#header,
#frame,
#application,
.test-info,
.test-actions li {
overflow: hidden;
}
#frame {
#application {
margin: 10px;
}
#frame iframe {
#application iframe {
width: 100%;
height: 758px;
}
#frame .popout {
#application .popout {
float: right;
}
#frame iframe {
#application iframe {
border: none;
}
@@ -154,6 +163,10 @@ body {
margin-left: 6em;
}
.test-describe {
padding-bottom: 0.5em;
}
.test-describe .test-describe {
margin: 5px 5px 10px 2em;
}
@@ -178,11 +191,11 @@ body {
}
#specs h2,
#frame h2 {
#application h2 {
background-color: #efefef;
}
#frame {
#application {
border: 1px solid #BABAD1;
}
+5 -81
View File
@@ -1,86 +1,10 @@
@charset "UTF-8";
.ng-format-negative {
color: red;
[ng\:cloak], [ng-cloak], [data-ng-cloak], [x-ng-cloak],
.ng-cloak, .x-ng-cloak {
display: none;
}
.ng-exception {
border: 2px solid #FF0000;
font-family: "Courier New", Courier, monospace;
font-size: smaller;
}
.ng-validation-error {
border: 2px solid #FF0000;
}
/*****************
* TIP
*****************/
#ng-callout {
margin: 0;
padding: 0;
border: 0;
outline: 0;
font-size: 13px;
font-weight: normal;
font-family: Verdana, Arial, Helvetica, sans-serif;
vertical-align: baseline;
background: transparent;
text-decoration: none;
}
#ng-callout .ng-arrow-left{
background-image: url("data:image/gif;base64,R0lGODlhCwAXAKIAAMzMzO/v7/f39////////wAAAAAAAAAAACH5BAUUAAQALAAAAAALABcAAAMrSLoc/AG8FeUUIN+sGebWAnbKSJodqqlsOxJtqYooU9vvk+vcJIcTkg+QAAA7");
background-repeat: no-repeat;
background-position: left top;
position: absolute;
z-index:101;
left:-12px;
height:23px;
width:10px;
top:-3px;
}
#ng-callout .ng-arrow-right{
background-image: url("data:image/gif;base64,R0lGODlhCwAXAKIAAMzMzO/v7/f39////////wAAAAAAAAAAACH5BAUUAAQALAAAAAALABcAAAMrCLTcoM29yN6k9socs91e5X3EyJloipYrO4ohTMqA0Fn2XVNswJe+H+SXAAA7");
background-repeat: no-repeat;
background-position: left top;
position: absolute;
z-index:101;
height:23px;
width:11px;
top:-2px;
}
#ng-callout {
position: absolute;
z-index:100;
border: 2px solid #CCCCCC;
background-color: #fff;
}
#ng-callout .ng-content{
padding:10px 10px 10px 10px;
color:#333333;
}
#ng-callout .ng-title{
background-color: #CCCCCC;
text-align: left;
padding-left: 8px;
padding-bottom: 5px;
padding-top: 2px;
font-weight:bold;
}
/*****************
* indicators
*****************/
.ng-input-indicator-wait {
background-image: url("data:image/png;base64,R0lGODlhEAAQAPQAAP///wAAAPDw8IqKiuDg4EZGRnp6egAAAFhYWCQkJKysrL6+vhQUFJycnAQEBDY2NmhoaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH/C05FVFNDQVBFMi4wAwEAAAAh/hpDcmVhdGVkIHdpdGggYWpheGxvYWQuaW5mbwAh+QQJCgAAACwAAAAAEAAQAAAFdyAgAgIJIeWoAkRCCMdBkKtIHIngyMKsErPBYbADpkSCwhDmQCBethRB6Vj4kFCkQPG4IlWDgrNRIwnO4UKBXDufzQvDMaoSDBgFb886MiQadgNABAokfCwzBA8LCg0Egl8jAggGAA1kBIA1BAYzlyILczULC2UhACH5BAkKAAAALAAAAAAQABAAAAV2ICACAmlAZTmOREEIyUEQjLKKxPHADhEvqxlgcGgkGI1DYSVAIAWMx+lwSKkICJ0QsHi9RgKBwnVTiRQQgwF4I4UFDQQEwi6/3YSGWRRmjhEETAJfIgMFCnAKM0KDV4EEEAQLiF18TAYNXDaSe3x6mjidN1s3IQAh+QQJCgAAACwAAAAAEAAQAAAFeCAgAgLZDGU5jgRECEUiCI+yioSDwDJyLKsXoHFQxBSHAoAAFBhqtMJg8DgQBgfrEsJAEAg4YhZIEiwgKtHiMBgtpg3wbUZXGO7kOb1MUKRFMysCChAoggJCIg0GC2aNe4gqQldfL4l/Ag1AXySJgn5LcoE3QXI3IQAh+QQJCgAAACwAAAAAEAAQAAAFdiAgAgLZNGU5joQhCEjxIssqEo8bC9BRjy9Ag7GILQ4QEoE0gBAEBcOpcBA0DoxSK/e8LRIHn+i1cK0IyKdg0VAoljYIg+GgnRrwVS/8IAkICyosBIQpBAMoKy9dImxPhS+GKkFrkX+TigtLlIyKXUF+NjagNiEAIfkECQoAAAAsAAAAABAAEAAABWwgIAICaRhlOY4EIgjH8R7LKhKHGwsMvb4AAy3WODBIBBKCsYA9TjuhDNDKEVSERezQEL0WrhXucRUQGuik7bFlngzqVW9LMl9XWvLdjFaJtDFqZ1cEZUB0dUgvL3dgP4WJZn4jkomWNpSTIyEAIfkECQoAAAAsAAAAABAAEAAABX4gIAICuSxlOY6CIgiD8RrEKgqGOwxwUrMlAoSwIzAGpJpgoSDAGifDY5kopBYDlEpAQBwevxfBtRIUGi8xwWkDNBCIwmC9Vq0aiQQDQuK+VgQPDXV9hCJjBwcFYU5pLwwHXQcMKSmNLQcIAExlbH8JBwttaX0ABAcNbWVbKyEAIfkECQoAAAAsAAAAABAAEAAABXkgIAICSRBlOY7CIghN8zbEKsKoIjdFzZaEgUBHKChMJtRwcWpAWoWnifm6ESAMhO8lQK0EEAV3rFopIBCEcGwDKAqPh4HUrY4ICHH1dSoTFgcHUiZjBhAJB2AHDykpKAwHAwdzf19KkASIPl9cDgcnDkdtNwiMJCshACH5BAkKAAAALAAAAAAQABAAAAV3ICACAkkQZTmOAiosiyAoxCq+KPxCNVsSMRgBsiClWrLTSWFoIQZHl6pleBh6suxKMIhlvzbAwkBWfFWrBQTxNLq2RG2yhSUkDs2b63AYDAoJXAcFRwADeAkJDX0AQCsEfAQMDAIPBz0rCgcxky0JRWE1AmwpKyEAIfkECQoAAAAsAAAAABAAEAAABXkgIAICKZzkqJ4nQZxLqZKv4NqNLKK2/Q4Ek4lFXChsg5ypJjs1II3gEDUSRInEGYAw6B6zM4JhrDAtEosVkLUtHA7RHaHAGJQEjsODcEg0FBAFVgkQJQ1pAwcDDw8KcFtSInwJAowCCA6RIwqZAgkPNgVpWndjdyohACH5BAkKAAAALAAAAAAQABAAAAV5ICACAimc5KieLEuUKvm2xAKLqDCfC2GaO9eL0LABWTiBYmA06W6kHgvCqEJiAIJiu3gcvgUsscHUERm+kaCxyxa+zRPk0SgJEgfIvbAdIAQLCAYlCj4DBw0IBQsMCjIqBAcPAooCBg9pKgsJLwUFOhCZKyQDA3YqIQAh+QQJCgAAACwAAAAAEAAQAAAFdSAgAgIpnOSonmxbqiThCrJKEHFbo8JxDDOZYFFb+A41E4H4OhkOipXwBElYITDAckFEOBgMQ3arkMkUBdxIUGZpEb7kaQBRlASPg0FQQHAbEEMGDSVEAA1QBhAED1E0NgwFAooCDWljaQIQCE5qMHcNhCkjIQAh+QQJCgAAACwAAAAAEAAQAAAFeSAgAgIpnOSoLgxxvqgKLEcCC65KEAByKK8cSpA4DAiHQ/DkKhGKh4ZCtCyZGo6F6iYYPAqFgYy02xkSaLEMV34tELyRYNEsCQyHlvWkGCzsPgMCEAY7Cg04Uk48LAsDhRA8MVQPEF0GAgqYYwSRlycNcWskCkApIyEAOwAAAAAAAAAAAA==");
background-position: right;
background-repeat: no-repeat;
ng\:form {
display: block;
}
@@ -0,0 +1,719 @@
@ngdoc overview
@name angular.module.ng.$compileProvider.directive
@description
Directives are a way to teach HTML new tricks. During DOM compilation directives are matched
against the HTML and executed. This allows directives to register behavior, or transform the DOM.
Angular comes with a built in set of directives which are useful for building web applications but
can be extended such that HTML can be turned into a declarative domain specific language (DSL).
# Invoking directives from HTML
Directives have camel cased names such as 'ngBind'. The directive can be invoked by translating
the camel case name into snake case with these special characters `:`, `-`, or `_`. Optionally the
directive can be prefixed with `x-`, or `data-` to make it HTML validator compliant. Here is a
list of some of the possible directive names: `ng:bind`, `ng-bind`, `ng_bind`, `x-ng-bind` and
`data-ng-bind`.
The directives can be placed in element names, attributes, class names, as well as comments. Here
are some equivalent examples of invoking `myDir`. (However, most directives are restricted to
attribute only.)
<pre>
<span my-dir="exp"></span>
<span class="my-dir: exp;"></span>
<my-dir></my-dir>
<!-- directive: my-dir exp -->
</pre>
Directives can be invoked in many different ways, but are equivalent in the end result as shown in
the following example.
<doc:example>
<doc:source >
<script>
function Ctrl1($scope) {
$scope.name = 'angular';
}
</script>
<div ng-controller="Ctrl1">
Hello <input ng-model='name' ng-model-instant> <hr/>
&ltspan ng:bind="name"&gt <span ng:bind="name"></span> <br/>
&ltspan ng_bind="name"&gt <span ng_bind="name"></span> <br/>
&ltspan ng-bind="name"&gt <span ng-bind="name"></span> <br/>
&ltspan data-ng-bind="name"&gt <span data-ng-bind="name"></span> <br/>
&ltspan x-ng-bind="name"&gt <span x-ng-bind="name"></span> <br/>
</div>
</doc:source>
<doc:scenario>
it('should load template1.html', function() {
expect(element('div[ng-controller="Ctrl1"] span[ng-bind]').text()).toBe('angular');
});
</doc:scenario>
</doc:example>
# String interpolation
During the compilation process the {@link angular.module.ng.$compile compiler} matches text and
attributes using the {@link angular.module.ng.$interpolate $interpolate} service to see if they
contain embedded expressions. These expressions are registered as {@link
angular.module.ng.$rootScope.Scope#$watch watches} and will update as part of normal {@link
angular.module.ng.$rootScope.Scope#$digest digest} cycle. An example of interpolation is shown
here:
<pre>
<img src="img/{{username}}.jpg">Hello {{username}}!</img>
</pre>
# Compilation process, and directive matching
Compilation of HTML happens in three phases:
1. First the HTML is parsed into DOM using the standard browser API. This is important to
realize because the templates must be parsable HTML. This is in contrast to most templating
systems that operate on strings, rather then on DOM elements.
2. The compilation of the DOM is performed by the call to {@link angular.module.ng.$compile
$compile()} method. The method traverses the DOM and matches the directives. If a match is found
it is added to the list of directives associated with the given DOM element. Once all directives
for a given DOM element have been identified they are sorted by priority and their `compile()`
functions are executed. The directive compile function has a chance to modify the DOM structure
and is responsible for producing a `link()` function explained next. The {@link
angular.module.ng.$compile $compile()} method returns a combined linking function, which is a
collection of all of the linking functions returned from the individual directive compile
functions.
3. Link the template with scope by calling the liking function returned from the previous step.
This in turn will call the linking function of the individual directives allowing them to
register any listeners on the elements and set up any {@link
angular.module.ng.$rootScope.Scope#$watch watches} with the {@link
angular.module.ng.$rootScope.Scope scope}. The result of this is a live binding between the
scope and the DOM. A change in the scope is reflected in the DOM.
<pre>
var $compile = ...; // injected into your code
var scope = ...;
var html = '<div ng-bind='exp'></div>';
// Step 1: parse HTML into DOM element
var template = angular.element(html);
// Step 2: compile the template
var linkFn = $compile(template);
// Step 3: link the compiled template with the scope.
linkFn(scope);
</pre>
## Reasons behind the compile/link separation
At this point you may wonder why is the compile process broken down to a compile and link phase.
To understand this, lets look at a real world example with repeater:
<pre>
Hello {{user}}, you have these actions:
<ul>
<li ng-repeat="action in user.actions">
{{action.description}}
</li>
</ul>
</pre>
The short answer is that compile and link separation is needed any time a change in model causes
a change in DOM structure such as in repeaters.
When the above example is compiled, the compiler visits every node and looks for directives. The
`{{user}}` is an example of {@link angular.module.ng.$interpolate interpolation} directive. {@link
angular.module.ng.$compileProvider.directive.ng-repeat ng-repeat} is another directive. But {@link
angular.module.ng.$compileProvider.directive.ng-repeat ng-repeat} has a dilemma. It needs to be
able to quickly stamp out new `li`s for every `action` in `user.actions`. This means that it needs
to save a clean copy of the `li` element for cloning purposes and as new `action`s are inserted,
the template `li` element needs to be cloned and inserted into `ul`. But cloning the `li` element
is not enough. It also needs to compile the `li` so that its directives such as
`{{action.descriptions}}` evaluate against the right {@link angular.module.ng.$rootScope.Scope
scope}. A naive method would be to simply insert a copy of the `li` elemnt and then compile it.
But compiling on every `li` element clone would be slow, since the compilation requires that we
traverse the DOM tree and look for directives and execute them. If we put the compilation inside a
repeater which needs to unroll 100 items we would quickly run into performance problem.
The solution is to break the compilation process into two phases the compile phase where all of
the directives are identified and sorted by priority, and a linking phase where any work which
links a specific instance of the {@link angular.module.ng.$rootScope.Scope scope} and the specific
instance of an `li` is performed.
{@link angular.module.ng.$compileProvider.directive.ng-repeat ng-repeat} works by preventing the
compilation process form descending into `li` element. Instead the {@link
angular.module.ng.$compileProvider.directive.ng-repeat ng-repeat} directive compiles `li`
seperatly. The result of of the `li` element compilation is a linking function which contains all
of the directives contained in the `li` element ready to be attached to a specific clone of `li`
element. At runtime the {@link angular.module.ng.$compileProvider.directive.ng-repeat ng-repeat}
watches the expression and as items are added to the array it clones the `li` element, creates a
new {@link angular.module.ng.$rootScope.Scope scope} for the cloned `li` element and calls the
link function on the cloned `li`.
Summary:
* *compile function* - The compile function is relatively rare in directives, since most
directives are concerned with working with a specific DOM element instance rather then
transforming the template DOM element. Any operation which can be shared among the instance of
directives should be moved to the compile function for performance reasons.
* *link function* - It is rare for the directive not to have a link function. Link function
allows the directive to register listeners to the specific cloned DOM element instance as well
as to copy content into the DOM from the scope.
# Writing directives (short version)
In this example we will build a directive which displays the current time.
<doc:example module="time">
<doc:source>
<script>
function Ctrl2($scope) {
$scope.format = 'M/d/yy h:mm:ss a';
}
angular.module('time', [])
// Register the 'myCurrentTime' directive factory method.
// We inject $defer and dateFilter service since the factory method is DI.
.directive('myCurrentTime', function($defer, dateFilter) {
// return the directive link function. (compile function not needed)
return function(scope, element, attrs) {
var format, // date format
deferId; // deferId, so that we can cancel the time updates
// used to update the UI
function updateTime() {
element.text(dateFilter(new Date(), format));
}
// watch the expression, and update the UI on change.
scope.$watch(attrs.myCurrentTime, function(value) {
format = value;
updateTime();
});
// schedule update in one second
function updateLater() {
// save the deferId for canceling
deferId = $defer(function() {
updateTime(); // update DOM
updateLater(); // schedule another update
}, 1000);
}
// listen on DOM destroy (removal) event, and cancel the next UI update
// to prevent updating time ofter the DOM element was removed.
element.bind('$destroy', function() {
$defer.cancel(deferId);
});
updateLater(); // kick of the UI update process.
}
});
</script>
<div ng-controller="Ctrl2">
Date format: <input ng-model='format'> <hr/>
Current time is: <span my-current-time="format"></span
</div>
</doc:source>
<doc:scenario>
</doc:scenario>
</doc:example>
# Writing directives (long version)
The full skeleton of the directive is shown here:
<pre>
var myModule = angular.module(...);
myModule.directive('directiveName', function factory(injectables) {
var directiveDefinitionObject = {
priority: 0,
template: '<div></div>',
templateUrl: 'directive.html',
replace: false,
transclude: false,
restrict: 'A',
scope: false,
compile: function compile(tElement, tAttrs, transclude) {
return {
pre: function preLink(scope, iElement, iAttrs, controller) { ... },
post: function postLink(scope, iElement, iAttrs, controller) { ... }
}
},
link: function postLink(scope, iElement, iAttrs) { ... }
};
return directiveDefinitionObject;
});
</pre>
In most cases you will not need such fine control and so the above can be simplified. All of the
different parts of this skeleton are explained in following sections. In this section we are
interested only isomers of this skeleton.
The first step in simplyfing the code is to rely on the deafult values. Therefore the above can be
simplified as:
<pre>
var myModule = angular.module(...);
myModule.directive('directiveName', function factory(injectables) {
var directiveDefinitionObject = {
compile: function compile(tElement, tAttrs) {
return function postLink(scope, iElement, iAttrs) { ... }
}
};
return directiveDefinitionObject;
});
</pre>
Most directives concern themselves only with instances not with template transformations allowing
further simplification:
<pre>
var myModule = angular.module(...);
myModule.directive('directiveName', function factory(injectables) {
return function postLink(scope, iElement, iAttrs) { ... }
});
</pre>
## Factory method
The factory method is responsible for creating the directive. It is invoked only once, when the
{@link angular.module.ng.$compile compiler} matches the directive for the first time. You can
perform any initialization work here. The method is invoked using the {@link
http://localhost:8000/build/docs/api/angular.module.AUTO.$injector#invoke $injector.invoke} which
makes it injectable following all of the rules of injection annotation.
## Directive Definition Object
The directive definition object provides instructions to the {@link angular.module.ng.$compile
compiler}. The attributes are:
* `name` - Name of the current scope. Optional defaults to the name at registration.
* `priority` - When there are multiple directives defined on a single DOM element, sometimes it
is necessary to specify the order in which the directives are applied. The `priority` is used
to sort the directives before their `compile` functions get called. Higher `priority` goes
first. The order of directives within the same priority is undefined.
* `terminal` - If set to true then the current `priority` will be the last set of directives
which will execute (any directives at the current priority will still execute
as the order of execution on same `priority` is undefined).
* `scope` - If set to:
* `true` - then a new scope will be created for this directive. If multiple directives on the
same element request new scope, only one new scope is created. The new scope rule does not
apply for the root of the template since the root of the template always gets a new scope.
* `{}` (object hash) - then a new 'isolate' scope is created. The 'isolate' scope differs from
normal scope that it does not prototypically inherit from the parent scope. This is useful
when creating reusable components, which should not accidentally read or modify data in
parent scope. <br/>
The 'isolate' scope takes an object hash which defines a set of local scope properties
derived from the parent scope. These local properties are useful for aliasing values for
templates. Locals definition is a hash of normalized element attribute name to their
corresponding binding strategy. Valid binding strategies are:
* `attribute` - one time read of element attribute value and save it to widget scope. <br/>
Given `<widget my-attr='abc'>` and widget definition of `scope: {myAttr:'attribute'}`,
then widget scope property `myAttr` will be `"abc"`.
* `evaluate` - one time evaluation of expression stored in the attribute. <br/> Given
`<widget my-attr='name'>` and widget definition of `scope: {myAttr:'evaluate'}`, and
parent scope `{name:'angular'}` then widget scope property `myAttr` will be `"angular"`.
* `bind` - Set up one way binding from the element attribute to the widget scope. <br/>
Given `<widget my-attr='{{name}}'>` and widget definition of `scope: {myAttr:'bind'}`,
and parent scope `{name:'angular'}` then widget scope property `myAttr` will be
`"angular"`, but any changes in the parent scope will be reflected in the widget scope.
* `accessor` - Set up getter/setter function for the expression in the widget element
attribute to the widget scope. <br/> Given `<widget my-attr='name'>` and widget definition
of `scope: {myAttr:'prop'}`, and parent scope `{name:'angular'}` then widget scope
property `myAttr` will be a function such that `myAttr()` will return `"angular"` and
`myAttr('new value')` will update the parent scope `name` property. This is useful for
treating the element as a data-model for reading/writing.
* `expression` - Treat element attribute as an expression to be executed on the parent scope.
<br/>
Given `<widget my-attr='doSomething()'>` and widget definition of `scope:
{myAttr:'expression'}`, and parent scope `{doSomething:function() {}}` then calling the
widget scope function `myAttr` will execute the expression against the parent scope.
* `controller` - Controller constructor function. The controller is instantiated before the
pre-linking phase and it is shared with other directives if they request it by name (see
`require` attribute). This allows the directives to communicate with each other and augment
each other behavior. The controller is injectable with the following locals:
* `$scope` - Current scope associated with the element
* `$element` - Current element
* `$attrs` - Current attributes obeject for the element
* `$transclude` - A transclude linking function pre-bound to the correct transclusion scope:
`function(cloneLinkingFn)`.
* `require` - Require another controller be passed into current directive linking function. The
`require` takes a name of the directive controller to pass in. If no such controller can be
found an error is raised. The name can be prefixed with:
* `?` - Don't raise an error. This makes the require dependency optional.
* `^` - Look for the controller on parent elements as well.
* `inject` (object hash) - Specifies a way to inject bindings into a controller. Injection
definition is a hash of normalized element attribute names to their corresponding binding
strategy. Valid binding strategies are:
* `attribute` - inject attribute value. <br/>
Given `<widget my-attr='abc'>` and widget definition of `inject: {myAttr:'attribute'}`, then
`myAttr` will inject `"abc"`.
* `evaluate` - inject one time evaluation of expression stored in the attribute. <br/>
Given `<widget my-attr='name'>` and widget definition of `inject: {myAttr:'evaluate'}`, and
parent scope `{name:'angular'}` then `myAttr` will inject `"angular"`.
* `accessor` - inject a getter/setter function for the expression in the widget element
attribute to the widget scope. <br/>
Given `<widget my-attr='name'>` and widget definition of `inject: {myAttr:'prop'}`, and
parent scope `{name:'angular'}` then injecting `myAttr` will inject a function such
that `myAttr()` will return `"angular"` and `myAttr('new value')` will update the parent
scope `name` property. This is usefull for treating the element as a data-model for
reading/writing.
* `expression` - Inject expression function. <br/>
Given `<widget my-attr='doSomething()'>` and widget definition of
`inject: {myAttr:'expression'}`, and parent scope `{doSomething:function() {}}` then
injecting `myAttr` will inject a function which when called will execute the expression
against the parent scope.
* `restrict` - String of subset of `EACM` which restricts the directive to a specific directive
declaration style. If omitted directives are allowed on attributes only.
* `E` - Element name: `<my-directive></my-directive>`
* `A` - Attribute: `<div my-directive="exp"></div>`
* `C` - Class: `<div class="my-directive: exp;"></div>`
* `M` - Comment: `<!-- directive: my-directive exp -->`
* `template` - replace the current element with the contents of the HTML. The replacement process
migrates all of the attributes / classes from the old element to the new one. See Creating
Widgets section below for more information.
* `templateURL` - Same as `template` but the template is loaded from the specified URL. Because
the template loading is asynchronous the compilation/linking is suspended until the template
is loaded.
* `replace` - if set to `true` then the template will replace the current element, rather then
append the template to the element.
* `transclude` - compile the content of the element and make it available to the directive.
Typically used with {@link api/angular.module.ng.$compileProvider.directive.ng-transclude
ng-transclude}. The advantage of transclusion is that the linking function receives a
transclusion function which is pre-bound to the correct scope. In a typical setup the widget
creates an `isolate` scope, but the transclusion is not a child, but a sibling of the `isolate`
scope. This makes it possible for the widget to have private state, and the transclusion to
be bound to the parent (pre-`isolate`) scope.
* `true` - transclude the content of the directive.
* `'element'` - transclude the whole element including any directives defined at lower priority.
* `compile`: This is the compile function described in the section below.
* `link`: This is the link function described in the section below. This property is used only
if the `compile` property is not defined.
## Compile function
<pre>
function compile(tElement, tAttrs, transclude) { ... }
</pre>
Compile function deals with transforming the template DOM. Since most directives do not do
template transformation, it is not used often. Examples which require compile functions are
directives which transform template DOM such as {@link
angular.module.ng.$compileProvider.directive.ng-repeat ng-repeat} or load the contents
asynchronously such as {@link angular.module.ng.$compileProvider.directive.ng-view ng-view}. The
compile functions takes the following arguments.
* `tElement` - template element - The element where the directive has been declared. It is
safe to do template transformation on the element and child elements only.
* `tAttrs` - template attributes - Normalized list of attributes declared on this element shared
between all directive compile functions. See {@link
#Attributes Attributes}
* `transclude` - A transclude linking function: `function(scope, cloneLinkingFn)`.
NOTE: The template instance and the link instance may not be the same objects if the template has
been cloned. For this reason it is not safe in the compile function to do anything other the DOM
transformation that applies to all DOM clones. Specifically, DOM listener registration should be
done in a linking function rather than in a compile function.
A compile function can have a return value which can be either a function or an object.
* returning a function - is equivalent to registering the linking function via the `link` property
of the config object when the compile function is empty.
* returning an object with function(s) registered via `pre` and `post` properties - allows you to
control when a linking function should be called during the linking phase. See info about
pre-linking and post-linking functions below.
## Linking function
<pre>
function link(scope, iElement, iAttrs, controller) { ... }
</pre>
Link function is responsible for registering DOM listeners as well as updating the DOM. It is
executed after the template has been cloned. This is where most of the directive logic will be
put.
* `scope` - {@link angular.module.ng.$rootScope.Scope Scope} - The scope to be used by the
directive for registering {@link angular.module.ng.$rootScope.Scope#$watch watches}.
* `iElement` - instance element - The element where the directive is to be used. It is safe to
manipulate the children of the element only in `postLink` function since the children have
already been linked.
* `iAttrs` - instance attributes - Normalized list of attributes declared on this element shared
between all directive linking functions. See {@link #Attributes Attributes}
* `controller` - a controller instance - A controller instance if at least one directive on the
element defines a controller. The controller is shared among all the directives, which allows
the directives to use the controllers as a communication channel.
### Pre-linking function
Executed before the child elements are linked. Not safe to do DOM transformation since the
compiler linking function will fail to locate the correct elements for linking.
### Post-linking function
Executed after the child elements are linked. Safe to do DOM transformation in here.
<a name="Attributes"></a>
## Attributes
The attributes object - passed as a parameter in the link() or compile() functions - is a way of
accessing:
* *normalized attribute names:* Since a directive such as 'ngBind' can be expressed in many ways
sucha s as 'ng:bind', or 'x-ng-bind', the attributes object allows for a normalize accessed to
the attributes.
* *directive inter-communication:* All directives share the same instance of the attributes
object which allows the directives to use the attributes object as inter directive
communication.
* *supports interpolation:* Interpolation attributes are assigned to the attribute object
allowing other directives to read the interpolated value.
* *observing interpolated attributes:* Use `$observe` to observe the value changes of attributes
that contain interpolation (e.g. `src="{{bar}}"`). Not only is this very efficient but it's also
the only way to easily get the actual value because during the linking phase the interpolation
hasn't been evaluated yet and so the value is at this time set to `undefined`.
<pre>
function linkingFn(scope, elm, attrs, ctrl) {
// get the attribute value
console.log(attrs.ngModel);
// change the attribute
attrs.$set('ngModel', 'new value');
// observe changes to interpolated attribute
attrs.$observe('ngModel', function(value) {
console.log('ngModel has changed value to ' + value);
});
}
</pre>
# Understanding Transclusion and Scopes
It is often desirable to have reusable components. Below is a pseudo code showing how a simplified
dialog component may work.
<pre>
<div>
<button ng-click="show=true">show</button>
<dialog title="Hello {{username}}."
visible="show"
on-cancel="show = false"
on-ok="show = false; doSomething()">
Body goes here: {{username}} is {{title}}.
</dialog>
</pre>
Clicking on the "show" button will open the dialog. The dialog will have a title, which is
data bound to `username`, and it will also have a body which we would like to transclude
into the dialog.
Here is an example of what the template definition for the `dialog` widget may look like.
<pre>
<div ng-show="show()">
<h3>{{title}}</h3>
<div class="body" ng-transclude></div>
<div class="footer">
<button ng-click="onOk()">Save changes</button>
<button ng-click="onCancel()">Close</button>
</div>
</div>
</pre>
This will not render properly, unless we do some scope magic.
The first issue we have to solve is that the dialog box template expect `title` to be defined, but
the place of instantiation would like to bind to `username`. Furthermore the buttons expect `onOk`
as well as `onCancel` functions to be present in the scope. This limits the usefulness of the
widget. To solve the mapping issue we use the `locals` to create local variables which the template
expects as follows:
<pre>
scope: {
title: 'bind', // set up title to accept data-binding
onOk: 'exp', // create a delegate onOk function
onCancel: 'exp', // create a delegate onCancel function
show: 'prop' // create a getter/setter function for visibility.
}
</pre>
Creating local properties on widget scope creates two problems:
1. isolation - if the user forgets to set `title` attribute of the dialog widget the dialog
template will bind to parent scope property. This is unpredictable and undesirable.
2. transclusion - the transcluded DOM can see the widget locals, which may overwrite the
properties which the transclusion needs for data-binding. In our example the `title`
property of the widget clobbers the `title` property of the transclusion.
To solve the issue of lack of isolation, the directive declares a new `isolated` scope. An
isolated scope does not prototypically inherit from the child scope, and therefore we don't have
to worry about accidentally clobbering any properties.
However 'isolated' scope creates a new problem: if a transcluded DOM is a child of the widget
isolated scope then it will not be able to bind to anything. For this reason the transcluded scope
is a child of the original scope, before the widget created an isolated scope for its local
variables. This makes the transcluded and widget isolated scope siblings.
This may seem as unexpected complexity, but it gives the widget user and developer the least
surprise.
Therefore the final directive definition looks something like this:
<pre>
transclude: true,
scope: {
title: 'bind', // set up title to accept data-binding
onOk: 'exp', // create a delegate onOk function
onCancel: 'exp', // create a delegate onCancel function
show: 'prop' // create a getter/setter function for visibility.
}
</pre>
# Creating Components
It is often desirable to replace a single directive with a more complex DOM structure. This
allows the directives to become a short hand for reusable components from which applications
can be built.
Following is an example of building a reusable widget.
<doc:example module="zippyModule">
<doc:source>
<script>
function Ctrl3($scope) {
$scope.title = 'Lorem Ipsum';
$scope.text = 'Neque porro quisquam est qui dolorem ipsum quia dolor...';
}
angular.module('zippyModule', [])
.directive('zippy', function(){
return {
restrict: 'C',
// This HTML will replace the zippy directive.
replace: true,
transclude: true,
scope: { zippyTitle:'bind' },
template: '<div>' +
'<div class="title">{{zippyTitle}}</div>' +
'<div class="body" ng-transclude></div>' +
'</div>',
// The linking function will add behavior to the template
link: function(scope, element, attrs) {
// Title element
var title = angular.element(element.children()[0]),
// Opened / closed state
opened = true;
// Clicking on title should open/close the zippy
title.bind('click', toggle);
// Toggle the closed/opened state
function toggle() {
opened = !opened;
element.removeClass(opened ? 'closed' : 'opened');
element.addClass(opened ? 'opened' : 'closed');
}
// initialize the zippy
toggle();
}
}
});
</script>
<style>
.zippy {
border: 1px solid black;
display: inline-block;
width: 250px;
}
.zippy.opened > .title:before { content: '▼ '; }
.zippy.opened > .body { display: block; }
.zippy.closed > .title:before { content: '► '; }
.zippy.closed > .body { display: none; }
.zippy > .title {
background-color: black;
color: white;
padding: .1em .3em;
cursor: pointer;
}
.zippy > .body {
padding: .1em .3em;
}
</style>
<div ng-controller="Ctrl3">
Title: <input ng-model="title"> <br>
Text: <textarea ng-model="text"></textarea>
<hr>
<div class="zippy" zippy-title="Details: {{title}}...">{{text}}</div>
</div>
</doc:source>
<doc:scenario>
it('should bind and open / close', function() {
input('title').enter('TITLE');
input('text').enter('TEXT');
expect(element('.title').text()).toEqual('Details: TITLE...');
expect(binding('text')).toEqual('TEXT');
expect(element('.zippy').prop('className')).toMatch(/closed/);
element('.zippy > .title').click();
expect(element('.zippy').prop('className')).toMatch(/opened/);
});
</doc:scenario>
</doc:example>
+5
View File
@@ -0,0 +1,5 @@
@ngdoc overview
@name angular.module.ng
@description
The `ng` is an angular module which contains all of the core angular services.
+63
View File
@@ -0,0 +1,63 @@
@ngdoc overview
@name API Reference
@description
## Angular Compiler API
* {@link angular.module.ng.$compileProvider.directive Directives} - Angular DOM element attributes
* {@link angular.module.ng.$filter Filters} - Angular output filters
* {@link angular.module.ng.$compile $compile} - Template compiler
## Angular Scope API
* {@link angular.module.ng.$rootScope.Scope Scope Object} - Angular scope object
## Angular Services & Dependency Injection API
* {@link angular.module.ng Angular Services}
* {@link angular.injector angular.injector() }
## Angular Testing API
* {@link angular.module.ngMock Testing Mocks API} - Mock objects for testing
* {@link guide/dev_guide.e2e-testing Angular Scenario Runner} - Automated scenario testing
documentation
## Angular Utility Functions
### HTML & DOM Manipulation
* {@link angular.element angular.element()}
### Misc
* {@link angular.bind angular.bind() }
* {@link angular.extend angular.extend() }
* {@link angular.forEach angular.forEach() }
* {@link angular.identity angular.identity() }
* {@link angular.noop angular.noop() }
## Type Identification
* {@link angular.isArray angular.isArray() }
* {@link angular.isDate angular.isDate() }
* {@link angular.isDefined angular.isDefined() }
* {@link angular.isFunction angular.isFunction() }
* {@link angular.isNumber angular.isNumber() }
* {@link angular.isObject angular.isObject() }
* {@link angular.isString angular.isString() }
* {@link angular.isUndefined angular.isUndefined() }
## Strings
* {@link angular.lowercase angular.lowercase() }
* {@link angular.uppercase angular.uppercase() }
### JSON
* {@link angular.fromJson angular.fromJson() }
* {@link angular.toJson angular.toJson() }
+127
View File
@@ -0,0 +1,127 @@
@ngdoc overview
@name Cookbook: Advanced Form
@description
Here we extend the basic form example to include common features such as reverting, dirty state
detection, and preventing invalid form submission.
<doc:example>
<doc:source>
<script>
function UserForm($scope) {
var master = {
name: 'John Smith',
address:{
line1: '123 Main St.',
city:'Anytown',
state:'AA',
zip:'12345'
},
contacts:[
{type:'phone', value:'1(234) 555-1212'}
]
};
$scope.state = /^\w\w$/;
$scope.zip = /^\d\d\d\d\d$/;
$scope.cancel = function() {
$scope.form = angular.copy(master);
};
$scope.save = function() {
master = $scope.form;
$scope.cancel();
};
$scope.addContact = function() {
$scope.form.contacts.push({type:'', value:''});
};
$scope.removeContact = function(contact) {
var contacts = $scope.form.contacts;
for (var i = 0, ii = contacts.length; i < ii; i++) {
if (contact === contacts[i]) {
contacts.splice(i, 1);
}
}
};
$scope.isCancelDisabled = function() {
return angular.equals(master, $scope.form);
};
$scope.isSaveDisabled = function() {
return $scope.myForm.$invalid || angular.equals(master, $scope.form);
};
$scope.cancel();
}
</script>
<div ng-controller="UserForm">
<form name="myForm">
<label>Name:</label><br/>
<input type="text" ng-model="form.name" required/> <br/><br/>
<label>Address:</label> <br/>
<input type="text" ng-model="form.address.line1" size="33" required/> <br/>
<input type="text" ng-model="form.address.city" size="12" required/>,
<input type="text" ng-model="form.address.state" size="2"
ng-pattern="state" required/>
<input type="text" ng-model="form.address.zip" size="5"
ng-pattern="zip" required/><br/><br/>
<label>Contacts:</label>
[ <a href="" ng-click="addContact()">add</a> ]
<div ng-repeat="contact in form.contacts">
<select ng-model="contact.type">
<option>email</option>
<option>phone</option>
<option>pager</option>
<option>IM</option>
</select>
<input type="text" ng-model="contact.value" required/>
[ <a href="" ng-click="removeContact(contact)">X</a> ]
</div>
<button ng-click="cancel()" ng-disabled="{{isCancelDisabled()}}">Cancel</button>
<button ng-click="save()" ng-disabled="{{isSaveDisabled()}}">Save</button>
</form>
<hr/>
Debug View:
<pre>form={{form}}</pre>
</div>
</doc:source>
<doc:scenario>
it('should enable save button', function() {
expect(element(':button:contains(Save)').attr('disabled')).toBeTruthy();
input('form.name').enter('');
expect(element(':button:contains(Save)').attr('disabled')).toBeTruthy();
input('form.name').enter('change');
expect(element(':button:contains(Save)').attr('disabled')).toBeFalsy();
element(':button:contains(Save)').click();
expect(element(':button:contains(Save)').attr('disabled')).toBeTruthy();
});
it('should enable cancel button', function() {
expect(element(':button:contains(Cancel)').attr('disabled')).toBeTruthy();
input('form.name').enter('change');
expect(element(':button:contains(Cancel)').attr('disabled')).toBeFalsy();
element(':button:contains(Cancel)').click();
expect(element(':button:contains(Cancel)').attr('disabled')).toBeTruthy();
expect(element(':input[ng\\:model="form.name"]').val()).toEqual('John Smith');
});
</doc:scenario>
</doc:example>
#Things to notice
* Cancel & save buttons are only enabled if the form is dirty — there is something to cancel or
save.
* Save button is only enabled if there are no validation errors on the form.
* Cancel reverts the form changes back to original state.
* Save updates the internal model of the form.
* Debug view shows the two models. One presented to the user form and the other being the pristine
copy master.
+63
View File
@@ -0,0 +1,63 @@
@ngdoc overview
@name Cookbook: Resources - Buzz
@description
External resources are URLs that provide JSON data, which are then rendered with the help of
templates. angular has a resource factory that can be used to give names to the URLs and then
attach behavior to them. For example you can use the
{@link http://code.google.com/apis/buzz/v1/getting_started.html#background-operations| Google Buzz
API}
to retrieve Buzz activity and comments.
<doc:example>
<doc:source>
<script>
BuzzController.$inject = ['$resource'];
function BuzzController($resource) {
this.userId = 'googlebuzz';
this.Activity = $resource(
'https://www.googleapis.com/buzz/v1/activities/:userId/:visibility/:activityId/:comments',
{alt: 'json', callback: 'JSON_CALLBACK'},
{ get: {method: 'JSONP', params: {visibility: '@self'}},
replies: {method: 'JSONP', params: {visibility: '@self', comments: '@comments'}}
});
}
BuzzController.prototype = {
fetch: function() {
this.activities = this.Activity.get({userId:this.userId});
},
expandReplies: function(activity) {
activity.replies = this.Activity.replies({userId: this.userId, activityId: activity.id});
}
};
</script>
<div ng-controller="BuzzController">
<input ng-model="userId"/>
<button ng-click="fetch()">fetch</button>
<hr/>
<div class="buzz" ng-repeat="item in activities.data.items">
<h1 style="font-size: 15px;">
<img ng-src="{{item.actor.thumbnailUrl}}" style="max-height:30px;max-width:30px;"/>
<a ng-href="{{item.actor.profileUrl}}">{{item.actor.name}}</a>
<a href ng-click="expandReplies(item)" style="float: right;">
Expand replies: {{item.links.replies[0].count}}
</a>
</h1>
{{item.object.content | html}}
<div class="reply" ng-repeat="reply in item.replies.data.items" style="margin-left: 20px;">
<img ng-src="{{reply.actor.thumbnailUrl}}" style="max-height:30px;max-width:30px;"/>
<a ng-href="{{reply.actor.profileUrl}}">{{reply.actor.name}}</a>:
{{reply.content | html}}
</div>
</div>
</div>
</doc:source>
<doc:scenario>
xit('fetch buzz and expand', function() {
element(':button:contains(fetch)').click();
expect(repeater('div.buzz').count()).toBeGreaterThan(0);
element('.buzz a:contains(Expand replies):first').click();
expect(repeater('div.reply').count()).toBeGreaterThan(0);
});
</doc:scenario>
</doc:example>
+112
View File
@@ -0,0 +1,112 @@
@ngdoc overview
@name Cookbook: Deep Linking
@description
Deep linking allows you to encode the state of the application in the URL so that it can be
bookmarked and the application can be restored from the URL to the same state.
While <angular/> does not force you to deal with bookmarks in any particular way, it has services
which make the common case described here very easy to implement.
# Assumptions
Your application consists of a single HTML page which bootstraps the application. We will refer
to this page as the chrome.
Your application is divided into several screens (or views) which the user can visit. For example,
the home screen, settings screen, details screen, etc. For each of these screens, we would like to
assign a URL so that it can be bookmarked and later restored. Each of these screens will be
associated with a controller which define the screen's behavior. The most common case is that the
screen will be constructed from an HTML snippet, which we will refer to as the partial. Screens can
have multiple partials, but a single partial is the most common construct. This example makes the
partial boundary visible using a blue line.
You can make a routing table which shows which URL maps to which partial view template and which
controller.
# Example
In this example we have a simple app which consist of two screens:
* Welcome: url `welcome` Show the user contact information.
* Settings: url `settings` Show an edit screen for user contact information.
The two partials are defined in the following URLs:
* <a href="./examples/settings.html" ng-ext-link>./examples/settings.html</a>
* <a href="./examples/welcome.html" ng-ext-link>./examples/welcome.html</a>
<doc:example module="deepLinking">
<doc:source jsfiddle="false">
<script>
angular.module('deepLinking', [])
.config(function($routeProvider) {
$routeProvider.when("/welcome", {template:'./examples/welcome.html', controller:WelcomeCntl});
$routeProvider.when("/settings", {template:'./examples/settings.html', controller:SettingsCntl});
});
AppCntl.$inject = ['$scope', '$route']
function AppCntl($scope, $route) {
// initialize the model to something useful
$scope.person = {
name:'anonymous',
contacts:[{type:'email', url:'anonymous@example.com'}]
};
}
function WelcomeCntl($scope) {
$scope.greet = function() {
alert("Hello " + $scope.person.name);
};
}
function SettingsCntl($scope, $location) {
$scope.cancel = function() {
$scope.form = angular.copy($scope.person);
};
$scope.save = function() {
angular.copy($scope.form, $scope.person);
$location.path('/welcome');
};
$scope.cancel();
}
</script>
<div ng-controller="AppCntl">
<h1>Your App Chrome</h1>
[ <a href="welcome">Welcome</a> | <a href="settings">Settings</a> ]
<hr/>
<span style="background-color: blue; color: white; padding: 3px;">
Partial: {{$route.current.template}}
</span>
<ng:view style="border: 1px solid blue; margin: 0; display:block; padding:1em;"></ng:view>
<small>Your app footer </small>
</div>
</doc:source>
<doc:scenario>
it('should navigate to URL', function() {
element('a:contains(Welcome)').click();
expect(element('ng\\:view').text()).toMatch(/Hello anonymous/);
element('a:contains(Settings)').click();
input('form.name').enter('yourname');
element(':button:contains(Save)').click();
element('a:contains(Welcome)').click();
expect(element('ng\\:view').text()).toMatch(/Hello yourname/);
});
</doc:scenario>
</doc:example>
# Things to notice
* Routes are defined in the `AppCntl` class. The initialization of the controller causes the
initialization of the {@link api/angular.module.ng.$route $route} service with the proper URL
routes.
* The {@link api/angular.module.ng.$route $route} service then watches the URL and instantiates the
appropriate controller when the URL changes.
* The {@link api/angular.module.ng.$compileProvider.directive.ng-view ng-view} widget loads the
view when the URL changes. It also sets the view scope to the newly instantiated controller.
* Changing the URL is sufficient to change the controller and view. It makes no difference whether
the URL is changed programatically or by the user.
+115
View File
@@ -0,0 +1,115 @@
@ngdoc overview
@name Cookbook: Form
@description
A web application's main purpose is to present and gather data. For this reason angular strives
to make both of these operations trivial. This example shows off how you can build a simple form to
allow a user to enter data.
<doc:example>
<doc:source>
<script>
function FormController($scope) {
$scope.user = {
name: 'John Smith',
address:{line1: '123 Main St.', city:'Anytown', state:'AA', zip:'12345'},
contacts:[{type:'phone', value:'1(234) 555-1212'}]
};
$scope.state = /^\w\w$/;
$scope.zip = /^\d\d\d\d\d$/;
$scope.addContact = function() {
$scope.user.contacts.push({type:'', value:''});
};
$scope.removeContact = function(contact) {
for (var i = 0, ii = this.user.contacts.length; i < ii; i++) {
if (contact === this.user.contacts[i]) {
$scope.user.contacts.splice(i, 1);
}
}
};
}
</script>
<div ng-controller="FormController" class="example">
<label>Name:</label><br/>
<input type="text" ng-model="user.name" required/> <br/><br/>
<label>Address:</label><br/>
<input type="text" ng-model="user.address.line1" size="33" required> <br/>
<input type="text" ng-model="user.address.city" size="12" required>,
<input type="text" ng-model="user.address.state" size="2"
ng-pattern="state" required>
<input type="text" ng-model="user.address.zip" size="5"
ng-pattern="zip" required><br/><br/>
<label>Phone:</label>
[ <a href="" ng-click="addContact()">add</a> ]
<div ng-repeat="contact in user.contacts">
<select ng-model="contact.type">
<option>email</option>
<option>phone</option>
<option>pager</option>
<option>IM</option>
</select>
<input type="text" ng-model="contact.value" required/>
[ <a href="" ng-click="removeContact(contact)">X</a> ]
</div>
<hr/>
Debug View:
<pre>user={{user}}</pre>
</div>
</doc:source>
<doc:scenario>
it('should show debug', function() {
expect(binding('user')).toMatch(/John Smith/);
});
it('should add contact', function() {
using('.example').element('a:contains(add)').click();
using('.example div:last').input('contact.value').enter('you@example.org');
expect(binding('user')).toMatch(/\(234\) 555\-1212/);
expect(binding('user')).toMatch(/you@example.org/);
});
it('should remove contact', function() {
using('.example').element('a:contains(X)').click();
expect(binding('user')).not().toMatch(/\(234\) 555\-1212/);
});
it('should validate zip', function() {
expect(using('.example').
element(':input[ng\\:model="user.address.zip"]').
prop('className')).not().toMatch(/ng-invalid/);
using('.example').input('user.address.zip').enter('abc');
expect(using('.example').
element(':input[ng\\:model="user.address.zip"]').
prop('className')).toMatch(/ng-invalid/);
});
it('should validate state', function() {
expect(using('.example').element(':input[ng\\:model="user.address.state"]').prop('className'))
.not().toMatch(/ng-invalid/);
using('.example').input('user.address.state').enter('XXX');
expect(using('.example').element(':input[ng\\:model="user.address.state"]').prop('className'))
.toMatch(/ng-invalid/);
});
</doc:scenario>
</doc:example>
# Things to notice
* The user data model is initialized {@link api/angular.module.ng.$compileProvider.directive.ng-controller controller} and is
available in the {@link api/angular.module.ng.$rootScope.Scope scope} with the initial data.
* For debugging purposes we have included a debug view of the model to better understand what
is going on.
* The {@link api/angular.module.ng.$compileProvider.directive.input input directives} simply refer
to the model and are data-bound.
* The inputs {@link guide/dev_guide.forms validate}. (Try leaving them blank or entering non digits
in the zip field)
* In your application you can simply read from or write to the model and the form will be updated.
* By clicking the 'add' link you are adding new items into the `user.contacts` array which are then
reflected in the view.
+39
View File
@@ -0,0 +1,39 @@
@ngdoc overview
@name Cookbook: Hello World
@description
<doc:example>
<doc:source>
<script>
function HelloCntl($scope) {
$scope.name = 'World';
}
</script>
<div ng-controller="HelloCntl">
Your name: <input type="text" ng-model="name" value="World"/>
<hr/>
Hello {{name}}!
</div>
</doc:source>
<doc:scenario>
it('should change the binding when user enters text', function() {
expect(binding('name')).toEqual('World');
input('name').enter('angular');
expect(binding('name')).toEqual('angular');
});
</doc:scenario>
</doc:example>
# Things to notice
Take a look through the source and note:
* The script tag that {@link guide/dev_guide.bootstrap bootstraps} the angular environment.
* The text {@link api/angular.module.ng.$compileProvider.directive.input input widget} which is
bound to the greeting name text.
* No need for listener registration and event firing on change events.
* The implicit presence of the `name` variable which is in the root {@link api/angular.module.ng.$rootScope.Scope scope}.
* The double curly brace `{{markup}}`, which binds the name variable to the greeting text.
* The concept of {@link guide/dev_guide.templates.databinding data binding}, which reflects any
changes to the
input field in the greeting text.
+58
View File
@@ -0,0 +1,58 @@
@ngdoc overview
@name Cookbook
@description
Welcome to the angular cookbook. Here we will show you typical uses of angular by example.
# Hello World
{@link helloworld Hello World}: The simplest possible application that demonstrates the
classic Hello World!
# Basic Form
{@link form Basic Form}: Displaying forms to the user for editing is the bread and butter
of web applications. Angular makes forms easy through bidirectional data binding.
# Advanced Form
{@link advancedform Advanced Form}: Taking the form example to the next level and
providing advanced features such as dirty detection, form reverting and submit disabling if
validation errors exist.
# Model View Controller
{@link mvc MVC}: Tic-Tac-Toe: Model View Controller (MVC) is a time-tested design pattern
to separate the behavior (JavaScript controller) from the presentation (HTML view). This
separation aids in maintainability and testability of your project.
# Multi-page App and Deep Linking
{@link deeplinking Deep Linking}: An AJAX application never navigates away from the
first page it loads. Instead, it changes the DOM of its single page. Eliminating full-page reloads
is what makes AJAX apps responsive, but it creates a problem in that apps with a single URL
prevent you from emailing links to a particular screen within your application.
Deep linking tries to solve this by changing the URL anchor without reloading a page, thus
allowing you to send links to specific screens in your app.
# Services
{@link api/angular.module.ng Services}: Services are long lived objects in your applications that are
available across controllers. A collection of useful services are pre-bundled with angular but you
will likely add your own. Services are initialized using dependency injection, which resolves the
order of initialization. This safeguards you from the perils of global state (a common way to
implement long lived objects).
# External Resources
{@link buzz Resources}: Web applications must be able to communicate with the external
services to get and update data. Resources are the abstractions of external URLs which are
specially tailored to angular data binding.
+127
View File
@@ -0,0 +1,127 @@
@ngdoc overview
@name Cookbook: MVC
@description
MVC allows for a clean an testable separation between the behavior (controller) and the view
(HTML template). A Controller is just a JavaScript class which is grafted onto the scope of the
view. This makes it very easy for the controller and the view to share the model.
The model is simply the controller's this. This makes it very easy to test the controller in
isolation since one can simply instantiate the controller and test without a view, because there is
no connection between the controller and the view.
<doc:example>
<doc:source>
<script>
function TicTacToeCntl($scope, $location) {
$scope.cellStyle= {
'height': '20px',
'width': '20px',
'border': '1px solid black',
'text-align': 'center',
'vertical-align': 'middle',
'cursor': 'pointer'
};
$scope.reset = function() {
$scope.board = [
['', '', ''],
['', '', ''],
['', '', '']
];
$scope.nextMove = 'X';
$scope.winner = '';
setUrl();
};
$scope.dropPiece = function(row, col) {
if (!$scope.winner && !$scope.board[row][col]) {
$scope.board[row][col] = $scope.nextMove;
$scope.nextMove = $scope.nextMove == 'X' ? 'O' : 'X';
setUrl();
}
};
$scope.reset();
$scope.$watch(function() { return $location.search().board;}, readUrl);
function setUrl() {
var rows = [];
angular.forEach($scope.board, function(row) {
rows.push(row.join(','));
});
$location.search({board: rows.join(';') + '/' + $scope.nextMove});
}
function grade() {
var b = $scope.board;
$scope.winner =
row(0) || row(1) || row(2) ||
col(0) || col(1) || col(2) ||
diagonal(-1) || diagonal(1);
function row(row) { return same(b[row][0], b[row][1], b[row][2]);}
function col(col) { return same(b[0][col], b[1][col], b[2][col]);}
function diagonal(i) { return same(b[0][1-i], b[1][1], b[2][1+i]);}
function same(a, b, c) { return (a==b && b==c) ? a : '';};
}
function readUrl(value) {
if (value) {
value = value.split('/');
$scope.nextMove = value[1];
angular.forEach(value[0].split(';'), function(row, col){
$scope.board[col] = row.split(',');
});
grade();
}
}
}
</script>
<h3>Tic-Tac-Toe</h3>
<div ng-controller="TicTacToeCntl">
Next Player: {{nextMove}}
<div class="winner" ng-show="winner">Player {{winner}} has won!</div>
<table class="board">
<tr ng-repeat="row in board" style="height:15px;">
<td ng-repeat="cell in row" ng-style="cellStyle"
ng-click="dropPiece($parent.$index, $index)">{{cell}}</td>
</tr>
</table>
<button ng-click="reset()">reset board</button>
</div>
</doc:source>
<doc:scenario>
it('should play a game', function() {
piece(1, 1);
expect(binding('nextMove')).toEqual('O');
piece(3, 1);
expect(binding('nextMove')).toEqual('X');
piece(1, 2);
piece(3, 2);
piece(1, 3);
expect(element('.winner').text()).toEqual('Player X has won!');
});
function piece(row, col) {
element('.board tr:nth-child('+row+') td:nth-child('+col+')').click();
}
</doc:scenario>
</doc:example>
# Things to notice
* The controller is defined in JavaScript and has no reference to the rendering logic.
* The controller is instantiated by <angular/> and injected into the view.
* The controller can be instantiated in isolation (without a view) and the code will still execute.
This makes it very testable.
* The HTML view is a projection of the model. In the above example, the model is stored in the
board variable.
* All of the controller's properties (such as board and nextMove) are available to the view.
* Changing the model changes the view.
* The view can call any controller function.
* In this example, the `setUrl()` and `readUrl()` functions copy the game state to/from the URL's
hash so the browser's back button will undo game steps. See deep-linking. This example calls {@link
api/angular.module.ng.$rootScope.Scope#$watch $watch()} to set up a listener that invokes `readUrl()` when needed.
@@ -0,0 +1,49 @@
@ngdoc overview
@name Developer Guide: Initializing Angular: Automatic Initialization
@description
Angular initializes automatically when you load the angular script into your page that contains an element
with `ng-app` directive:
<pre>
<!doctype html>
<html ng-app>
<head>
<script src="angular.js"></script>
</head>
<body>
I can add: {{ 1+2 }}.
</body>
</html>
</pre>
From a high-level view, this is what happens during angular's automatic initialization process:
1. The browser loads the page, and then runs the angular script. Angular waits for the
`DOMContentLoaded` (or 'Load') event to attempt to bootstrap.
2. Angular looks for the `ng-app` directive. If found it then proceeds to compile the DOM element and its children.
Optionally the `ng-app` may specify a {@link api/angular.module module} to load before the compilation. For details on
how the compiler works, see {@link dev_guide.compiler Angular HTML Compiler}.
## Initialization Options
The reason why `ng-app` exists is because angular should not assume that the entire HTML
document should be processed just because the `angular.js` script is included. In order to compile
only a part of the document set the `ng-app` on the root element of this portion.
## Global Angular Object
The angular script creates a single global variable `angular` in the global namespace. All angular
APIs are bound to fields of this global object.
## Related Topics
* {@link dev_guide.bootstrap Initializing Angular}
* {@link dev_guide.bootstrap.manual_bootstrap Manual Initialization}
## Related API
{@link api/angular.module.ng.$compile Compiler API}
@@ -0,0 +1,46 @@
@ngdoc overview
@name Developer Guide: Initializing Angular: Manual Initialization
@description
Letting angular handle the initialization process (bootstrapping) is a handy way to start using
angular, but advanced users who want more control over the initialization process can choose to use
the manual bootstrapping method instead.
The best way to get started with manual bootstrapping is to look at the what happens when you use
{@link api/angular.module.ng.$compileProvider.directive.ng-app ng-app}, by showing each step of the process
explicitly.
<pre>
<!doctype html>
<html>
<head>
<script src="http://code.angularjs.org/angular.js"></script>
<script>
angular.element(document).ready(function() {
angular.bootstrap(document);
});
</script>
</head>
<body>
Hello {{'World'}}!
</body>
</html>
</pre>
This is the sequence that your code should follow if you bootstrap angular on your own:
1. After the page is loaded, find the root of the HTML template, which is typically the root of
the document.
2. Call {@link api/angular.bootstrap} to {@link dev_guide.compiler compile} the template into
an executable, bi-directionally bound application.
## Related Topics
* {@link dev_guide.bootstrap Initializing Angular}
* {@link dev_guide.bootstrap.auto_bootstrap Automatic Initialization}
* {@link dev_guide.compiler Angular HTML compiler}
## Related API
{@link api/angular.module.ng.$compile Compiler API}
@@ -0,0 +1,65 @@
@ngdoc overview
@name Developer Guide: Initializing Angular
@description
Initializing angular consists of loading the `angular.js` script in your page, and specifying how
angular should process and manage the page. To initialize angular you do the following:
* Specify the angular namespace in the `<html>` page
* Choose which flavor of angular script to load (debug or production)
* Specify whether or not angular should process and manage the page automatically (`ng-app`)
The simplest way to initialize angular is to load the angular script and tell angular to compile
and manage the whole page. You do this as follows:
<pre>
<!doctype html>
<html ng-app>
<head>
...
</head>
<body>
...
<script src="angular.js">
</body>
</pre>
## Specifying the Angular Namespace
<html xmlns:ng="http://angularjs.org">
You need to add the angular namespace declaration if you use `ng:something` style of declaring
angular directives and you write your templates as XHTML. Or when you are targeting Internet
Explorer older than version 9 (because older versions of IE do not render namespace
properly for either HTML or XHTML). For more info please read {@link ie Internet Explorer
Compatibility} doc.
## Creating Your Own Namespaces
When you are ready to define your own {@link api/angular.module.ng.$compileProvider.directive
directive}, you may chose to create your own namespace in addition to specifying the angular
namespace. You use your own namespace to form the fully qualified name for directives that you
create.
For example, you could map the alias `my` to your domain, and create a directive called `my:directive`.
To create your own namespace, simply add another `xmlns` tag to your page, create an alias, and set
it to your unique domain:
<html xmlns:ng="http://angularjs.org" xmlns:my="http://mydomain.com">
## Loading the Angular Bootstrap Script
The angular bootstrap script comes in two flavors; a debug script, and a production script:
* angular-[version].js - This is a human-readable file, suitable for development and debugging.
* angular-[version].min.js - This is a compressed and obfuscated file, suitable for use in
production.
## Related Topics
* {@link dev_guide.bootstrap.auto_bootstrap Automatic Initialization}
* {@link dev_guide.bootstrap.manual_bootstrap Manual Initialization}
@@ -0,0 +1,23 @@
@ngdoc overview
@name Developer Guide: Angular HTML Compiler
@description
The core of angular is its HTML compiler. The compiler processes angular directives allowing them
to transform a static HTML page into a dynamic web application.
The default HTML transformations that the angular compiler provides are useful for building generic
apps, but you can also extend the compiler to create a domain-specific language for building
specific types of web applications.
All compilation takes place in the web browser; no server is involved.
## Related Topics
* {@link dev_guide.compiler.understanding_compiler Understanding How the Compiler Works}
* {@link dev_guide.compiler.testing_dom_element Testing a New DOM Element}
## Related API
* {@link api/angular.module.ng.$compile Angular Compiler API}
* {@link api/angular.module.ng.$compileProvider.directive Directives API}
@@ -0,0 +1,16 @@
@ngdoc overview
@name Developer Guide: Angular HTML Compiler: Testing a New DOM Element
@description
"Testing, testing, come in, over?"
## Related Topics
* {@link dev_guide.compiler Angular HTML Compiler}
* {@link dev_guide.compiler.understanding_compiler Understanding How the Compiler Works}
## Related API
* {@link api/angular.module.ng.$compile $compile()}
@@ -0,0 +1,34 @@
@ngdoc overview
@name Developer Guide: Angular HTML Compiler: Understanding How the Compiler Works
@description
The {@link api/angular.module.ng.$compile compiler} is responsible for applying
{@link api/angular.module.ng.$compileProvider.directive directives} to the HTML. The directives
extend the behavior of HTML elements and can effect the DOM structure, presentation, and behavior.
This allows Angular to teach the browser new tricks.
The compilation starts at the root element and proceeds in a depth-first order. As the compiler
visits each node it collects the directives, orders them by priority and executes their compile
function. The result of the compilation process is a linking function. The linking function
can be used on the template clones to quickly bind the directives with the scope.
The result of the compilation process is a live view. We say 'live' since any changes to the
model attached to the {@link api/angular.module.ng.$rootScope.Scope scope} are reflected in the view,
and any changes in the view are reflected in the scope. This makes the scope the 'single source of
truth'.
Since directives allow attachment of behavior to the HTML, the angular philosophy is to use the
HTML as Domain Specific Language (DSL) when building an application. For example it may be useful
to declare `TabPanel` directive, or `KeyboardShortcut` directive when for an application.
For details on how directives are created see {@link api/angular.module.ng.$compileProvider.directive
directives}
## Related Topics
* {@link dev_guide.compiler Angular HTML Compiler}
* {@link dev_guide.compiler.testing_dom_element Testing a New DOM Element}
## Related API
* {@link api/angular.module.ng.$compile $compile()}
+32
View File
@@ -0,0 +1,32 @@
@ngdoc overview
@name Developer Guide: About Dependency Injection (DI)
@description
Dependency Injection (DI) is an object-oriented software design pattern that supports the
decoupling and dependency management of application components.
The idea behind DI is to decouple each component from all of the other components that it depends
on to do its particular job. The way this is done in DI is by moving the responsibility for
managing dependencies out of each individual component and into a provider component. The provider
(or injector) component manages the life cycles and dependencies for all of the other components in
an application.
Angular has a built-in dependency management subsystem that helps to make your applications easier
to develop, understand, and test.
For more information on DI in general, see {@link http://en.wikipedia.org/wiki/Dependency_injection
Dependency Injection} at Wikipedia, and {@link http://martinfowler.com/articles/injection.html
Inversion of Control} by Martin Fowler, or read about DI in your favorite software design pattern
book.
## Related Topics
* {@link dev_guide.di.understanding_di Understanding DI in Angular}
* {@link dev_guide.services Angular Services}
## Related API
* {@link api/angular.module.ng Service API}
* {@link api/angular.injector Angular Injector API}
@@ -0,0 +1,193 @@
@ngdoc overview
@name Developer Guide: DI: Understanding DI in Angular
@description
While DI is widely used in statically typed languages such as Java or C++, it has not been widely
used in JavaScript. Angular brings the benefits of DI into JavaScript apps.
In angular, DI is implemented as a subsystem that manages dependencies between services,
controllers, widgets, and filters.
Services are objects that handle common tasks in web applications. Angular provides several {@link
api/angular.module.ng built-in services}, and you can create your
{@link dev_guide.services.creating_services own custom services}.
The main job of angular's DI subsystem is to provide services to angular components that depend on
them. The way the DI subsystem provides services is as follows: all services are registered with
angular's {@link api/angular.module.ng service API}, and all components that depend on services
define those dependencies as a property (`$inject`). With this information, the DI subsystem
manages the creation of service objects and the provision of those objects to the components that
need them, at the time they need them. The following illustration steps through the sequence of
events:
<img src="img/guide/di_sequence_final.png">
In the illustration above, the dependency injection sequence proceeds as follows:
1. Module "phonecat" is created and all the service providers are registered with this module.
(the "ng" module is created by Angular behind the scenes as well)
2. `ng-app` triggers bootstrap sequence on given element, during which angular creates injector,
loads "phonecat" and "ng" modules and compiles the template.
3. The `ng-controller` directive implicitly creates a new child scope and instantiates
`PhoneListCtrl` controller.
4. Injector identifies the `$http` service as `PhoneListCtrl` controller's only dependency.
5. Injector checks its instances cache whether the `$http` service has already been instantiated.
If not uses the provider from the available modules to construct it.
6. Injector provides the instance of `$http` service to the `PhoneListCtrl` controller constructor.
## How Scope Relates to DI
The root scope of the application is just a service that is available for injection to any part of
the application under the service name "$rootScope".
## Inferring dependencies from the signature of the factory function or constructor
**EXPERIMENTAL FEATURE**: This is an experimental feature. See the important note at the end of
this section for drawbacks.
We resort to `$inject` and our own annotation because there is no way in JavaScript to get a list
of arguments. Or is there? It turns out that calling `.toString()` on a function returns the
function declaration along with the argument names as shown below:
<pre>
function myFn(a,b){}
expect(myFn.toString()).toEqual('function myFn(a,b){}');
</pre>
This means that angular can infer the function names after all and use that information to generate
the `$inject` annotation automatically. Therefore the following two function definitions are
equivalent:
<pre>
// given a user defined service
angular.module('module1', [], function($provide) {
$provide.factory('serviceA', ...);
});
// inject '$window', 'serviceA', curry 'name';
function fnA($window, serviceA, name){};
fnA.$inject = ['$window', 'serviceA'];
// inject '$window', 'serviceA', curry 'name';
function fnB($window, serviceA_, name){};
// implies: fnB.$inject = ['$window', 'serviceA'];
</pre>
If angular does not find a `$inject` annotation on the function, then it calls the `.toString()`
method and tries to infer what should be injected by using function argument names as dependency
identifiers.
**IMPORTANT**
Minifiers/obfuscators change the names of function arguments and will therefore break the `$inject`
inference. For this reason, either explicitly declare the `$inject` or do not use
minifiers/obfuscators. In the future, we may provide a pre-processor which will scan the source
code and insert the `$inject` into the source code so that it can be minified/obfuscated.
### Dependency inference and variable name shadowing
During inference, the injector considers argument names with leading and trailing underscores to be
equivivalent to the name without these underscores. For example `_fooSvc_` argument name is treated
as if it was `fooSvc`, this is useful especially in tests where variable name shadowing can cause
some friction. This is best illustrated on examples:
When testing a service, it's common to need a reference to it in every single test. This can be
done in jasmine with DI inference like this:
<pre>
describe('fooSvc', function() {
it('should do this thing', inject(function(fooSvc) {
//test fooSvc
}));
it('should do that thing', inject(function(fooSvc) {
//test fooSvc
}));
// more its
});
</pre>
... but having to inject the service over and over gets easily tiresome.
It's likely better to rewrite these tests with a use of jasmine's `beforeEach`:
<pre>
describe('fooSvc', function() {
var fooSvc;
beforeEach(inject(function(fooSvc) {
fooSvc = fooSvc; // DOESN'T WORK! outer fooSvc is being shadowed
}));
it('should do this thing', function() {
//test fooSvc
});
it('should do that thing', function() {
//test fooSvc
});
// more its
});
</pre>
This obviously won't work because `fooSvc` variable in the describe block is being shadowed by the
`fooSvc` argument of the beforeEach function. So we have to resort to alternative solutions, like
for example use of array notation to annotate the beforeEach fn:
<pre>
describe('fooSvc', function() {
var fooSvc;
beforeEach(inject(['fooSvc', function(fooSvc_) {
fooSvc = fooSvc_;
}]));
it('should do this thing', function() {
//test fooSvc
});
it('should do that thing', function() {
//test fooSvc
});
});
</pre>
That's better, but it's still annoying, especially if you have many services to inject.
To resolve this shadowing problem, the injector considers `_fooSvc_` argument names equal to
`fooSvc`, so the test can be rewritten like this:
<pre>
describe('fooSvc', function() {
var fooSvc;
beforeEach(inject(function(_fooSvc_) {
fooSvc = _fooSvc_;
}));
it('should do this thing', function() {
//test fooSvc
});
it('should do that thing', function() {
//test fooSvc
});
// more its
});
</pre>
## Related Topics
* {@link dev_guide.services Angular Services}
## Related API
* {@link api/angular.module.ng Services API}
@@ -0,0 +1,53 @@
@ngdoc overview
@name Developer Guide: DI: Using DI in Controllers
@description
The most common place to use dependency injection in angular applications is in {@link
dev_guide.mvc.understanding_controller controllers}. Here is a simple example:
<pre>
function MyController($route){
// configure the route service
$route.when(...);
}
MyController.$inject = ['$route'];
</pre>
In this example, the `MyController` constructor function takes one argument, the {@link
api/angular.module.ng.$route $route} service. Angular is then responsible for supplying the instance
of `$route` to the controller when the constructor is instantiated. There are two ways to cause
controller instantiation by configuring routes with the `$route` service, or by referencing the
controller from the HTML template, as follows:
<pre>
<!doctype html>
<html ng-controller="MyController" ng-app>
<script src="http://code.angularjs.org/angular.min.js"></script>
<body>
...
</body>
</html>
</pre>
When angular is instantiating your controller, it needs to know what services, if any, should be
injected (passed in as arguments) into the controller. Since there is no reflection in JavaScript,
we have to supply this information to angular in the form of an additional property on the
controller constructor function called `$inject`. Think of it as annotations for JavaScript.
<pre>
MyController.$inject = ['$route'];
</pre>
The information in `$inject` is then used by the {@link api/angular.injector injector} to call the
function with the correct arguments.
## Related Topics
* {@link dev_guide.di About Dependency Injection}
* {@link dev_guide.di.understanding_di Understanding Dependency Injection in Angular}
* {@link dev_guide.services Angular Services}
## Related API
* {@link api/angular.injector Angular Injector API}
@@ -0,0 +1,178 @@
@workInProgress
@ngdoc overview
@name Developer Guide: E2E Testing
@description
As applications grow in size and complexity, it becomes unrealistic to rely on manual testing to
verify the correctness of new features, catch bugs and notice regressions.
To solve this problem, we have built an Angular Scenario Runner which simulates user interactions
that will help you verify the health of your Angular application.
# Overview
You will write scenario tests in JavaScript, which describe how your application should behave,
given a certain interaction in a specific state. A scenario is comprised of one or more it blocks
(you can think of these as the requirements of your application), which in turn are made of
**commands** and **expectations**. Commands tell the Runner to do something with the application
(such as navigate to a page or click on a button), and expectations tell the Runner to assert
something about the state (such as the value of a field or the current URL). If any expectation
fails, the runner marks the `it` as "failed" and continues on to the next one. Scenarios may also
have **beforeEach** and **afterEach** blocks, which will be run before (or after) each `it` block,
regardless of whether they pass or fail.
<img src="img/guide/scenario_runner.png">
In addition to the above elements, scenarios may also contain helper functions to avoid duplicating
code in the `it` blocks.
Here is an example of a simple scenario:
<pre>
describe('Buzz Client', function() {
it('should filter results', function() {
input('user').enter('jacksparrow');
element(':button').click();
expect(repeater('ul li').count()).toEqual(10);
input('filterText').enter('Bees');
expect(repeater('ul li').count()).toEqual(1);
});
});
</pre>
This scenario describes the requirements of a Buzz Client, specifically, that it should be able to
filter the stream of the user. It starts by entering a value in the 'user' input field, clicking
the only button on the page, and then it verifies that there are 10 items listed. It then enters
'Bees' in the 'filterText' input field and verifies that the list is reduced to a single item.
The API section below lists the available commands and expectations for the Runner.
# API
Source: {@link https://github.com/angular/angular.js/blob/master/src/scenario/dsl.js}
## pause()
Pauses the execution of the tests until you call `resume()` in the console (or click the resume
link in the Runner UI).
## sleep(seconds)
Pauses the execution of the tests for the specified number of `seconds`.
## browser().navigateTo(url)
Loads the `url` into the test frame.
## browser().navigateTo(url, fn)
Loads the URL returned by `fn` into the testing frame. The given `url` is only used for the test
output. Use this when the destination URL is dynamic (that is, the destination is unknown when you
write the test).
## browser().reload()
Refreshes the currently loaded page in the test frame.
## browser().window().href()
Returns the window.location.href of the currently loaded page in the test frame.
## browser().window().path()
Returns the window.location.pathname of the currently loaded page in the test frame.
## browser().window().search()
Returns the window.location.search of the currently loaded page in the test frame.
## browser().window().hash()
Returns the window.location.hash (without `#`) of the currently loaded page in the test frame.
## browser().location().url()
Returns the {@link api/angular.module.ng.$location $location.url()} of the currently loaded page in
the test frame.
## browser().location().path()
Returns the {@link api/angular.module.ng.$location $location.path()} of the currently loaded page in
the test frame.
## browser().location().search()
Returns the {@link api/angular.module.ng.$location $location.search()} of the currently loaded page
in the test frame.
## browser().location().hash()
Returns the {@link api/angular.module.ng.$location $location.hash()} of the currently loaded page in
the test frame.
## expect(future).{matcher}
Asserts the value of the given `future` satisfies the `matcher`. All API statements return a
`future` object, which get a `value` assigned after they are executed. Matchers are defined using
`angular.scenario.matcher`, and they use the value of futures to run the expectation. For example:
`expect(browser().location().href()).toEqual('http://www.google.com')`
## expect(future).not().{matcher}
Asserts the value of the given `future` satisfies the negation of the `matcher`.
## using(selector, label)
Scopes the next DSL element selection.
## binding(name)
Returns the value of the first binding matching the given `name`.
## input(name).enter(value)
Enters the given `value` in the text field with the given `name`.
## input(name).check()
Checks/unchecks the checkbox with the given `name`.
## input(name).select(value)
Selects the given `value` in the radio button with the given `name`.
## input(name).val()
Returns the current value of an input field with the given `name`.
## repeater(selector, label).count()
Returns the number of rows in the repeater matching the given jQuery `selector`. The `label` is
used for test ouput.
## repeater(selector, label).row(index)
Returns an array with the bindings in the row at the given `index` in the repeater matching the
given jQuery `selector`. The `label` is used for test output.
## repeater(selector, label).column(binding)
Returns an array with the values in the column with the given `binding` in the repeater matching
the given jQuery `selector`. The `label` is used for test output.
## select(name).option(value)
Picks the option with the given `value` on the select with the given `name`.
## select(name).option(value1, value2...)
Picks the options with the given `values` on the multi select with the given `name`.
## element(selector, label).count()
Returns the number of elements that match the given jQuery `selector`. The `label` is used for test
output.
## element(selector, label).click()
Clicks on the element matching the given jQuery `selector`. The `label` is used for test output.
## element(selector, label).query(fn)
Executes the function `fn(selectedElements, done)`, where selectedElements are the elements that
match the given jQuery `selector` and `done` is a function that is called at the end of the `fn`
function. The `label` is used for test output.
## element(selector, label).{method}()
Returns the result of calling `method` on the element matching the given jQuery `selector`, where
`method` can be any of the following jQuery methods: `val`, `text`, `html`, `height`,
`innerHeight`, `outerHeight`, `width`, `innerWidth`, `outerWidth`, `position`, `scrollLeft`,
`scrollTop`, `offset`. The `label` is used for test output.
## element(selector, label).{method}(value)
Executes the `method` passing in `value` on the element matching the given jQuery `selector`, where
`method` can be any of the following jQuery methods: `val`, `text`, `html`, `height`,
`innerHeight`, `outerHeight`, `width`, `innerWidth`, `outerWidth`, `position`, `scrollLeft`,
`scrollTop`, `offset`. The `label` is used for test output.
## element(selector, label).{method}(key)
Returns the result of calling `method` passing in `key` on the element matching the given jQuery
`selector`, where `method` can be any of the following jQuery methods: `attr`, `prop`, `css`. The
`label` is used for test output.
## element(selector, label).{method}(key, value)
Executes the `method` passing in `key` and `value` on the element matching the given jQuery
`selector`, where `method` can be any of the following jQuery methods: `attr`, `prop`, `css`. The
`label` is used for test output.
JavaScript is a dynamically typed language which comes with great power of expression, but it also
come with almost no-help from the compiler. For this reason we feel very strongly that any code
written in JavaScript needs to come with a strong set of tests. We have built many features into
angular which makes testing your angular applications easy. So there is no excuse for not do it.
@@ -0,0 +1,245 @@
@ngdoc overview
@name Developer Guide: Understanding Angular Expressions
@description
Expressions are {@link dev_guide.templates.databinding bindings} that you write in HTML and embed
in templates in order to create views in angular. Angular expressions are similar but not
equivalent to JavaScript expressions.
For example, these are all valid expressions in angular:
* `1+2={{1+2}}`
* `3*10|currency`
* `Hello {{name}}!`
* `Hello {{'World'}}!`
## Angular Expressions vs. JS Expressions
It might be tempting to think of angular view expressions as JavaScript expressions, but that is
not entirely correct. Angular does not use a simple JavaScript eval of the expression text. You can
think of angular expressions as JavaScript expressions with these differences:
* **Attribute Evaluation:** evaluation of all attributes are against the current scope, not to the
global window as in JavaScript.
* **Forgiving:** expression evaluation is forgiving to undefined and null, unlike in JavaScript.
* **No Control Flow Statements:** you cannot do the following from an angular expression:
conditionals, loops, or throw.
* **Type Augmentation:** the scope expression evaluator augments built-in types.
* **Filters:** you can add filters to an expression, for example to convert raw data into a
human-readable format.
* **The $:** angular reserves this prefix to differentiate its API names from others.
If, on the other hand, you do want to run arbitrary JavaScript code, you should make it a
controller method and call that. If you want to `eval()` an angular expression from JavaScript, use
the `Scope:$eval()` method.
## Example
<doc:example>
<doc:source>
1+2={{1+2}}
</doc:source>
<doc:scenario>
it('should calculate expression in binding', function() {
expect(binding('1+2')).toEqual('3');
});
</doc:scenario>
</doc:example>
You can try evaluating different expressions here:
<doc:example>
<doc:source>
<script>
function Cntl2($scope) {
$scope.exprs = [];
$scope.expr = '3*10|currency';
$scope.addExp = function(expr) {
this.exprs.push(expr);
};
$scope.removeExp = function(index) {
this.exprs.splice(index, 1);
};
}
</script>
<div ng-controller="Cntl2" class="expressions">
Expression:
<input type='text' ng-model="expr" size="80"/>
<button ng-click="addExp(expr)">Evaluate</button>
<ul>
<li ng-repeat="expr in exprs">
[ <a href="" ng-click="removeExp($index)">X</a> ]
<tt>{{expr}}</tt> => <span ng-bind="$parent.$eval(expr)"></span>
</li>
</ul>
</div>
</doc:source>
<doc:scenario>
it('should allow user expression testing', function() {
element('.expressions :button').click();
var li = using('.expressions ul').repeater('li');
expect(li.count()).toBe(1);
expect(li.row(0)).toEqual(["3*10|currency", "$30.00"]);
});
</doc:scenario>
</doc:example>
# Attribute Evaluation
Evaluation of all attributes takes place against the current scope. Unlike JavaScript, where names
default to global window properties, angular expressions have to use `$window` to refer to the
global object. For example, if you want to call `alert()`, which is defined on `window`, an
expression must use `$window.alert()`. This is done intentionally to prevent accidental access to
the global state (a common source of subtle bugs).
<doc:example>
<doc:source>
<script>
function Cntl1($window, $scope){
$scope.name = 'World';
$scope.greet = function() {
($window.mockWindow || $window).alert('Hello ' + this.name);
}
}
</script>
<div class="example2" ng-controller="Cntl1">
Name: <input ng-model="name" type="text"/>
<button ng-click="greet()">Greet</button>
</div>
</doc:source>
<doc:scenario>
it('should calculate expression in binding', function() {
var alertText;
this.addFutureAction('set mock', function($window, $document, done) {
$window.mockWindow = {
alert: function(text){ alertText = text; }
};
done();
});
element(':button:contains(Greet)').click();
expect(this.addFuture('alert text', function(done) {
done(null, alertText);
})).toBe('Hello World');
});
</doc:scenario>
</doc:example>
## Forgiving
Expression evaluation is forgiving to undefined and null. In JavaScript, evaluating `a.b.c` throws
an exception if `a` is not an object. While this makes sense for a general purpose language, the
expression evaluations are primarily used for data binding, which often look like this:
{{a.b.c}}
It makes more sense to show nothing than to throw an exception if `a` is undefined (perhaps we are
waiting for the server response, and it will become defined soon). If expression evaluation wasn't
forgiving we'd have to write bindings that clutter the code, for example: `{{((a||{}).b||{}).c}}`
Similarly, invoking a function `a.b.c()` on undefined or null simply returns undefined.
Assignments work the same way in reverse:
a.b.c = 10
...creates the intermediary objects even if a is undefined.
## No Control Flow Statements
You cannot write a control flow statement in an expression. The reason behind this is core to the
angular philosophy that application logic should be in controllers, not in the view. If you need a
conditional (including ternary operators), loop, or to throw from a view expression, delegate to a
JavaScript method instead.
## Type Augmentation
Built-in types have methods like `[].push()`, but the richness of these methods is limited.
Consider the example below, which allows you to do a simple search over a canned set of contacts.
The example would be much more complicated if we did not have the `Array:$filter()`. There is no
built-in method on `Array` called {@link api/angular.module.ng.$filter.filter $filter} and angular doesn't add
it to `Array.prototype` because that could collide with other JavaScript frameworks.
For this reason the scope expression evaluator augments the built-in types to make them act like
they have extra methods. The actual method for `$filter()` is `angular.module.ng.$filter.filter()`. You can
call it from JavaScript.
Extensions: You can further extend the expression vocabulary by adding new methods to
`angular.module.ng.$filter` or `angular.String`, etc.
<doc:example>
<doc:source>
<div ng-init="friends = [
{name:'John', phone:'555-1212'},
{name:'Mary', phone:'555-9876'},
{name:'Mike', phone:'555-4321'},
{name:'Adam', phone:'555-5678'},
{name:'Julie', phone:'555-8765'}]"></div>
Search: <input ng-model="searchText"/>
<table class="example3">
<thead>
<tr><th>Name</th><th>Phone</th><tr>
</thead>
<tbody>
<tr ng-repeat="friend in friends | filter:searchText">
<td>{{friend.name}}</td>
<td>{{friend.phone}}</td>
</tr>
</tbody>
</table>
</doc:source>
<doc:scenario>
it('should filter the list', function() {
var tr = using('table.example3 tbody').repeater('tr');
expect(tr.count()).toBe(5);
input('searchText').enter('a');
expect(tr.count()).toBe(2);
});
</doc:scenario>
</doc:example>
## Filters
When presenting data to the user, you might need to convert the data from its raw format to a
user-friendly format. For example, you might have a data object that needs to be formatted
according to the locale before displaying it to the user. You can pass expressions through a chain
of filters like this:
name | uppercase
The expression evaluator simply passes the value of name to angular.module.ng.$filter.uppercase.
Chain filters using this syntax:
value | filter1 | filter2
You can also pass colon-delimited arguments to filters, for example, to display the number 123 with
2 decimal points:
123 | number:2
# The $
You might be wondering, what is the significance of the $ prefix? It is simply a prefix that
angular uses, to differentiate its API names from others. If angular didn't use $, then evaluating
`a.length()` would return undefined because neither a nor angular define such a property.
Consider that in a future version of angular we might choose to add a length method, in which case
the behavior of the expression would change. Worse yet, you the developer could create a length
property and then we would have a collision. This problem exists because angular augments existing
objects with additional behavior. By prefixing its additions with $ we are reserving our namespace
so that angular developers and developers who use angular can develop in harmony without collisions.
## Related Topics
* {@link dev_guide.templates.filters Understanding Angular Filters}
## Related API
* {@link api/angular.module.ng.$compile Angular Compiler API}
+328
View File
@@ -0,0 +1,328 @@
@ngdoc overview
@name Developer Guide: Forms
@description
Controls (`input`, `select`, `textarea`) are a way for user to enter data.
Form is a collection of controls for the purpose of grouping related controls together.
Form and controls provide validation services, so that the user can be notified of invalid input.
This provides a better user experience, because the user gets instant feedback on how to correct the error.
Keep in mind that while client-side validation plays an important role in providing good user experience, it can easily be circumvented and thus can not be trusted.
Server-side validation is still necessary for a secure application.
# Simple form
The key directive in understanding two-way data-binding is {@link api/angular.module.ng.$compileProvider.directive.ng-model ng-model}.
The `ng-model` provides the two-way data-binding by synchronizing the model to the view, as well as view to the model.
In addition it provides {@link api/angular.module.ng.$compileProvider.directive.ng-model.NgModelController API} for other directives to augment its behavior.
<doc:example>
<doc:source>
<div ng-controller="Controller">
<form novalidate class="simple-form">
Name: <input type="text" ng-model="user.name" ng-model-instant /><br />
E-mail: <input type="email" ng-model="user.email" /><br />
Gender: <input type="radio" ng-model="user.gender" value="male" />male
<input type="radio" ng-model="user.gender" value="female" />female<br />
<button ng-click="reset()">RESET</button>
<button ng-click="update(user)">SAVE</button>
</form>
<pre>form = {{user | json}}</pre>
<pre>master = {{master | json}}</pre>
</div>
<script type="text/javascript">
function Controller($scope) {
$scope.master= {};
$scope.update = function(user) {
$scope.master= angular.copy(user);
};
$scope.reset = function() {
$scope.user = angular.copy($scope.master);
};
$scope.reset();
}
</script>
</doc:source>
</doc:example>
Note that:
* the {@link api/angular.module.ng.$compileProvider.directive.ng-model-instant ng-model-instant} causes the `user.name` to be updated immediately.
* `novalidate` is used to disable browser's native form validation.
# Using CSS classes
To allow styling of form as well as controls, `ng-model` add these CSS classes:
- `ng-valid`
- `ng-invalid`
- `ng-pristine`
- `ng-dirty`
Following example uses the CSS to display validity of each form control.
In the example both `user.name` and `user.email` are required, but are rendered with red background only when they are dirty.
This ensures that the user is not distracted with an error until after interacting with the control, and failing to satisfy its validity.
<doc:example>
<doc:source>
<div ng-controller="Controller">
<form novalidate class="css-form">
Name:
<input type="text" ng-model="user.name" ng-model-instant required /><br />
E-mail: <input type="email" ng-model="user.email" required /><br />
Gender: <input type="radio" ng-model="user.gender" value="male" />male
<input type="radio" ng-model="user.gender" value="female" />female<br />
<button ng-click="reset()">RESET</button>
<button ng-click="update(user)">SAVE</button>
</form>
</div>
<style type="text/css">
.css-form input.ng-invalid.ng-dirty {
background-color: #FA787E;
}
.css-form input.ng-valid.ng-dirty {
background-color: #78FA89;
}
</style>
<script type="text/javascript">
function Controller($scope) {
$scope.master= {};
$scope.update = function(user) {
$scope.master= angular.copy(user);
};
$scope.reset = function() {
$scope.user = angular.copy($scope.master);
};
$scope.reset();
}
</script>
</doc:source>
</doc:example>
# Binding to form and control state
A form is in instance of {@link api/angular.module.ng.$compileProvider.directive.form.FormController FormController}.
The form instance can optionally be published into the scope using the `name` attribute.
Similarly control is an instance of {@link api/angular.module.ng.$compileProvider.directive.ng-model.NgModelController NgModelController}.
The control instance can similarly be published into the form instance using the `name` attribute.
This implies that the internal state of both the form and the control is available for binding in the view using the standard binding primitives.
This allows us to extend the above example with these features:
- RESET button is enabled only if form has some changes
- SAVE button is enabled only if form has some changes and is valid
- custom error messages for `user.email` and `user.agree`
<doc:example>
<doc:source>
<div ng-controller="Controller">
<form name="form" class="css-form" novalidate>
Name:
<input type="text" ng-model="user.name" name="uName" required /><br />
E-mail:
<input type="email" ng-model="user.email" name="uEmail" required/><br />
<div ng-show="form.uEmail.$dirty && form.uEmail.$invalid">Invalid:
<span ng-show="form.uEmail.$error.required">Tell us your email.</span>
<span ng-show="form.uEmail.$error.email">This is not a valid email.</span>
</div>
Gender: <input type="radio" ng-model="user.gender" value="male" />male
<input type="radio" ng-model="user.gender" value="female" />female<br />
<input type="checkbox" ng-model="user.agree" name="userAgree" required />
I agree: <input ng-show="user.agree" type="text" ng-model="user.agreeSign"
ng-model-instant required /><br />
<div ng-show="!user.agree || !user.agreeSign">Please agree and sign.</div>
<button ng-click="reset()" disabled="{{isUnchanged(user)}}">RESET</button>
<button ng-click="update(user)"
disabled="{{form.$invalid || isUnchanged(user)}}">SAVE</button>
</form>
</div>
<script type="text/javascript">
function Controller($scope) {
$scope.master= {};
$scope.update = function(user) {
$scope.master= angular.copy(user);
};
$scope.reset = function() {
$scope.user = angular.copy($scope.master);
};
$scope.isUnchanged = function(user) {
return angular.equals(user, $scope.master);
};
$scope.reset();
}
</script>
</doc:source>
</doc:example>
# Custom Validation
Angular provides basic implementation for most common html5 {@link api/angular.module.ng.$compileProvider.directive.input input}
types: ({@link api/angular.module.ng.$compileProvider.directive.input.text text}, {@link api/angular.module.ng.$compileProvider.directive.input.number number}, {@link api/angular.module.ng.$compileProvider.directive.input.url url}, {@link api/angular.module.ng.$compileProvider.directive.input.email email}, {@link api/angular.module.ng.$compileProvider.directive.input.radio radio}, {@link api/angular.module.ng.$compileProvider.directive.input.checkbox checkbox}), as well as some directives for validation (`required`, `pattern`, `minlength`, `maxlength`, `min`, `max`).
Defining your own validator can be done by defining your own directive which adds a custom validation function to the `ng-model` {@link api/angular.module.ng.$compileProvider.directive.ng-model.NgModelController controller}.
To get a hold of the controller the directive specifies a dependency as shown in the example below.
The validation can occur in two places:
* **Model to View update** -
Whenever the bound model changes, all functions in {@link api/angular.module.ng.$compileProvider.directive.ng-model.NgModelController#$formatters NgModelController#$formatters} array are pipe-lined, so that each of these functions has an opportunity to format the value and change validity state of the form control through {@link api/angular.module.ng.$compileProvider.directive.ng-model.NgModelController#$setValidity NgModelController#$setValidity}.
* **View to Model update** -
In a similar way, whenever a user interacts with a control, the controll calls {@link api/angular.module.ng.$compileProvider.directive.ng-model.NgModelController#$setViewValue NgModelController#$setViewValue}.
This in turn pipelines all functions in {@link api/angular.module.ng.$compileProvider.directive.ng-model.NgModelController#$parsers NgModelController#$parsers} array, so that each of these functions has an opportunity to convert the value and change validity state of the form control through {@link api/angular.module.ng.$compileProvider.directive.ng-model.NgModelController#$setValidity NgModelController#$setValidity}.
In the following example we create two directives.
* The first one is `integer` and it validates whether the input is a valid integer.
For example `1.23` is an invalid value, since it contains a fraction.
Note, that we unshift the array instead of pushing.
This is because we want to be first parser and consume the control string value, as we need to execute the validation function before a conversion to number occurs.
* The second directive is a `smart-float`.
It parses both `1.2` and `1,2` into a valid float number `1.2`.
Note that, we can't use input type `number` here as HTML5 browsers would not allow the user to type what it would consider an invalid number such as `1,2`.
<doc:example module="form-example1">
<doc:source>
<div ng-controller="Controller">
<form name="form" class="css-form" novalidate>
<div>
Size (integer 0 - 10):
<input type="number" ng-model="size" name="size"
min="0" max="10" integer />{{size}}<br />
<span ng-show="form.size.$error.integer">This is not valid integer!</span>
<span ng-show="form.size.$error.min || form.size.$error.max">
The value must be in range 0 to 10!</span>
</div>
<div>
Length (float):
<input type="text" ng-model="length" name="length" smart-float />
{{length}}<br />
<span ng-show="form.length.$error.float">
This is not a valid float number!</span>
</div>
</form>
</div>
<script type="text/javascript">
var app = angular.module('form-example1', []);
var INTEGER_REGEXP = /^\-?\d*$/;
app.directive('integer', function() {
return {
require: 'ngModel',
link: function(scope, elm, attrs, ctrl) {
ctrl.$parsers.unshift(function(viewValue) {
if (INTEGER_REGEXP.test(viewValue)) {
// it is valid
ctrl.$setValidity('integer', true);
return viewValue;
} else {
// it is invalid, return undefined (no model update)
ctrl.$setValidity('integer', false);
return undefined;
}
});
}
};
});
var FLOAT_REGEXP = /^\-?\d+((\.|\,)\d+)?$/;
app.directive('smartFloat', function() {
return {
require: 'ngModel',
link: function(scope, elm, attrs, ctrl) {
ctrl.$parsers.unshift(function(viewValue) {
if (FLOAT_REGEXP.test(viewValue)) {
ctrl.$setValidity('float', true);
return parseFloat(viewValue.replace(',', '.'));
} else {
ctrl.$setValidity('float', false);
return undefined;
}
});
}
};
});
</script>
</doc:source>
</doc:example>
# Implementing custom form control (using ng-model)
Angular implements all of the basic HTML form controls ({@link api/angular.module.ng.$compileProvider.directive.input input}, {@link api/angular.module.ng.$compileProvider.directive.select select}, {@link api/angular.module.ng.$compileProvider.directive.textarea textarea}), which should be sufficient for most cases.
However, if you need more flexibility, you can write your own form control as a directive.
In order for custom control to work with `ng-model` and to achieve two-way data-binding it needs to:
- implement `render` method, which is responsible for rendering the data after it passed the {@link api/angular.module.ng.$compileProvider.directive.ng-model.NgModelController#$formatters NgModelController#$formatters},
- call `$setViewValue` method, whenever the user interacts with the control and model needs to be updated. This is usually done inside a DOM Event listener.
See {@link api/angular.module.ng.$compileProvider.directive $compileProvider.directive} for more info.
The following example shows how to add two-way data-binding to contentEditable elements.
<doc:example module="form-example2">
<doc:source>
<script type="text/javascript">
angular.module('form-example2', []).directive('contenteditable', function() {
return {
require: 'ngModel',
link: function(scope, elm, attrs, ctrl) {
// view -> model
elm.bind('blur', function() {
scope.$apply(function() {
ctrl.$setViewValue(elm.html());
});
});
// model -> view
ctrl.render = function(value) {
elm.html(value);
};
// load init value from DOM
ctrl.$setViewValue(elm.html());
}
};
});
</script>
<div contentEditable="true" ng-model="content" title="Click to edit">Some</div>
<pre>model = {{content}}</pre>
<style type="text/css">
div[contentEditable] {
cursor: pointer;
background-color: #D0D0D0;
}
</style>
</doc:source>
</doc:example>
+124
View File
@@ -0,0 +1,124 @@
@ngdoc overview
@name Developer Guide: i18n and l10n
@description
# I18n and L10n in AngularJS
**What is i18n and l10n?**
Internationalization, abbreviated i18n, is the process of developing products in such a way that
they can be localized for languages and cultures easily. Localization, abbreviated l10n, is the
process of adapting applications and text to enable their usability in a particular cultural or
linguistic market. For application developers, internationalizing an application means abstracting
all of the strings and other locale-specific bits (such as date or currency formats) out of the
application. Localizing an application means providing translations and localized formats for the
abstracted bits.
**What level of support for i18n/l10n is currently in Angular?**
Currently, Angular supports i18n/l10n for {@link
http://docs.angularjs.org/#!/api/angular.module.ng.$filter.date datetime}, {@link
http://docs.angularjs.org/#!/api/angular.module.ng.$filter.number number} and {@link
http://docs.angularjs.org/#!/api/angular.module.ng.$filter.currency currency} filters.
Additionally, Angular supports localizable pluralization support provided by the {@link
api/angular.module.ng.$compileProvider.directive.ng-pluralize ng-pluralize directive}.
All localizable Angular components depend on locale-specific rule sets managed by the {@link
api/angular.module.ng.$locale $locale service}.
For readers who want to jump straight into examples, we have a few web pages that showcase how to
use Angular filters with various locale rule sets. You can find these examples either on {@link
https://github.com/angular/angular.js/tree/master/i18n/e2e Github} or in the i18n/e2e folder of
Angular development package.
**What is a locale id?**
A locale is a specific geographical, political, or cultural region. The most commonly used locale
ID consists of two parts: language code and country code. For example, en-US, en-AU, zh-CN are all
valid locale IDs that have both language codes and country codes. Because specifying a country code
in locale ID is optional, locale IDs such as en, zh, and sk are also valid. See the {@link
http://userguide.icu-project.org/locale ICU } website for more information about using locale IDs.
**Supported locales in Angular**
Angular separates number and datetime format rule sets into different files, each file for a
particular locale. You can find a list of currently supported locales {@link
https://github.com/angular/angular.js/tree/master/i18n/locale here}
# Providing locale rules to Angular
There are two approaches to providing locale rules to Angular:
**1. Pre-bundled rule sets**
You can pre-bundle the desired locale file with Angular by concatenating the content of the
locale-specific file to the end of `angular.js` or `angular.min.js` file.
For example on *nix, to create a an angular.js file that contains localization rules for german
locale, you can do the following:
`cat angular.js i18n/angular-locale_de-ge.js > angular_de-ge.js`
When the application containing `angular_de-ge.js` script instead of the generic angular.js script
starts, Angular is automatically pre-configured with localization rules for the german locale.
**2. Including locale js script in index.html page**
You can also include the locale specific js file in the index.html page. For example, if one client
requires German locale, you would serve index_de-ge.html which will look something like this:
<pre>
<html ng-app>
<head>
….
<script src="angular.js"></script>
<script src="i18n/angular-locale_de-ge.js"></script>
….
</head>
</html>
</pre>
**Comparison of the two approaches**
Both approaches described above requires you to prepare different index.html pages or js files for
each locale that your app may be localized into. You also need to configure your server to serve
the correct file that correspond to the desired locale.
However, the second approach (Including locale js script in index.html page) is likely to be slower
because an extra script needs to be loaded.
# "Gotchas"
**Currency symbol "gotcha"**
Angular's {@link http://docs.angularjs.org/#!/api/angular.module.ng.$filter.currency currency filter} allows
you to use the default currency symbol from the {@link api/angular.module.ng.$locale locale service},
or you can provide the filter with a custom currency symbol. If your app will be used only in one
locale, it is fine to rely on the default currency symbol. However, if you anticipate that viewers
in other locales might use your app, you should provide your own currency symbol to make sure the
actual value is understood.
For example, if you want to display account balance of 1000 dollars with the following binding
containing currency filter: `{{ 1000 | currency }}`, and your app is currently in en-US locale.
'$1000.00' will be shown. However, if someone in a different local (say, Japan) views your app, her
browser will specify the locale as ja, and the balance of '¥1000.00' will be shown instead. This
will really upset your client.
In this case, you need to override the default currency symbol by providing the {@link
http://docs.angularjs.org/#!/api/angular.module.ng.$filter.currency currency filter} with a currency symbol as
a parameter when you configure the filter, for example, {{ 1000 | currency:"USD$"}}. This way,
Angular will always show a balance of 'USD$1000' and disregard any locale changes.
**Translation length "gotcha"**
Keep in mind that translated strings/datetime formats can vary greatly in length. For example,
`June 3, 1977` will be translated to Spanish as `3 de junio de 1977`. There are bound to be other
more extreme cases. Hence, when internationalizing your apps, you need to apply CSS rules
accordingly and do thorough testing to make sure UI components do not overlap.
**Timezones**
Keep in mind that Angular datetime filter uses the time zone settings of the browser. So the same
application will show different time information depending on the time zone settings of the
computer that the application is running on. Neither Javascript nor Angular currently supports
displaying the date with a timezone specified by the developer.
@@ -0,0 +1,42 @@
@ngdoc overview
@name Developer Guide: Introduction
@description
Angular is pure client-side technology, written entirely in JavaScript. It works with the
long-established technologies of the web (HTML, CSS, and JavaScript) to make the development of web
apps easier and faster than ever before.
One important way that angular simplifies web development is by increasing the level of abstraction
between the developer and most low-level web app development tasks. Angular automatically takes
care of many of these tasks, including:
* DOM Manipulation
* Setting Up Listeners and Notifiers
* Input Validation
Because angular handles much of the work involved in these tasks, developers can concentrate more
on application logic and less on repetitive, error-prone, lower-level coding.
At the same time that angular simplifies the development of web apps, it brings relatively
sophisticated techniques to the client-side, including:
* Separation of data, application logic, and presentation components
* Data Binding between data and presentation components
* Services (common web app operations, implemented as substitutable objects)
* Dependency Injection (used primarily for wiring together services)
* An extensible HTML compiler (written entirely in JavaScript)
* Ease of Testing
These techniques have been for the most part absent from the client-side for far too long.
## Single-page / Round-trip Applications
You can use angular to develop both single-page and round-trip apps, but angular is designed
primarily for developing single-page apps. Angular supports browser history, forward and back
buttons, and bookmarking in single-page apps.
You normally wouldn't want to load angular with every page change, as would be the case with using
angular in a round-trip app. However, it would make sense to do so if you were adding a subset of
angular's features (for example, templates to leverage angular's data-binding feature) to an
existing round-trip app. You might follow this course of action if you were migrating an older app
to a single-page angular app.
+24
View File
@@ -0,0 +1,24 @@
@ngdoc overview
@name Developer Guide: About MVC in Angular
@description
While Model-View-Controller (MVC) has acquired different shades of meaning over the years since it
first appeared, angular incorporates the basic principles behind the original {@link
http://en.wikipedia.org/wiki/Modelviewcontroller MVC} software design pattern into its way of
building client-side web applications.
The MVC pattern greatly summarized:
* Separate applications into distinct presentation, data, and logic components
* Encourage loose coupling between these components
Along with {@link dev_guide.services services} and {@link dev_guide.di dependency injection}, MVC
makes angular applications better structured, easier to maintain and more testable.
The following topics explain how angular incorporates the MVC pattern into the angular way of
developing web applications:
* {@link dev_guide.mvc.understanding_model Understanding the Model Component}
* {@link dev_guide.mvc.understanding_controller Understanding the Controller Component}
* {@link dev_guide.mvc.understanding_view Understanding the View Component}
@@ -0,0 +1,259 @@
@ngdoc overview
@name Developer Guide: About MVC in Angular: Understanding the Controller Component
@description
In angular, a controller is a JavaScript function(type/class) that is used to augment instances of
angular {@link dev_guide.scopes Scope}, excluding the root scope. When you or angular create a new
child scope object via the {@link api/angular.module.ng.$rootScope.Scope#$new scope.$new} API , there is an
option to pass in a controller as a method argument. This will tell angular to associate the
controller with the new scope and to augment its behavior.
Use controllers to:
- Set up the initial state of a scope object.
- Add behavior to the scope object.
# Setting up the initial state of a scope object
Typically, when you create an application you need to set up an initial state for an angular scope.
Angular applies (in the sense of JavaScript's `Function#apply`) the controller constructor function
to a new angular scope object, which sets up an initial scope state. This means that angular never
creates instances of the controller type (by invoking the `new` operator on the controller
constructor). Constructors are always applied to an existing scope object.
You set up the initial state of a scope by creating model properties. For example:
function GreetingCtrl($scope) {
$scope.greeting = 'Hola!';
}
The `GreetingCtrl` controller creates a `greeting` model which can be referred to in a template.
When a controller function is applied to an angular scope object, the `this` of the controller
function becomes the scope of the angular scope object, so any assignment to `this` within the
controller function happens on the angular scope object.
# Adding Behavior to a Scope Object
Behavior on an angular scope object is in the form of scope method properties available to the
template/view. This behavior interacts with and modifies the application model.
As discussed in the {@link dev_guide.mvc.understanding_model Model} section of this guide, any
objects (or primitives) assigned to the scope become model properties. Any functions assigned to
the scope, along with any prototype methods of the controller type, become functions available in
the template/view, and can be invoked via angular expressions and `ng-` event handlers (e.g. {@link
api/angular.module.ng.$compileProvider.directive.ng-click ng-click}). These controller methods are always evaluated within the
context of the angular scope object that the controller function was applied to (which means that
the `this` keyword of any controller method is always bound to the scope that the controller
augments). This is how the second task of adding behavior to the scope is accomplished.
# Using Controllers Correctly
In general, a controller shouldn't try to do too much. It should contain only the business logic
needed for a single view.
The most common way to keep controllers slim is by encapsulating work that doesn't belong to
controllers into services and then using these services in controllers via dependency injection.
This is discussed in the {@link dev_guide.di Dependency Injection} {@link dev_guide.services
Services} sections of this guide.
Do not use controllers for:
- Any kind of DOM manipulation — Controllers should contain only business logic. DOM
manipulation—the presentation logic of an application—is well known for being hard to test.
Putting any presentation logic into controllers significantly affects testability of the business
logic. Angular offers {@link dev_guide.templates.databinding} for automatic DOM manipulation. If
you have to perform your own manual DOM manipulation, encapsulate the presentation logic in
{@link api/angular.module.ng.$compileProvider.directive directives}.
- Input formatting — Use {@link dev_guide.forms angular form controls} instead.
- Output filtering — Use {@link dev_guide.templates.filters angular filters} instead.
- Run stateless or stateful code shared across controllers — Use {@link dev_guide.services angular
services} instead.
- Instantiate or manage the life-cycle of other components (for example, to create service
instances).
# Associating Controllers with Angular Scope Objects
You can associate controllers with scope objects explicitly via the {@link api/angular.module.ng.$rootScope.Scope#$new
scope.$new} api or implicitly via the {@link api/angular.module.ng.$compileProvider.directive.ng-controller ng-controller
directive} or {@link api/angular.module.ng.$route $route service}.
## Controller Constructor and Methods Example
To illustrate how the controller component works in angular, let's create a little app with the
following components:
- A {@link dev_guide.templates template} with two buttons and a simple message
- A model consisting of a string named `spice`
- A controller with two functions that set the value of `spice`
The message in our template contains a binding to the `spice` model, which by default is set to the
string "very". Depending on which button is clicked, the `spice` model is set to `chili` or
`jalapeño`, and the message is automatically updated by data-binding.
## A Spicy Controller Example
<pre>
<body ng-controller="SpicyCtrl">
<button ng-click="chiliSpicy()">Chili</button>
<button ng-click="jalapenoSpicy()">Jalapeño</button>
<p>The food is {{spice}} spicy!</p>
</body>
function SpicyCtrl($scope) {
$scope.spice = 'very';
$scope.chiliSpicy = function() {
this.spice = 'chili';
}
}
SpicyCtrl.prototype.jalapenoSpicy = function() {
this.spice = 'jalapeño';
}
</pre>
Things to notice in the example above:
- The `ng-controller` directive is used to (implicitly) create a scope for our template, and the
scope is augmented (managed) by the `SpicyCtrl` controller.
- `SpicyCtrl` is just a plain JavaScript function. As an (optional) naming convention the name
starts with capital letter and ends with "Ctrl" or "Controller".
- The JavaScript keyword `this` in the `SpicyCtrl` function is bound to the scope that the
controller augments.
- Assigning a property to `this` creates or updates the model.
- Controller methods can be created through direct assignment to scope (the `chiliSpicy` method) or
as prototype methods of the controller constructor function(the `jalapenoSpicy` method)
- Both controller methods are available in the template (for the `body` element and and its
children).
Controller methods can also take arguments, as demonstrated in the following variation of the
previous example.
## Controller Method Arguments Example
<pre>
<body ng-controller="SpicyCtrl">
<input ng-model="customSpice" value="wasabi">
<button ng-click="spicy('chili')">Chili</button>
<button ng-click="spicy(customSpice)">Custom spice</button>
<p>The food is {{spice}} spicy!</p>
</body>
function SpicyCtrl($scope) {
$scope.spice = 'very';
$scope.spicy = function(spice) {
this.spice = spice;
}
}
</pre>
Notice that the `SpicyCtrl` controller now defines just one method called `spicy`, which takes one
argument called `spice`. The template then refers to this controller method and passes in a string
constant `'chili'` in the binding for the first button and a model property `spice` (bound to an
input box) in the second button.
## Controller Inheritance Example
Controller inheritance in angular is based on {@link api/angular.module.ng.$rootScope.Scope Scope} inheritance. Let's
have a look at an example:
<pre>
<body ng-controller="MainCtrl">
<p>Good {{timeOfDay}}, {{name}}!</p>
<div ng-controller="ChildCtrl">
<p>Good {{timeOfDay}}, {{name}}!</p>
<p ng-controller="BabyCtrl">Good {{timeOfDay}}, {{name}}!</p>
</body>
function MainCtrl($scope) {
$scope.timeOfDay = 'morning';
$scope.name = 'Nikki';
}
function ChildCtrl($scope) {
$scope.name = 'Mattie';
}
function BabyCtrl($scope) {
$scope.timeOfDay = 'evening';
$scope.name = 'Gingerbreak Baby';
}
</pre>
Notice how we nested three `ng-controller` directives in our template. This template construct will
result in 4 scopes being created for our view:
- The root scope
- The `MainCtrl` scope, which contains `timeOfDay` and `name` models
- The `ChildCtrl` scope, which shadows the `name` model from the previous scope and inherits the
`timeOfDay` model
- The `BabyCtrl` scope, which shadows both the `timeOfDay` model defined in `MainCtrl` and `name`
model defined in the ChildCtrl
Inheritance works between controllers in the same way as it does with models. So in our previous
examples, all of the models could be replaced with controller methods that return string values.
Note: Standard prototypical inheritance between two controllers doesn't work as one might expect,
because as we mentioned earlier, controllers are not instantiated directly by angular, but rather
are applied to the scope object.
## Testing Controllers
The way to test a controller depends upon how complicated the controller is.
- If your controller doesn't use DI or scope methods — create the controller with the `new`
operator and test away. For example:
Controller Function:
<pre>
function myController() {
this.spices = [{"name":"pasilla", "spiciness":"mild"},
{"name":"jalapeno", "spiceiness":"hot hot hot!"},
{"name":"habanero", "spiceness":"LAVA HOT!!"}];
this.spice = "habanero";
}
</pre>
Controller Test:
<pre>
describe('myController function', function() {
describe('myController', function() {
var ctrl;
beforeEach(function() {
ctrl = new myController();
});
it('should create "spices" model with 3 spices', function() {
expect(ctrl.spices.length).toBe(3);
});
it('should set the default value of spice', function() {
expect(ctrl.spice).toBe('habanero');
});
});
});
</pre>
- If your controller does use DI or scope methods — create a root scope, then create the controller
in the root scope with `scope.$new(MyController)`. Test the controller using `$eval`, if necessary.
- If you need to test a nested controller that depends on its parent's state — create a root scope,
create a parent scope, create a child scope, and test the controller using $eval if necessary.
## Related Topics
* {@link dev_guide.mvc About MVC in Angular}
* {@link dev_guide.mvc.understanding_model Understanding the Model Component}
* {@link dev_guide.mvc.understanding_view Understanding the View Component}
@@ -0,0 +1,71 @@
@ngdoc overview
@name Developer Guide: About MVC in Angular: Understanding the Model Component
@description
Depending on the context of the discussion in angular documentation, the term _model_ can refer to
either a single object representing one entity (for example, a model called "phones" with its value
being an array of phones) or the entire data model for the application (all entities).
In angular, a model is any data that is reachable as a property of an angular {@link
dev_guide.scopes Scope} object. The name of the property is the model identifier and the value is
any JavaScript object (including arrays and primitives).
The only requirement for a JavaScript object to be a model in angular is that the object must be
referenced by an angular scope as a property of that scope object. This property reference can be
created explicitly or implicitly.
You can create models by explicitly creating scope properties referencing JavaScript objects in the
following ways:
* Make a direct property assignment to the scope object in JavaScript code; this most commonly
occurs in controllers:
function MyCtrl($scope) {
// create property 'foo' on the MyCtrl's scope
// and assign it an initial value 'bar'
$scope.foo = 'bar';
}
* Use an {@link dev_guide.expressions angular expression} with an assignment operator in templates:
<button ng-click="{{foos='ball'}}">Click me</button>
* Use {@link api/angular.module.ng.$compileProvider.directive.ng-init ng-init directive} in templates (for toy/example apps
only, not recommended for real applications):
<body ng-init=" foo = 'bar' ">
Angular creates models implicitly (by creating a scope property and assigning it a suitable value)
when processing the following template constructs:
* Form input, select, textarea and other form elements:
<input ng-model="query" value="fluffy cloud">
The code above creates a model called "query" on the current scope with the value set to "fluffy
cloud".
* An iterator declaration in {@link api/angular.module.ng.$compileProvider.directive.ng-repeat ng-repeater}:
<p ng-repeat="phone in phones"></p>
The code above creates one child scope for each item in the "phones" array and creates a "phone"
object (model) on each of these scopes with its value set to the value of "phone" in the array.
In angular, a JavaScript object stops being a model when:
* No angular scope contains a property that references the object.
* All angular scopes that contain a property referencing the object become stale and eligible for
garbage collection.
The following illustration shows a simple data model created implicitly from a simple template:
<img src="img/guide/about_model_final.png">
## Related Topics
* {@link dev_guide.mvc About MVC in Angular}
* {@link dev_guide.mvc.understanding_controller Understanding the Controller Component}
* {@link dev_guide.mvc.understanding_view Understanding the View Component}
@@ -0,0 +1,22 @@
@ngdoc overview
@name Developer Guide: About MVC in Angular: Understanding the View Component
@description
In angular, the view is the DOM loaded and rendered in the browser, after angular has transformed
the DOM based on information in the template, controller and model.
<img src="img/guide/about_view_final.png">
In the angular implementation of MVC, the view has knowledge of both the model and the controller.
The view knows about the model where two-way data-binding occurs. The view has knowledge of the
controller through angular directives, such as {@link api/angular.module.ng.$compileProvider.directive.ng-controller
ng-controller} and {@link api/angular.module.ng.$compileProvider.directive.ng-view ng-view}, and through bindings of this form:
`{{someControllerFunction()}}`. In these ways, the view can call functions in an associated
controller function.
## Related Topics
* {@link dev_guide.mvc About MVC in Angular}
* {@link dev_guide.mvc.understanding_model Understanding the Model Component}
* {@link dev_guide.mvc.understanding_controller Understanding the Controller Component}
+236
View File
@@ -0,0 +1,236 @@
@ngdoc overview
@name Developer Guide: Overview
@description
# What Is Angular?
The short answer: angular is a new, powerful, client-side technology that makes it much easier for
you to create dynamic web sites and complex web apps, all without leaving the comfort of your HTML
/ JavaScript home.
The long answer: it depends on where you're coming from...
* If you're a web designer, you might perceive angular to be a sweet {@link dev_guide.templates
templating} system, that doesn't get in your way and provides you with lots of nice built-ins that
make it easier to do what you want to do.
* If you're a web developer, you might be thrilled that angular functions as an excellent web
framework, one that assists you all the way through the development cycle.
* If you want to go deeper, you can immerse yourself in angular's extensible HTML {@link
dev_guide.compiler compiler} that runs in your browser. The angular compiler teaches your browser
new tricks.
Angular is not just a templating system, but you can create fantastic templates with it. Angular is
not just a web framework, but it features a very nice framework. Angular is not just an extensible
HTML compiler, but the compiler is at the core of Angular. Angular includes all of these
components, along with others. Angular is far greater than the sum of its parts. It is a new,
better way to develop web applications!
## An Introductory Angular Example
Let's say that you are a web designer, and you've spent many thous — erm, hundreds of hours
designing web sites. But at this point, the thought of manipulating the DOM, writing listeners and
input validators, all just to implement a simple form? No. You either don't want to go there in
the first place or you've been there and the thrill is gone.
So look over the following simple example written using angular. Note that it features only the
templating aspect of angular, but this should suffice for now to quickly demonstrate how much
easier a web developer's life can if they're using angular:
<doc:example>
<doc:source>
<script>
function InvoiceCntl($scope) {
$scope.qty = 1;
$scope.cost = 19.95;
}
</script>
<div ng-controller="InvoiceCntl">
<b>Invoice:</b>
<br />
<br />
<table>
<tr><td> </td><td> </td>
<tr><td>Quantity</td><td>Cost</td></tr>
<tr>
<td><input type="integer" min="0" ng-model="qty" required ></td>
<td><input type="number" ng-model="cost" required ></td>
</tr>
</table>
<hr />
<b>Total:</b> {{qty * cost | currency}}
</div>
</doc:source>
<!--
<doc:scenario>
it('should show of angular binding', function() {
expect(binding('qty * cost')).toEqual('$19.95');
input('qty').enter('2');
input('cost').enter('5.00');
expect(binding('qty * cost')).toEqual('$10.00');
});
</doc:scenario>
-->
</doc:example>
Try out the Live Preview above, and then let's walk through the example and describe what's going
on.
In the `<html>` tag we specify that this is an angular application with the `ng-app` directive.
The `ng-app' will cause the angular to {@link dev_guide.bootstrap auto initialize} your application.
<html ng-app>
We load the angular using the `<script>` tag:
<script src="http://code.angularjs.org/angular-?.?.?.min.js"></script>
From the `ng-model` attribute of the `<input>` tags, angular automatically sets up two-way data
binding, and we also demonstrate some easy input validation:
Quantity: <input type="integer" min="0" ng-model="qty" required >
Cost: <input type="number" ng-model="cost" required >
These input widgets look normal enough, but consider these points:
* When this page loaded, angular bound the names of the input widgets (`qty` and `cost`) to
variables of the same name. Think of those variables as the "Model" component of the
Model-View-Controller design pattern.
* Note the angular/HTML widget, {@link api/angular.module.ng.$compileProvider.directive.input input}.
You may have noticed that when you enter invalid data
or leave the the input fields blank, the borders turn red color, and the display value disappears.
These widgets make it easier to implement field validation than coding them in JavaScript,
no? Yes.
And finally, the mysterious `{{ double curly braces }}`:
Total: {{qty * cost | currency}}
This notation, `{{ _expression_ }}`, is a bit of built-in angular binding markup, a shortcut for
displaying data to the user. The expression within curly braces is monitored and its evaluated value
is updated into the view by angular's template compiler. Alternatively, one could use angular's
{@link api/angular.module.ng.$compileProvider.directive.ng-bind ng-bind}) directive. The expression
itself can be a combination of both an expression and a {@link dev_guide.templates.filters filter}:
`{{ expression | filter }}`. Angular provides filters for formatting display data.
In the example above, the expression in double-curly braces directs angular to, "Bind the data we
got from the input widgets to the display, multiply them together, and format the resulting number
into output that looks like money."
# The Angular Philosophy
Angular is built around the belief that declarative code is better than imperative when it comes to
building UIs and wiring software components together, while imperative code is excellent for
expressing business logic.
Not to put too fine a point on it, but if you wanted to add a new label to your application, you
could do so by simply adding text to the HTML template, saving the code, and refreshing your
browser:
<pre>
<span class="label">Hello</span>
</pre>
Or, as in programmatic systems (like {@link http://code.google.com/webtoolkit/ GWT}), you would
have to write the code and then run the code like this:
<pre>
var label = new Label();
label.setText('Hello');
label.setClass('label');
parent.addChild(label);
</pre>
That's one line of markup versus four times as much code.
## More Angular Philosophy
* It is a very good idea to decouple DOM manipulation from app logic. This dramatically improves
the testability of the code.
* It is a really, _really_ good idea to regard app testing as equal in importance to app writing.
Testing difficulty is dramatically affected by the way the code is structured.
* It is an excellent idea to decouple the client side of an app from the server side. This allows
development work to progress in parallel, and allows for reuse of both sides.
* It is very helpful indeed if the framework guides developers through the entire journey of
building an app: from designing the UI, through writing the business logic, to testing.
* It is always good to make common tasks trivial and difficult tasks possible.
Now that we're homing in on what angular is, perhaps now would be a good time to list a few things
that angular is not:
* It's not a Library. You don't just call its functions, although it does provide you with some
utility APIs.
* It's not a DOM Manipulation Library. Angular uses jQuery to manipulate the DOM behind the scenes,
rather than give you functions to manipulate the DOM yourself.
* It's not a Widget Library. There are lots of existing widget libraries that you can integrate
with angular.
* It's not "Just Another Templating System". A part of angular is a templating system. The
templating subsystem of angular is different from the traditional approach for these reasons:
* It Uses HTML/CSS syntax: This makes it easy to read and can be edited with existing HTML/CSS
authoring tools.
* It Extends HTML vocabulary: Angular allows you to create new HTML tags, which expand into
dynamic UI components.
* It Executes in the browser: Removes the round trip to the server for many operations and
creates instant feedback for users as well as developers.
* It Has Bidirectional data binding: The model is the single source of truth. Programmatic
changes to the model are automatically reflected in the view. Any changes by the user to the view
are automatically reflected in the model.
# Why You Want Angular
Angular frees you from the following pain:
* **Registering callbacks:** Registering callbacks clutters your code, making it hard to see the
forest for the trees. Removing common boilerplate code such as callbacks is a good thing. It vastly
reduces the amount of JavaScript coding _you_ have to do, and it makes it easier to see what your
application does.
* **Manipulating HTML DOM programatically:** Manipulating HTML DOM is a cornerstone of AJAX
applications, but it's cumbersome and error-prone. By declaratively describing how the UI should
change as your application state changes, you are freed from low level DOM manipulation tasks. Most
applications written with angular never have to programatically manipulate the DOM, although you
can if you want to.
* **Marshaling data to and from the UI:** CRUD operations make up the majority of AJAX
applications. The flow of marshaling data from the server to an internal object to an HTML form,
allowing users to modify the form, validating the form, displaying validation errors, returning to
an internal model, and then back to the server, creates a lot of boilerplate code. Angular
eliminates almost all of this boilerplate, leaving code that describes the overall flow of the
application rather than all of the implementation details.
* **Writing tons of initialization code just to get started:** Typically you need to write a lot of
plumbing just to get a basic "Hello World" AJAX app working. With angular you can bootstrap your
app easily using services, which are auto-injected into your application in a {@link
http://code.google.com/p/google-guice/ Guice}-like dependency-injection style. This allows you to
get started developing features quickly. As a bonus, you get full control over the initialization
process in automated tests.
# Watch a Presentation About Angular
Here is an early presentation on angular, but note that substantial development has occurred since
the talk was given in July of 2010.
<object width="480" height="385">
<param name="movie" value="http://www.youtube.com/v/elvcgVSynRg&amp;hl=en_US&amp;fs=1"></param>
<param name="allowFullScreen" value="true"></param>
<param name="allowscriptaccess" value="always"></param>
<embed src="http://www.youtube.com/v/elvcgVSynRg&amp;hl=en_US&amp;fs=1"
type="application/x-shockwave-flash" allowscriptaccess="always"
allowfullscreen="true" width="480" height="385"></embed>
</object>
{@link
https://docs.google.com/present/edit?id=0Abz6S2TvsDWSZDQ0OWdjaF8yNTRnODczazdmZg&hl=en&authkey=CO-b7oID
Presentation}
|
{@link
https://docs.google.com/document/edit?id=1ZHVhqC0apbzPRQcgnb1Ye-bAUbNJ-IlFMyPBPCZ2cYU&hl=en&authkey=CInnwLYO
Source}
@@ -0,0 +1,230 @@
@ngdoc overview
@name Developer Guide: Scopes: Scope Internals
@description
## What is a scope?
A scope is an execution context for {@link dev_guide.expressions expressions}. You can think of a
scope as a JavaScript object that has an extra set of APIs for registering change listeners and for
managing its own life cycle. In Angular's implementation of the model-view-controller design
pattern, a scope's properties comprise both the model and the controller methods.
### Scope characteristics
- Scopes provide APIs ({@link api/angular.module.ng.$rootScope.Scope#$watch $watch}) to observe model mutations.
- Scopes provide APIs ({@link api/angular.module.ng.$rootScope.Scope#$apply $apply}) to propagate any model changes
through the system into the view from outside of the "Angular realm" (controllers, services,
Angular event handlers).
- Scopes can be nested to isolate application components while providing access to shared model
properties. A scope (prototypically) inherits properties from its parent scope.
- In some parts of the system (such as controllers, services and directives), the scope is made
available as `this` within the given context. (Note: This api will change before 1.0 is released.)
### Root scope
Every application has a root scope, which is the ancestor of all other scopes.
### What is scope used for?
{@link dev_guide.expressions Expressions} in the view are {@link api/angular.module.ng.$rootScope.Scope#$eval evaluated}
against the current scope. When HTML DOM elements are attached to a scope, expressions in those
elements are evaluated against the attached scope.
There are two kinds of expressions:
- Binding expressions, which are observations of property changes. Property changes are reflected
in the view during the {@link api/angular.module.ng.$rootScope.Scope#$digest digest cycle}.
- Action expressions, which are expressions with side effects. Typically, the side effects cause
execution of a method in a controller in response to a user action, such as clicking on a button.
### Scope inheritance
A scope (prototypically) inherits properties from its parent scope. Since a given property may not
reside on a child scope, if a property read does not find the property on a scope, the read will
recursively check the parent scope, grandparent scope, etc. all the way to the root scope before
defaulting to undefined.
{@link api/angular.module.ng.$compileProvider.directive directives} associated with elements
(ng-controller, ng-repeat, ng-include, etc.) create new child scopes that inherit properties from
the current parent scope. Any code in Angular is free to create a new scope. Whether or not your
code does so is an implementation detail of the directive, that is, you can decide when or if this
happens. Inheritance typically mimics HTML DOM element nesting, but does not do so with the same
granularity.
A property write will always write to the current scope. This means that a write can hide a parent
property within the scope it writes to, as shown in the following example.
<pre>
it('should inherit properties', inject(function($rootScope)) {
var root = $rootScope;
var child = root.$new();
root.name = 'angular';
expect(child.name).toEqual('angular');
expect(root.name).toEqual('angular');
child.name = 'super-heroic framework';
expect(child.name).toEqual('super-heroic framework');
expect(root.name).toEqual('angular');
});
</pre>
### Scope life cycle
1. **Creation**
* The root scope is created by the {@link api/angular.module.ng.$rootScope $rootScope} service.
* To create a child scopes, you should call {@link api/angular.module.ng.$rootScope.Scope#$new parentScope.$new()}.
2. **Watcher registration**
Watcher registration can happen at any time and on any scope (root or child) via {@link
api/angular.module.ng.$rootScope.Scope#$watch scope.$watch()} API.
3. **Model mutation**
For mutations to be properly observed, you should make them only within the execution of the
function passed into {@link api/angular.module.ng.$rootScope.Scope#$apply scope.$apply()} call. (Angular apis do this
implicitly, so no extra `$apply` call is needed when doing synchronous work in controllers, or
asynchronous work with {@link api/angular.module.ng.$http $http} or {@link api/angular.module.ng.$defer
$defer} services.
4. **Mutation observation**
At the end of each `$apply` call {@link api/angular.module.ng.$rootScope.Scope#$digest $digest} cycle is started on
the root scope, which then propagates throughout all child scopes.
During the `$digest` cycle, all `$watch-ers` expressions or functions are checked for model
mutation and if a mutation is detected, the `$watch-er` listener is called.
5. **Scope destruction**
When child scopes are no longer needed, it is the responsibility of the child scope creator to
destroy them via {@link api/angular.module.ng.$rootScope.Scope#$destroy scope.$destroy()} API. This will stop
propagation of `$digest` calls into the child scope and allow for memory used by the child scope
models to be reclaimed by the garbage collector.
The root scope can't be destroyed via the `$destroy` API. Instead, it is enough to remove all
references from your application to the scope object and garbage collector will do its magic.
## Scopes in Angular applications
To understand how Angular applications work, you need to understand how scopes work within an
application. This section describes the typical life cycle of an application so you can see how
scopes come into play throughout and get a sense of their interactions.
### How scopes interact in applications
1. At application compile time, a root scope is created and is attached to the root `<HTML>` DOM
element.
2. During the compilation phase, the {@link dev_guide.compiler compiler} matches {@link
api/angular.module.ng.$compileProvider.directive directives} against the DOM template. The directives
usually fall into one of two categories:
- Observing {@link api/angular.module.ng.$compileProvider.directive directives}, such as double-curly
expressions `{{expression}}`, register listeners using the {@link
api/angular.module.ng.$rootScope.Scope#$watch $watch()} method. This type of directive needs to
be notified whenever the expression changes so that it can update the view.
- Listener directives, such as {@link api/angular.module.ng.$compileProvider.directive.ng-click
ng-click}, register a listener with the DOM. When the DOM listener fires, the directive executes
the associated expression and updates the view using the {@link
api/angular.module.ng.$rootScope.Scope#$apply $apply()} method.
3. When an external event (such as a user action, timer or XHR) is received, the associated {@link
dev_guide.expressions expression} must be applied to the scope through the {@link
api/angular.module.ng.$rootScope.Scope#$apply $apply()} method so that all listeners are updated correctly.
### Directives that create scopes
In most cases, {@link api/angular.module.ng.$compileProvider.directive directives} and scopes interact but do not create new
instances of scope. However, some directives, such as {@link api/angular.module.ng.$compileProvider.directive.ng-controller
ng-controller} and {@link api/angular.module.ng.$compileProvider.directive.ng-repeat ng-repeat}, create new child scopes using
the {@link api/angular.module.ng.$rootScope.Scope#$new $new()} method and then attach the child scope to the
corresponding DOM element. You can retrieve a scope for any DOM element by using an
`angular.element(aDomElement).scope()` method call.)
### Controllers and scopes
Scopes and controllers interact with each other in the following situations:
- Controllers use scopes to expose controller methods to templates (see {@link
api/angular.module.ng.$compileProvider.directive.ng-controller ng-controller}).
- Controllers define methods (behavior) that can mutate the model (properties on the scope).
- Controllers may register {@link api/angular.module.ng.$rootScope.Scope#$watch watches} on the model. These watches
execute immediately after the controller behavior executes, but before the DOM gets updated.
See the {@link dev_guide.mvc.understanding_controller controller docs} for more information.
### Updating scope properties
You can update a scope by calling its {@link api/angular.module.ng.$rootScope.Scope#$apply $apply()} method with an
expression or a function as the function argument. However it is typically not necessary to do this
explicitly. In most cases, angular intercepts all external events (such as user interactions, XHRs,
and timers) and wraps their callbacks into the `$apply()` method call on the scope object for you
at the right time. The only time you might need to call `$apply()` explicitly is when you create
your own custom asynchronous widget or service.
The reason it is unnecessary to call `$apply()` from within your controller functions when you use
built-in angular widgets and services is because your controllers are typically called from within
an `$apply()` call already.
When a user inputs data, angularized widgets invoke `$apply()` on the current scope and evaluate an
angular expression or execute a function on this scope. Afterwards `$apply` will trigger `$digest`
call on the root scope, to propagate your changes through the entire system, which results in
$watch-ers firing and view getting updated. Similarly, when a request to fetch data from a server
is made and the response comes back, the data is written into the model (scope) within an $apply,
which then pushes updates through to the view and any other dependents.
A widget that creates scopes (such as {@link api/angular.module.ng.$compileProvider.directive.ng-repeat ng-repeat}) via `$new`,
doesn't need to worry about propagating the `$digest` call from the parent scope to child scopes.
This happens automatically.
## Scopes in unit-testing
You can create scopes, including the root scope, in tests by having the $rootScope injected into
your spec. This allows you to mimic the run-time environment and have full control over
the life cycle of the scope so that you can assert correct model transitions. Since these scopes
are created outside the normal compilation process, their life cycles must be managed by the test.
### Using scopes in unit-testing
The following example demonstrates how the scope life cycle needs to be manually triggered from
within the unit-tests.
<pre>
// example of a test
it('should trigger a watcher', inject(function($rootScope) {
var scope = $rootScope;
scope.$watch('name', function(name) {
scope.greeting = 'Hello ' + name + '!';
});
scope.name = 'angular';
// The watch does not fire yet since we have to manually trigger the digest phase.
expect(scope.greeting).toEqual(undefined);
// manually trigger digest phase from the test
scope.$digest();
expect(scope.greeting).toEqual('Hello Angular!');
}
</pre>
### Dependency injection in Tests
When you find it necessary to inject your own mocks in your tests, use a scope to override the
service instances, as shown in the following example.
<pre>
it('should allow override of providers', inject(
function($provide) {
$provide.value('$location', {mode:'I am a mock'});
},
function($location){
expect($location.mode).toBe('I am a mock');
}
)};
</pre>
## Related Topics
* {@link dev_guide.scopes Angular Scope Objects}
* {@link dev_guide.scopes.understanding_scopes Understanding Scopes}
## Related API
* {@link api/angular.module.ng.$rootScope.Scope Angular Scope API}
+35
View File
@@ -0,0 +1,35 @@
@ngdoc overview
@name Developer Guide: Scopes
@description
An Angular scope is a JavaScript object with additional APIs useful for watching property changes,
Angular scope is the model in Model-View-Controller paradigm. Instances of scope serve as the
context within which all {@link dev_guide.expressions expressions} get evaluated.
You can think of Angular scope objects as the medium through which the model, view, and controller
communicate. Scopes are linked during the compilation process with the view. This linkage provides
the contexts in which Angular creates data-bindings between the model and the view.
In addition to providing the context in which data is evaluated, Angular scope objects watch for
model changes. The scope objects also notify all components interested in any model changes (for
example, functions registered through {@link api/angular.module.ng.$rootScope.Scope#$watch $watch}, bindings created by
{@link api/angular.module.ng.$compileProvider.directive.ng-bind ng-bind}, or HTML input elements).
Angular scope objects:
* Link the model, controller and view template together.
* Provide the mechanism to watch for model changes ({@link api/angular.module.ng.$rootScope.Scope#$watch $watch}).
* Apply model changes to the system ({@link api/angular.module.ng.$rootScope.Scope#$apply $apply}).
* Provide the context in which expressions are evaluated ({@link api/angular.module.ng.$rootScope.Scope#$eval $eval}).
## Related Topics
* {@link dev_guide.scopes.understanding_scopes Understanding Scopes}
* {@link dev_guide.scopes.internals Scopes Internals}
## Related API
* {@link api/angular.module.ng.$rootScope.Scope Angular Scope API}
@@ -0,0 +1,66 @@
@ngdoc overview
@name Developer Guide: Scopes: Understanding Scopes
@description
Angular automatically creates a root scope during initialization, and attaches it to the page's
root DOM element (usually `<html>`). The root scope object, along with any of its child scope
objects, serves as the infrastructure on which your data model is built. The data model (JavaScript
objects, arrays, or primitives) is attached to angular scope properties. Angular binds the property
values to the DOM where bindings are specified in the template. Angular attaches any controller
functions you have created to their respective scope objects.
<img src="img/guide/simple_scope_final.png">
Angular scopes can be nested, so a child scope has a parent scope upstream in the DOM. When you
display an angular expression in the view, angular walks the DOM tree looking in the closest
attached scope object for the specified data. If it doesn't find the data in the closest attached
scope, it looks further up the scope hierarchy until it finds the data.
A child scope object inherits properties from its parents. For example, in the following snippet of
code, observe how the value of `name` changes, based on the HTML element it is displayed in:
<doc:example>
<doc:source>
<ul ng-init="name='Hank'; names=['Igor', 'Misko', 'Gail', 'Kai']">
<li ng-repeat="name in names">
Name = {{name}}!
</li>
</ul>
<pre>Name={{name}}</pre>
</doc:source>
<doc:scenario>
it('should override the name property', function() {
expect(using('.doc-example-live').repeater('li').row(0)).
toEqual(['Igor']);
expect(using('.doc-example-live').repeater('li').row(1)).
toEqual(['Misko']);
expect(using('.doc-example-live').repeater('li').row(2)).
toEqual(['Gail']);
expect(using('.doc-example-live').repeater('li').row(3)).
toEqual(['Kai']);
expect(using('.doc-example-live').element('pre').text()).
toBe('Name=Hank');
});
</doc:scenario>
</doc:example>
The angular {@link api/angular.module.ng.$compileProvider.directive.ng-repeat ng-repeat} directive creates a new scope for each
element that it repeats (in this example the elements are list items). In the `<ul>` element, we
initialized `name` to "Hank", and we created an array called `names` to use as the data source for
the list items. In each `<li>` element, `name` is overridden. Outside of the `<li>` repeater, the
original value of `name` is displayed.
The following illustration shows the DOM and angular scopes for the example above:
<img src="img/guide/dom_scope_final.png">
## Related Topics
* {@link dev_guide.scopes Angular Scope Objects}
* {@link dev_guide.scopes.internals Scopes Internals}
## Related API
* {@link api/angular.module.ng.$rootScope.Scope Angular Scope API}
@@ -0,0 +1,636 @@
@ngdoc overview
@name Developer Guide: Angular Services: Using $location
@description
# What does it do?
The `$location` service parses the URL in the browser address bar (based on the {@link
https://developer.mozilla.org/en/window.location window.location}) and makes the URL available to
your application. Changes to the URL in the address bar are reflected into $location service and
changes to $location are reflected into the browser address bar.
**The $location service:**
- Exposes the current URL in the browser address bar, so you can
- Watch and observe the URL.
- Change the URL.
- Synchronizes the URL with the browser when the user
- Changes the address bar.
- Clicks the back or forward button (or clicks a History link).
- Clicks on a link.
- Represents the URL object as a set of methods (protocol, host, port, path, search, hash).
## Comparing $location to window.location
<table>
<thead>
<tr>
<td class="empty-corner-lt"></td>
<td>window.location</td>
<td>$location service</td>
</tr>
</thead>
<tbody>
<tr>
<td class="head">purpose</td>
<td>allow read/write access to the current browser location</td>
<td>same</td>
</tr>
<tr>
<td class="head">API</td>
<td>exposes "raw" object with properties that can be directly modified</td>
<td>exposes jQuery-style getters and setters</td>
</tr>
<tr>
<td class="head">integration with angular application life-cycle</td>
<td>none</td>
<td>knows about all internal life-cycle phases, integrates with $watch, ...</td>
</tr>
<tr>
<td class="head">seamless integration with HTML5 API</td>
<td>no</td>
<td>yes (with a fallback for legacy browsers)</td>
</tr>
<tr>
<td class="head">aware of docroot/context from which the application is loaded</td>
<td>no - window.location.path returns "/docroot/actual/path"</td>
<td>yes - $location.path() returns "/actual/path"</td>
</tr>
</tbody>
</table>
## When should I use $location?
Any time your application needs to react to a change in the current URL or if you want to change
the current URL in the browser.
## What does it not do?
Does not cause a full page reload when the browser URL is changed. To reload the page after
changing the URL, use the lower-level API, `$window.location.href`.
# General overview of the API
The `$location` service can behave differently, depending on the configuration that was provided to
it when it was instantiated. The default configuration is suitable for many applications, for
others customizing the configuration can enable new features.
Once the `$location` service is instantiated, you can interact with it via jQuery-style getter and
setter methods that allow you to get or change the current URL in the browser.
## $location service configuration
To configure the `$location` service, retrieve the
{@link api/angular.module.ng.$locationProvider $locationProvider} and set the parameters as follows:
- **html5Mode(mode)**: {boolean}<br />
`true` - see HTML5 mode<br />
`false` - see Hashbang mode<br />
default: `false`
- **hashPrefix(prefix)**: {string}<br />
prefix used for Hashbang URLs (used in Hashbang mode or in legacy browser in Html5 mode)<br />
default: `'!'`
### Example configuration
<pre>
$locationProvider.html5Mode(true).hashPrefix('!');
</pre>
## Getter and setter methods
`$location` service provides getter methods for read-only parts of the URL (absUrl, protocol, host,
port) and getter / setter methods for url, path, search, hash:
<pre>
// get the current path
$location.path();
// change the path
$location.path('/newValue')
</pre>
All of the setter methods return the same `$location` object to allow chaining. For example, to
change multiple segments in one go, chain setters like this:
<pre>$location.path('/newValue').search({key: value});</pre>
There is a special `replace` method which can be used to tell the $location service that the next
time the $location service is synced with the browser, the last history record should be replaced
instead of creating a new one. This is useful when you want to implement redirection, which would
otherwise break the back button (navigating back would retrigger the redirection). To change the
current URL without creating a new browser history record you can call:
<pre>
$location.path('/someNewPath');
$location.replace();
// or you can chain these as: $location.path('/someNewPath').replace();
</pre>
Note that the setters don't update `window.location` immediately. Instead, `$location` service is
aware of the {@link api/angular.module.ng.$rootScope.Scope scope} life-cycle and coalesces multiple `$location`
mutations into one "commit" to the `window.location` object during the scope `$digest` phase. Since
multiple changes to the $location's state will be pushed to the browser as a single change, it's
enough to call the `replace()` method just once to make the entire "commit" a replace operation
rather than addition to the browser history. Once the browser is updated, the $location service
resets the flag set by `replace()` method and future mutations will create new history records,
unless `replace()` is called again.
### Setters and character encoding
You can pass special characters to `$location` service and it will encode them according to rules
specified in {@link http://www.ietf.org/rfc/rfc3986.txt RFC 3986}. When you access the methods:
- All values that are passed to `$location` setter methods, `path()`, `search()`, `hash()`, are
encoded.
- Getters (calls to methods without parameters) return decoded values for the following methods
`path()`, `search()`, `hash()`.
- When you call the `absUrl()` method, the returned value is a full url with its segments encoded.
- When you call the `url()` method, the returned value is path, search and hash, in the form
`/path?search=a&b=c#hash`. The segments are encoded as well.
# Hashbang and HTML5 Modes
`$location` service has two configuration modes which control the format of the URL in the browser
address bar: **Hashbang mode** (the default) and the **HTML5 mode** which is based on using the
HTML5 {@link http://www.w3.org/TR/html5/history.html History API}. Applications use the same API in
both modes and the `$location` service will work with appropriate URL segments and browser APIs to
facilitate the browser URL change and history management.
<img src="img/guide/hashbang_vs_regular_url.jpg">
<table>
<thead>
<tr>
<td class="empty-corner-lt"></td>
<td>Hashbang mode</td>
<td>HTML5 mode</td>
</tr>
</thead>
<tbody>
<tr>
<td class="head">configuration</td>
<td>the default</td>
<td>{ html5Mode: true }</td>
</tr>
<tr>
<td class="head">URL format</td>
<td>hashbang URLs in all browsers</td>
<td>regular URLs in modern browser, hashbang URLs in old browser</td>
</tr>
<tr>
<td class="head">&lt;a href=""&gt; link rewriting</td>
<td>no</td>
<td>yes</td>
</tr>
<tr>
<td class="head">requires server-side configuration</td>
<td>no</td>
<td>yes</td>
</tr>
</tbody>
</table>
## Hashbang mode (default mode)
In this mode, `$location` uses Hashbang URLs in all browsers.
### Example
<pre>
it('should show example', inject(
function($locationProvider) {
$locationProvider.html5mode = false;
$locationProvider.hashPrefix = '!';
},
function($location) {
// open http://host.com/base/index.html#!/a
$location.absUrl() == 'http://host.com/base/index.html#!/a'
$location.path() == '/a'
$location.path('/foo')
$location.absUrl() == 'http://host.com/base/index.html#!/foo'
$location.search() == {}
$location.search({a: 'b', c: true});
$location.absUrl() == 'http://host.com/base/index.html#!/foo?a=b&c'
$location.path('/new').search('x=y');
$location.absUrl() == 'http://host.com/base/index.html#!/new?x=y'
}
));
</pre>
### Crawling your app
To allow indexing of your AJAX application, you have to add special meta tag in the head section of
your document:
<pre><meta name="fragment" content="!" /></pre>
This will cause crawler bot to request links with `_escaped_fragment_` param so that your server
can recognize the crawler and serve a HTML snapshots. For more information about this technique,
see {@link http://code.google.com/web/ajaxcrawling/docs/specification.html Making AJAX Applications
Crawlable}.
## HTML5 mode
In HTML5 mode, the `$location` service getters and setters interact with the browser URL address
through the HTML5 history API, which allows for use of regular URL path and search segments,
instead of their hashbang equivalents. If the HTML5 History API is not supported by a browser, the
`$location` service will fall back to using the hashbang URLs automatically. This frees you from
having to worry about whether the browser displaying your app supports the history API or not; the
`$location` service transparently uses the best available option.
- Opening a regular URL in a legacy browser -> redirects to a hashbang URL
- Opening hashbang URL in a modern browser -> rewrites to a regular URL
### Example
<pre>
it('should show example', inject(
function($locationProvider) {
$locationProvider.html5mode = true;
$locationProvider.hashPrefix = '!';
},
function($location) {
// in browser with HTML5 history support:
// open http://host.com/#!/a -> rewrite to http://host.com/a
// (replacing the http://host.com/#!/a history record)
$location.path() == '/a'
$location.path('/foo');
$location.absUrl() == 'http://host.com/foo'
$location.search() == {}
$location.search({a: 'b', c: true});
$location.absUrl() == 'http://host.com/foo?a=b&c'
$location.path('/new').search('x=y');
$location.url() == 'new?x=y'
$location.absUrl() == 'http://host.com/new?x=y'
// in browser without html5 history support:
// open http://host.com/new?x=y -> redirect to http://host.com/#!/new?x=y
// (again replacing the http://host.com/new?x=y history item)
$location.path() == '/new'
$location.search() == {x: 'y'}
$location.path('/foo/bar');
$location.path() == '/foo/bar'
$location.url() == '/foo/bar?x=y'
$location.absUrl() == 'http://host.com/#!/foo/bar?x=y'
}
));
</pre>
### Fallback for legacy browsers
For browsers that support the HTML5 history API, `$location` uses the HTML5 history API to write
path and search. If the history API is not supported by a browser, `$location` supplies a Hasbang
URL. This frees you from having to worry about whether the browser viewing your app supports the
history API or not; the `$location` service makes this transparent to you.
### Html link rewriting
When you use the history API mode, you will need different links in different browser, but all you
have to do is specify regular URL links, such as: `&lt;a href="/some?foo=bar"&gt;link&lt;/a&gt;`
When a user clicks on this link,
- In a legacy browser, the URL changes to `/index.html#!/some?foo=bar`
- In a modern browser, the URL changes to `/some?foo=bar`
In cases like the following, links are not rewritten; instead, the browser will perform a full page
reload to the original link.
- Links with an `ng-ext-link` directive<br />
Example: `<a href="/ext/link?a=b" ng-ext-link>link</a>`
- Links that contain `target="_blank"`<br />
Example: `<a href="/ext/link?a=b" target="_blank">link</a>`
- Absolute links that go to a different domain<br />
Example: `<a href="http://angularjs.org/">link</a>`
### Server side
Using this mode requires URL rewriting on server side, basically you have to rewrite all your links
to entry point of your application (e.g. index.html)
### Crawling your app
If you want your AJAX application to be indexed by web crawlers, you rill need to add the following
meta tag to the HEAD section of your document:
<pre><meta name="fragment" content="!" /></pre>
This statement causes a crawler to request links with empty `_escaped_fragment_` parameter so that
your server can recognize the crawler and serve it HTML snapshots. For more information about this
technique, see {@link http://code.google.com/web/ajaxcrawling/docs/specification.html Making AJAX
Applications Crawlable}.
### Relative links
Be sure to check all relative links, images, scripts etc. You must use an absolute path because the
path is going to be rewritten. You can use `<base href="" />` tag as well.
Running Angular apps with the History API enabled from document root is strongly encouraged as it
takes care of all relative link issues. **Otherwise you have to specify &lt;base href="" /&gt; !**
### Sending links among different browsers
Because of rewriting capability in HTML5 mode, your users will be able to open regular url links in
legacy browsers and hashbang links in modern browser:
- Modern browser will rewrite hashbang URLs to regular URLs.
- Older browsers will redirect regular URLs to hashbang URLs.
### Example
Here you can see two `$location` instances, both in **Html5 mode**, but on different browsers, so
that you can see the differences. These `$location` services are connected to a fake browsers. Each
input represents address bar of the browser.
Note that when you type hashbang url into first browser (or vice versa) it doesn't rewrite /
redirect to regular / hashbang url, as this conversion happens only during parsing the initial URL
= on page reload.
In this examples we use `<base href="/base/index.html" />`
<doc:example>
<doc:source source="false">
<div ng-non-bindable class="html5-hashbang-example">
<div id="html5-mode" ng-controller="Html5Cntl">
<h3>Browser with History API</h3>
<ng-address-bar browser="html5"></ng-address-bar><br /><br />
$location.protocol() = {{$location.protocol()}}<br />
$location.host() = {{$location.host()}}<br />
$location.port() = {{$location.port()}}<br />
$location.path() = {{$location.path()}}<br />
$location.search() = {{$location.search()}}<br />
$location.hash() = {{$location.hash()}}<br />
<a href="/base/first?a=b">/base/first?a=b</a> |
<a href="sec/ond?flag#hash">sec/ond?flag#hash</a> |
<a href="/base/another?search" ng-ext-link>external</a>
</div>
<div id="hashbang-mode" ng-controller="HashbangCntl">
<h3>Browser without History API</h3>
<ng-address-bar browser="hashbang"></ng-address-bar><br /><br />
$location.protocol() = {{$location.protocol()}}<br />
$location.host() = {{$location.host()}}<br />
$location.port() = {{$location.port()}}<br />
$location.path() = {{$location.path()}}<br />
$location.search() = {{$location.search()}}<br />
$location.hash() = {{$location.hash()}}<br />
<a href="/base/first?a=b">/base/first?a=b</a> |
<a href="sec/ond?flag#hash">sec/ond?flag#hash</a> |
<a href="/base/another?search" ng-ext-link>external</a>
</div>
</div>
<script type="text/javascript">
function FakeBrowser(initUrl, baseHref) {
this.onUrlChange = function(fn) {
this.urlChange = fn;
};
this.url = function() {
return initUrl;
};
this.defer = function(fn, delay) {
setTimeout(function() { fn(); }, delay || 0);
};
this.baseHref = function() {
return baseHref;
};
this.hover = angular.noop;
this.notifyWhenOutstandingRequests = angular.noop;
}
var browsers = {
html5: new FakeBrowser('http://www.host.com/base/path?a=b#h', '/base/index.html'),
hashbang: new FakeBrowser('http://www.host.com/base/index.html#!/path?a=b#h', '/base/index.html')
};
function Html5Cntl($location) {
this.$location = $location;
}
function HashbangCntl($location) {
this.$location = $location;
}
function initEnv(name) {
var root = angular.element(document.getElementById(name + '-mode'));
angular.bootstrap(root, [function($compileProvider, $locationProvider, $provide){
$locationProvider.html5Mode = true;
$locationProvider.hashPrefix = '!';
$provide.value('$browser', browsers[name]);
$provide.value('$document', root);
$provide.value('$sniffer', {history: name == 'html5'});
$compileProvider.directive('ngAddressBar', function() {
return function(scope, elm, attrs) {
var browser = browsers[attrs.browser],
input = angular.element('<input type="text" />').val(browser.url()),
delay;
input.bind('keypress keyup keydown', function() {
if (!delay) {
delay = setTimeout(fireUrlChange, 250);
}
});
browser.url = function(url) {
return input.val(url);
};
elm.append('Address: ').append(input);
function fireUrlChange() {
delay = null;
browser.urlChange(input.val());
}
};
});
}]);
root.bind('click', function(e) {
e.stopPropagation();
});
}
initEnv('html5');
initEnv('hashbang');
</script>
</doc:source>
</doc:example>
# Caveats
## Page reload navigation
The `$location` service allows you to change only the URL; it does not allow you to reload the
page. When you need to change the URL and reload the page or navigate to a different page, please
use a lower level API, {@link api/angular.module.ng.$window $window.location.href}.
## Using $location outside of the scope life-cycle
`$location` knows about Angular's {@link api/angular.module.ng.$rootScope.Scope scope} life-cycle. When a URL changes in
the browser it updates the `$location` and calls `$apply` so that all $watchers / $observers are
notified.
When you change the `$location` inside the `$digest` phase everything is ok; `$location` will
propagate this change into browser and will notify all the $watchers / $observers.
When you want to change the `$location` from outside Angular (for example, through a DOM Event or
during testing) - you must call `$apply` to propagate the changes.
## $location.path() and ! or / prefixes
A path should always begin with forward slash (`/`); the `$location.path()` setter will add the
forward slash if it is missing.
Note that the `!` prefix in the hashbang mode is not part of `$location.path()`; it is actually
hashPrefix.
# Testing with the $location service
When using `$location` service during testing, you are outside of the angular's {@link
api/angular.module.ng.$rootScope.Scope scope} life-cycle. This means it's your responsibility to call `scope.$apply()`.
<pre>
describe('serviceUnderTest', function() {
beforeEach(module(function($provide) {
$provide.factory('serviceUnderTest', function($location){
// whatever it does...
});
});
it('should...', inject(function($location, $rootScope, serviceUnderTest) {
$location.path('/new/path');
$rootScope.$apply();
// test whatever the service should do...
}));
});
</pre>
# Migrating from earlier AngularJS releases
In earlier releases of Angular, `$location` used `hashPath` or `hashSearch` to process path and
search methods. With this release, the `$location` service processes path and search methods and
then uses the information it obtains to compose hashbang URLs (such as
`http://server.com/#!/path?search=a`), when necessary.
## Changes to your code
<table>
<tr class="head">
<td>Navigation inside the app</td>
<td>Change to</td>
</tr>
<tr>
<td>$location.href = value<br />$location.hash = value<br />$location.update(value)<br
/>$location.updateHash(value)</td>
<td>$location.path(path).search(search)</td>
</tr>
<tr>
<td>$location.hashPath = path</td>
<td>$location.path(path)</td>
</tr>
<tr>
<td>$location.hashSearch = search</td>
<td>$location.search(search)</td>
</tr>
<tr class="head">
<td>Navigation outside the app</td>
<td>Use lower level API</td>
</tr>
<tr>
<td>$location.href = value<br />$location.update(value)</td>
<td>$window.location.href = value</td>
</tr>
<tr>
<td>$location[protocol | host | port | path | search]</td>
<td>$window.location[protocol | host | port | path | search]</td>
</tr>
<tr class="head">
<td>Read access</td>
<td>Change to</td>
</tr>
<tr>
<td>$location.hashPath</td>
<td>$location.path()</td>
</tr>
<tr>
<td>$location.hashSearch</td>
<td>$location.search()</td>
</tr>
<tr>
<td>$location.href<br />$location.protocol<br />$location.host<br />$location.port<br
/>$location.hash</td>
<td>$location.absUrl()<br />$location.protocol()<br />$location.host()<br />$location.port()<br
/>$location.path() + $location.search()</td>
</tr>
<tr>
<td>$location.path<br />$location.search</td>
<td>$window.location.path<br />$window.location.search</td>
</tr>
</table>
## Two-way binding to $location
The Angular's compiler currently does not support two-way binding for methods (see {@link
https://github.com/angular/angular.js/issues/404 issue}). If you should require two-way binding,
you will need to specify an extra property that has two watchers. For example:
<pre>
<!-- html -->
<input type="text" ng-model="locationPath" />
</pre>
<pre>
// js - controller
this.$watch('locationPath', function(path) {
$location.path(path);
});
this.$watch('$location.path()', function(path) {
scope.locationPath = path;
});
</pre>
# Related API
* {@link api/angular.module.ng.$location $location API}
@@ -0,0 +1,104 @@
@ngdoc overview
@name Developer Guide: Angular Services: Creating Services
@description
While angular offers several useful services, for any nontrivial application you'll find it useful
to write your own custom services. To do this you begin by registering a service factory function
with a module either via the {@link api/angular.module Module#factory api} or directly
via the {@link api/angular.module.AUTO.$provide $provide} api inside of module config function.
All angular services participate in {@link dev_guide.di dependency injection (DI)} by registering
themselves with Angular's DI system (injector) under a `name` (id) as well as by declaring
dependencies which need to be provided for the factory function of the registered service. The
ability to swap dependencies for mocks/stubs/dummies in tests allows for services to be highly
testable.
# Registering Services
To register a service, you must have a module that this service will be part of. Afterwards, you
can register the service with the module either via the {@link api/angular.Module Module api} or
by using the {@link api/angular.module.AUTO.$provide $provide} service in the module configuration
function.The following pseudo-code shows both approaches:
Using the angular.Module api:
<pre>
var myModule = angular.module('myModule', []);
myModule.factory('serviceId', function() {
var shinyNewServiceInstance;
//factory function body that constructs shinyNewServiceInstance
return shinyNewServiceInstance;
});
</pre>
Using the $provide service:
<pre>
angular.module('myModule', [], function($provide) {
$provide.factory('serviceId', function() {
var shinyNewServiceInstance;
//factory function body that constructs shinyNewServiceInstance
return shinyNewServiceInstance;
});
});
</pre>
Note that you are not registering a service instance, but rather a factory function that will
create this instance when called.
# Dependencies
Services can not only be depended upon, but also have its own dependencies. These can be specified
as arguments of the factory function. {@link dev_guide.di.understanding_di Read more} about the DI
in Angular and the use of array notation and $inject property to make DI annotation
minification-proof.
Following is an example of a very simple service. This service depends on the `$window` service
(which is passed as a parameter to the factory function) and is just a function. The service simply
stores all notifications; after the third one, the service displays all of the notifications by
window alert.
<pre>
angular.module('myModule', [], function($provide) {
$provide.factory('notify', ['$window', function(win) {
var msgs = [];
return function(msg) {
msgs.push(msg);
if (msgs.length == 3) {
win.alert(msgs.join("\n"));
msgs = [];
}
};
}]);
});
</pre>
# Instantiating Angular Services
All services in Angular are instantiates services lazily, this means that a service will be created
only when it is needed for instantiation of a service or an application component that depends on it.
In other words, angular won't instantiate lazy services unless they are requested directly or
indirectly by the application.
# Services as singletons
Lastly, it is important to realize that all angular services are application singletons. This means
that there is only one instance of a given service per injector. Since angular is lethally allergic
to the global state, it is possible to create multiple injectors, each with its own instance of a
given service, but that is rarely needed, except in tests where this property is crucially
important.
## Related Topics
* {@link dev_guide.services.understanding_services Understanding Angular Services}
* {@link dev_guide.services.managing_dependencies Managing Service Dependencies}
* {@link dev_guide.services.injecting_controllers Injecting Services Into Controllers }
* {@link dev_guide.services.testing_services Testing Angular Services}
## Related API
* {@link api/angular.module.ng Angular Service API}
@@ -0,0 +1,118 @@
@ngdoc overview
@name Developer Guide: Angular Services: Injecting Services Into Controllers
@description
Using services as dependencies for controllers is very similar to using services as dependencies
for another service.
Since JavaScript is a dynamic language, DI can't figure out which services to inject by static
types (like in static typed languages). Therefore, you can specify the service name by using the
`$inject` property, which is an array containing strings with names of services to be injected.
The name must match the corresponding service ID registered with angular. The order of the service
IDs matters: the order of the services in the array will be used when calling the factory function
with injected parameters. The names of parameters in factory function don't matter, but by
convention they match the service IDs, which has added benefits discussed below.
<pre>
function myController($loc, $log) {
this.firstMethod = function() {
// use $location service
$loc.setHash();
};
this.secondMethod = function() {
// use $log service
$log.info('...');
};
}
// which services to inject ?
myController.$inject = ['$location', '$log'];
</pre>
<doc:example module="MyServiceModule">
<doc:source>
<script type="text/javascript">
angular.
module('MyServiceModule', []).
factory('notify', ['$window', function(win) {
var msgs = [];
return function(msg) {
msgs.push(msg);
if (msgs.length == 3) {
win.alert(msgs.join("\n"));
msgs = [];
}
};
}]);
function myController(scope, notifyService) {
scope.callNotify = function(msg) {
notifyService(msg);
};
}
myController.$inject = ['$scope','notify'];
</script>
<div ng-controller="myController">
<p>Let's try this simple notify service, injected into the controller...</p>
<input ng-init="message='test'" ng-model="message" >
<button ng-click="callNotify(message);">NOTIFY</button>
</div>
</doc:source>
<doc:scenario>
it('should test service', function() {
expect(element(':input[ng\\:model="message"]').val()).toEqual('test');
});
</doc:scenario>
</doc:example>
## Implicit Dependency Injection
A new feature of Angular DI allows it to determine the dependency from the name of the parameter.
Let's rewrite the above example to show the use of this implicit dependency injection of
`$window`, `$scope`, and our `notify` service:
<doc:example module="MyServiceModuleDI">
<doc:source>
<script type="text/javascript">
angular.
module('MyServiceModuleDI', []).
factory('notify', function($window) {
var msgs = [];
return function(msg) {
msgs.push(msg);
if (msgs.length == 3) {
$window.alert(msgs.join("\n"));
msgs = [];
}
};
});
function myController($scope, notify) {
$scope.callNotify = function(msg) {
notify(msg);
};
}
</script>
<div ng-controller="myController">
<p>Let's try the notify service, that is implicitly injected into the controller...</p>
<input ng-init="message='test'" ng-model="message">
<button ng-click="callNotify(message);">NOTIFY</button>
</div>
</doc:source>
</doc:example>
However, if you plan to {@link http://en.wikipedia.org/wiki/Minification_(programming) minify} your
code, your variable names will get renamed in which case you will still need to explicitly specify
dependencies with the `$inject` property.
## Related Topics
{@link dev_guide.services.understanding_services Understanding Angular Services}
{@link dev_guide.services.creating_services Creating Angular Services}
{@link dev_guide.services.managing_dependencies Managing Service Dependencies}
{@link dev_guide.services.testing_services Testing Angular Services}
## Related API
{@link api/angular.module.ng Angular Service API}
@@ -0,0 +1,114 @@
@ngdoc overview
@name Developer Guide: Angular Services: Managing Service Dependencies
@description
Angular allows services to declare other services as dependencies needed for construction of their
instances.
To declare dependencies, you specify them in the factory function signature and annotate the
function with the inject annotations either using by setting the `$inject` property, as an array of
string identifiers or using the array notation. Optionally the `$inject` property declaration can be
dropped (see "Inferring `$inject`" but note that that is currently an experimental feature).
Using the array notation:
<pre>
function myModuleCfgFn($provide) {
$provide.factory('myService', ['dep1', 'dep2', function(dep1, dep2) {}]);
}
</pre>
Using the $inject property:
<pre>
function myModuleCfgFn($provide) {
var myServiceFactory = function(dep1, dep2) {};
myServiceFactory.$inject = ['dep1', 'dep2'];
$provide.factory('myService', myServiceFactory);
}
</pre>
Using DI inference (incompatible with minifiers):
<pre>
function myModuleCfgFn($provide) {
$provide.factory('myService', function(dep1, dep2) {});
}
</pre>
Here is an example of two services that depend on each other, as well as on other services that are
provided by Angular's web framework:
<pre>
/**
* batchLog service allows for messages to be queued in memory and flushed
* to the console.log every 50 seconds.
*
* @param {*} message Message to be logged.
*/
function batchLogModule($provide){
$provide.factory('batchLog', ['$defer', '$log', function($defer, $log) {
var messageQueue = [];
function log() {
if (messageQueue.length) {
$log('batchLog messages: ', messageQueue);
messageQueue = [];
}
$defer(log, 50000);
}
// start periodic checking
log();
return function(message) {
messageQueue.push(message);
}
}]);
/**
* routeTemplateMonitor monitors each $route change and logs the current
* template via the batchLog service.
*/
$provide.factory('routeTemplateMonitor',
['$route', 'batchLog', '$rootScope',
function($route, batchLog, $rootScope) {
$rootScope.$on('$afterRouteChange', function() {
batchLog($route.current ? $route.current.template : null);
});
}]);
}
// get the main service to kick of the application
angular.injector([batchLogModule]).get('routeTemplateMonitor');
</pre>
Things to notice in this example:
* The `batchLog` service depends on the built-in {@link api/angular.module.ng.$defer $defer} and
{@link api/angular.module.ng.$log $log} services, and allows messages to be logged into the
`console.log` in batches.
* The `routeTemplateMonitor` service depends on the built-in {@link api/angular.module.ng.$route
$route} service as well as our custom `batchLog` service.
* Both of our services use the factory function signature and array notation for inject annotations
to declare their dependencies. It is important that the order of the string identifiers in the array
is the same as the order of argument names in the signature of the factory function. Unless the
dependencies are inferred from the function signature, it is this array with IDs and their order
that the injector uses to determine which services and in which order to inject.
## Related Topics
* {@link dev_guide.services.understanding_services Understanding Angular Services}
* {@link dev_guide.services.creating_services Creating Angular Services}
* {@link dev_guide.services.injecting_controllers Injecting Services Into Controllers }
* {@link dev_guide.services.testing_services Testing Angular Services}
## Related API
* {@link api/angular.module.ng Angular Service API}
* {@link api/angular.injector Angular Injector API}
@@ -0,0 +1,21 @@
@ngdoc overview
@name Developer Guide: Angular Services
@description
Services are a feature that angular brings to client-side web apps from the server side, where
services have been commonly used for a long time. Services in angular apps are substitutable
objects that are wired together using {@link dev_guide.di dependency injection (DI)}. Services are
most often used with {@link dev_guide.di dependency injection}, also a key feature of angular apps.
## Related Topics
* {@link dev_guide.services.understanding_services Understanding Angular Services}
* {@link dev_guide.services.creating_services Creating Angular Services}
* {@link dev_guide.services.managing_dependencies Managing Service Dependencies}
* {@link dev_guide.services.injecting_controllers Injecting Services Into Controllers}
* {@link dev_guide.services.testing_services Testing Angular Services}
## Related API
* {@link api/angular.module.ng Angular Service API}
@@ -0,0 +1,62 @@
@ngdoc overview
@name Developer Guide: Angular Services: Testing Angular Services
@description
Following is a unit test for the service in the example in {@link
dev_guide.services.creating_services Creating Angular Services}. The unit test example uses Jasmine
spy (mock) instead of a real browser alert.
<pre>
var mock, notify;
beforeEach(function() {
mock = {alert: jasmine.createSpy()};
module(function($provide) {
$provide.value('$window', mock);
});
inject(function($injector) {
notify = $injector.get('notify');
});
});
it('should not alert first two notifications', function() {
notify('one');
notify('two');
expect(mock.alert).not.toHaveBeenCalled();
});
it('should alert all after third notification', function() {
notify('one');
notify('two');
notify('three');
expect(mock.alert).toHaveBeenCalledWith("one\ntwo\nthree");
});
it('should clear messages after alert', function() {
notify('one');
notify('two');
notify('third');
notify('more');
notify('two');
notify('third');
expect(mock.alert.callCount).toEqual(2);
expect(mock.alert.mostRecentCall.args).toEqual(["more\ntwo\nthird"]);
});
</pre>
## Related Topics
* {@link dev_guide.services.understanding_services Understanding Angular Services}
* {@link dev_guide.services.creating_services Creating Angular Services}
* {@link dev_guide.services.managing_dependencies Managing Service Dependencies}
* {@link dev_guide.services.injecting_controllers Injecting Services Into Conrollers}
## Related API
* {@link api/angular.module.ng Angular Service API}
@@ -0,0 +1,36 @@
@ngdoc overview
@name Developer Guide: Angular Services: Understanding Angular Services
@description
Angular services are singletons that carry out specific tasks common to web apps, such as the
{@link api/angular.module.ng.$http $http service} that provides low level access to the browser's
`XMLHttpRequest` object.
To use an angular service, you identify it as a dependency for the dependent (a controller, or
another service) that depends on the service. Angular's dependency injection subsystem takes care
of the rest. The angular injector subsystem is in charge of service instantiation, resolution of
dependencies, and provision of dependencies to factory functions as requested.
Angular injects dependencies using "constructor" injection (the service is passed in via a factory
function). Because JavaScript is a dynamically typed language, Angular's dependency injection
subsystem cannot use static types to identify service dependencies. For this reason a dependent
must explicitly define its dependencies by using the `$inject` property. For example:
myController.$inject = ['$location'];
The angular web framework provides a set of services for common operations. Like other core angular
variables and identifiers, the built-in services always start with `$` (such as `$http` mentioned
above). You can also create your own custom services.
## Related Topics
* {@link dev_guide.di About Angular Dependency Injection}
* {@link dev_guide.services.creating_services Creating Angular Services}
* {@link dev_guide.services.managing_dependencies Managing Service Dependencies}
* {@link dev_guide.services.testing_services Testing Angular Services}
## Related API
* {@link api/angular.module.ng Angular Service API}
* {@link api/angular.injector Injector API}
@@ -0,0 +1,23 @@
@ngdoc overview
@name Developer Guide: Templates: Working With CSS in Angular
@description
Angular sets these CSS classes. It is up to your application to provide useful styling.
# CSS classes used by angular
* `ng-invalid`, `ng-valid`
- **Usage:** angular applies this class to an input widget element if that element's input does
notpass validation. (see {@link api/angular.module.ng.$compileProvider.directive.input input} widget).
* `ng-pristine`, `ng-dirty`
- **Usage:** angular {@link api/angular.module.ng.$compileProvider.directive.input input} widget applies `ng-pristine` class
to a new input widget element which did not have user interaction. Once the user interacts with
the input widget the class is changed to `ng-dirty`.
## Related Topics
* {@link dev_guide.templates Angular Templates}
* {@link dev_guide.forms Angular Forms}
@@ -0,0 +1,38 @@
@ngdoc overview
@name Developer Guide: Templates: Data Binding in Angular
@description
Data-binding in angular web apps is the automatic syncing of data between the model and view
components. The way that angular implements data-binding lets you treat the model as the
single-source-of-truth in your application. The view is a projection of the model at all times.
When the model changes, the view reflects the change, and vice versa.
## Data Binding in Classical Template Systems
<img class="right" src="img/One_Way_Data_Binding.png"/>
Most templating systems bind data in only one direction: they merge template and model components
together into a view, as illustrated in the diagram. After the merge occurs, changes to the model
or related sections of the view are NOT automatically reflected in the view. Worse, any changes
that the user makes to the view are not reflected in the model. This means that the developer has
to write code that constantly syncs the view with the model and the model with the view.
## Data Binding in Angular Templates
<img class="right" src="img/Two_Way_Data_Binding.png"/>
The way angular templates works is different, as illustrated in the diagram. They are different
because first the template (which is the uncompiled HTML along with any additional markup or
directives) is compiled on the browser, and second, the compilation step produces a live view. We
say live because any changes to the view are immediately reflected in the model, and any changes in
the model are propagated to the view. This makes the model always the single-source-of-truth for
the application state, greatly simplifying the programing model for the developer. You can think of
the view as simply an instant projection of your model.
Because the view is just a projection of the model, the controller is completely separated from the
view and unaware of it. This makes testing a snap because it is easy to test your controller in
isolation without the view and the related DOM/browser dependency.
## Related Topics
* {@link dev_guide.scopes Angular Scopes}
* {@link dev_guide.templates Angular Templates}
@@ -0,0 +1,66 @@
@ngdoc overview
@name Developer Guide: Templates: Filters: Creating Angular Filters
@description
Writing your own filter is very easy: just define a JavaScript function on the `angular.module.ng.$filter`
object.
The framework passes in the input value as the first argument to your function. Any filter
arguments are passed in as additional function arguments.
You can use these variables in the function:
* `this` — The current scope.
* `this.$element` — The DOM element containing the binding. The `$element` variable allows the
filter to manipulate the DOM.
The following sample filter reverses a text string. In addition, it conditionally makes the
text upper-case and assigns color.
<doc:example module="MyReverseModule">
<doc:source>
<script type="text/javascript">
angular.module('MyReverseModule', []).
filter('reverse', function() {
return function(input, uppercase) {
var out = "";
for (var i = 0; i < input.length; i++) {
out = input.charAt(i) + out;
}
// conditional based on optional argument
if (uppercase) {
out = out.toUpperCase();
}
return out;
}
});
function Ctrl($scope) {
$scope.greeting = 'hello';
}
</script>
<div ng-controller="Ctrl">
<input ng-model="greeting" type="greeting"><br>
No filter: {{greeting}}<br>
Reverse: {{greeting|reverse}}<br>
Reverse + uppercase: {{greeting|reverse:true}}<br>
</div>
</doc:source>
<doc:scenario>
it('should reverse greeting', function() {
expect(binding('greeting|reverse')).toEqual('olleh');
input('greeting').enter('ABC');
expect(binding('greeting|reverse')).toEqual('CBA');
});
</doc:scenario>
</doc:example>
## Related Topics
* {@link dev_guide.templates.filters Understanding Angular Filters}
* {@link dev_guide.compiler Angular HTML Compiler}
## Related API
* {@link api/angular.module.ng.$filter Angular Filter API}
@@ -0,0 +1,28 @@
@ngdoc overview
@name Developer Guide: Templates: Understanding Angular Filters
@description
Angular filters format data for display to the user. In addition to formatting data, filters can
also modify the DOM. This allows filters to handle tasks such as conditionally applying CSS styles
to filtered output.
For example, you might have a data object that needs to be formatted according to the locale before
displaying it to the user. You can pass expressions through a chain of filters like this:
name | uppercase
The expression evaluator simply passes the value of name to
{@link api/angular.module.ng.$filter.uppercase uppercase filter}.
In addition to formatting data, filters can also modify the DOM. This allows filters to handle
tasks such as conditionally applying CSS styles to filtered output.
## Related Topics
* {@link dev_guide.templates.filters.using_filters Using Angular Filters}
* {@link dev_guide.templates.filters.creating_filters Creating Angular Filters}
## Related API
* {@link api/angular.module.ng.$filter Angular Filter API}
@@ -0,0 +1,40 @@
@ngdoc overview
@name Developer Guide: Templates: Filters: Using Angular Filters
@description
Filters can be part of any {@link api/angular.module.ng.$rootScope.Scope} evaluation but are typically used to format
expressions in bindings in your templates:
{{ expression | filter }}
Filters typically transform the data to a new data type, formatting the data in the process.
Filters can also be chained, and can take optional arguments.
You can chain filters using this syntax:
{{ expression | filter1 | filter2 }}
You can also pass colon-delimited arguments to filters, for example, to display the number 123 with
2 decimal points:
123 | number:2
Here are some examples that show values before and after applying different filters to an
expression in a binding:
* No filter: `{{1234.5678}}` => `1234.5678`
* Number filter: `{{1234.5678|number}}` => `1,234.57`. Notice the "," and rounding to two
significant digits.
* Filter with arguments: `{{1234.5678|number:5}}` => `1,234.56780`. Filters can take optional
arguments, separated by colons in a binding. For example, the "number" filter takes a number
argument that specifies how many digits to display to the right of the decimal point.
## Related Topics
* {@link dev_guide.templates.filters Understanding Angular Filters}
* {@link dev_guide.templates.filters.creating_filters Creating Angular Filters}
## Related API
* {@link api/angular.module.ng.$filter Angular Filter API}
@@ -0,0 +1,57 @@
@ngdoc overview
@name Developer Guide: Understanding Angular Templates
@description
An angular template is the declarative specification that, along with information from the model
and controller, becomes the rendered view that a user sees in the browser. It is the static DOM,
containing HTML, CSS, and angular-specific elements and angular-specific element attributes. The
angular elements and attributes direct angular to add behavior and transform the template DOM into
the dynamic view DOM.
These are the types of angular elements and element attributes you can use in a template:
* {@link api/angular.module.ng.$compileProvider.directive Directive} — An attribute or element that
augments an existing DOM element or represents a reusable DOM component - a widget.
* {@link api/angular.module.ng.$interpolate Markup} — The double
curly brace notation `{{ }}` to bind expressions to elements is built-in angular markup.
* {@link dev_guide.templates.filters Filter} — Formats your data for display to the user.
* {@link dev_guide.forms Form controls} — Lets you validate user input.
Note: In addition to declaring the elements above in templates, you can also access these elements
in JavaScript code.
The following code snippet shows a simple angular template made up of standard HTML tags along with
angular {@link api/angular.module.ng.$compileProvider.directive directives} and curly-brace bindings
with {@link dev_guide.expressions expressions}:
<pre>
<html ng-app>
<!-- Body tag augmented with ng-controller directive -->
<body ng-controller="MyController">
<input ng-model="foo" value="bar">
<!-- Button tag with ng-click directive, and
string expression 'buttonText'
wrapped in "{{ }}" markup -->
<button ng-click="changeFoo()">{{buttonText}}</button>
<script src="angular.js">
</body>
</html>
</pre>
In a simple single-page app, the template consists of HTML, CSS, and angular directives contained
in just one HTML file (usually `index.html`). In a more complex app, you can display multiple views
within one main page using "partials", which are segments of template located in separate HTML
files. You "include" the partials in the main page using the {@link api/angular.module.ng.$route
$route} service in conjunction with the {@link api/angular.module.ng.$compileProvider.directive.ng-view ng-view} directive. An
example of this technique is shown in the {@link tutorial/ angular tutorial}, in steps seven and
eight.
## Related Topics
* {@link dev_guide.templates.filters Angular Filters}
* {@link dev_guide.forms Angular Forms}
## Related API
* {@link api/index API Reference}
@@ -0,0 +1,281 @@
@ngdoc overview
@name Developer Guide: Unit Testing
@description
JavaScript is a dynamically typed language which comes with great power of expression, but it also
come with almost no-help from the compiler. For this reason we feel very strongly that any code
written in JavaScript needs to come with a strong set of tests. We have built many features into
angular which makes testing your angular applications easy. So there is no excuse for not do it.
# It is all about NOT mixing concerns
Unit testing as the name implies is about testing individual units of code. Unit tests try to
answer the question: Did I think about the logic correctly. Does the sort function order the list
in the right order. In order to answer such question it is very important that we can isolate it.
That is because when we are testing the sort function we don't want to be forced into crating
related pieces such as the DOM elements, or making any XHR calls in getting the data to sort. While
this may seem obvious it usually is very difficult to be able to call an individual function on a
typical project. The reason is that the developers often time mix concerns, and they end up with a
piece of code which does everything. It reads the data from XHR, it sorts it and then it
manipulates the DOM. With angular we try to make it easy for you to do the right thing, and so we
provide dependency injection for your XHR (which you can mock out) and we crated abstraction which
allow you to sort your model without having to resort to manipulating the DOM. So that in the end,
it is easy to write a sort function which sorts some data, so that your test can create a data set,
apply the function, and assert that the resulting model is in the correct order. The test does not
have to wait for XHR, or create the right kind of DOM, or assert that your function has mutated the
DOM in the right way. Angular is written with testability in mind, but it still requires that you
do the right thing. We tried to make the right thing easy, but angular is not magic, which means if
you don't follow these, you may very well end up with an untestable application.
## Dependency Inject
There are several ways in which you can get a hold of a dependency:
1. You could create it using the `new` operator.
2. You could look for it in a well know place, also known as global singleton.
3. You could ask a registry (also known as service registry) for it. (But how do you get a hold of
the registry? Must likely by looking it up in a well know place. See #2)
4. You could expect that the it be handed to you.
Out of the list above only the last of is testable. Lets look at why:
### Using the `new` operator
While there is nothing wrong with the `new` operator fundamentally the issue is that calling a new
on a constructor permanently binds the call site to the type. For example lets say that we are
trying to instantiate an `XHR` so that we can get some data from the server.
<pre>
function MyClass() {
this.doWork = function() {
var xhr = new XHR();
xhr.open(method, url, true);
xhr.onreadystatechange = function() {...}
xhr.send();
}
}
</pre>
The issue becomes, that in tests, we would very much like to instantiate a `MockXHR` which would
allow us to return fake data and simulate network failures. By calling `new XHR()` we are
permanently bound to the actual one, and there is no good way to replace it. Yes there is monkey
patching, that is a bad idea for many reasons, which is outside the scope of this document.
The class above is hard to test since we have to resort to monkey patching:
<pre>
var oldXHR = XHR;
XHR = function MockXHR() {};
var myClass = new MyClass();
myClass.doWork();
// assert that MockXHR got called with the right arguments
XHR = oldXHR; // if you forget this bad things will happen
</pre>
### Global look-up:
Another way to approach the problem is look for the service in a well known location.
<pre>
function MyClass() {
this.doWork = function() {
global.xhr({
method:'...',
url:'...',
complete:function(response){ ... }
})
}
}
</pre>
While no new instance of dependency is being created, it is fundamentally the same as `new`, in
that there is no good way to intercept the call to `global.xhr` for testing purposes, other then
through monkey patching. The basic issue for testing is that global variable needs to be mutated in
order to replace it with call to a mock method. For further explanation why this is bad see: {@link
http://misko.hevery.com/code-reviewers-guide/flaw-brittle-global-state-singletons/ Brittle Global
State & Singletons}
The class above is hard to test since we have to change global state:
<pre>
var oldXHR = glabal.xhr;
glabal.xhr = function mockXHR() {};
var myClass = new MyClass();
myClass.doWork();
// assert that mockXHR got called with the right arguments
global.xhr = oldXHR; // if you forget this bad things will happen
</pre>
### Service Registry:
It may seem as that this can be solved by having a registry for all of the services, and then
having the tests replace the services as needed.
<pre>
function MyClass() {
var serviceRegistry = ????;
this.doWork = function() {
var xhr = serviceRegistry.get('xhr');
xhr({
method:'...',
url:'...',
complete:function(response){ ... }
})
}
</pre>
However, where dose the serviceRegistry come from? if it is:
* `new`-ed up, the the test has no chance to reset the services for testing
* global look-up, then the service returned is global as well (but resetting is easier, since
there is only one global variable to be reset).
The class above is hard to test since we have to change global state:
<pre>
var oldServiceLocator = glabal.serviceLocator;
glabal.serviceLocator.set('xhr', function mockXHR() {});
var myClass = new MyClass();
myClass.doWork();
// assert that mockXHR got called with the right arguments
glabal.serviceLocator = oldServiceLocator; // if you forget this bad things will happen
</pre>
### Passing in Dependencies:
Lastly the dependency can be passed in.
<pre>
function MyClass(xhr) {
this.doWork = function() {
xhr({
method:'...',
url:'...',
complete:function(response){ ... }
})
}
</pre>
This is the preferred way since the code makes no assumptions as to where the `xhr` comes from,
rather that whoever created the class was responsible for passing it in. Since the creator of the
class should be different code than the user of the class, it separates the responsibility of
creation from the logic, and that is what dependency-injection is in a nutshell.
The class above is very testable, since in the test we can write:
<pre>
function xhrMock(args) {...}
var myClass = new MyClass(xhrMock);
myClass.doWork();
// assert that xhrMock got called with the right arguments
</pre>
Notice that no global variables were harmed in the writing of this test.
Angular comes with {@link dev_guide.di dependency-injection} built in which makes the right thing
easy to do, but you still need to do it if you wish to take advantage of the testability story.
## Controllers
What makes each application unique is its logic, which is what we would like to test. If the logic
for your application is mixed in with DOM manipulation, it will be hard to test as in the example
below:
<pre>
function PasswordController() {
// get references to DOM elements
var msg = $('.ex1 span');
var input = $('.ex1 input');
var strength;
this.grade = function() {
msg.removeClass(strength);
var pwd = input.val();
password.text(pwd);
if (pwd.length > 8) {
strength = 'strong';
} else if (pwd.length > 3) {
strength = 'medium';
} else {
strength = 'weak';
}
msg
.addClass(strength)
.text(strength);
}
}
</pre>
The code above is problematic from testability, since it requires your test to have the right kind
of DOM present when the code executes. The test would look like this:
<pre>
var input = $('<input type="text"/>');
var span = $('<span>');
$('body').html('<div class="ex1">')
.find('div')
.append(input)
.append(span);
var pc = new PasswordController();
input.val('abc');
pc.grade();
expect(span.text()).toEqual('weak');
$('body').html('');
</pre>
In angular the controllers are strictly separated from the DOM manipulation logic which results in
a much easier testability story as can be seen in this example:
<pre>
function PasswordCntrl() {
this.password = '';
this.grade = function() {
var size = this.password.length;
if (size > 8) {
this.strength = 'strong';
} else if (size > 3) {
this.strength = 'medium';
} else {
this.strength = 'weak';
}
};
}
</pre>
and the tests is straight forward
<pre>
var pc = new PasswordController();
pc.password('abc');
pc.grade();
expect(span.strength).toEqual('weak');
</pre>
Notice that the test is not only much shorter but it is easier to follow what is going on. We say
that such a test tells a story, rather then asserting random bits which don't seem to be related.
## Filters
{@link api/angular.module.ng.$filter Filters} are functions which transform the data into user readable
format. They are important because they remove the formatting responsibility from the application
logic, further simplifying the application logic.
<pre>
myModule.filter('length', function() {
return function(text){
return (''+(text||'')).length;
}
});
var length = $filter('length');
expect(length(null)).toEqual(0);
expect(length('abc')).toEqual(3);
</pre>
## Directives
Directives in angular are responsible for updating the DOM when the state of the model changes.
## Mocks
oue
## Global State Isolation
oue
# Preferred way of Testing
uo
## JavaScriptTestDriver
ou
## Jasmine
ou
## Sample project
uoe
+162
View File
@@ -0,0 +1,162 @@
@ngdoc overview
@name Developer Guide: Internet Explorer Compatibility
@description
# Overview
This document describes the Internet Explorer (IE) idiosyncrasies when dealing with custom HTML
attributes and tags. Read this document if you are planning on deploying your angular application
on IE v8.0 or earlier.
# Short Version
To make your angular application work on IE please make sure that:
1. you **do not** use custom element tags such as `<ng:view>` (use the attribute version `<div
ng-view>` instead), or
2. if you **do use** custom element tags, then you must take these steps to make IE happy:
<pre>
<html xmlns:ng="http://angularjs.org">
<head>
<!--[if lte IE 8]>
<script>
document.createElement('ng-include');
document.createElement('ng-pluralize');
document.createElement('ng-view');
// Optionally these for CSS
document.createElement('ng:include');
document.createElement('ng:pluralize');
document.createElement('ng:view');
</script>
<![endif]-->
</head>
<body>
...
</body>
</html>
</pre>
The **important** parts are:
* `xmlns:ng` - *namespace* - you need one namespace for each custom tay you are planning on
using.
* `document.createElement(yourTagName)` - *creation of custom tag names* - Since this is an
issue only for older version of IE you need to load it conditionally. For each tag which does
not have namespace and which is not defined in HTML you need to pre-declare it to make IE
happy.
# Long Version
IE has an issues with element tag names which are not standard HTML tag names. These fall into two
categories, and each category has its own fix.
* If the tag name starts with `my:` prefix than it is considered an XML namespace and must
have corresponding namespace declaration on `<html xmlns:my="ignored">`
* If the tag has no `:` but it is not a standard HTML tag, then it must be pre-created using
`document.createElement('my-tag')`
* If you have are planning on styling the custom tag with CSS selectors, then it must be
pre-created using `document.createElement('my-tag')` regardless of XML namespace.
## The Good News
The good news is that these restrictions only apply to element tag names, and not to element
attribute names. So this requires no special handling in IE: `<div my-tag your:tag></div>`.
## What happens if I fail to do this?
Suppose you have HTML with unknown tag `mytag` (this could also be `my:tag` or `my-tag` with same
result):
<pre>
<html>
<body>
<mytag>some text</mytag>
</body>
</html>
</pre>
It should pares into the following DOM:
<pre>
#document
+- HTML
+- BODY
+- mytag
+- #text: some text
</pre>
The expected behavior is that the `BODY` element has a child element `mytag`, which in turn has
the text `some text`.
But this is not what IE does (if the above fixes are not included):
<pre>
#document
+- HTML
+- BODY
+- mytag
+- #text: some text
+- /mytag
</pre>
In IE, the behavior is that the `BODY` element has three children:
1. A self closing `mytag`. Example of self closing tag is `<br/>`. The trailing `/` is optional,
but the `<br>` tag is not allowed to have any children, and browsers consider `<br>some
text</br>` as three siblings not a `<br>` with `some text` as child.
2. A text node with `some text`. This should have been a child of `mytag` above, not a sibling.
3. A corrupt self closing `/mytag`. This is corrupt since element names are not allowed to have
the `/` character. Furthermore this closing element should not be part of the DOM since it is
only used to delimitate the structure of the DOM.
## CSS Styling of Custom Tag Names
The to make CSS selector work with custom elements the custom element name must be shived with the
`document.createElement('my-tag')` regardless of XML namespace.
<pre>
<html xmlns:ng="needed for ng: namespace">
<head>
<!--[if lte IE 8]>
<script>
// needed to make ng-include parse properly
document.createElement('ng-include');
// needed to enable CSS reference
document.createElement('ng:view');
</script>
<![endif]-->
<style>
ng\\:view {
display: block;
border: 1px solid red;
}
ng-include {
display: block;
border: 1px solid blue;
}
</style>
</head>
<body>
<ng:view></ng:view>
<ng-include></ng-include>
...
</body>
</html>
</pre>
+53
View File
@@ -0,0 +1,53 @@
@ngdoc overview
@name Developer Guide
@description
Welcome to the angular Developer Guide. If you are here to learn the details of how to use angular
to develop web apps, you've come to the right place.
If you are completely or relatively unfamiliar with angular, you may want to check out one or both
of the following documents before returning here to the Developer Guide:
* {@link misc/started Getting Started}
* {@link tutorial/index Angular Tutorial}
<hr>
## {@link dev_guide.overview Overview of Angular}
## {@link dev_guide.bootstrap Initializing Angular}
* {@link dev_guide.bootstrap.auto_bootstrap Understanding Automatic Initialization}
* {@link dev_guide.bootstrap.manual_bootstrap Understanding Manual Initialization}
## {@link dev_guide.mvc About MVC in Angular}
* {@link dev_guide.mvc.understanding_model Understanding the Model Component}
* {@link dev_guide.mvc.understanding_controller Understanding the Controller Component}
* {@link dev_guide.mvc.understanding_view Understanding the View Component}
## {@link dev_guide.scopes Angular Scope Objects}
* {@link dev_guide.scopes.understanding_scopes Understanding Angular Scope Objects}
* {@link dev_guide.scopes.internals Angular Scope Internals}
## {@link dev_guide.compiler Angular HTML Compiler}
* {@link api/angular.module.ng.$compileProvider.directive Understanding Angular Directives}
## {@link dev_guide.templates Angular Templates}
* {@link dev_guide.templates.filters Understanding Angular Filters}
* {@link dev_guide.forms Understanding Angular Forms}
## {@link dev_guide.services Angular Services}
* {@link dev_guide.services.understanding_services Understanding Angular Services}
* {@link dev_guide.services.creating_services Creating Angular Services}
* {@link dev_guide.services.managing_dependencies Managing Service Dependencies}
* {@link dev_guide.services.testing_services Testing Angular Services}
## {@link dev_guide.di About Dependency Injection}
* {@link dev_guide.di.understanding_di Understanding DI in Angular}
* {@link dev_guide.di.using_di_controllers Using DI in Controllers}
+258
View File
@@ -0,0 +1,258 @@
@ngdoc overview
@name Developer Guide: Modules
@description
# What is a Module?
Most applications have a main method which instantiates, wires, and bootstraps the application.
Angular apps don't have a main method, instead the modules serves the purpose of declaratively
specifying how an application should be bootstrapped. There are several advantages to this
approach:
* The process is more declarative which is easier to understand
* In unit-testing there is no need to load all modules, which may aid in writing unit-tests.
* Additional modules can be loaded in scenario tests, which can override some of the
configuration and help end-to-end test the application
* Third party code can be packaged as reusable modules.
* The modules can be loaded in any/parallel order (due to delayed nature of module execution).
# The Basics
Ok, I'm in a hurry how do i get a Hello World module working?
Important things to notice:
* {@link api/angular.Module Module} API
* Notice the reference to the `myApp` module in the `<html ng-app="myApp">`, it is what
bootstraps the app using your module.
<doc:example module='simpleApp'>
<doc:source>
<script>
// declare a module
var simpleAppModule = angular.module('simpleApp', []);
// configure the module.
// in this example we will create a greeting filter
simpleAppModule.filter('greet', function() {
return function(name) {
return 'Hello, ' + name + '!';
};
});
</script>
<div>
{{ 'World' | greet }}
</div>
</doc:source>
</doc:example>
# Recommended Setup
While the example above is simple, it will not scale to large applications. Instead we recommend
that you break your application to multiple modules like this:
* A service module, for service declaration
* A directive module, for directive declaration
* A filter module, for filter declaration
* And an application level module which depends on the above modules, and which has
initialization code.
The reason for this breakup is that in your tests, it is often necessary to ignore the
initialization code, which tends to be difficult to test. By putting it into separate module it
can be easily ignored in tests. The tests can also be more focused by only loading the modules
which are relevant to tests.
The above is only a suggestion, so feel free to tailor it to your needs.
<doc:example module='xmpl'>
<doc:source>
<script>
angular.module('xmpl.service', []).
value('greeter', {
salutation: 'Hello',
localize: function(localization) {
this.salutation = localization.salutation;
},
greet: function(name) {
return this.salutation + ' ' + name + '!';
}
}).
value('user', {
load: function(name) {
this.name = name;
}
});
angular.module('xmpl.directive', []);
angular.module('xmpl.filter', []);
angular.module('xmpl', ['xmpl.service', 'xmpl.directive', 'xmpl.filter']).
run(function(greeter, user) {
// This is effectively part of the main method initialization code
greeter.localize({
salutation: 'Bonjour'
});
user.load('World');
})
// A Controller for your app
var XmplController = function($scope, greeter, user) {
$scope.greeting = greeter.greet(user.name);
}
</script>
<div ng-controller="XmplController">
{{ greeting }}!
</div>
</doc:source>
</doc:example>
# Module Loading & Dependencies
A module is a collection of configuration and run blocks which get applied to the application
during the bootstrap process. In its simplest form the module consist of collection of two kinds
of blocks:
1. **Configuration blocks** - get executed during the provider registrations and configuration
phase. Only providers and constants can be injected into configuration blocks. This is to
prevent accidental instantiation of services before they have been fully configured.
2. **Run blocks** - get executed after the injector is created and are used to kickstart the
application. Only instances and constants can be injected into run blocks. This is to prevent
further system configuration during application run time.
<pre>
angular.module('myModule', []).
config(function(injectables) { // provider-injector
// This is an example of config block.
// You can have as many of these as you want.
// You can only inject Providers (not instances)
// into the config blocks.
}).
run(function(injectables) { // instance-injector
// This is an example of a run block.
// You can have as many of these as you want.
// You can only inject instances (not Providers)
// int the run blocks
});
</pre>
## Configuration Blocks
There are some convenience methods on the module which are equivalent to the config block. For
example:
<pre>
angular.module('myModule', []).
value('a', 123).
factory('a', function() { return 123; }).
directive('directiveName', ...).
filter('filterName', ...);
// is same as
angular.module('myModule', []).
config(function($provide, $compileProvider, $filterProvider) {
$provide.value('a', 123)
$provide.factory('a', function() { return 123; })
$compileProvider.directive('directiveName', ...).
$filterProvider.register('filterName', ...);
});
</pre>
The configuration blocks get applied in the order in which they are registered. The only exception
to it are constant definitions, which are placed at the beginning of all configuration blocks.
## Run Blocks
Run blocks are the closest thing in Angular to the main method. A run block is the code which
needs to run to kickstart the application. It is executed after all of the service have been
configured and the injector has been created. Run blocks typically contain code which is hard
to unit-test, and for this reason should be declared in isolated modules, so that they can be
ignored in the unit-tests.
## Dependencies
Modules can list other modules as their dependencies. Depending on a module implies that required
module needs to be loaded before the requiring module is loaded. In other words the configuration
blocks of the required modules execute before the configuration blocks or the requiring module.
The same is true for the run blocks. Each module can only be loaded once, even if multiple other
modules require it.
## Asynchronous Loading
Modules are a way of managing $injector configuration, and have nothing to do with loading of
scripts into a VM. There are existing projects which deal with script loading, which may be used
with Angular. Because modules do nothing at load time they can be loaded into the VM in any order
and thus script loaders can take advantage of this property and paralyze the loading process.
# Unit Testing
In its simplest form a unit-test is a way of instantiating a subset of the application in test and
then applying a stimulus to it. It is important to realize that each module can only be loaded
once per injector. Typically an app has only one injector. But in tests, each test has its own
injector, which means that the modules are loaded multiple times per VM. Properly structured
modules can help with unit testing, as in this example:
In all of these examples we are going to assume this module definition:
<pre>
angular.module('greetMod', []).
factory('alert', function($window) {
return function(text) {
$window.alert(text);
}
}).
value('salutation', 'Hello').
factory('greet', function(alert, salutation) {
return function(name) {
alert(salutation + ' ' + name + '!');
}
});
</pre>
Let's write some tests:
<pre>
describe('myApp', function() {
// load the application relevant modules then load a special
// test module which overrides the $window with mock version,
// so that calling window.alert() will not block the test
// runner with a real alert box. This is an example of overriding
// configuration information in tests.
beforeEach(module('greetMod', function($provide) {
$provide.value('$window', {
alert: jasmine.createSpy('alert')
});
});
// The inject() will create the injector and inject the greet and
// $window into the tests. The test need not concern itself with
// wiring of the application, only with testing it.
it('should alert on $window', inject(function(greet, $window) {
greet('World');
expect($window.alert).toHaveBeenCalledWith('Hello World!');
}));
// this is another way of overriding configuration in the
// tests using an inline module and inject methods.
it('should alert using the alert service', function() {
var alertSpy = jasmine.createSpy('alert');
module(function($provide) {
$provide.value('alert', alertSpy);
});
inject(function(greet) {
greet('World');
expect(alertSpy).toHaveBeenCalledWith('World');
});
});
});
</pre>
+262
View File
@@ -0,0 +1,262 @@
@ngdoc overview
@name Contributing
@description
* <a href="#H1_1">License</a>
* <a href="#H1_2">Contributing to Source Code</a>
* <a href="#H1_3">Applying Code Standards</a>
* <a href="#H1_4">Checking Out and Building `Angular`</a>
* <a href="#H1_5">Submitting Your Changes</a>
<a name="H1_1"></a>
# License
`Angular` is an open source project licensed under the {@link
http://github.com/angular/angular.js/blob/master/LICENSE MIT license}. Your contributions are
always welcome. When working with `angular` source base, please follow the guidelines provided on
this page.
<a name="H1_2"></a>
# Contributing to Source Code
We'd love for you to contribute to our source code and to make `angular` even better than it is
today! Here are the guidelines we'd like you to use:
* Major changes that you intend to contribute to the project must be discussed first on our {@link
https://groups.google.com/forum/?hl=en#!forum/angular mailing list} so that we can better
coordinate our efforts, prevent duplication of work, and help you to craft the change so that it
is successfully accepted upstream.
* Small changes and bug fixes can be crafted and submitted to Github as a <a href="#H1_5">pull
request</a>.
<a name="H1_3"></a>
# Applying Code Standards
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 <a href="#unit-tests">specs</a>.
* 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 ngdocs.
* With the exceptions listed below, we follow the rules contained in {@link
http://google-styleguide.googlecode.com/svn/trunk/javascriptguide.xml Google's JavaScript Style
Guide}:
* Do not use namespaces: Instead, we wrap the entire `angular` 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 prototypical
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, internally we use aliases 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 `angular`. The best guidance is to do what makes the most sense.
<a name="H1_4"></a>
# Checking Out and Building Angular
The `angular` source code is hosted at {@link http://github.com Github}, which we also use to
accept code contributions. Several steps are needed to check out and build `angular`:
## Installation Dependencies
Before you can build `angular`, you must install or configure the following dependencies on your
machine:
* {@link http://rake.rubyforge.org Rake}: We use Rake as our build system, which is pre-installed
on most Macintosh and Linux machines. If that is not true in your case, you can grab it from the
Rake website.
* {@link http://nodejs.org Node.js}: We use Node to generate the documentation and to run a
development web server. Depending on your system, you can install Node either from source or as a
pre-packaged bundle.
You'll also need npm and the following npm modules:
* install npm: `curl http://npmjs.org/install.sh | sh`
* install q: `npm install q`
* install qq: `npm install qq`
* install q-fs: `npm install q-fs`
* install jasmine-node: `npm install jasmine`
* Java: The Java runtime is used to run {@link http://code.google.com/p/js-test-driver
JsTestDriver} (JSTD), which we use to run our unit test suite. JSTD binaries are part of the
`angular` source base, which means there is no need to install or configure it separately.
* Git: The {@link http://help.github.com/mac-git-installation Github Guide to Installing Git} is
quite a good source for information on Git.
## Creating a Github Account and Forking Angular
To create a Github account, follow the instructions {@link https://github.com/signup/free here}.
Afterwards, go ahead and {@link http://help.github.com/forking fork} the {@link
https://github.com/angular/angular.js main angular repository}.
## Building `Angular`
To build `angular`, you check out the source code and use Rake to generate the non-minified and
minified `angular` files:
1. To clone your Github repository, run:
git clone git@github.com:<github username>/angular.js.git
2. To go to the `angular` directory, run:
cd angular.js
3. To add the main `angular` repository as an upstream remote to your repository, run:
git remote add upstream https://github.com/angular/angular.js.git
4. To build `angular`, run:
rake package
The build output can be located under the `build` directory. It consists of the following files and
directories:
* `angular-<version>.tgz` — This is the complete tarball, which contains all of the release build
artifacts.
* `angular.js` — The non-minified `angular` script.
* `angular.min.js` — The minified `angular` script.
* `angular-scenario.js` — The `angular` End2End test runner.
* `angular-ie-compat.js` — The Internet Explorer compatibility patch file.
* `docs/` — A directory that contains all of the files needed to run `docs.angularjs.org`.
* `docs/index.html` — The main page for the documentation.
* `docs/docs-scenario.html` — The End2End test runner for the documentation application.
## Running a Local Development Web Server
To debug or test code, it is often useful to have a local HTTP server. For this purpose, we have
made available a local web server based on Node.js.
1. To start the web server, run:
./nodeserver.sh
2. To access the local server, go to this website:
http://localhost:8000/
By default, it serves the contents of the `angular` project directory.
<a name="unit-tests"></a>
## Running the Unit Test Suite
Our unit and integration tests are written with Jasmine and executed with JsTestDriver. To run the
tests:
1. To start the JSTD server, run:
./server.sh
2. To capture one or more browsers, go to this website:
http://localhost:9876/
3. To trigger a test execution, run:
./test.sh
4. To automatically run the test suite each time one or more of the files in the project directory
is changed, you can install `watchr` and then run:
watchr watchr.rb
5. To view the output of each test run, you can tail this log file:
./logs/jstd.log
## Running the End2End Test Suite
To run the End2End test suite:
1. Start the local web server.
2. In a browser, go to:
http://localhost:8000/build/docs/docs-scenario.html
The tests are executed automatically.
<a name="H1_5"></a>
# Submitting Your Changes
To create and submit a change:
1. Create a new branch off the master for your changes:
git branch my-fix-branch
2. Check out the branch:
git checkout my-fix-branch
3. Create your patch, make sure to have plenty of tests (that pass).
4. Commit your changes:
git commit -a
5. Run JavaScript Lint and be sure to address all new warnings and errors:
rake lint
6. Push your branch to Github:
git push origin my-fix-branch
7. In Github, send a pull request to `angular:master`.
8. When the patch is reviewed and merged, delete your branch and pull yours — and other — changes
from the main (upstream) repository:
1. To delete the branch in Github, run:
git push origin :my-fix-branch
2. To check out the master branch, run:
git checkout master
3. To delete a local branch, run:
git branch -D my-fix-branch
4. To update your master with the latest upstream version, run:
git pull --ff upstream master
That's it! Thank you for your contribution!
+70
View File
@@ -0,0 +1,70 @@
@ngdoc overview
@name Downloading
@description
# Including angular scripts from the angular server
The quickest way to get started is to point your html `<script>` tag to a
<http://code.angularjs.org/> URL. This way, you don't have to download anything or maintain a
local copy.
There are two types of angular script URLs you can point to, one for development and one for
production:
* __angular-<version>.js__ — This is the human-readable, non-minified version, suitable for web
development.
* __angular-<version>.min.js__ — This is the minified version, which we strongly suggest you use in
production.
To point your code to an angular script on the angular server, use the following template. This
example points to (non-minified) version 0.10.6:
<pre>
<!doctype html>
<html ng-app>
<head>
<title>My Angular App</title>
<script src="http://code.angularjs.org/angular-0.10.6.js"></script>
</head>
<body>
</body>
</html>
</pre>
# Downloading and hosting angular files locally
This option is for those who want to work with angular offline, or those who want to host the
angular files on their own servers.
If you navigate to <http://code.angularjs.org/>, you'll see a directory listing with all of the
angular versions since we started releasing versioned build artifacts (quite late in the project
lifetime). Each directory contains all artifacts that we released for a particular version.
Download the version you want and have fun.
Each directory under <http://code.angularjs.org/> includes the following set of files:
* __`angular-<version>.js`__ — This file is non-obfuscated, non-minified, and human-readable by
opening it it any editor or browser. In order to get better error messages during development, you
should always use this non-minified angular script.
* __`angular-<version>.min.js`__ — This is a minified and obfuscated version of
`angular-<version>.js` created with the Closure compiler. Use this version for production in order
to minimize the size of the application that is downloaded by your user's browser.
* __`angular-<version>.tgz`__ — This is a tarball archive that contains all of the files released
for this angular version. Use this file to get everything in a single download.
* __`angular-ie-compat-<version>.js`__ — This is a special file that contains code and data
specifically tailored for getting Internet Explorer to work with angular. If you host your own copy
of angular files, make sure that this file is available for download, and that it resides under the
same parent path as `angular-<version>.js` or `angular-<version>.min.js`.
* __`angular-mocks-<version>.js`__ — This file contains an implementation of mocks that makes
testing angular apps even easier. Your unit/integration test harness should load this file after
`angular-<version>.js` is loaded.
* __`angular-scenario-<version>.js`__ — This file is a very nifty JavaScript file that allows you
to write and execute end-to-end tests for angular applications.
* __`docs-<version>`__ — this directory contains all the files that compose the
<http://docs.angularjs.org/> documentation app. These files are handy to see the older version of
our docs, or even more importantly, view the docs offline.
+81
View File
@@ -0,0 +1,81 @@
@ngdoc overview
@name FAQ
@description
#FAQ
### Why is this project called "angular"? Why is the namespace called "ng"?
Because HTML has angular brackets and "ng" sounds like "angular".
### Is <angular/> an HTML5 tag?
No, <angular/> is not an HTML5 tag. angular is an orthogonal project to HTML5; you can use the two
together.
### Is angular a {library, framework, DOM manipulation library, widget library, native plugin}?
No, angular is none of these. You don't call its functions, it does not call your functions,
it does not provide a way to manipulate DOM, but does provide primitives to create UI projections
of your data. There are lots of existing widget libraries which you can integrate with angular.
It is 100% JavaScript, 100% client side and compatible with both desktop and mobile browsers.
### Do I need to worry about security holes in angular?
Like with any technology, angular is not impervious to attack. angular does, however, provide
built-in protection from basic security holes including cross-site scripting and HTML injection
attacks. angular does round-trip escaping on all strings for you.
### Can I download the source, build, and host the angular environment locally?
Yes. See instructions in {@link downloading}.
### Is angular a templating system?
At the highest level, angular does look like a just another templating system. But there is one
important reason why angular templating system is different and makes it very good fit for
application development: bidirectional data binding. The template is compiled on the browser and
the compilation step produces a live view. This means you, the developer, don't need to write
code to constantly sync the view with the model and the model with the view as in other
templating systems.
### What browsers does angular work with?
Webkit-based browsers (Safari, Chrome, iPhone, Android, WebOS, BlackBerry 6), Firefox, IE6 and
above. Note that CSS only works on IE7 and above.
### What's angular's performance like?
angular takes ~300ms to load, render, and compile. In Chrome it uses about 2-5MB of memory. Your
app's performance will vary depending on how many bindings you use.
### How big is the angular bootstrap JS file that I need to include?
The size of the library itself is < 50KB compressed and obfuscated.
### Can I use the open-source Closure Library with angular?
Yes, you can use widgets from the {@link http://code.google.com/closure/library Closure Library}
in angular.
### Does angular use the jQuery library?
Yes, angular uses {@link http://jquery.com/ jQuery}, the open source DOM manipulation library.
If jQuery is not present in your script path, angular falls back on its own implementation of
{@link api/angular.element jQuery lite}. If jQuery is present in the path, angular uses it to
manipulate the DOM.
### What is testability like in angular?
Very testable. It has an integrated dependency injection framework. See
{@link api/angular.module.ng service} for details.
### How can I learn more about angular?
Watch the July 28, 2010 talk
"{@link http://www.youtube.com/watch?v=elvcgVSynRg| Angular: A Radically Different Way of Building
AJAX Apps}".
### How is angular licensed?
The MIT License.
+143
View File
@@ -0,0 +1,143 @@
@ngdoc overview
@name Getting Started
@description
# Hello World!
A great way for you to get started with AngularJS is to create the tradtional
"Hello World!" app:
1. In your favorite text editor, create an HTML file
(for example, `helloworld.html`).
2. From the __Source__ box below, copy and paste the code into your HTML file.
(Double-click on the source to easily select all.)
3. Open the file in your web browser.
<doc:example>
<doc:source>
Hello {{'World'}}!
</doc:source>
</doc:example>
The resulting web page should look something like the following:
<img class="center" src="img/helloworld.png" border="1">
Now let's take a closer look at that code, and see what is going on behind
the scenes.
The `ng-app` tags tells angular to process the entire HTML page and bootstrap the app when the page
is loaded:
<pre>
<html ng-app>
</pre>
The next line downloads the angular script:
<pre>
<script src="http://code.angularjs.org/angular-?.?.?.min.js"></script>
</pre>
(For details on what happens when angular processes an HTML page,
see {@link guide/dev_guide.bootstrap Bootstrap}.)
Finally, this line in the `<body>` of the page is the template that describes
how to display our greeting in the UI:
<pre>
Hello {{'World'}}!
</pre>
Note the use of the double curly brace markup (`{{ }}`) to bind the expression to
the greeting text. Here the expression is the string literal 'World'.
Next let's look at a more interesting example, that uses AngularJS to
bind a dynamic expression to our greeting text.
# Hello AngularJS World!
This example demonstrates angular's two-way data binding:
1. Edit the HTML file you created in the "Hello World!" example above.
2. Replace the contents of `<body>` with the code from the __Source__ box below.
3. Refresh your browser window.
<doc:example>
<doc:source>
Your name: <input type="text" ng-model="yourname" value="World"/>
<hr/>
Hello {{yourname}}!
</doc:source>
</doc:example>
After the refresh, the page should look something like this:
<img class="left" src="img/helloworld_2way.png" border="1" />
These are some of the important points to note from this example:
* The text input {@link api/angular.module.ng.$compileProvider.directive directive}
is bound to a model variable called `yourname`.
* The double curly braces notation binds the `yourname` model to the greeting text.
* You did not need to explicitly register an event listener or define an event handler for events!
Now try typing your name into the input box, and notice the immediate change to
the displayed greeting. This demonstrates the concept of angular's
{@link guide/dev_guide.templates.databinding bi-directional data binding}. Any changes to the input
field are immediately
reflected in the model (one direction), and any changes to the model are
reflected in the greeting text (the other direction).
# Anatomy Of An Angular App
This section describes the 3 parts of an angular app, and explains how they map to the
Model-View-Controller design pattern:
## Templates
Templates, which you write in HTML and CSS, serve as the View. You add elements, attributes, and
markup to HTML, which serve as instructions to the angular compiler. The angular compiler is fully
extensible, meaning that with angular you can build your own declarative language on top of HTML!
## Application Logic and Behavior
Application Logic and Behavior, which you define in JavaScript, serve as the Controller. With
angular (unlike with standard AJAX applications) you don't need to write additional listeners or
DOM manipulators, because they are built-in. This feature makes your application logic very easy to
write, test, maintain, and understand.
## Data
The Model is referenced from properties on {@link guide/dev_guide.scopes angular scope objects}.
The data in your model could be Javascript objects, arrays, or primitives, it doesn't matter. What
matters is that these are all referenced by the scope object.
Angular employs scopes to keep your data model and your UI in sync. Whenever something occurs to
change the state of the model, angular immediately reflects that change in the UI, and vice versa.
The following illustration shows the parts of an angular application and how they work together:
<img class="left" src="img/angular_parts.png" border="0" />
In addition, angular comes with a set of Services, which have the following properties:
* The services provided are very useful for building web applications.
* You can extend and add application-specific behavior to services.
* Services include Dependency-Injection, XHR, caching, URL routing, and browser abstraction.
# Where To Go Next
* If you like what you've learned so far, you should definitely check out our awesome {@link
tutorial/ Tutorial}, which walks you through the process of building real apps with AngularJS.
* For further explanations and examples of the AngularJS concepts presented on this page, see the
{@link guide/index Developer Guide}.
* For additional hands-on examples of using AngularJS, including more source code that you can
copy and paste into your own pages, take a look through the {@link cookbook/ Cookbook}.
+2
View File
@@ -0,0 +1,2 @@
controller: {{name}}<br />
Book Id: {{params.bookId}}<br />
+3
View File
@@ -0,0 +1,3 @@
controller: {{name}}<br />
Book Id: {{prams.bookId}}<br />
Chapter Id: {{params.chapterId}}
+1
View File
@@ -0,0 +1 @@
Hello, $http!
+1
View File
@@ -0,0 +1 @@
Content of template1.html
+1
View File
@@ -0,0 +1 @@
Content of template2.html
+18
View File
@@ -0,0 +1,18 @@
<label>Name:</label>
<input type="text" ng:model="form.name" required>
<div ng:repeat="contact in form.contacts">
<select ng:model="contact.type">
<option>url</option>
<option>email</option>
<option>phone</option>
</select>
<input type="text" ng:model="contact.url">
[ <a href="" ng:click="form.contacts.$remove(contact)">X</a> ]
</div>
<div>
[ <a href="" ng:click="form.contacts.$add()">add</a> ]
</div>
<button ng:click="cancel()">Cancel</button>
<button ng:click="save()">Save</button>
+5
View File
@@ -0,0 +1,5 @@
Hello {{person.name}},
<div>
Your contact information:
<div ng:repeat="contact in person.contacts">{{contact.type}}: {{contact.url|linky}}</div>
</div>
Binary file not shown.

After

Width:  |  Height:  |  Size: 32 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 49 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 57 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 212 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 54 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 232 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 29 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 40 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 117 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 13 KiB

BIN
View File
Binary file not shown.

After

Width:  |  Height:  |  Size: 692 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 97 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 27 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 141 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 158 KiB

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