Add public API to retrieve scope from element.

This commit is contained in:
Misko Hevery 2011-02-07 13:28:42 -08:00
parent a004d487c4
commit 0a5c00abf8
8 changed files with 61 additions and 38 deletions

View file

@ -18,6 +18,9 @@
- setting the parent scope for scopes created by the service via `#parent()`
- reloading the current route via `#reload()`
### API
- added `angular.element(...).scope()` method to retrieve scope for a given element.
### Bug Fixes
- <option> value attribute gets clobbered when the element contains new line character(s).
- <ng:view> widget now works when nested inside an <ng:include> widget

View file

@ -9,16 +9,17 @@ Wraps a raw DOM element or HTML string as [jQuery](http://jquery.com) element.
jQuery is loaded or a function that wraps the element or string in angular's jQuery lite
implementation.
Real jQuery always takes precedence if it was loaded before angular.
Real jQuery always takes precedence (as long as it was loaded before `DOMContentEvent`)
Angular's jQuery lite implementation is a tiny API-compatible subset of jQuery which allows
angular to manipulate DOM. The functions implemented are usually just the basic versions of
them and might not support arguments and invocation styles.
angular to manipulate DOM. The jQuery lite implements only a subset of jQuery api, with the
focus on the most commonly needed functionality and minimal footprint. For this reason only a
limited number of jQuery methods, arguments and invocation styles are supported.
NOTE: All element references in angular are always wrapped with jQuery (lite) and are never
raw DOM references.
Angular's jQuery lite implements these functions:
## Angular's jQuery lite implements these functions:
- [addClass()](http://api.jquery.com/addClass/)
- [after()](http://api.jquery.com/after/)
@ -39,5 +40,9 @@ Angular's jQuery lite implements these functions:
- [text()](http://api.jquery.com/text/)
- [trigger()](http://api.jquery.com/trigger/)
## Additionally these methods are available in both jQuery and jQuery lite version.
- `scope()` - retrieves the current angular scope of the element.
@param {string|DOMElement} element HTML string or DOMElement to be wrapped into jQuery.
@returns {Object} jQuery object.

View file

@ -1032,5 +1032,12 @@ function angularJsConfig(document, config) {
function bindJQuery(){
// bind to jQuery if present;
jQuery = window.jQuery;
angular.element = jqLite = jQuery || jqLiteWrap;
// reset to jQuery or default to us.
if (window.jQuery) {
jqLite = window.jQuery;
jqLite.fn.scope = JQLite.prototype.scope;
} else {
jqLite = jqLiteWrap;
}
angular.element = jqLite;
}

View file

@ -69,18 +69,6 @@ Template.prototype = {
}
};
/*
* Function walks up the element chain looking for the scope associated with the give element.
*/
function retrieveScope(element) {
var scope;
element = jqLite(element);
while (element && element.length && !(scope = element.data($$scope))) {
element = element.parent();
}
return scope;
}
///////////////////////////////////
//Compiler
//////////////////////////////////

View file

@ -87,6 +87,15 @@ JQLite.prototype = {
})(this[0]);
},
scope: function() {
var scope, element = this;
while (element && element.length && !(scope = element.data($$scope))) {
element = element.parent();
}
return scope;
},
ready: function(fn) {
var fired = false;

View file

@ -561,7 +561,7 @@ angularWidget('option', function(){
return function(option) {
var select = option.parent();
var isMultiple = select[0].type == 'select-multiple';
var scope = retrieveScope(select);
var scope = select.scope();
var model = modelAccessor(scope, select);
//if parent select doesn't have a name, don't bother doing anything any more

View file

@ -166,24 +166,4 @@ describe('compiler', function(){
scope = compile('A---B---C===D');
expect(sortedHtml(scope.$element)).toEqual('<div>A<hr></hr>B<hr></hr>C<p></p>D</div>');
});
describe('retrieveScope', function() {
it('should retrieve scope attached to the current element', function() {
scope = compile('<i>foo</i>');
expect(retrieveScope(scope.$element)).toBe(scope);
});
it('should walk up the dom to find scope', function() {
scope = compile('<ul><li><p><b>deep deep</b><p></li></ul>');
var deepChild = scope.$element[0].getElementsByTagName('b')[0];
expect(retrieveScope(deepChild)).toBe(scope);
});
it('should return undefined when no scope was found', function() {
var html = jqLite('<ul><li><p><b>deep deep</b><p></li></ul>'),
deepChild = html[0].getElementsByTagName('b')[0];
expect(retrieveScope(deepChild)).toBeNull();
});
});
});

31
test/jqLiteSpec.js Normal file
View file

@ -0,0 +1,31 @@
describe('jqLite', function(){
var scope;
beforeEach(function(){
scope = angular.scope();
});
describe('scope', function() {
it('should retrieve scope attached to the current element', function() {
var element = jqLite('<i>foo</i>');
element.data('$scope', scope);
expect(element.scope()).toBe(scope);
dealoc(element);
});
it('should walk up the dom to find scope', function() {
var element = jqLite('<ul><li><p><b>deep deep</b><p></li></ul>');
var deepChild = jqLite(element[0].getElementsByTagName('b')[0]);
element.data('$scope', scope);
expect(deepChild.scope()).toBe(scope);
dealoc(element);
});
it('should return undefined when no scope was found', function() {
var element = jqLite('<ul><li><p><b>deep deep</b><p></li></ul>');
var deepChild = jqLite(element[0].getElementsByTagName('b')[0]);
expect(deepChild.scope()).toBeNull();
dealoc(element);
});
});
});