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
- 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)
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.
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.
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
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)
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-RdEmC0kCloses#321Closes#425
Breaks controller methods are not exported to scope automatically
Breaks Scope#$new() does not take controller as argument anymore
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)
- 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
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.
$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
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.
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
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.
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.
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
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).
- 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
- 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
- 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
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.
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
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.
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
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.
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.
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.
Because only controllers don't have currying, we can infer its arguments, all other APIs needing currying, automatic inference complicates the matters unecessary.
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
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.
- 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
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 (".").
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.
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
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.
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.
- 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
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
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.
* 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
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()
- 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
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.
- 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
- 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
- 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
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
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
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.
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...
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.
- 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