diff options
| author | Misko Hevery | 2011-12-07 21:01:19 -0800 | 
|---|---|---|
| committer | Misko Hevery | 2012-01-25 11:46:36 -0800 | 
| commit | 5001c1a1217772d2bffe108bafd475b24badf559 (patch) | |
| tree | 8c16f111ae4bfcf4b098b14d395b327443917501 /src | |
| parent | 0f6b2ef9823953533dd98849fc29c08e6a05c4a4 (diff) | |
| download | angular.js-5001c1a1217772d2bffe108bafd475b24badf559.tar.bz2 | |
refactor($interpolate): improve interpolation service add documentation
Diffstat (limited to 'src')
| -rw-r--r-- | src/service/interpolate.js | 205 | 
1 files changed, 134 insertions, 71 deletions
| diff --git a/src/service/interpolate.js b/src/service/interpolate.js index 03692824..6d3ae868 100644 --- a/src/service/interpolate.js +++ b/src/service/interpolate.js @@ -1,82 +1,145 @@  'use strict'; -function $InterpolateProvider(){ -  this.$get = ['$parse', function($parse){ -    return function(text, templateOnly) { -      var bindings = parseBindings(text); -      if (hasBindings(bindings) || !templateOnly) { -        return compileBindTemplate(text); -      } -    }; -  }]; -} +/** + * @ngdoc function + * @name angular.module.ng.$interpolateProvider + * @function + * + * @description + * + * Used for configuring the interpolation markup. Deafults to `{{` and `}}`. + */ +function $InterpolateProvider() { +  var startSymbol = '{{'; +  var endSymbol = '}}'; -var bindTemplateCache = {}; -function compileBindTemplate(template){ -  var fn = bindTemplateCache[template]; -  if (!fn) { -    var bindings = []; -    forEach(parseBindings(template), function(text){ -      var exp = binding(text); -      bindings.push(exp -        ? function(scope, element) { return scope.$eval(exp); } -        : function() { return text; }); -    }); -    bindTemplateCache[template] = fn = function(scope, element, prettyPrintJson) { -      var parts = [], -          hadOwnElement = scope.hasOwnProperty('$element'), -          oldElement = scope.$element; +  /** +   * @ngdoc method +   * @name angular.module.ng.$interpolateProvider#startSymbol +   * @methodOf angular.module.ng.$interpolateProvider +   * @description +   * Symbol to denote start of expression in the interpolated string. Defaults to `{{`. +   * +   * @prop {string=} value new value to set the starting symbol to. +   */ +  this.startSymbol = function(value){ +    if (value) { +      startSymbol = value; +      return this; +    } else { +      return startSymbol; +    } +  }; -      // TODO(misko): get rid of $element -      scope.$element = element; -      try { -        for (var i = 0; i < bindings.length; i++) { -          var value = bindings[i](scope, element); -          if (isElement(value)) -            value = ''; -          else if (isObject(value)) -            value = toJson(value, prettyPrintJson); -          parts.push(value); -        } -        return parts.join(''); -      } finally { -        if (hadOwnElement) { -          scope.$element = oldElement; -        } else { -          delete scope.$element; -        } -      } -    }; -  } -  return fn; -} +  /** +   * @ngdoc method +   * @name angular.module.ng.$interpolateProvider#endSymbol +   * @methodOf angular.module.ng.$interpolateProvider +   * @description +   * Symbol to denote the end of expression in the interpolated string. Defaults to `}}`. +   * +   * @prop {string=} value new value to set the ending symbol to. +   */ +  this.endSymbol = function(value){ +    if (value) { +      endSymbol = value; +      return this; +    } else { +      return startSymbol; +    } +  }; -function parseBindings(string) { -  var results = []; -  var lastIndex = 0; -  var index; -  while((index = string.indexOf('{{', lastIndex)) > -1) { -    if (lastIndex < index) -      results.push(string.substr(lastIndex, index - lastIndex)); -    lastIndex = index; +  this.$get = ['$parse', function($parse) { +    var startSymbolLength = startSymbol.length, +        endSymbolLength = endSymbol.length; -    index = string.indexOf('}}', index); -    index = index < 0 ? string.length : index + 2; +    /** +     * @ngdoc function +     * @name angular.module.ng.$interpolate +     * @function +     * +     * @requires $parse +     * +     * @description +     * +     * Compiles a string with markup into an interpolation function. This service is used by the +     * HTML {@link angular.module.ng.$compile $compile} service for data binding. See +     * {@link angular.module.ng.$interpolateProvider $interpolateProvider} for configuring the +     * interpolation markup. +     * +     * +       <pre> +         var $interpolate = ...; // injected +         var exp = $interpolate('Hello {{name}}!'); +         expect(exp({name:'Angular'}).toEqual('Hello Angular!'); +       </pre> +     * +     * +     * @param {string} text The text with markup to interpolate. +     * @param {boolean=} mustHaveExpression if set to true then the interpolation string must have +     *    embedded expression in order to return an interpolation function. Strings with no +     *    embedded expression will return null for the interpolation function. +     * @returns {function(context)} an interpolation function which is used to compute the interpolated +     *    string. The function has these parameters: +     * +     *    * `context`: an object against which any expressions embedded in the strings are evaluated +     *      against. +     * +     */ +    return function(text, mustHaveExpression) { +      var startIndex, +          endIndex, +          index = 0, +          parts = [], +          length = text.length, +          hasInterpolation = false, +          fn, +          exp, +          concat = []; -    results.push(string.substr(lastIndex, index - lastIndex)); -    lastIndex = index; -  } -  if (lastIndex != string.length) -    results.push(string.substr(lastIndex, string.length - lastIndex)); -  return results.length === 0 ? [ string ] : results; -} +      while(index < length) { +        if ( ((startIndex = text.indexOf(startSymbol, index)) != -1) && +             ((endIndex = text.indexOf(endSymbol, startIndex + startSymbolLength)) != -1) ) { +          (index != startIndex) && parts.push(text.substring(index, startIndex)); +          parts.push(fn = $parse(exp = text.substring(startIndex + startSymbolLength, endIndex))); +          fn.exp = exp; +          index = endIndex + endSymbolLength; +          hasInterpolation = true; +        } else { +          // we did not find anything, so we have to add the remainder to the parts array +          (index != length) && parts.push(text.substring(index)); +          index = length; +        } +      } -function binding(string) { -  var binding = string.replace(/\n/gm, ' ').match(/^\{\{(.*)\}\}$/); -  return binding ? binding[1] : null; -} +      if (!(length = parts.length)) { +        // we added, nothing, must have been an empty string. +        parts.push(''); +        length = 1; +      } -function hasBindings(bindings) { -  return bindings.length > 1 || binding(bindings[0]) !== null; +      if (!mustHaveExpression  || hasInterpolation) { +        concat.length = length; +        fn = function(context) { +          for(var i = 0, ii = length, part; i<ii; i++) { +            if (typeof (part = parts[i]) == 'function') { +              part = part(context); +              if (part == null || part == undefined) { +                part = ''; +              } else if (typeof part != 'string') { +                part = toJson(part); +              } +            } +            concat[i] = part; +          } +          return concat.join(''); +        }; +        fn.exp = text; +        fn.parts = parts; +        return fn; +      } +    }; +  }];  } + | 
