Commit 9f3ee34c authored by Pascal Hartig's avatar Pascal Hartig

Merge pull request #719 from torifat/gh-pages

angularjs: upgrade angular to 1.2.1 & fixed filter bug & angularjs-perf: upgrade angular to 1.2.1
parents 11a31d38 7bc2c261
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
"name": "todomvc-angular-perf", "name": "todomvc-angular-perf",
"version": "0.0.0", "version": "0.0.0",
"dependencies": { "dependencies": {
"angular": "~1.0.7", "angular": "~1.2.1",
"todomvc-common": "~0.1.4" "todomvc-common": "~0.1.9"
} }
} }
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -26,7 +26,7 @@ ...@@ -26,7 +26,7 @@
<button class="destroy" ng-click="removeTodo(todo)"></button> <button class="destroy" ng-click="removeTodo(todo)"></button>
</div> </div>
<form ng-submit="doneEditing(todo)"> <form ng-submit="doneEditing(todo)">
<input class="edit" ng-model="todo.title" todo-blur="doneEditing(todo)" todo-focus="todo == editedTodo"> <input class="edit" ng-trim="false" ng-model="todo.title" todo-blur="doneEditing(todo)" todo-focus="todo == editedTodo">
</form> </form>
</li> </li>
</ul> </ul>
......
/** /**
* @license AngularJS v1.2.0 * @license AngularJS v1.2.1
* (c) 2010-2012 Google, Inc. http://angularjs.org * (c) 2010-2012 Google, Inc. http://angularjs.org
* License: MIT * License: MIT
*/ */
...@@ -40,11 +40,11 @@ function minErr(module) { ...@@ -40,11 +40,11 @@ function minErr(module) {
template = arguments[1], template = arguments[1],
templateArgs = arguments, templateArgs = arguments,
stringify = function (obj) { stringify = function (obj) {
if (isFunction(obj)) { if (typeof obj === 'function') {
return obj.toString().replace(/ \{[\s\S]*$/, ''); return obj.toString().replace(/ \{[\s\S]*$/, '');
} else if (isUndefined(obj)) { } else if (typeof obj === 'undefined') {
return 'undefined'; return 'undefined';
} else if (!isString(obj)) { } else if (typeof obj !== 'string') {
return JSON.stringify(obj); return JSON.stringify(obj);
} }
return obj; return obj;
...@@ -56,11 +56,11 @@ function minErr(module) { ...@@ -56,11 +56,11 @@ function minErr(module) {
if (index + 2 < templateArgs.length) { if (index + 2 < templateArgs.length) {
arg = templateArgs[index + 2]; arg = templateArgs[index + 2];
if (isFunction(arg)) { if (typeof arg === 'function') {
return arg.toString().replace(/ ?\{[\s\S]*$/, ''); return arg.toString().replace(/ ?\{[\s\S]*$/, '');
} else if (isUndefined(arg)) { } else if (typeof arg === 'undefined') {
return 'undefined'; return 'undefined';
} else if (!isString(arg)) { } else if (typeof arg !== 'string') {
return toJson(arg); return toJson(arg);
} }
return arg; return arg;
...@@ -68,7 +68,7 @@ function minErr(module) { ...@@ -68,7 +68,7 @@ function minErr(module) {
return match; return match;
}); });
message = message + '\nhttp://errors.angularjs.org/' + version.full + '/' + message = message + '\nhttp://errors.angularjs.org/1.2.1/' +
(module ? module + '/' : '') + code; (module ? module + '/' : '') + code;
for (i = 2; i < arguments.length; i++) { for (i = 2; i < arguments.length; i++) {
message = message + (i == 2 ? '?' : '&') + 'p' + (i-2) + '=' + message = message + (i == 2 ? '?' : '&') + 'p' + (i-2) + '=' +
...@@ -1429,6 +1429,7 @@ function getBlockElements(block) { ...@@ -1429,6 +1429,7 @@ function getBlockElements(block) {
function setupModuleLoader(window) { function setupModuleLoader(window) {
var $injectorMinErr = minErr('$injector'); var $injectorMinErr = minErr('$injector');
var ngMinErr = minErr('ng');
function ensure(obj, name, factory) { function ensure(obj, name, factory) {
return obj[name] || (obj[name] = factory()); return obj[name] || (obj[name] = factory());
...@@ -1489,6 +1490,12 @@ function setupModuleLoader(window) { ...@@ -1489,6 +1490,12 @@ function setupModuleLoader(window) {
* @returns {module} new module with the {@link angular.Module} api. * @returns {module} new module with the {@link angular.Module} api.
*/ */
return function module(name, requires, configFn) { return function module(name, requires, configFn) {
var assertNotHasOwnProperty = function(name, context) {
if (name === 'hasOwnProperty') {
throw ngMinErr('badname', 'hasOwnProperty is not a valid {0} name', context);
}
};
assertNotHasOwnProperty(name, 'module'); assertNotHasOwnProperty(name, 'module');
if (requires && modules.hasOwnProperty(name)) { if (requires && modules.hasOwnProperty(name)) {
modules[name] = null; modules[name] = null;
...@@ -1801,11 +1808,11 @@ function setupModuleLoader(window) { ...@@ -1801,11 +1808,11 @@ function setupModuleLoader(window) {
* - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat". * - `codeName` – `{string}` – Code name of the release, such as "jiggling-armfat".
*/ */
var version = { var version = {
full: '1.2.0', // all of these placeholder strings will be replaced by grunt's full: '1.2.1', // all of these placeholder strings will be replaced by grunt's
major: 1, // package task major: 1, // package task
minor: "NG_VERSION_MINOR", minor: 2,
dot: 0, dot: 1,
codeName: 'timely-delivery' codeName: 'underscore-empathy'
}; };
...@@ -4696,8 +4703,9 @@ function $TemplateCacheProvider() { ...@@ -4696,8 +4703,9 @@ function $TemplateCacheProvider() {
* When there are multiple directives defined on a single DOM element, sometimes it * 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 * 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. Priority is defined as a * to sort the directives before their `compile` functions get called. Priority is defined as a
* number. Directives with greater numerical `priority` are compiled first. The order of directives with * number. Directives with greater numerical `priority` are compiled first. Pre-link functions
* the same priority is undefined. The default priority is `0`. * are also run in priority order, but post-link functions are run in reverse order. The order
* of directives with the same priority is undefined. The default priority is `0`.
* *
* #### `terminal` * #### `terminal`
* If set to true then the current `priority` will be the last set of directives * If set to true then the current `priority` will be the last set of directives
...@@ -4758,8 +4766,9 @@ function $TemplateCacheProvider() { ...@@ -4758,8 +4766,9 @@ function $TemplateCacheProvider() {
* * `$scope` - Current scope associated with the element * * `$scope` - Current scope associated with the element
* * `$element` - Current element * * `$element` - Current element
* * `$attrs` - Current attributes object for the element * * `$attrs` - Current attributes object for the element
* * `$transclude` - A transclude linking function pre-bound to the correct transclusion scope: * * `$transclude` - A transclude linking function pre-bound to the correct transclusion scope.
* `function(cloneLinkingFn)`. * The scope can be overridden by an optional first argument.
* `function([scope], cloneLinkingFn)`.
* *
* *
* #### `require` * #### `require`
...@@ -4852,7 +4861,7 @@ function $TemplateCacheProvider() { ...@@ -4852,7 +4861,7 @@ function $TemplateCacheProvider() {
* * `tAttrs` - template attributes - Normalized list of attributes declared on this element shared * * `tAttrs` - template attributes - Normalized list of attributes declared on this element shared
* between all directive compile functions. * between all directive compile functions.
* *
* * `transclude` - A transclude linking function: `function(scope, cloneLinkingFn)`. * * `transclude` - [*DEPRECATED*!] A transclude linking function: `function(scope, cloneLinkingFn)`
* *
* <div class="alert alert-warning"> * <div class="alert alert-warning">
* **Note:** The template instance and the link instance may be different objects if the template has * **Note:** The template instance and the link instance may be different objects if the template has
...@@ -4861,6 +4870,12 @@ function $TemplateCacheProvider() { ...@@ -4861,6 +4870,12 @@ function $TemplateCacheProvider() {
* should be done in a linking function rather than in a compile function. * should be done in a linking function rather than in a compile function.
* </div> * </div>
* *
* <div class="alert alert-error">
* **Note:** The `transclude` function that is passed to the compile function is deperecated, as it
* e.g. does not know about the right outer scope. Please use the transclude function that is passed
* to the link function instead.
* </div>
* A compile function can have a return value which can be either a function or an object. * A compile function can have a return value which can be either a function or an object.
* *
* * returning a (post-link) function - is equivalent to registering the linking function via the * * returning a (post-link) function - is equivalent to registering the linking function via the
...@@ -4875,7 +4890,7 @@ function $TemplateCacheProvider() { ...@@ -4875,7 +4890,7 @@ function $TemplateCacheProvider() {
* This property is used only if the `compile` property is not defined. * This property is used only if the `compile` property is not defined.
* *
* <pre> * <pre>
* function link(scope, iElement, iAttrs, controller) { ... } * function link(scope, iElement, iAttrs, controller, transcludeFn) { ... }
* </pre> * </pre>
* *
* The link function is responsible for registering DOM listeners as well as updating the DOM. It is * The link function is responsible for registering DOM listeners as well as updating the DOM. It is
...@@ -4896,6 +4911,10 @@ function $TemplateCacheProvider() { ...@@ -4896,6 +4911,10 @@ function $TemplateCacheProvider() {
* element defines a controller. The controller is shared among all the directives, which allows * element defines a controller. The controller is shared among all the directives, which allows
* the directives to use the controllers as a communication channel. * the directives to use the controllers as a communication channel.
* *
* * `transcludeFn` - A transclude linking function pre-bound to the correct transclusion scope.
* The scope can be overridden by an optional first argument. This is the same as the `$transclude`
* parameter of directive controllers.
* `function([scope], cloneLinkingFn)`.
* *
* *
* #### Pre-linking function * #### Pre-linking function
...@@ -5401,7 +5420,7 @@ function $CompileProvider($provide) { ...@@ -5401,7 +5420,7 @@ function $CompileProvider($provide) {
var compositeLinkFn = var compositeLinkFn =
compileNodes($compileNodes, transcludeFn, $compileNodes, compileNodes($compileNodes, transcludeFn, $compileNodes,
maxPriority, ignoreDirective, previousCompileContext); maxPriority, ignoreDirective, previousCompileContext);
return function publicLinkFn(scope, cloneConnectFn){ return function publicLinkFn(scope, cloneConnectFn, transcludeControllers){
assertArg(scope, 'scope'); assertArg(scope, 'scope');
// important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart // important!!: we must call our jqLite.clone() since the jQuery one is trying to be smart
// and sometimes changes the structure of the DOM. // and sometimes changes the structure of the DOM.
...@@ -5409,6 +5428,10 @@ function $CompileProvider($provide) { ...@@ -5409,6 +5428,10 @@ function $CompileProvider($provide) {
? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!! ? JQLitePrototype.clone.call($compileNodes) // IMPORTANT!!!
: $compileNodes; : $compileNodes;
forEach(transcludeControllers, function(instance, name) {
$linkNode.data('$' + name + 'Controller', instance);
});
// Attach scope only to non-text nodes. // Attach scope only to non-text nodes.
for(var i = 0, ii = $linkNode.length; i<ii; i++) { for(var i = 0, ii = $linkNode.length; i<ii; i++) {
var node = $linkNode[i]; var node = $linkNode[i];
...@@ -5507,15 +5530,7 @@ function $CompileProvider($provide) { ...@@ -5507,15 +5530,7 @@ function $CompileProvider($provide) {
childTranscludeFn = nodeLinkFn.transclude; childTranscludeFn = nodeLinkFn.transclude;
if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) { if (childTranscludeFn || (!boundTranscludeFn && transcludeFn)) {
nodeLinkFn(childLinkFn, childScope, node, $rootElement, nodeLinkFn(childLinkFn, childScope, node, $rootElement,
(function(transcludeFn) { createBoundTranscludeFn(scope, childTranscludeFn || transcludeFn)
return function(cloneFn) {
var transcludeScope = scope.$new();
transcludeScope.$$transcluded = true;
return transcludeFn(transcludeScope, cloneFn).
on('$destroy', bind(transcludeScope, transcludeScope.$destroy));
};
})(childTranscludeFn || transcludeFn)
); );
} else { } else {
nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn); nodeLinkFn(childLinkFn, childScope, node, undefined, boundTranscludeFn);
...@@ -5527,6 +5542,23 @@ function $CompileProvider($provide) { ...@@ -5527,6 +5542,23 @@ function $CompileProvider($provide) {
} }
} }
function createBoundTranscludeFn(scope, transcludeFn) {
return function boundTranscludeFn(transcludedScope, cloneFn, controllers) {
var scopeCreated = false;
if (!transcludedScope) {
transcludedScope = scope.$new();
transcludedScope.$$transcluded = true;
scopeCreated = true;
}
var clone = transcludeFn(transcludedScope, cloneFn, controllers);
if (scopeCreated) {
clone.on('$destroy', bind(transcludedScope, transcludedScope.$destroy));
}
return clone;
};
}
/** /**
* Looks for directives on the given node and adds them to the directive collection which is * Looks for directives on the given node and adds them to the directive collection which is
...@@ -5664,9 +5696,9 @@ function $CompileProvider($provide) { ...@@ -5664,9 +5696,9 @@ function $CompileProvider($provide) {
* @returns {Function} * @returns {Function}
*/ */
function groupElementsLinkFnWrapper(linkFn, attrStart, attrEnd) { function groupElementsLinkFnWrapper(linkFn, attrStart, attrEnd) {
return function(scope, element, attrs, controllers) { return function(scope, element, attrs, controllers, transcludeFn) {
element = groupScan(element[0], attrStart, attrEnd); element = groupScan(element[0], attrStart, attrEnd);
return linkFn(scope, element, attrs, controllers); return linkFn(scope, element, attrs, controllers, transcludeFn);
}; };
} }
...@@ -5703,7 +5735,9 @@ function $CompileProvider($provide) { ...@@ -5703,7 +5735,9 @@ function $CompileProvider($provide) {
controllerDirectives = previousCompileContext.controllerDirectives, controllerDirectives = previousCompileContext.controllerDirectives,
newIsolateScopeDirective = previousCompileContext.newIsolateScopeDirective, newIsolateScopeDirective = previousCompileContext.newIsolateScopeDirective,
templateDirective = previousCompileContext.templateDirective, templateDirective = previousCompileContext.templateDirective,
transcludeDirective = previousCompileContext.transcludeDirective, nonTlbTranscludeDirective = previousCompileContext.nonTlbTranscludeDirective,
hasTranscludeDirective = false,
hasElementTranscludeDirective = false,
$compileNode = templateAttrs.$$element = jqLite(compileNode), $compileNode = templateAttrs.$$element = jqLite(compileNode),
directive, directive,
directiveName, directiveName,
...@@ -5754,15 +5788,18 @@ function $CompileProvider($provide) { ...@@ -5754,15 +5788,18 @@ function $CompileProvider($provide) {
} }
if (directiveValue = directive.transclude) { if (directiveValue = directive.transclude) {
hasTranscludeDirective = true;
// Special case ngIf and ngRepeat so that we don't complain about duplicate transclusion. // Special case ngIf and ngRepeat so that we don't complain about duplicate transclusion.
// This option should only be used by directives that know how to how to safely handle element transclusion, // This option should only be used by directives that know how to how to safely handle element transclusion,
// where the transcluded nodes are added or replaced after linking. // where the transcluded nodes are added or replaced after linking.
if (!directive.$$tlb) { if (!directive.$$tlb) {
assertNoDuplicate('transclusion', transcludeDirective, directive, $compileNode); assertNoDuplicate('transclusion', nonTlbTranscludeDirective, directive, $compileNode);
transcludeDirective = directive; nonTlbTranscludeDirective = directive;
} }
if (directiveValue == 'element') { if (directiveValue == 'element') {
hasElementTranscludeDirective = true;
terminalPriority = directive.priority; terminalPriority = directive.priority;
$template = groupScan(compileNode, attrStart, attrEnd); $template = groupScan(compileNode, attrStart, attrEnd);
$compileNode = templateAttrs.$$element = $compileNode = templateAttrs.$$element =
...@@ -5778,9 +5815,9 @@ function $CompileProvider($provide) { ...@@ -5778,9 +5815,9 @@ function $CompileProvider($provide) {
// - newIsolateScopeDirective or templateDirective - combining templates with // - newIsolateScopeDirective or templateDirective - combining templates with
// element transclusion doesn't make sense. // element transclusion doesn't make sense.
// //
// We need only transcludeDirective so that we prevent putting transclusion // We need only nonTlbTranscludeDirective so that we prevent putting transclusion
// on the same element more than once. // on the same element more than once.
transcludeDirective: transcludeDirective nonTlbTranscludeDirective: nonTlbTranscludeDirective
}); });
} else { } else {
$template = jqLite(jqLiteClone(compileNode)).contents(); $template = jqLite(jqLiteClone(compileNode)).contents();
...@@ -5849,7 +5886,7 @@ function $CompileProvider($provide) { ...@@ -5849,7 +5886,7 @@ function $CompileProvider($provide) {
controllerDirectives: controllerDirectives, controllerDirectives: controllerDirectives,
newIsolateScopeDirective: newIsolateScopeDirective, newIsolateScopeDirective: newIsolateScopeDirective,
templateDirective: templateDirective, templateDirective: templateDirective,
transcludeDirective: transcludeDirective nonTlbTranscludeDirective: nonTlbTranscludeDirective
}); });
ii = directives.length; ii = directives.length;
} else if (directive.compile) { } else if (directive.compile) {
...@@ -5873,7 +5910,7 @@ function $CompileProvider($provide) { ...@@ -5873,7 +5910,7 @@ function $CompileProvider($provide) {
} }
nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope === true; nodeLinkFn.scope = newScopeDirective && newScopeDirective.scope === true;
nodeLinkFn.transclude = transcludeDirective && childTranscludeFn; nodeLinkFn.transclude = hasTranscludeDirective && childTranscludeFn;
// might be normal or delayed nodeLinkFn depending on if templateUrl is present // might be normal or delayed nodeLinkFn depending on if templateUrl is present
return nodeLinkFn; return nodeLinkFn;
...@@ -5900,7 +5937,7 @@ function $CompileProvider($provide) { ...@@ -5900,7 +5937,7 @@ function $CompileProvider($provide) {
} }
function getControllers(require, $element) { function getControllers(require, $element, elementControllers) {
var value, retrievalMethod = 'data', optional = false; var value, retrievalMethod = 'data', optional = false;
if (isString(require)) { if (isString(require)) {
while((value = require.charAt(0)) == '^' || value == '?') { while((value = require.charAt(0)) == '^' || value == '?') {
...@@ -5910,13 +5947,12 @@ function $CompileProvider($provide) { ...@@ -5910,13 +5947,12 @@ function $CompileProvider($provide) {
} }
optional = optional || value == '?'; optional = optional || value == '?';
} }
value = null;
value = $element[retrievalMethod]('$' + require + 'Controller'); if (elementControllers && retrievalMethod === 'data') {
value = elementControllers[require];
if ($element[0].nodeType == 8 && $element[0].$$controller) { // Transclusion comment node
value = value || $element[0].$$controller;
$element[0].$$controller = null;
} }
value = value || $element[retrievalMethod]('$' + require + 'Controller');
if (!value && !optional) { if (!value && !optional) {
throw $compileMinErr('ctreq', throw $compileMinErr('ctreq',
...@@ -5927,7 +5963,7 @@ function $CompileProvider($provide) { ...@@ -5927,7 +5963,7 @@ function $CompileProvider($provide) {
} else if (isArray(require)) { } else if (isArray(require)) {
value = []; value = [];
forEach(require, function(require) { forEach(require, function(require) {
value.push(getControllers(require, $element)); value.push(getControllers(require, $element, elementControllers));
}); });
} }
return value; return value;
...@@ -5935,7 +5971,7 @@ function $CompileProvider($provide) { ...@@ -5935,7 +5971,7 @@ function $CompileProvider($provide) {
function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) { function nodeLinkFn(childLinkFn, scope, linkNode, $rootElement, boundTranscludeFn) {
var attrs, $element, i, ii, linkFn, controller, isolateScope; var attrs, $element, i, ii, linkFn, controller, isolateScope, elementControllers = {}, transcludeFn;
if (compileNode === linkNode) { if (compileNode === linkNode) {
attrs = templateAttrs; attrs = templateAttrs;
...@@ -6029,14 +6065,14 @@ function $CompileProvider($provide) { ...@@ -6029,14 +6065,14 @@ function $CompileProvider($provide) {
} }
}); });
} }
transcludeFn = boundTranscludeFn && controllersBoundTransclude;
if (controllerDirectives) { if (controllerDirectives) {
forEach(controllerDirectives, function(directive) { forEach(controllerDirectives, function(directive) {
var locals = { var locals = {
$scope: directive === newIsolateScopeDirective || directive.$$isolateScope ? isolateScope : scope, $scope: directive === newIsolateScopeDirective || directive.$$isolateScope ? isolateScope : scope,
$element: $element, $element: $element,
$attrs: attrs, $attrs: attrs,
$transclude: boundTranscludeFn $transclude: transcludeFn
}, controllerInstance; }, controllerInstance;
controller = directive.controller; controller = directive.controller;
...@@ -6045,16 +6081,16 @@ function $CompileProvider($provide) { ...@@ -6045,16 +6081,16 @@ function $CompileProvider($provide) {
} }
controllerInstance = $controller(controller, locals); controllerInstance = $controller(controller, locals);
// For directives with element transclusion the element is a comment,
// Directives with element transclusion and a controller need to attach controller // but jQuery .data doesn't support attaching data to comment nodes as it's hard to
// to the comment node created by the compiler, but jQuery .data doesn't support // clean up (http://bugs.jquery.com/ticket/8335).
// attaching data to comment nodes so instead we set it directly on the element and // Instead, we save the controllers for the element in a local hash and attach to .data
// remove it after we read it later. // later, once we have the actual element.
if ($element[0].nodeType == 8) { // Transclusion comment node elementControllers[directive.name] = controllerInstance;
$element[0].$$controller = controllerInstance; if (!hasElementTranscludeDirective) {
} else {
$element.data('$' + directive.name + 'Controller', controllerInstance); $element.data('$' + directive.name + 'Controller', controllerInstance);
} }
if (directive.controllerAs) { if (directive.controllerAs) {
locals.$scope[directive.controllerAs] = controllerInstance; locals.$scope[directive.controllerAs] = controllerInstance;
} }
...@@ -6066,7 +6102,7 @@ function $CompileProvider($provide) { ...@@ -6066,7 +6102,7 @@ function $CompileProvider($provide) {
try { try {
linkFn = preLinkFns[i]; linkFn = preLinkFns[i];
linkFn(linkFn.isolateScope ? isolateScope : scope, $element, attrs, linkFn(linkFn.isolateScope ? isolateScope : scope, $element, attrs,
linkFn.require && getControllers(linkFn.require, $element)); linkFn.require && getControllers(linkFn.require, $element, elementControllers), transcludeFn);
} catch (e) { } catch (e) {
$exceptionHandler(e, startingTag($element)); $exceptionHandler(e, startingTag($element));
} }
...@@ -6086,11 +6122,28 @@ function $CompileProvider($provide) { ...@@ -6086,11 +6122,28 @@ function $CompileProvider($provide) {
try { try {
linkFn = postLinkFns[i]; linkFn = postLinkFns[i];
linkFn(linkFn.isolateScope ? isolateScope : scope, $element, attrs, linkFn(linkFn.isolateScope ? isolateScope : scope, $element, attrs,
linkFn.require && getControllers(linkFn.require, $element)); linkFn.require && getControllers(linkFn.require, $element, elementControllers), transcludeFn);
} catch (e) { } catch (e) {
$exceptionHandler(e, startingTag($element)); $exceptionHandler(e, startingTag($element));
} }
} }
// This is the function that is injected as `$transclude`.
function controllersBoundTransclude(scope, cloneAttachFn) {
var transcludeControllers;
// no scope passed
if (arguments.length < 2) {
cloneAttachFn = scope;
scope = undefined;
}
if (hasElementTranscludeDirective) {
transcludeControllers = elementControllers;
}
return boundTranscludeFn(scope, cloneAttachFn, transcludeControllers);
}
} }
} }
...@@ -6169,6 +6222,7 @@ function $CompileProvider($provide) { ...@@ -6169,6 +6222,7 @@ function $CompileProvider($provide) {
dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value; dst['class'] = (dst['class'] ? dst['class'] + ' ' : '') + value;
} else if (key == 'style') { } else if (key == 'style') {
$element.attr('style', $element.attr('style') + ';' + value); $element.attr('style', $element.attr('style') + ';' + value);
dst['style'] = (dst['style'] ? dst['style'] + ';' : '') + value;
// `dst` will never contain hasOwnProperty as DOM parser won't let it. // `dst` will never contain hasOwnProperty as DOM parser won't let it.
// You will get an "InvalidCharacterError: DOM Exception 5" error if you // You will get an "InvalidCharacterError: DOM Exception 5" error if you
// have an attribute like "has-own-property" or "data-has-own-property", etc. // have an attribute like "has-own-property" or "data-has-own-property", etc.
...@@ -6199,7 +6253,7 @@ function $CompileProvider($provide) { ...@@ -6199,7 +6253,7 @@ function $CompileProvider($provide) {
$http.get($sce.getTrustedResourceUrl(templateUrl), {cache: $templateCache}). $http.get($sce.getTrustedResourceUrl(templateUrl), {cache: $templateCache}).
success(function(content) { success(function(content) {
var compileNode, tempTemplateAttrs, $template; var compileNode, tempTemplateAttrs, $template, childBoundTranscludeFn;
content = denormalizeTemplate(content); content = denormalizeTemplate(content);
...@@ -6244,7 +6298,7 @@ function $CompileProvider($provide) { ...@@ -6244,7 +6298,7 @@ function $CompileProvider($provide) {
var scope = linkQueue.shift(), var scope = linkQueue.shift(),
beforeTemplateLinkNode = linkQueue.shift(), beforeTemplateLinkNode = linkQueue.shift(),
linkRootElement = linkQueue.shift(), linkRootElement = linkQueue.shift(),
controller = linkQueue.shift(), boundTranscludeFn = linkQueue.shift(),
linkNode = $compileNode[0]; linkNode = $compileNode[0];
if (beforeTemplateLinkNode !== beforeTemplateCompileNode) { if (beforeTemplateLinkNode !== beforeTemplateCompileNode) {
...@@ -6252,9 +6306,13 @@ function $CompileProvider($provide) { ...@@ -6252,9 +6306,13 @@ function $CompileProvider($provide) {
linkNode = jqLiteClone(compileNode); linkNode = jqLiteClone(compileNode);
replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode); replaceWith(linkRootElement, jqLite(beforeTemplateLinkNode), linkNode);
} }
if (afterTemplateNodeLinkFn.transclude) {
childBoundTranscludeFn = createBoundTranscludeFn(scope, afterTemplateNodeLinkFn.transclude);
} else {
childBoundTranscludeFn = boundTranscludeFn;
}
afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement, afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, linkNode, $rootElement,
controller); childBoundTranscludeFn);
} }
linkQueue = null; linkQueue = null;
}). }).
...@@ -6262,14 +6320,14 @@ function $CompileProvider($provide) { ...@@ -6262,14 +6320,14 @@ function $CompileProvider($provide) {
throw $compileMinErr('tpload', 'Failed to load template: {0}', config.url); throw $compileMinErr('tpload', 'Failed to load template: {0}', config.url);
}); });
return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, controller) { return function delayedNodeLinkFn(ignoreChildLinkFn, scope, node, rootElement, boundTranscludeFn) {
if (linkQueue) { if (linkQueue) {
linkQueue.push(scope); linkQueue.push(scope);
linkQueue.push(node); linkQueue.push(node);
linkQueue.push(rootElement); linkQueue.push(rootElement);
linkQueue.push(controller); linkQueue.push(boundTranscludeFn);
} else { } else {
afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, controller); afterTemplateNodeLinkFn(afterTemplateChildLinkFn, scope, node, rootElement, boundTranscludeFn);
} }
}; };
} }
...@@ -6974,9 +7032,11 @@ function $HttpProvider() { ...@@ -6974,9 +7032,11 @@ function $HttpProvider() {
* *
* # Caching * # Caching
* *
* To enable caching, set the configuration property `cache` to `true`. When the cache is * To enable caching, set the request configuration `cache` property to `true` (to use default
* enabled, `$http` stores the response from the server in local cache. Next time the * cache) or to a custom cache object (built with {@link ng.$cacheFactory `$cacheFactory`}).
* response is served from the cache without sending a request to the server. * When the cache is enabled, `$http` stores the response from the server in the specified
* cache. The next time the same request is made, the response is served from the cache without
* sending a request to the server.
* *
* Note that even if the response is served from cache, delivery of the data is asynchronous in * Note that even if the response is served from cache, delivery of the data is asynchronous in
* the same way that real requests are. * the same way that real requests are.
...@@ -6985,9 +7045,13 @@ function $HttpProvider() { ...@@ -6985,9 +7045,13 @@ function $HttpProvider() {
* cache, but the cache is not populated yet, only one request to the server will be made and * cache, but the cache is not populated yet, only one request to the server will be made and
* the remaining requests will be fulfilled using the response from the first request. * the remaining requests will be fulfilled using the response from the first request.
* *
* A custom default cache built with $cacheFactory can be provided in $http.defaults.cache. * You can change the default cache to a new object (built with
* To skip it, set configuration property `cache` to `false`. * {@link ng.$cacheFactory `$cacheFactory`}) by updating the
* {@link ng.$http#properties_defaults `$http.defaults.cache`} property. All requests who set
* their `cache` property to `true` will now use this cache object.
* *
* If you set the default cache to `false` then only requests that specify their own custom
* cache object will be cached.
* *
* # Interceptors * # Interceptors
* *
...@@ -8251,8 +8315,8 @@ function encodePath(path) { ...@@ -8251,8 +8315,8 @@ function encodePath(path) {
return segments.join('/'); return segments.join('/');
} }
function parseAbsoluteUrl(absoluteUrl, locationObj) { function parseAbsoluteUrl(absoluteUrl, locationObj, appBase) {
var parsedUrl = urlResolve(absoluteUrl); var parsedUrl = urlResolve(absoluteUrl, appBase);
locationObj.$$protocol = parsedUrl.protocol; locationObj.$$protocol = parsedUrl.protocol;
locationObj.$$host = parsedUrl.hostname; locationObj.$$host = parsedUrl.hostname;
...@@ -8260,12 +8324,12 @@ function parseAbsoluteUrl(absoluteUrl, locationObj) { ...@@ -8260,12 +8324,12 @@ function parseAbsoluteUrl(absoluteUrl, locationObj) {
} }
function parseAppUrl(relativeUrl, locationObj) { function parseAppUrl(relativeUrl, locationObj, appBase) {
var prefixed = (relativeUrl.charAt(0) !== '/'); var prefixed = (relativeUrl.charAt(0) !== '/');
if (prefixed) { if (prefixed) {
relativeUrl = '/' + relativeUrl; relativeUrl = '/' + relativeUrl;
} }
var match = urlResolve(relativeUrl); var match = urlResolve(relativeUrl, appBase);
locationObj.$$path = decodeURIComponent(prefixed && match.pathname.charAt(0) === '/' ? locationObj.$$path = decodeURIComponent(prefixed && match.pathname.charAt(0) === '/' ?
match.pathname.substring(1) : match.pathname); match.pathname.substring(1) : match.pathname);
locationObj.$$search = parseKeyValue(match.search); locationObj.$$search = parseKeyValue(match.search);
...@@ -8320,7 +8384,7 @@ function LocationHtml5Url(appBase, basePrefix) { ...@@ -8320,7 +8384,7 @@ function LocationHtml5Url(appBase, basePrefix) {
this.$$html5 = true; this.$$html5 = true;
basePrefix = basePrefix || ''; basePrefix = basePrefix || '';
var appBaseNoFile = stripFile(appBase); var appBaseNoFile = stripFile(appBase);
parseAbsoluteUrl(appBase, this); parseAbsoluteUrl(appBase, this, appBase);
/** /**
...@@ -8335,7 +8399,7 @@ function LocationHtml5Url(appBase, basePrefix) { ...@@ -8335,7 +8399,7 @@ function LocationHtml5Url(appBase, basePrefix) {
appBaseNoFile); appBaseNoFile);
} }
parseAppUrl(pathUrl, this); parseAppUrl(pathUrl, this, appBase);
if (!this.$$path) { if (!this.$$path) {
this.$$path = '/'; this.$$path = '/';
...@@ -8387,7 +8451,7 @@ function LocationHtml5Url(appBase, basePrefix) { ...@@ -8387,7 +8451,7 @@ function LocationHtml5Url(appBase, basePrefix) {
function LocationHashbangUrl(appBase, hashPrefix) { function LocationHashbangUrl(appBase, hashPrefix) {
var appBaseNoFile = stripFile(appBase); var appBaseNoFile = stripFile(appBase);
parseAbsoluteUrl(appBase, this); parseAbsoluteUrl(appBase, this, appBase);
/** /**
...@@ -8407,7 +8471,7 @@ function LocationHashbangUrl(appBase, hashPrefix) { ...@@ -8407,7 +8471,7 @@ function LocationHashbangUrl(appBase, hashPrefix) {
throw $locationMinErr('ihshprfx', 'Invalid url "{0}", missing hash prefix "{1}".', url, throw $locationMinErr('ihshprfx', 'Invalid url "{0}", missing hash prefix "{1}".', url,
hashPrefix); hashPrefix);
} }
parseAppUrl(withoutHashUrl, this); parseAppUrl(withoutHashUrl, this, appBase);
this.$$compose(); this.$$compose();
}; };
...@@ -9055,23 +9119,18 @@ var promiseWarning; ...@@ -9055,23 +9119,18 @@ var promiseWarning;
// ------------------------------ // ------------------------------
// Angular expressions are generally considered safe because these expressions only have direct // Angular expressions are generally considered safe because these expressions only have direct
// access to $scope and locals. However, one can obtain the ability to execute arbitrary JS code by // access to $scope and locals. However, one can obtain the ability to execute arbitrary JS code by
// obtaining a reference to native JS functions such as the Function constructor, the global Window // obtaining a reference to native JS functions such as the Function constructor.
// or Document object. In addition, many powerful functions for use by JavaScript code are
// published on scope that shouldn't be available from within an Angular expression.
// //
// As an example, consider the following Angular expression: // As an example, consider the following Angular expression:
// //
// {}.toString.constructor(alert("evil JS code")) // {}.toString.constructor(alert("evil JS code"))
// //
// We want to prevent this type of access. For the sake of performance, during the lexing phase we // We want to prevent this type of access. For the sake of performance, during the lexing phase we
// disallow any "dotted" access to any member named "constructor" or to any member whose name begins // disallow any "dotted" access to any member named "constructor".
// or ends with an underscore. The latter allows one to exclude the private / JavaScript only API
// available on the scope and controllers from the context of an Angular expression.
// //
// For reflective calls (a[b]), we check that the value of the lookup is not the Function // For reflective calls (a[b]) we check that the value of the lookup is not the Function constructor
// constructor, Window or DOM node while evaluating the expression, which is a stronger but more // while evaluating the expression, which is a stronger but more expensive test. Since reflective
// expensive test. Since reflective calls are expensive anyway, this is not such a big deal compared // calls are expensive anyway, this is not such a big deal compared to static dereferencing.
// to static dereferencing.
// //
// This sandboxing technique is not perfect and doesn't aim to be. The goal is to prevent exploits // This sandboxing technique is not perfect and doesn't aim to be. The goal is to prevent exploits
// against the expression language, but not to prevent exploits that were enabled by exposing // against the expression language, but not to prevent exploits that were enabled by exposing
...@@ -9085,20 +9144,12 @@ var promiseWarning; ...@@ -9085,20 +9144,12 @@ var promiseWarning;
// In general, it is not possible to access a Window object from an angular expression unless a // In general, it is not possible to access a Window object from an angular expression unless a
// window or some DOM object that has a reference to window is published onto a Scope. // window or some DOM object that has a reference to window is published onto a Scope.
function ensureSafeMemberName(name, fullExpression, allowConstructor) { function ensureSafeMemberName(name, fullExpression) {
if (typeof name !== 'string' && toString.apply(name) !== "[object String]") { if (name === "constructor") {
return name;
}
if (name === "constructor" && !allowConstructor) {
throw $parseMinErr('isecfld', throw $parseMinErr('isecfld',
'Referencing "constructor" field in Angular expressions is disallowed! Expression: {0}', 'Referencing "constructor" field in Angular expressions is disallowed! Expression: {0}',
fullExpression); fullExpression);
} }
if (name.charAt(0) === '_' || name.charAt(name.length-1) === '_') {
throw $parseMinErr('isecprv',
'Referencing private fields in Angular expressions is disallowed! Expression: {0}',
fullExpression);
}
return name; return name;
} }
...@@ -9782,10 +9833,7 @@ Parser.prototype = { ...@@ -9782,10 +9833,7 @@ Parser.prototype = {
return extend(function(self, locals) { return extend(function(self, locals) {
var o = obj(self, locals), var o = obj(self, locals),
// In the getter, we will not block looking up "constructor" by name in order to support user defined i = indexFn(self, locals),
// constructors. However, if value looked up is the Function constructor, we will still block it in the
// ensureSafeObject call right after we look up o[i] (a few lines below.)
i = ensureSafeMemberName(indexFn(self, locals), parser.text, true /* allowConstructor */),
v, p; v, p;
if (!o) return undefined; if (!o) return undefined;
...@@ -9801,7 +9849,7 @@ Parser.prototype = { ...@@ -9801,7 +9849,7 @@ Parser.prototype = {
return v; return v;
}, { }, {
assign: function(self, value, locals) { assign: function(self, value, locals) {
var key = ensureSafeMemberName(indexFn(self, locals), parser.text); var key = indexFn(self, locals);
// prevent overwriting of Function.constructor which would break ensureSafeObject check // prevent overwriting of Function.constructor which would break ensureSafeObject check
var safe = ensureSafeObject(obj(self, locals), parser.text); var safe = ensureSafeObject(obj(self, locals), parser.text);
return safe[key] = value; return safe[key] = value;
...@@ -10461,7 +10509,7 @@ function $ParseProvider() { ...@@ -10461,7 +10509,7 @@ function $ParseProvider() {
* // Propagate promise resolution to 'then' functions using $apply(). * // Propagate promise resolution to 'then' functions using $apply().
* $rootScope.$apply(); * $rootScope.$apply();
* expect(resolvedValue).toEqual(123); * expect(resolvedValue).toEqual(123);
* }); * }));
* </pre> * </pre>
*/ */
function $QProvider() { function $QProvider() {
...@@ -12278,10 +12326,10 @@ function $SceDelegateProvider() { ...@@ -12278,10 +12326,10 @@ function $SceDelegateProvider() {
* *
* <pre class="prettyprint"> * <pre class="prettyprint">
* <input ng-model="userHtml"> * <input ng-model="userHtml">
* <div ng-bind-html="{{userHtml}}"> * <div ng-bind-html="userHtml">
* </pre> * </pre>
* *
* Notice that `ng-bind-html` is bound to `{{userHtml}}` controlled by the user. With SCE * Notice that `ng-bind-html` is bound to `userHtml` controlled by the user. With SCE
* disabled, this application allows the user to render arbitrary HTML into the DIV. * disabled, this application allows the user to render arbitrary HTML into the DIV.
* In a more realistic example, one may be rendering user comments, blog articles, etc. via * In a more realistic example, one may be rendering user comments, blog articles, etc. via
* bindings. (HTML is just one example of a context where rendering user controlled input creates * bindings. (HTML is just one example of a context where rendering user controlled input creates
...@@ -13202,8 +13250,14 @@ function $TimeoutProvider() { ...@@ -13202,8 +13250,14 @@ function $TimeoutProvider() {
// exactly the behavior needed here. There is little value is mocking these out for this // exactly the behavior needed here. There is little value is mocking these out for this
// service. // service.
var urlParsingNode = document.createElement("a"); var urlParsingNode = document.createElement("a");
/*
Matches paths for file protocol on windows,
such as /C:/foo/bar, and captures only /foo/bar.
*/
var windowsFilePathExp = /^\/?.*?:(\/.*)/;
var originUrl = urlResolve(window.location.href, true); var originUrl = urlResolve(window.location.href, true);
/** /**
* *
* Implementation Notes for non-IE browsers * Implementation Notes for non-IE browsers
...@@ -13222,7 +13276,7 @@ var originUrl = urlResolve(window.location.href, true); ...@@ -13222,7 +13276,7 @@ var originUrl = urlResolve(window.location.href, true);
* browsers. However, the parsed components will not be set if the URL assigned did not specify * browsers. However, the parsed components will not be set if the URL assigned did not specify
* them. (e.g. if you assign a.href = "foo", then a.protocol, a.host, etc. will be empty.) We * them. (e.g. if you assign a.href = "foo", then a.protocol, a.host, etc. will be empty.) We
* work around that by performing the parsing in a 2nd step by taking a previously normalized * work around that by performing the parsing in a 2nd step by taking a previously normalized
* URL (e.g. by assining to a.href) and assigning it a.href again. This correctly populates the * URL (e.g. by assigning to a.href) and assigning it a.href again. This correctly populates the
* properties such as protocol, hostname, port, etc. * properties such as protocol, hostname, port, etc.
* *
* IE7 does not normalize the URL when assigned to an anchor node. (Apparently, it does, if one * IE7 does not normalize the URL when assigned to an anchor node. (Apparently, it does, if one
...@@ -13256,8 +13310,10 @@ var originUrl = urlResolve(window.location.href, true); ...@@ -13256,8 +13310,10 @@ var originUrl = urlResolve(window.location.href, true);
* | pathname | The pathname, beginning with "/" * | pathname | The pathname, beginning with "/"
* *
*/ */
function urlResolve(url) { function urlResolve(url, base) {
var href = url; var href = url,
pathname;
if (msie) { if (msie) {
// Normalize before parse. Refer Implementation Notes on why this is // Normalize before parse. Refer Implementation Notes on why this is
// done in two steps on IE. // done in two steps on IE.
...@@ -13267,7 +13323,22 @@ function urlResolve(url) { ...@@ -13267,7 +13323,22 @@ function urlResolve(url) {
urlParsingNode.setAttribute('href', href); urlParsingNode.setAttribute('href', href);
// $$urlParsingNode provides the UrlUtils interface - http://url.spec.whatwg.org/#urlutils /*
* In Windows, on an anchor node on documents loaded from
* the filesystem, the browser will return a pathname
* prefixed with the drive name ('/C:/path') when a
* pathname without a drive is set:
* * a.setAttribute('href', '/foo')
* * a.pathname === '/C:/foo' //true
*
* Inside of Angular, we're always using pathnames that
* do not include drive names for routing.
*/
pathname = removeWindowsDriveName(urlParsingNode.pathname, url, base);
pathname = (pathname.charAt(0) === '/') ? pathname : '/' + pathname;
// urlParsingNode provides the UrlUtils interface - http://url.spec.whatwg.org/#urlutils
return { return {
href: urlParsingNode.href, href: urlParsingNode.href,
protocol: urlParsingNode.protocol ? urlParsingNode.protocol.replace(/:$/, '') : '', protocol: urlParsingNode.protocol ? urlParsingNode.protocol.replace(/:$/, '') : '',
...@@ -13276,8 +13347,7 @@ function urlResolve(url) { ...@@ -13276,8 +13347,7 @@ function urlResolve(url) {
hash: urlParsingNode.hash ? urlParsingNode.hash.replace(/^#/, '') : '', hash: urlParsingNode.hash ? urlParsingNode.hash.replace(/^#/, '') : '',
hostname: urlParsingNode.hostname, hostname: urlParsingNode.hostname,
port: urlParsingNode.port, port: urlParsingNode.port,
pathname: urlParsingNode.pathname && urlParsingNode.pathname.charAt(0) === '/' ? pathname: pathname
urlParsingNode.pathname : '/' + urlParsingNode.pathname
}; };
} }
...@@ -13295,6 +13365,26 @@ function urlIsSameOrigin(requestUrl) { ...@@ -13295,6 +13365,26 @@ function urlIsSameOrigin(requestUrl) {
parsed.host === originUrl.host); parsed.host === originUrl.host);
} }
function removeWindowsDriveName (path, url, base) {
var firstPathSegmentMatch;
//Get the relative path from the input URL.
if (url.indexOf(base) === 0) {
url = url.replace(base, '');
}
/*
* The input URL intentionally contains a
* first path segment that ends with a colon.
*/
if (windowsFilePathExp.exec(url)) {
return path;
}
firstPathSegmentMatch = windowsFilePathExp.exec(path);
return firstPathSegmentMatch ? firstPathSegmentMatch[1] : path;
}
/** /**
* @ngdoc object * @ngdoc object
* @name ng.$window * @name ng.$window
...@@ -14811,7 +14901,7 @@ var nullFormCtrl = { ...@@ -14811,7 +14901,7 @@ var nullFormCtrl = {
* @property {Object} $error Is an object hash, containing references to all invalid controls or * @property {Object} $error Is an object hash, containing references to all invalid controls or
* forms, where: * forms, where:
* *
* - keys are validation tokens (error names) — such as `required`, `url` or `email`), * - keys are validation tokens (error names) — such as `required`, `url` or `email`,
* - values are arrays of controls or forms that are invalid with given error. * - values are arrays of controls or forms that are invalid with given error.
* *
* @description * @description
...@@ -15996,6 +16086,11 @@ var VALID_CLASS = 'ng-valid', ...@@ -15996,6 +16086,11 @@ var VALID_CLASS = 'ng-valid',
* } * }
* ngModel.$formatters.push(formatter); * ngModel.$formatters.push(formatter);
* </pre> * </pre>
*
* @property {Array.<Function>} $viewChangeListeners Array of functions to execute whenever the
* view value has changed. It is called with no arguments, and its return value is ignored.
* This can be used in place of additional $watches against the model value.
*
* @property {Object} $error An object hash with all errors as keys. * @property {Object} $error An object hash with all errors as keys.
* *
* @property {boolean} $pristine True if user has not interacted with the control yet. * @property {boolean} $pristine True if user has not interacted with the control yet.
...@@ -16259,14 +16354,19 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$ ...@@ -16259,14 +16354,19 @@ var NgModelController = ['$scope', '$exceptionHandler', '$attrs', '$element', '$
* @methodOf ng.directive:ngModel.NgModelController * @methodOf ng.directive:ngModel.NgModelController
* *
* @description * @description
* Read a value from view. * Update the view value.
* *
* This method should be called from within a DOM event handler. * This method should be called when the view value changes, typically from within a DOM event handler.
* For example {@link ng.directive:input input} or * For example {@link ng.directive:input input} and
* {@link ng.directive:select select} directives call it. * {@link ng.directive:select select} directives call it.
* *
* It internally calls all `$parsers` (including validators) and updates the `$modelValue` and the actual model path. * It will update the $viewValue, then pass this value through each of the functions in `$parsers`,
* Lastly it calls all registered change listeners. * which includes any validators. The value that comes out of this `$parsers` pipeline, be applied to
* `$modelValue` and the **expression** specified in the `ng-model` attribute.
*
* Lastly, all the registered change listeners, in the `$viewChangeListeners` list, are called.
*
* Note that calling this function does not trigger a `$digest`.
* *
* @param {string} value Value from the view. * @param {string} value Value from the view.
*/ */
...@@ -16768,27 +16868,33 @@ var ngBindTemplateDirective = ['$interpolate', function($interpolate) { ...@@ -16768,27 +16868,33 @@ var ngBindTemplateDirective = ['$interpolate', function($interpolate) {
* @param {expression} ngBindHtml {@link guide/expression Expression} to evaluate. * @param {expression} ngBindHtml {@link guide/expression Expression} to evaluate.
* *
* @example * @example
* Try it here: enter text in text box and watch the greeting change. Try it here: enter text in text box and watch the greeting change.
<doc:example module="ngBindHtmlExample" deps="angular-sanitize.js" >
<doc:source>
<script>
angular.module('ngBindHtmlExample', ['ngSanitize'])
.controller('ngBindHtmlCtrl', ['$scope', function ngBindHtmlCtrl($scope) { <example module="ngBindHtmlExample" deps="angular-sanitize.js">
$scope.myHTML = 'I am an <code>HTML</code>string with <a href="#">links!</a> and other <em>stuff</em>'; <file name="index.html">
}]);
</script>
<div ng-controller="ngBindHtmlCtrl"> <div ng-controller="ngBindHtmlCtrl">
<p ng-bind-html="myHTML"></p> <p ng-bind-html="myHTML"></p>
</div> </div>
</doc:source> </file>
<doc:scenario>
<file name="script.js">
angular.module('ngBindHtmlExample', ['ngSanitize'])
.controller('ngBindHtmlCtrl', ['$scope', function ngBindHtmlCtrl($scope) {
$scope.myHTML =
'I am an <code>HTML</code>string with <a href="#">links!</a> and other <em>stuff</em>';
}]);
</file>
<file name="scenario.js">
it('should check ng-bind-html', function() { it('should check ng-bind-html', function() {
expect(using('.doc-example-live').binding('myHTML')). expect(using('.doc-example-live').binding('myHTML')).
toBe('I am an <code>HTML</code>string with <a href="#">links!</a> and other <em>stuff</em>'); toBe(
'I am an <code>HTML</code>string with <a href="#">links!</a> and other <em>stuff</em>'
);
}); });
</doc:scenario> </file>
</doc:example> </example>
*/ */
var ngBindHtmlDirective = ['$sce', '$parse', function($sce, $parse) { var ngBindHtmlDirective = ['$sce', '$parse', function($sce, $parse) {
return function(scope, element, attr) { return function(scope, element, attr) {
...@@ -16901,18 +17007,18 @@ function classDirective(name, selector) { ...@@ -16901,18 +17007,18 @@ function classDirective(name, selector) {
* @example Example that demonstrates basic bindings via ngClass directive. * @example Example that demonstrates basic bindings via ngClass directive.
<example> <example>
<file name="index.html"> <file name="index.html">
<p ng-class="{strike: strike, bold: bold, red: red}">Map Syntax Example</p> <p ng-class="{strike: deleted, bold: important, red: error}">Map Syntax Example</p>
<input type="checkbox" ng-model="bold"> bold <input type="checkbox" ng-model="deleted"> deleted (apply "strike" class)<br>
<input type="checkbox" ng-model="strike"> strike <input type="checkbox" ng-model="important"> important (apply "bold" class)<br>
<input type="checkbox" ng-model="red"> red <input type="checkbox" ng-model="error"> error (apply "red" class)
<hr> <hr>
<p ng-class="style">Using String Syntax</p> <p ng-class="style">Using String Syntax</p>
<input type="text" ng-model="style" placeholder="Type: bold strike red"> <input type="text" ng-model="style" placeholder="Type: bold strike red">
<hr> <hr>
<p ng-class="[style1, style2, style3]">Using Array Syntax</p> <p ng-class="[style1, style2, style3]">Using Array Syntax</p>
<input ng-model="style1" placeholder="Type: bold"><br> <input ng-model="style1" placeholder="Type: bold, strike or red"><br>
<input ng-model="style2" placeholder="Type: strike"><br> <input ng-model="style2" placeholder="Type: bold, strike or red"><br>
<input ng-model="style3" placeholder="Type: red"><br> <input ng-model="style3" placeholder="Type: bold, strike or red"><br>
</file> </file>
<file name="style.css"> <file name="style.css">
.strike { .strike {
...@@ -16931,10 +17037,10 @@ function classDirective(name, selector) { ...@@ -16931,10 +17037,10 @@ function classDirective(name, selector) {
expect(element('.doc-example-live p:first').prop('className')).not().toMatch(/bold/); expect(element('.doc-example-live p:first').prop('className')).not().toMatch(/bold/);
expect(element('.doc-example-live p:first').prop('className')).not().toMatch(/red/); expect(element('.doc-example-live p:first').prop('className')).not().toMatch(/red/);
input('bold').check(); input('important').check();
expect(element('.doc-example-live p:first').prop('className')).toMatch(/bold/); expect(element('.doc-example-live p:first').prop('className')).toMatch(/bold/);
input('red').check(); input('error').check();
expect(element('.doc-example-live p:first').prop('className')).toMatch(/red/); expect(element('.doc-example-live p:first').prop('className')).toMatch(/red/);
}); });
...@@ -17806,22 +17912,21 @@ var ngIfDirective = ['$animate', function($animate) { ...@@ -17806,22 +17912,21 @@ var ngIfDirective = ['$animate', function($animate) {
terminal: true, terminal: true,
restrict: 'A', restrict: 'A',
$$tlb: true, $$tlb: true,
compile: function (element, attr, transclude) { link: function ($scope, $element, $attr, ctrl, $transclude) {
return function ($scope, $element, $attr) {
var block, childScope; var block, childScope;
$scope.$watch($attr.ngIf, function ngIfWatchAction(value) { $scope.$watch($attr.ngIf, function ngIfWatchAction(value) {
if (toBoolean(value)) { if (toBoolean(value)) {
if (!childScope) {
childScope = $scope.$new(); childScope = $scope.$new();
transclude(childScope, function (clone) { $transclude(childScope, function (clone) {
block = { block = {
startNode: clone[0], startNode: clone[0],
endNode: clone[clone.length++] = document.createComment(' end ngIf: ' + $attr.ngIf + ' ') endNode: clone[clone.length++] = document.createComment(' end ngIf: ' + $attr.ngIf + ' ')
}; };
$animate.enter(clone, $element.parent(), $element); $animate.enter(clone, $element.parent(), $element);
}); });
}
} else { } else {
if (childScope) { if (childScope) {
...@@ -17835,7 +17940,6 @@ var ngIfDirective = ['$animate', function($animate) { ...@@ -17835,7 +17940,6 @@ var ngIfDirective = ['$animate', function($animate) {
} }
} }
}); });
};
} }
}; };
}]; }];
...@@ -17994,12 +18098,12 @@ var ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile' ...@@ -17994,12 +18098,12 @@ var ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile'
priority: 400, priority: 400,
terminal: true, terminal: true,
transclude: 'element', transclude: 'element',
compile: function(element, attr, transclusion) { compile: function(element, attr) {
var srcExp = attr.ngInclude || attr.src, var srcExp = attr.ngInclude || attr.src,
onloadExp = attr.onload || '', onloadExp = attr.onload || '',
autoScrollExp = attr.autoscroll; autoScrollExp = attr.autoscroll;
return function(scope, $element) { return function(scope, $element, $attr, ctrl, $transclude) {
var changeCounter = 0, var changeCounter = 0,
currentScope, currentScope,
currentElement; currentElement;
...@@ -18028,7 +18132,7 @@ var ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile' ...@@ -18028,7 +18132,7 @@ var ngIncludeDirective = ['$http', '$templateCache', '$anchorScroll', '$compile'
if (thisChangeId !== changeCounter) return; if (thisChangeId !== changeCounter) return;
var newScope = scope.$new(); var newScope = scope.$new();
transclusion(newScope, function(clone) { $transclude(newScope, function(clone) {
cleanupLastIncludeContent(); cleanupLastIncludeContent();
currentScope = newScope; currentScope = newScope;
...@@ -18557,8 +18661,7 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) { ...@@ -18557,8 +18661,7 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
priority: 1000, priority: 1000,
terminal: true, terminal: true,
$$tlb: true, $$tlb: true,
compile: function(element, attr, linker) { link: function($scope, $element, $attr, ctrl, $transclude){
return function($scope, $element, $attr){
var expression = $attr.ngRepeat; var expression = $attr.ngRepeat;
var match = expression.match(/^\s*(.+)\s+in\s+(.*?)\s*(\s+track\s+by\s+(.+)\s*)?$/), var match = expression.match(/^\s*(.+)\s+in\s+(.*?)\s*(\s+track\s+by\s+(.+)\s*)?$/),
trackByExp, trackByExpGetter, trackByIdExpFn, trackByIdArrayFn, trackByIdObjFn, trackByExp, trackByExpGetter, trackByIdExpFn, trackByIdArrayFn, trackByIdObjFn,
...@@ -18720,7 +18823,7 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) { ...@@ -18720,7 +18823,7 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
// jshint bitwise: true // jshint bitwise: true
if (!block.startNode) { if (!block.startNode) {
linker(childScope, function(clone) { $transclude(childScope, function(clone) {
clone[clone.length++] = document.createComment(' end ngRepeat: ' + expression + ' '); clone[clone.length++] = document.createComment(' end ngRepeat: ' + expression + ' ');
$animate.enter(clone, null, jqLite(previousNode)); $animate.enter(clone, null, jqLite(previousNode));
previousNode = clone; previousNode = clone;
...@@ -18733,7 +18836,6 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) { ...@@ -18733,7 +18836,6 @@ var ngRepeatDirective = ['$parse', '$animate', function($parse, $animate) {
} }
lastBlockMap = nextBlockMap; lastBlockMap = nextBlockMap;
}); });
};
} }
}; };
}]; }];
...@@ -19242,10 +19344,10 @@ var ngSwitchWhenDirective = ngDirective({ ...@@ -19242,10 +19344,10 @@ var ngSwitchWhenDirective = ngDirective({
transclude: 'element', transclude: 'element',
priority: 800, priority: 800,
require: '^ngSwitch', require: '^ngSwitch',
compile: function(element, attrs, transclude) { compile: function(element, attrs) {
return function(scope, element, attr, ctrl) { return function(scope, element, attr, ctrl, $transclude) {
ctrl.cases['!' + attrs.ngSwitchWhen] = (ctrl.cases['!' + attrs.ngSwitchWhen] || []); ctrl.cases['!' + attrs.ngSwitchWhen] = (ctrl.cases['!' + attrs.ngSwitchWhen] || []);
ctrl.cases['!' + attrs.ngSwitchWhen].push({ transclude: transclude, element: element }); ctrl.cases['!' + attrs.ngSwitchWhen].push({ transclude: $transclude, element: element });
}; };
} }
}); });
...@@ -19254,11 +19356,9 @@ var ngSwitchDefaultDirective = ngDirective({ ...@@ -19254,11 +19356,9 @@ var ngSwitchDefaultDirective = ngDirective({
transclude: 'element', transclude: 'element',
priority: 800, priority: 800,
require: '^ngSwitch', require: '^ngSwitch',
compile: function(element, attrs, transclude) { link: function(scope, element, attr, ctrl, $transclude) {
return function(scope, element, attr, ctrl) {
ctrl.cases['?'] = (ctrl.cases['?'] || []); ctrl.cases['?'] = (ctrl.cases['?'] || []);
ctrl.cases['?'].push({ transclude: transclude, element: element }); ctrl.cases['?'].push({ transclude: $transclude, element: element });
};
} }
}); });
......
...@@ -19,7 +19,7 @@ ...@@ -19,7 +19,7 @@
<input id="toggle-all" type="checkbox" ng-model="allChecked" ng-click="markAll(allChecked)"> <input id="toggle-all" type="checkbox" ng-model="allChecked" ng-click="markAll(allChecked)">
<label for="toggle-all">Mark all as complete</label> <label for="toggle-all">Mark all as complete</label>
<ul id="todo-list"> <ul id="todo-list">
<li ng-repeat="todo in todos track by $index | filter:statusFilter" ng-class="{completed: todo.completed, editing: todo == editedTodo}"> <li ng-repeat="todo in todos | filter:statusFilter" ng-class="{completed: todo.completed, editing: todo == editedTodo}">
<div class="view"> <div class="view">
<input class="toggle" type="checkbox" ng-model="todo.completed"> <input class="toggle" type="checkbox" ng-model="todo.completed">
<label ng-dblclick="editTodo(todo)">{{todo.title}}</label> <label ng-dblclick="editTodo(todo)">{{todo.title}}</label>
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment