aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorMisko Hevery2011-02-12 10:13:28 -0800
committerMisko Hevery2011-02-16 01:03:12 -0500
commitef4bb28be13e99f96c9ace5936cf26a174a0e5f0 (patch)
tree833057505e430cac064214ac3d55c687338da2a9 /src
parent496e6bf9016d33a7cf2f4730d06a8655f01ca5cb (diff)
downloadangular.js-ef4bb28be13e99f96c9ace5936cf26a174a0e5f0.tar.bz2
Change API angular.compile(element)([scope], [element/true])
Diffstat (limited to 'src')
-rw-r--r--src/Angular.js51
-rw-r--r--src/Compiler.js22
-rw-r--r--src/widgets.js8
3 files changed, 55 insertions, 26 deletions
diff --git a/src/Angular.js b/src/Angular.js
index 9b2c7ea6..9eaeb093 100644
--- a/src/Angular.js
+++ b/src/Angular.js
@@ -793,21 +793,50 @@ function merge(src, dst) {
* @function
*
* @description
- * Compiles a piece of HTML or DOM into a {@link angular.scope scope} object.
+ * Compiles a piece of HTML string or DOM into a view and produces a linking function, which can
+ * then be used to link {@link angular.scope scope} and the template together. The compilation
+ * process walks the DOM tree and tries to match DOM elements to {@link angular.markup markup},
+ * {@link angular.attrMarkup attrMarkup}, {@link angular.widget widgets}, and
+ * {@link angular.directive directives}. For each match it executes coresponding markup, \
+ * attrMarkup, widget or directive template function and collects the instance functions into a
+ * single linking function which is then returned. The linking function can then be used
+ * many-times-over on clones of compiled DOM structure, (For example when compiling
+ * {@link angular.widget.@ng:repeat repeater} the resulting linking function is called once for
+ * each item in the collection. The `ng:repeat` does this by cloning the template DOM once for
+ * each item in collection and then calling the linking function to link the cloned template
+ * with the a new scope for each item in the collection.)
+ *
<pre>
- var scope1 = angular.compile(window.document);
+ var mvc1 = angular.compile(window.document)();
+ mvc1.view; // compiled view elment
+ mvc1.scope; // scope bound to the element
- var scope2 = angular.compile('<div ng:click="clicked = true">click me</div>');
+ var mvc2 = angular.compile('<div ng:click="clicked = true">click me</div>')();
</pre>
*
- * @param {string|DOMElement} element Element to compile.
- * @param {Object=} parentScope Scope to become the parent scope of the newly compiled scope.
- * @returns {Object} Compiled scope object.
+ * @param {string|DOMElement} element Element or HTML to compile into a template function.
+ * @returns {function([scope][, element])} a template function which is used to bind element
+ * and scope. Where:
+ *
+ * * `scope` - {@link angular.scope scope} A scope to bind to. If none specified, then a new
+ * root scope is created.
+ * * `element` - {@link angular.element element} Element to use as the template. If none
+ * specified then reuse the element from `angular.compile(element)`. If `true`
+ * then clone the `angular.compile(element)`. The element must be either the same
+ * element as `angular.compile(element)` or an identical clone to
+ * `angular.compile(element)`. Using an element with differnt structure will cause
+ * unpredictable behavior.
+ *
+ * Calling the template function returns object: `{scope:?, view:?}`, where:
+ *
+ * * `view` - the DOM element which represents the compiled template. Either same or clone of
+ * `element` specifed in compile or template function.
+ * * `scope` - scope to which the element is bound to. Either a root scope or scope specified
+ * in the template function.
*/
-function compile(element, parentScope) {
- var compiler = new Compiler(angularTextMarkup, angularAttrMarkup, angularDirective, angularWidget),
- $element = jqLite(element);
- return compiler.compile($element)($element, parentScope);
+function compile(element) {
+ return new Compiler(angularTextMarkup, angularAttrMarkup, angularDirective, angularWidget)
+ .compile(element);
}
/////////////////////////////////////////////////
@@ -989,7 +1018,7 @@ function toKeyValue(obj) {
function angularInit(config){
if (config.autobind) {
// TODO default to the source of angular.js
- var scope = compile(window.document, _null, {'$config':config}),
+ var scope = compile(window.document)(null, createScope({'$config':config})),
$browser = scope.$service('$browser');
if (config.css)
diff --git a/src/Compiler.js b/src/Compiler.js
index 6aee40b8..890f2510 100644
--- a/src/Compiler.js
+++ b/src/Compiler.js
@@ -80,30 +80,30 @@ function Compiler(markup, attrMarkup, directives, widgets){
}
Compiler.prototype = {
- compile: function(element) {
- element = jqLite(element);
+ compile: function(templateElement) {
+ templateElement = jqLite(templateElement);
var index = 0,
template,
- parent = element.parent();
+ parent = templateElement.parent();
if (parent && parent[0]) {
parent = parent[0];
for(var i = 0; i < parent.childNodes.length; i++) {
- if (parent.childNodes[i] == element[0]) {
+ if (parent.childNodes[i] == templateElement[0]) {
index = i;
}
}
}
- template = this.templatize(element, index, 0) || new Template();
- return function(element, parentScope){
- element = jqLite(element);
- var scope = parentScope && parentScope.$eval
- ? parentScope
- : createScope(parentScope);
+ template = this.templatize(templateElement, index, 0) || new Template();
+ return function(scope, element){
+ scope = scope || createScope();
+ element = element === true
+ ? templateElement.cloneNode()
+ : (jqLite(element) || templateElement);
element.data($$scope, scope);
template.attach(element, scope);
scope.$element = element;
scope.$eval();
- return scope;
+ return {scope:scope, view:element};
};
},
diff --git a/src/widgets.js b/src/widgets.js
index 58c22081..14d6fe10 100644
--- a/src/widgets.js
+++ b/src/widgets.js
@@ -676,7 +676,7 @@ angularWidget('ng:include', function(element){
xhr('GET', src, function(code, response){
element.html(response);
childScope = useScope || createScope(scope);
- compiler.compile(element)(element, childScope);
+ compiler.compile(element)(childScope);
scope.$eval(onloadExp);
});
} else {
@@ -793,7 +793,7 @@ var ngSwitch = angularWidget('ng:switch', function (element){
var caseElement = switchCase.element.cloneNode();
element.append(caseElement);
childScope.$tryEval(switchCase.change, element);
- switchCase.template(caseElement, childScope);
+ switchCase.template(childScope, caseElement);
}
});
});
@@ -945,7 +945,7 @@ angularWidget("@ng:repeat", function(expression, element){
(index == collectionLength - 1 ? 'last' : 'middle');
lastElement.after(cloneElement = element.cloneNode());
cloneElement.attr('ng:repeat-index', index);
- linker(cloneElement, childScope);
+ linker(childScope, cloneElement);
children.push(childScope);
}
childScope.$eval();
@@ -1067,7 +1067,7 @@ angularWidget('ng:view', function(element) {
if (src) {
$xhr('GET', src, function(code, response){
element.html(response);
- compiler.compile(element)(element, childScope);
+ compiler.compile(element)(childScope);
});
} else {
element.html('');