(scope, attrs, destination, bindings, directive)
| 9106 | // Set up $watches for isolate scope and controller bindings. This process |
| 9107 | // only occurs for isolate scopes and new scopes with controllerAs. |
| 9108 | function initializeDirectiveBindings(scope, attrs, destination, bindings, directive) { |
| 9109 | var removeWatchCollection = []; |
| 9110 | forEach(bindings, function(definition, scopeName) { |
| 9111 | var attrName = definition.attrName, |
| 9112 | optional = definition.optional, |
| 9113 | mode = definition.mode, // @, =, or & |
| 9114 | lastValue, |
| 9115 | parentGet, parentSet, compare; |
| 9116 | |
| 9117 | switch (mode) { |
| 9118 | |
| 9119 | case '@': |
| 9120 | if (!optional && !hasOwnProperty.call(attrs, attrName)) { |
| 9121 | destination[scopeName] = attrs[attrName] = void 0; |
| 9122 | } |
| 9123 | attrs.$observe(attrName, function(value) { |
| 9124 | if (isString(value)) { |
| 9125 | destination[scopeName] = value; |
| 9126 | } |
| 9127 | }); |
| 9128 | attrs.$$observers[attrName].$$scope = scope; |
| 9129 | lastValue = attrs[attrName]; |
| 9130 | if (isString(lastValue)) { |
| 9131 | // If the attribute has been provided then we trigger an interpolation to ensure |
| 9132 | // the value is there for use in the link fn |
| 9133 | destination[scopeName] = $interpolate(lastValue)(scope); |
| 9134 | } else if (isBoolean(lastValue)) { |
| 9135 | // If the attributes is one of the BOOLEAN_ATTR then Angular will have converted |
| 9136 | // the value to boolean rather than a string, so we special case this situation |
| 9137 | destination[scopeName] = lastValue; |
| 9138 | } |
| 9139 | break; |
| 9140 | |
| 9141 | case '=': |
| 9142 | if (!hasOwnProperty.call(attrs, attrName)) { |
| 9143 | if (optional) break; |
| 9144 | attrs[attrName] = void 0; |
| 9145 | } |
| 9146 | if (optional && !attrs[attrName]) break; |
| 9147 | |
| 9148 | parentGet = $parse(attrs[attrName]); |
| 9149 | if (parentGet.literal) { |
| 9150 | compare = equals; |
| 9151 | } else { |
| 9152 | compare = function(a, b) { return a === b || (a !== a && b !== b); }; |
| 9153 | } |
| 9154 | parentSet = parentGet.assign || function() { |
| 9155 | // reset the change, or we will throw this exception on every $digest |
| 9156 | lastValue = destination[scopeName] = parentGet(scope); |
| 9157 | throw $compileMinErr('nonassign', |
| 9158 | "Expression '{0}' in attribute '{1}' used with directive '{2}' is non-assignable!", |
| 9159 | attrs[attrName], attrName, directive.name); |
| 9160 | }; |
| 9161 | lastValue = destination[scopeName] = parentGet(scope); |
| 9162 | var parentValueWatch = function parentValueWatch(parentValue) { |
| 9163 | if (!compare(parentValue, destination[scopeName])) { |
| 9164 | // we are out of sync and need to copy |
| 9165 | if (!compare(parentValue, lastValue)) { |
no test coverage detected