|
212 | 212 | * * (no prefix) - Locate the required controller on the current element. Throw an error if not found. |
213 | 213 | * * `?` - Attempt to locate the required controller or pass `null` to the `link` fn if not found. |
214 | 214 | * * `^` - Locate the required controller by searching the element and its parents. Throw an error if not found. |
| 215 | + * * `^^` - Locate the required controller by searching the element's parents. Throw an error if not found. |
215 | 216 | * * `?^` - Attempt to locate the required controller by searching the element and its parents or pass |
216 | 217 | * `null` to the `link` fn if not found. |
| 218 | + * * `?^^` - Attempt to locate the required controller by searching the element's parents, or pass |
| 219 | + * `null` to the `link` fn if not found. |
217 | 220 | * |
218 | 221 | * |
219 | 222 | * #### `controllerAs` |
@@ -567,7 +570,8 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { |
567 | 570 | Suffix = 'Directive', |
568 | 571 | COMMENT_DIRECTIVE_REGEXP = /^\s*directive\:\s*([\d\w_\-]+)\s+(.*)$/, |
569 | 572 | CLASS_DIRECTIVE_REGEXP = /(([\d\w_\-]+)(?:\:([^;]+))?;?)/, |
570 | | - ALL_OR_NOTHING_ATTRS = makeMap('ngSrc,ngSrcset,src,srcset'); |
| 573 | + ALL_OR_NOTHING_ATTRS = makeMap('ngSrc,ngSrcset,src,srcset'), |
| 574 | + REQUIRE_PREFIX_REGEXP = /^(?:(\^\^?)?(\?)?(\^\^?)?)?/; |
571 | 575 |
|
572 | 576 | // Ref: http://developers.whatwg.org/webappapis.html#event-handler-idl-attributes |
573 | 577 | // The assumption is that future DOM event attribute names will begin with |
@@ -1589,22 +1593,34 @@ function $CompileProvider($provide, $$sanitizeUriProvider) { |
1589 | 1593 |
|
1590 | 1594 | function getControllers(directiveName, require, $element, elementControllers) { |
1591 | 1595 | var value, retrievalMethod = 'data', optional = false; |
| 1596 | + var $searchElement = $element; |
| 1597 | + var match; |
1592 | 1598 | if (isString(require)) { |
1593 | | - while((value = require.charAt(0)) == '^' || value == '?') { |
1594 | | - require = require.substr(1); |
1595 | | - if (value == '^') { |
1596 | | - retrievalMethod = 'inheritedData'; |
1597 | | - } |
1598 | | - optional = optional || value == '?'; |
| 1599 | + match = require.match(REQUIRE_PREFIX_REGEXP); |
| 1600 | + require = require.substring(match[0].length); |
| 1601 | + |
| 1602 | + if (match[3]) { |
| 1603 | + if (match[1]) match[3] = null; |
| 1604 | + else match[1] = match[3]; |
1599 | 1605 | } |
| 1606 | + if (match[1] === '^') { |
| 1607 | + retrievalMethod = 'inheritedData'; |
| 1608 | + } else if (match[1] === '^^') { |
| 1609 | + retrievalMethod = 'inheritedData'; |
| 1610 | + $searchElement = $element.parent(); |
| 1611 | + } |
| 1612 | + if (match[2] === '?') { |
| 1613 | + optional = true; |
| 1614 | + } |
| 1615 | + |
1600 | 1616 | value = null; |
1601 | 1617 |
|
1602 | 1618 | if (elementControllers && retrievalMethod === 'data') { |
1603 | 1619 | if (value = elementControllers[require]) { |
1604 | 1620 | value = value.instance; |
1605 | 1621 | } |
1606 | 1622 | } |
1607 | | - value = value || $element[retrievalMethod]('$' + require + 'Controller'); |
| 1623 | + value = value || $searchElement[retrievalMethod]('$' + require + 'Controller'); |
1608 | 1624 |
|
1609 | 1625 | if (!value && !optional) { |
1610 | 1626 | throw $compileMinErr('ctreq', |
|
0 commit comments