diff options
Diffstat (limited to 'src')
| -rw-r--r-- | src/Angular.js | 3 | ||||
| -rw-r--r-- | src/directives.js | 2 | ||||
| -rw-r--r-- | src/service/filter.js | 27 | ||||
| -rw-r--r-- | src/service/filter/filters.js | 182 | ||||
| -rw-r--r-- | src/service/parse.js | 26 | 
5 files changed, 137 insertions, 103 deletions
| diff --git a/src/Angular.js b/src/Angular.js index d8a726c0..17aa2d4a 100644 --- a/src/Angular.js +++ b/src/Angular.js @@ -109,8 +109,6 @@ var _undefined        = undefined,      angularDirective  = extensionMap(angular, 'directive', lowercase),      /** @name angular.widget */      angularWidget     = extensionMap(angular, 'widget', shivForIE), -    /** @name angular.filter */ -    angularFilter     = extensionMap(angular, 'filter'),      /** @name angular.service */      angularInputType  = extensionMap(angular, 'inputType', lowercase),      /** @name angular.service */ @@ -1054,6 +1052,7 @@ function ngModule($provide, $injector) {    $provide.service('$defer', $DeferProvider);    $provide.service('$document', $DocumentProvider);    $provide.service('$exceptionHandler', $ExceptionHandlerProvider); +  $provide.service('$filter', $FilterProvider);    $provide.service('$formFactory', $FormFactoryProvider);    $provide.service('$locale', $LocaleProvider);    $provide.service('$location', $LocationProvider); diff --git a/src/directives.js b/src/directives.js index 20235f64..b511541f 100644 --- a/src/directives.js +++ b/src/directives.js @@ -236,7 +236,7 @@ angularDirective("ng:controller", function(expression){  angularDirective("ng:bind", function(expression, element){    element.addClass('ng-binding');    return ['$exceptionHandler', '$parse', '$element', function($exceptionHandler, $parse, element) { -    var exprFn = parser(expression), +    var exprFn = $parse(expression),          lastValue = Number.NaN;      this.$watch(function(scope) { diff --git a/src/service/filter.js b/src/service/filter.js new file mode 100644 index 00000000..7b85c23d --- /dev/null +++ b/src/service/filter.js @@ -0,0 +1,27 @@ +'use strict'; + +$FilterProvider.$inject = ['$provide']; +function $FilterProvider($provide) { +  var suffix = '$Filter'; + +  $provide.filter = function(name, factory) { +    return $provide.factory(name + suffix, factory); +  }; + +  this.$get = ['$injector', function($injector) { +    return function(name) { +      return $injector(name + suffix); +    } +  }]; + +  //////////////////////////////////////// + +  $provide.filter('currency', currencyFilter); +  $provide.filter('number', numberFilter); +  $provide.filter('date', dateFilter); +  $provide.filter('json', jsonFilter); +  $provide.filter('lowercase', lowercaseFilter); +  $provide.filter('uppercase', uppercaseFilter); +  $provide.filter('html', htmlFilter); +  $provide.filter('linky', linkyFilter); +} diff --git a/src/service/filter/filters.js b/src/service/filter/filters.js index b9c3d2ef..eea3cbf2 100644 --- a/src/service/filter/filters.js +++ b/src/service/filter/filters.js @@ -72,13 +72,15 @@       </doc:scenario>     </doc:example>   */ -angularFilter.currency = function(amount, currencySymbol){ -  var formats = this.$service('$locale').NUMBER_FORMATS; -  this.$element.toggleClass('ng-format-negative', amount < 0); -  if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM; -  return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2). -              replace(/\u00A4/g, currencySymbol); -}; +currencyFilter.$inject = ['$locale']; +function currencyFilter($locale) { +  var formats = $locale.NUMBER_FORMATS; +  return function(amount, currencySymbol){ +    if (isUndefined(currencySymbol)) currencySymbol = formats.CURRENCY_SYM; +    return formatNumber(amount, formats.PATTERNS[1], formats.GROUP_SEP, formats.DECIMAL_SEP, 2). +                replace(/\u00A4/g, currencySymbol); +  }; +}  /**   * @ngdoc filter @@ -126,14 +128,17 @@ angularFilter.currency = function(amount, currencySymbol){     </doc:example>   */ -var DECIMAL_SEP = '.'; -angularFilter.number = function(number, fractionSize) { -  var formats = this.$service('$locale').NUMBER_FORMATS; -  return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, -                                                  formats.DECIMAL_SEP, fractionSize); -}; +numberFilter.$inject = ['$locale']; +function numberFilter($locale) { +  var formats = $locale.NUMBER_FORMATS; +  return function(number, fractionSize) { +    return formatNumber(number, formats.PATTERNS[0], formats.GROUP_SEP, formats.DECIMAL_SEP, +      fractionSize); +  }; +} +var DECIMAL_SEP = '.';  function formatNumber(number, pattern, groupSep, decimalSep, fractionSize) {    if (isNaN(number) || !isFinite(number)) return ''; @@ -260,9 +265,7 @@ var DATE_FORMATS = {       Z: timeZoneGetter  }; -var GET_TIME_ZONE = /[A-Z]{3}(?![+\-])/, -    DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/, -    OPERA_TOSTRING_PATTERN = /^[\d].*Z$/, +var DATE_FORMATS_SPLIT = /((?:[^yMdHhmsaZE']+)|(?:'(?:[^']|'')*')|(?:E+|y+|M+|d+|H+|h+|m+|s+|a|Z))(.*)/,      NUMBER_STRING = /^\d+$/;  /** @@ -343,49 +346,51 @@ var GET_TIME_ZONE = /[A-Z]{3}(?![+\-])/,       </doc:scenario>     </doc:example>   */ -angularFilter.date = function(date, format) { -  var $locale = this.$service('$locale'), -      text = '', -      parts = [], -      fn, match; - -  format = format || 'mediumDate' -  format = $locale.DATETIME_FORMATS[format] || format; -  if (isString(date)) { -    if (NUMBER_STRING.test(date)) { -      date = parseInt(date, 10); -    } else { -      date = angularString.toDate(date); +dateFilter.$inject = ['$locale']; +function dateFilter($locale) { +  return function(date, format) { +    var text = '', +        parts = [], +        fn, match; + +    format = format || 'mediumDate' +    format = $locale.DATETIME_FORMATS[format] || format; +    if (isString(date)) { +      if (NUMBER_STRING.test(date)) { +        date = parseInt(date, 10); +      } else { +        date = angularString.toDate(date); +      }      } -  } -  if (isNumber(date)) { -    date = new Date(date); -  } +    if (isNumber(date)) { +      date = new Date(date); +    } -  if (!isDate(date)) { -    return date; -  } +    if (!isDate(date)) { +      return date; +    } -  while(format) { -    match = DATE_FORMATS_SPLIT.exec(format); -    if (match) { -      parts = concat(parts, match, 1); -      format = parts.pop(); -    } else { -      parts.push(format); -      format = null; +    while(format) { +      match = DATE_FORMATS_SPLIT.exec(format); +      if (match) { +        parts = concat(parts, match, 1); +        format = parts.pop(); +      } else { +        parts.push(format); +        format = null; +      }      } -  } -  forEach(parts, function(value){ -    fn = DATE_FORMATS[value]; -    text += fn ? fn(date, $locale.DATETIME_FORMATS) -               : value.replace(/(^'|'$)/g, '').replace(/''/g, "'"); -  }); +    forEach(parts, function(value){ +      fn = DATE_FORMATS[value]; +      text += fn ? fn(date, $locale.DATETIME_FORMATS) +                 : value.replace(/(^'|'$)/g, '').replace(/''/g, "'"); +    }); -  return text; -}; +    return text; +  }; +}  /** @@ -417,10 +422,11 @@ angularFilter.date = function(date, format) {     </doc:example>   *   */ -angularFilter.json = function(object) { -  this.$element.addClass("ng-monospace"); -  return toJson(object, true, /^(\$|this$)/); -}; +function jsonFilter() { +  return function(object) { +    return toJson(object, true); +  }; +}  /** @@ -430,7 +436,7 @@ angularFilter.json = function(object) {   *   * @see angular.lowercase   */ -angularFilter.lowercase = lowercase; +var lowercaseFilter = valueFn(lowercase);  /** @@ -440,7 +446,7 @@ angularFilter.lowercase = lowercase;   *   * @see angular.uppercase   */ -angularFilter.uppercase = uppercase; +var uppercaseFilter = valueFn(uppercase);  /** @@ -537,9 +543,11 @@ angularFilter.uppercase = uppercase;       </doc:scenario>     </doc:example>   */ -angularFilter.html =  function(html, option){ -  return new HTML(html, option); -}; +function htmlFilter() { +  return function(html, option){ +    return new HTML(html, option); +  }; +}  /** @@ -619,29 +627,31 @@ angularFilter.html =  function(html, option){       </doc:scenario>     </doc:example>   */ -var LINKY_URL_REGEXP = /((ftp|https?):\/\/|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s\.\;\,\(\)\{\}\<\>]/, -    MAILTO_REGEXP = /^mailto:/; - -angularFilter.linky = function(text) { -  if (!text) return text; -  var match; -  var raw = text; -  var html = []; -  var writer = htmlSanitizeWriter(html); -  var url; -  var i; -  while ((match = raw.match(LINKY_URL_REGEXP))) { -    // We can not end in these as they are sometimes found at the end of the sentence -    url = match[0]; -    // if we did not match ftp/http/mailto then assume mailto -    if (match[2] == match[3]) url = 'mailto:' + url; -    i = match.index; -    writer.chars(raw.substr(0, i)); -    writer.start('a', {href:url}); -    writer.chars(match[0].replace(MAILTO_REGEXP, '')); -    writer.end('a'); -    raw = raw.substring(i + match[0].length); -  } -  writer.chars(raw); -  return new HTML(html.join('')); +function linkyFilter() { +  var LINKY_URL_REGEXP = /((ftp|https?):\/\/|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s\.\;\,\(\)\{\}\<\>]/, +      MAILTO_REGEXP = /^mailto:/; + +  return function(text) { +    if (!text) return text; +    var match; +    var raw = text; +    var html = []; +    var writer = htmlSanitizeWriter(html); +    var url; +    var i; +    while ((match = raw.match(LINKY_URL_REGEXP))) { +      // We can not end in these as they are sometimes found at the end of the sentence +      url = match[0]; +      // if we did not match ftp/http/mailto then assume mailto +      if (match[2] == match[3]) url = 'mailto:' + url; +      i = match.index; +      writer.chars(raw.substr(0, i)); +      writer.start('a', {href:url}); +      writer.chars(match[0].replace(MAILTO_REGEXP, '')); +      writer.end('a'); +      raw = raw.substring(i + match[0].length); +    } +    writer.chars(raw); +    return new HTML(html.join('')); +  };  }; diff --git a/src/service/parse.js b/src/service/parse.js index 465f416e..36f6b715 100644 --- a/src/service/parse.js +++ b/src/service/parse.js @@ -217,7 +217,7 @@ function lex(text){  ///////////////////////////////////////// -function parser(text, json){ +function parser(text, json, $filter){    var ZERO = valueFn(0),        value,        tokens = lex(text), @@ -227,8 +227,7 @@ function parser(text, json){        fieldAccess = _fieldAccess,        objectIndex = _objectIndex,        filterChain = _filterChain, -      functionIdent = _functionIdent, -      pipeFunction = _pipeFunction; +      functionIdent = _functionIdent;    if(json){      // The extra level of aliasing is here, just in case the lexer misses something, so that      // we prevent any accidental execution in JSON. @@ -239,7 +238,6 @@ function parser(text, json){        assignable =        filterChain =        functionIdent = -      pipeFunction =          function() { throwError("is not valid json", {text:text, index:0}); };      value = primary();    } else { @@ -346,13 +344,9 @@ function parser(text, json){    }    function filter() { -    return pipeFunction(angularFilter); -  } - -  function _pipeFunction(fnScope){ -    var fn = functionIdent(fnScope); +    var token = expect(); +    var fn = $filter(token.text);      var argsFn = []; -    var token;      while(true) {        if ((token = expect(':'))) {          argsFn.push(expression()); @@ -719,13 +713,13 @@ function getterFn(path) {  function $ParseProvider() {    var cache = {}; -  this.$get = ['$injector', function($injector) { +  this.$get = ['$filter', function($filter) {      return function(exp) {        switch(typeof exp) {          case 'string':            return cache.hasOwnProperty(exp)              ? cache[exp] -            : cache[exp] =  parser(exp); +            : cache[exp] =  parser(exp, false, $filter);          case 'function':            return exp;          default: @@ -735,10 +729,14 @@ function $ParseProvider() {    }];  } +function noFilters(){ +  throw Error('Filters not supported!'); +} +  // This is a special access for JSON parser which bypasses the injector  var parseJson = function(json) { -  return parser(json, true); +  return parser(json, true, noFilters);  };  // TODO(misko): temporary hack, until we get rid of the type augmentation -var expressionCompile = new $ParseProvider().$get[1](null); +var expressionCompile = new $ParseProvider().$get[1](noFilters); | 
