angular-rails-engine 1.0.7.0 → 1.1.5.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: adf55e5157bf8d1543fe36941bc9181e1f411eb8
4
- data.tar.gz: 0fc3c7a388b625813e22e18a4c7ac0c25cf4a2e1
3
+ metadata.gz: 26672e71f0500d424e50d99f4064f26d1ef11db9
4
+ data.tar.gz: 82e9f502e9224e38c81c1b6bb3009410f3974aa9
5
5
  SHA512:
6
- metadata.gz: 2db33b14ffd8537edaa99fff7f62df006dffac9f77576024f2a34651718418989752fc572a9e2f742085822b18209be291b7a5045591d3752ce1d8437384d277
7
- data.tar.gz: a2d51eb4924057b4d5ce0fd6afe38528499d112a435cca150a52bb2beafbc67bbb5f2c664ebe5b7ff8ad59b054ca2ae9011aa4d73ecec3d0591028d23a807687
6
+ metadata.gz: a71aaecf256d7e5e463f93b8809d8361a557eef011d0d9b412ad46c7584a2e101ca40da57bdbfade750506efe75bee23a8b179f7aae991a3d4d3ef2ccc8c815f
7
+ data.tar.gz: 9013d9a11734b93f100ac67f495ecd9fe7a5c42b2dbceda660b2480e93daf2228bb0a9d2bbf63a644f88c927bce1b439a2743eb9398250b7a59849731c6bc39d
Binary file
data.tar.gz.sig CHANGED
Binary file
data/README.md CHANGED
@@ -2,7 +2,11 @@
2
2
  Make [Angular.js](http://angularjs.org) into Rails Engine.
3
3
 
4
4
  ## Version
5
- Angular.js 1.0.7
5
+ Angular.js 1.1.5
6
+
7
+ ### Older Versions
8
+
9
+ For Angular.js 1.0.x, try [1.0 branch](https://github.com/yjchen/angular-rails-engine/tree/1.0) or gem version around 1.0.x.x.
6
10
 
7
11
  ## Rails 3.2 or later
8
12
  Include Gemfile,
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.0.7
2
+ * @license AngularJS v1.1.5
3
3
  * (c) 2010-2012 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /*
2
- AngularJS v1.0.7
2
+ AngularJS v1.1.5
3
3
  (c) 2010-2012 Google, Inc. http://angularjs.org
4
4
  License: MIT
5
5
  */
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.0.7
2
+ * @license AngularJS v1.1.5
3
3
  * (c) 2010-2012 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -25,7 +25,7 @@
25
25
  * the need to interact with the low level {@link ng.$http $http} service.
26
26
  *
27
27
  * # Installation
28
- * To use $resource make sure you have included the `angular-resource.js` that comes in Angular
28
+ * To use $resource make sure you have included the `angular-resource.js` that comes in Angular
29
29
  * package. You can also find this file on Google CDN, bower as well as at
30
30
  * {@link http://code.angularjs.org/ code.angularjs.org}.
31
31
  *
@@ -35,13 +35,21 @@
35
35
  *
36
36
  * and you are ready to get started!
37
37
  *
38
- * @param {string} url A parameterized URL template with parameters prefixed by `:` as in
39
- * `/user/:username`. If you are using a URL with a port number (e.g.
38
+ * @param {string} url A parametrized URL template with parameters prefixed by `:` as in
39
+ * `/user/:username`. If you are using a URL with a port number (e.g.
40
40
  * `http://example.com:8080/api`), you'll need to escape the colon character before the port
41
41
  * number, like this: `$resource('http://example.com\\:8080/api')`.
42
42
  *
43
+ * If you are using a url with a suffix, just add the suffix, like this:
44
+ * `$resource('http://example.com/resource.json')` or `$resource('http://example.com/:id.json')
45
+ * or even `$resource('http://example.com/resource/:resource_id.:format')`
46
+ * If the parameter before the suffix is empty, :resource_id in this case, then the `/.` will be
47
+ * collapsed down to a single `.`. If you need this sequence to appear and not collapse then you
48
+ * can escape it with `/\.`.
49
+ *
43
50
  * @param {Object=} paramDefaults Default values for `url` parameters. These can be overridden in
44
- * `actions` methods.
51
+ * `actions` methods. If any of the parameter value is a function, it will be executed every time
52
+ * when a param value needs to be obtained for a request (unless the param was overridden).
45
53
  *
46
54
  * Each key value in the parameter object is first bound to url template if present and then any
47
55
  * excess keys are appended to the url search query after the `?`.
@@ -53,21 +61,43 @@
53
61
  * the data object (useful for non-GET operations).
54
62
  *
55
63
  * @param {Object.<Object>=} actions Hash with declaration of custom action that should extend the
56
- * default set of resource actions. The declaration should be created in the following format:
64
+ * default set of resource actions. The declaration should be created in the format of {@link
65
+ * ng.$http#Parameters $http.config}:
57
66
  *
58
- * {action1: {method:?, params:?, isArray:?},
59
- * action2: {method:?, params:?, isArray:?},
67
+ * {action1: {method:?, params:?, isArray:?, headers:?, ...},
68
+ * action2: {method:?, params:?, isArray:?, headers:?, ...},
60
69
  * ...}
61
70
  *
62
71
  * Where:
63
72
  *
64
- * - `action` – {string} – The name of action. This name becomes the name of the method on your
73
+ * - **`action`** – {string} – The name of action. This name becomes the name of the method on your
65
74
  * resource object.
66
- * - `method` – {string} – HTTP request method. Valid methods are: `GET`, `POST`, `PUT`, `DELETE`,
67
- * and `JSONP`
68
- * - `params` – {object=} – Optional set of pre-bound parameters for this action.
69
- * - isArray {boolean=} If true then the returned object for this action is an array, see
75
+ * - **`method`** – {string} – HTTP request method. Valid methods are: `GET`, `POST`, `PUT`, `DELETE`,
76
+ * and `JSONP`.
77
+ * - **`params`** – {Object=} – Optional set of pre-bound parameters for this action. If any of the
78
+ * parameter value is a function, it will be executed every time when a param value needs to be
79
+ * obtained for a request (unless the param was overridden).
80
+ * - **`url`** – {string} – action specific `url` override. The url templating is supported just like
81
+ * for the resource-level urls.
82
+ * - **`isArray`** – {boolean=} – If true then the returned object for this action is an array, see
70
83
  * `returns` section.
84
+ * - **`transformRequest`** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –
85
+ * transform function or an array of such functions. The transform function takes the http
86
+ * request body and headers and returns its transformed (typically serialized) version.
87
+ * - **`transformResponse`** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –
88
+ * transform function or an array of such functions. The transform function takes the http
89
+ * response body and headers and returns its transformed (typically deserialized) version.
90
+ * - **`cache`** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the
91
+ * GET request, otherwise if a cache instance built with
92
+ * {@link ng.$cacheFactory $cacheFactory}, this cache will be used for
93
+ * caching.
94
+ * - **`timeout`** – `{number|Promise}` – timeout in milliseconds, or {@link ng.$q promise} that
95
+ * should abort the request when resolved.
96
+ * - **`withCredentials`** - `{boolean}` - whether to to set the `withCredentials` flag on the
97
+ * XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5
98
+ * requests with credentials} for more information.
99
+ * - **`responseType`** - `{string}` - see {@link
100
+ * https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#responseType requestType}.
71
101
  *
72
102
  * @returns {Object} A resource "class" object with methods for the default set of resource actions
73
103
  * optionally extended with custom `actions`. The default set contains these actions:
@@ -107,6 +137,24 @@
107
137
  * - non-GET instance actions: `instance.$action([parameters], [success], [error])`
108
138
  *
109
139
  *
140
+ * The Resource instances and collection have these additional properties:
141
+ *
142
+ * - `$then`: the `then` method of a {@link ng.$q promise} derived from the underlying
143
+ * {@link ng.$http $http} call.
144
+ *
145
+ * The success callback for the `$then` method will be resolved if the underlying `$http` requests
146
+ * succeeds.
147
+ *
148
+ * The success callback is called with a single object which is the {@link ng.$http http response}
149
+ * object extended with a new property `resource`. This `resource` property is a reference to the
150
+ * result of the resource action — resource object or array of resources.
151
+ *
152
+ * The error callback is called with the {@link ng.$http http response} object when an http
153
+ * error occurs.
154
+ *
155
+ * - `$resolved`: true if the promise has been resolved (either with success or rejection);
156
+ * Knowing if the Resource has been resolved is useful in data-binding.
157
+ *
110
158
  * @example
111
159
  *
112
160
  * # Credit card resource
@@ -149,7 +197,7 @@
149
197
  * The object returned from this function execution is a resource "class" which has "static" method
150
198
  * for each action in the definition.
151
199
  *
152
- * Calling these methods invoke `$http` on the `url` template with the given `method` and `params`.
200
+ * Calling these methods invoke `$http` on the `url` template with the given `method`, `params` and `headers`.
153
201
  * When the data is returned from the server then the object is an instance of the resource type and
154
202
  * all of the non-GET methods are available with `$` prefix. This allows you to easily support CRUD
155
203
  * operations (create, read, update, delete) on server-side data.
@@ -264,7 +312,7 @@ angular.module('ngResource', ['ng']).
264
312
 
265
313
  /**
266
314
  * This method is intended for encoding *key* or *value* parts of query component. We need a custom
267
- * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be
315
+ * method because encodeURIComponent is too aggressive and encodes stuff that doesn't have to be
268
316
  * encoded per http://tools.ietf.org/html/rfc3986:
269
317
  * query = *( pchar / "/" / "?" )
270
318
  * pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
@@ -283,32 +331,34 @@ angular.module('ngResource', ['ng']).
283
331
  }
284
332
 
285
333
  function Route(template, defaults) {
286
- this.template = template = template + '#';
334
+ this.template = template;
287
335
  this.defaults = defaults || {};
288
- var urlParams = this.urlParams = {};
289
- forEach(template.split(/\W/), function(param){
290
- if (param && (new RegExp("(^|[^\\\\]):" + param + "\\W").test(template))) {
291
- urlParams[param] = true;
292
- }
293
- });
294
- this.template = template.replace(/\\:/g, ':');
336
+ this.urlParams = {};
295
337
  }
296
338
 
297
339
  Route.prototype = {
298
- url: function(params) {
340
+ setUrlParams: function(config, params, actionUrl) {
299
341
  var self = this,
300
- url = this.template,
342
+ url = actionUrl || self.template,
301
343
  val,
302
344
  encodedVal;
303
345
 
346
+ var urlParams = self.urlParams = {};
347
+ forEach(url.split(/\W/), function(param){
348
+ if (param && (new RegExp("(^|[^\\\\]):" + param + "(\\W|$)").test(url))) {
349
+ urlParams[param] = true;
350
+ }
351
+ });
352
+ url = url.replace(/\\:/g, ':');
353
+
304
354
  params = params || {};
305
- forEach(this.urlParams, function(_, urlParam){
355
+ forEach(self.urlParams, function(_, urlParam){
306
356
  val = params.hasOwnProperty(urlParam) ? params[urlParam] : self.defaults[urlParam];
307
357
  if (angular.isDefined(val) && val !== null) {
308
358
  encodedVal = encodeUriSegment(val);
309
- url = url.replace(new RegExp(":" + urlParam + "(\\W)", "g"), encodedVal + "$1");
359
+ url = url.replace(new RegExp(":" + urlParam + "(\\W|$)", "g"), encodedVal + "$1");
310
360
  } else {
311
- url = url.replace(new RegExp("(\/?):" + urlParam + "(\\W)", "g"), function(match,
361
+ url = url.replace(new RegExp("(\/?):" + urlParam + "(\\W|$)", "g"), function(match,
312
362
  leadingSlashes, tail) {
313
363
  if (tail.charAt(0) == '/') {
314
364
  return tail;
@@ -318,16 +368,23 @@ angular.module('ngResource', ['ng']).
318
368
  });
319
369
  }
320
370
  });
321
- url = url.replace(/\/?#$/, '');
322
- var query = [];
371
+
372
+ // strip trailing slashes and set the url
373
+ url = url.replace(/\/+$/, '');
374
+ // then replace collapse `/.` if found in the last URL path segment before the query
375
+ // E.g. `http://url.com/id./format?q=x` becomes `http://url.com/id.format?q=x`
376
+ url = url.replace(/\/\.(?=\w+($|\?))/, '.');
377
+ // replace escaped `/\.` with `/.`
378
+ config.url = url.replace(/\/\\\./, '/.');
379
+
380
+
381
+ // set params - delegate param encoding to $http
323
382
  forEach(params, function(value, key){
324
383
  if (!self.urlParams[key]) {
325
- query.push(encodeUriQuery(key) + '=' + encodeUriQuery(value));
384
+ config.params = config.params || {};
385
+ config.params[key] = value;
326
386
  }
327
387
  });
328
- query.sort();
329
- url = url.replace(/\/*$/, '');
330
- return url + (query.length ? '?' + query.join('&') : '');
331
388
  }
332
389
  };
333
390
 
@@ -341,7 +398,8 @@ angular.module('ngResource', ['ng']).
341
398
  var ids = {};
342
399
  actionParams = extend({}, paramDefaults, actionParams);
343
400
  forEach(actionParams, function(value, key){
344
- ids[key] = value.charAt && value.charAt(0) == '@' ? getter(data, value.substr(1)) : value;
401
+ if (isFunction(value)) { value = value(); }
402
+ ids[key] = value && value.charAt && value.charAt(0) == '@' ? getter(data, value.substr(1)) : value;
345
403
  });
346
404
  return ids;
347
405
  }
@@ -358,6 +416,8 @@ angular.module('ngResource', ['ng']).
358
416
  var data;
359
417
  var success = noop;
360
418
  var error = null;
419
+ var promise;
420
+
361
421
  switch(arguments.length) {
362
422
  case 4:
363
423
  error = a4;
@@ -393,25 +453,45 @@ angular.module('ngResource', ['ng']).
393
453
  }
394
454
 
395
455
  var value = this instanceof Resource ? this : (action.isArray ? [] : new Resource(data));
396
- $http({
397
- method: action.method,
398
- url: route.url(extend({}, extractParams(data, action.params || {}), params)),
399
- data: data
400
- }).then(function(response) {
401
- var data = response.data;
402
-
403
- if (data) {
404
- if (action.isArray) {
405
- value.length = 0;
406
- forEach(data, function(item) {
407
- value.push(new Resource(item));
408
- });
409
- } else {
410
- copy(data, value);
411
- }
456
+ var httpConfig = {},
457
+ promise;
458
+
459
+ forEach(action, function(value, key) {
460
+ if (key != 'params' && key != 'isArray' ) {
461
+ httpConfig[key] = copy(value);
462
+ }
463
+ });
464
+ httpConfig.data = data;
465
+ route.setUrlParams(httpConfig, extend({}, extractParams(data, action.params || {}), params), action.url);
466
+
467
+ function markResolved() { value.$resolved = true; }
468
+
469
+ promise = $http(httpConfig);
470
+ value.$resolved = false;
471
+
472
+ promise.then(markResolved, markResolved);
473
+ value.$then = promise.then(function(response) {
474
+ var data = response.data;
475
+ var then = value.$then, resolved = value.$resolved;
476
+
477
+ if (data) {
478
+ if (action.isArray) {
479
+ value.length = 0;
480
+ forEach(data, function(item) {
481
+ value.push(new Resource(item));
482
+ });
483
+ } else {
484
+ copy(data, value);
485
+ value.$then = then;
486
+ value.$resolved = resolved;
412
487
  }
413
- (success||noop)(value, response.headers);
414
- }, error);
488
+ }
489
+
490
+ (success||noop)(value, response.headers);
491
+
492
+ response.resource = value;
493
+ return response;
494
+ }, error).then;
415
495
 
416
496
  return value;
417
497
  };
@@ -1,10 +1,11 @@
1
1
  /*
2
- AngularJS v1.0.7
2
+ AngularJS v1.1.5
3
3
  (c) 2010-2012 Google, Inc. http://angularjs.org
4
4
  License: MIT
5
5
  */
6
- (function(C,d,w){'use strict';d.module("ngResource",["ng"]).factory("$resource",["$http","$parse",function(x,y){function s(b,e){return encodeURIComponent(b).replace(/%40/gi,"@").replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%20/g,e?"%20":"+")}function t(b,e){this.template=b+="#";this.defaults=e||{};var a=this.urlParams={};h(b.split(/\W/),function(f){f&&RegExp("(^|[^\\\\]):"+f+"\\W").test(b)&&(a[f]=!0)});this.template=b.replace(/\\:/g,":")}function u(b,e,a){function f(m,a){var b=
7
- {},a=o({},e,a);h(a,function(a,z){var c;a.charAt&&a.charAt(0)=="@"?(c=a.substr(1),c=y(c)(m)):c=a;b[z]=c});return b}function g(a){v(a||{},this)}var k=new t(b),a=o({},A,a);h(a,function(a,b){a.method=d.uppercase(a.method);var e=a.method=="POST"||a.method=="PUT"||a.method=="PATCH";g[b]=function(b,c,d,B){var j={},i,l=p,q=null;switch(arguments.length){case 4:q=B,l=d;case 3:case 2:if(r(c)){if(r(b)){l=b;q=c;break}l=c;q=d}else{j=b;i=c;l=d;break}case 1:r(b)?l=b:e?i=b:j=b;break;case 0:break;default:throw"Expected between 0-4 arguments [params, data, success, error], got "+
8
- arguments.length+" arguments.";}var n=this instanceof g?this:a.isArray?[]:new g(i);x({method:a.method,url:k.url(o({},f(i,a.params||{}),j)),data:i}).then(function(b){var c=b.data;if(c)a.isArray?(n.length=0,h(c,function(a){n.push(new g(a))})):v(c,n);(l||p)(n,b.headers)},q);return n};g.prototype["$"+b]=function(a,d,h){var m=f(this),j=p,i;switch(arguments.length){case 3:m=a;j=d;i=h;break;case 2:case 1:r(a)?(j=a,i=d):(m=a,j=d||p);case 0:break;default:throw"Expected between 1-3 arguments [params, success, error], got "+
9
- arguments.length+" arguments.";}g[b].call(this,m,e?this:w,j,i)}});g.bind=function(d){return u(b,o({},e,d),a)};return g}var A={get:{method:"GET"},save:{method:"POST"},query:{method:"GET",isArray:!0},remove:{method:"DELETE"},"delete":{method:"DELETE"}},p=d.noop,h=d.forEach,o=d.extend,v=d.copy,r=d.isFunction;t.prototype={url:function(b){var e=this,a=this.template,f,g,b=b||{};h(this.urlParams,function(h,c){f=b.hasOwnProperty(c)?b[c]:e.defaults[c];d.isDefined(f)&&f!==null?(g=s(f,!0).replace(/%26/gi,"&").replace(/%3D/gi,
10
- "=").replace(/%2B/gi,"+"),a=a.replace(RegExp(":"+c+"(\\W)","g"),g+"$1")):a=a.replace(RegExp("(/?):"+c+"(\\W)","g"),function(a,b,c){return c.charAt(0)=="/"?c:b+c})});var a=a.replace(/\/?#$/,""),k=[];h(b,function(a,b){e.urlParams[b]||k.push(s(b)+"="+s(a))});k.sort();a=a.replace(/\/*$/,"");return a+(k.length?"?"+k.join("&"):"")}};return u}])})(window,window.angular);
6
+ (function(B,f,w){'use strict';f.module("ngResource",["ng"]).factory("$resource",["$http","$parse",function(x,y){function u(b,d){this.template=b;this.defaults=d||{};this.urlParams={}}function v(b,d,e){function j(c,b){var p={},b=m({},d,b);l(b,function(a,b){k(a)&&(a=a());var g;a&&a.charAt&&a.charAt(0)=="@"?(g=a.substr(1),g=y(g)(c)):g=a;p[b]=g});return p}function c(c){t(c||{},this)}var n=new u(b),e=m({},z,e);l(e,function(b,d){b.method=f.uppercase(b.method);var p=b.method=="POST"||b.method=="PUT"||b.method==
7
+ "PATCH";c[d]=function(a,d,g,A){function f(){h.$resolved=!0}var i={},e,o=q,r=null;switch(arguments.length){case 4:r=A,o=g;case 3:case 2:if(k(d)){if(k(a)){o=a;r=d;break}o=d;r=g}else{i=a;e=d;o=g;break}case 1:k(a)?o=a:p?e=a:i=a;break;case 0:break;default:throw"Expected between 0-4 arguments [params, data, success, error], got "+arguments.length+" arguments.";}var h=this instanceof c?this:b.isArray?[]:new c(e),s={};l(b,function(a,b){b!="params"&&b!="isArray"&&(s[b]=t(a))});s.data=e;n.setUrlParams(s,m({},
8
+ j(e,b.params||{}),i),b.url);i=x(s);h.$resolved=!1;i.then(f,f);h.$then=i.then(function(a){var d=a.data,g=h.$then,e=h.$resolved;if(d)b.isArray?(h.length=0,l(d,function(a){h.push(new c(a))})):(t(d,h),h.$then=g,h.$resolved=e);(o||q)(h,a.headers);a.resource=h;return a},r).then;return h};c.prototype["$"+d]=function(a,b,g){var e=j(this),f=q,i;switch(arguments.length){case 3:e=a;f=b;i=g;break;case 2:case 1:k(a)?(f=a,i=b):(e=a,f=b||q);case 0:break;default:throw"Expected between 1-3 arguments [params, success, error], got "+
9
+ arguments.length+" arguments.";}c[d].call(this,e,p?this:w,f,i)}});c.bind=function(c){return v(b,m({},d,c),e)};return c}var z={get:{method:"GET"},save:{method:"POST"},query:{method:"GET",isArray:!0},remove:{method:"DELETE"},"delete":{method:"DELETE"}},q=f.noop,l=f.forEach,m=f.extend,t=f.copy,k=f.isFunction;u.prototype={setUrlParams:function(b,d,e){var j=this,c=e||j.template,n,k,m=j.urlParams={};l(c.split(/\W/),function(b){b&&RegExp("(^|[^\\\\]):"+b+"(\\W|$)").test(c)&&(m[b]=!0)});c=c.replace(/\\:/g,
10
+ ":");d=d||{};l(j.urlParams,function(b,a){n=d.hasOwnProperty(a)?d[a]:j.defaults[a];f.isDefined(n)&&n!==null?(k=encodeURIComponent(n).replace(/%40/gi,"@").replace(/%3A/gi,":").replace(/%24/g,"$").replace(/%2C/gi,",").replace(/%20/g,"%20").replace(/%26/gi,"&").replace(/%3D/gi,"=").replace(/%2B/gi,"+"),c=c.replace(RegExp(":"+a+"(\\W|$)","g"),k+"$1")):c=c.replace(RegExp("(/?):"+a+"(\\W|$)","g"),function(b,a,c){return c.charAt(0)=="/"?c:a+c})});c=c.replace(/\/+$/,"");c=c.replace(/\/\.(?=\w+($|\?))/,".");
11
+ b.url=c.replace(/\/\\\./,"/.");l(d,function(c,a){if(!j.urlParams[a])b.params=b.params||{},b.params[a]=c})}};return v}])})(window,window.angular);
@@ -1,5 +1,5 @@
1
1
  /**
2
- * @license AngularJS v1.0.7
2
+ * @license AngularJS v1.1.5
3
3
  * (c) 2010-2012 Google, Inc. http://angularjs.org
4
4
  * License: MIT
5
5
  */
@@ -129,7 +129,7 @@ var START_TAG_REGEXP = /^<\s*([\w:-]+)((?:\s+[\w:-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:
129
129
  BEGING_END_TAGE_REGEXP = /^<\s*\//,
130
130
  COMMENT_REGEXP = /<!--(.*?)-->/g,
131
131
  CDATA_REGEXP = /<!\[CDATA\[(.*?)]]>/g,
132
- URI_REGEXP = /^((ftp|https?):\/\/|mailto:|#)/,
132
+ URI_REGEXP = /^((ftp|https?):\/\/|mailto:|tel:|#)/,
133
133
  NON_ALPHANUMERIC_REGEXP = /([^\#-~| |!])/g; // Match everything outside of normal chars and " (quote character)
134
134
 
135
135
 
@@ -433,6 +433,7 @@ angular.module('ngSanitize').directive('ngBindHtml', ['$sanitize', function($san
433
433
  * plain email address links.
434
434
  *
435
435
  * @param {string} text Input text.
436
+ * @param {string} target Window (_blank|_self|_parent|_top) or named frame to open links in.
436
437
  * @returns {string} Html-linkified text.
437
438
  *
438
439
  * @usage
@@ -449,6 +450,7 @@ angular.module('ngSanitize').directive('ngBindHtml', ['$sanitize', function($san
449
450
  'mailto:us@somewhere.org,\n'+
450
451
  'another@somewhere.org,\n'+
451
452
  'and one more: ftp://127.0.0.1/.';
453
+ $scope.snippetWithTarget = 'http://angularjs.org/';
452
454
  }
453
455
  </script>
454
456
  <div ng-controller="Ctrl">
@@ -468,6 +470,15 @@ angular.module('ngSanitize').directive('ngBindHtml', ['$sanitize', function($san
468
470
  <div ng-bind-html="snippet | linky"></div>
469
471
  </td>
470
472
  </tr>
473
+ <tr id="linky-target">
474
+ <td>linky target</td>
475
+ <td>
476
+ <pre>&lt;div ng-bind-html="snippetWithTarget | linky:'_blank'"&gt;<br>&lt;/div&gt;</pre>
477
+ </td>
478
+ <td>
479
+ <div ng-bind-html="snippetWithTarget | linky:'_blank'"></div>
480
+ </td>
481
+ </tr>
471
482
  <tr id="escaped-html">
472
483
  <td>no filter</td>
473
484
  <td><pre>&lt;div ng-bind="snippet"&gt;<br>&lt;/div&gt;</pre></td>
@@ -500,6 +511,11 @@ angular.module('ngSanitize').directive('ngBindHtml', ['$sanitize', function($san
500
511
  toBe('new <a href="http://link">http://link</a>.');
501
512
  expect(using('#escaped-html').binding('snippet')).toBe('new http://link.');
502
513
  });
514
+
515
+ it('should work with the target property', function() {
516
+ expect(using('#linky-target').binding("snippetWithTarget | linky:'_blank'")).
517
+ toBe('<a target="_blank" href="http://angularjs.org/">http://angularjs.org/</a>');
518
+ });
503
519
  </doc:scenario>
504
520
  </doc:example>
505
521
  */
@@ -507,7 +523,7 @@ angular.module('ngSanitize').filter('linky', function() {
507
523
  var LINKY_URL_REGEXP = /((ftp|https?):\/\/|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s\.\;\,\(\)\{\}\<\>]/,
508
524
  MAILTO_REGEXP = /^mailto:/;
509
525
 
510
- return function(text) {
526
+ return function(text, target) {
511
527
  if (!text) return text;
512
528
  var match;
513
529
  var raw = text;
@@ -516,6 +532,10 @@ angular.module('ngSanitize').filter('linky', function() {
516
532
  var writer = htmlSanitizeWriter(html);
517
533
  var url;
518
534
  var i;
535
+ var properties = {};
536
+ if (angular.isDefined(target)) {
537
+ properties.target = target;
538
+ }
519
539
  while ((match = raw.match(LINKY_URL_REGEXP))) {
520
540
  // We can not end in these as they are sometimes found at the end of the sentence
521
541
  url = match[0];
@@ -523,7 +543,8 @@ angular.module('ngSanitize').filter('linky', function() {
523
543
  if (match[2] == match[3]) url = 'mailto:' + url;
524
544
  i = match.index;
525
545
  writer.chars(raw.substr(0, i));
526
- writer.start('a', {href:url});
546
+ properties.href = url;
547
+ writer.start('a', properties);
527
548
  writer.chars(match[0].replace(MAILTO_REGEXP, ''));
528
549
  writer.end('a');
529
550
  raw = raw.substring(i + match[0].length);
@@ -1,13 +1,13 @@
1
1
  /*
2
- AngularJS v1.0.7
2
+ AngularJS v1.1.5
3
3
  (c) 2010-2012 Google, Inc. http://angularjs.org
4
4
  License: MIT
5
5
  */
6
- (function(I,g){'use strict';function i(a){var d={},a=a.split(","),b;for(b=0;b<a.length;b++)d[a[b]]=!0;return d}function z(a,d){function b(a,b,c,h){b=g.lowercase(b);if(m[b])for(;f.last()&&n[f.last()];)e("",f.last());o[b]&&f.last()==b&&e("",b);(h=p[b]||!!h)||f.push(b);var j={};c.replace(A,function(a,b,d,e,c){j[b]=k(d||e||c||"")});d.start&&d.start(b,j,h)}function e(a,b){var e=0,c;if(b=g.lowercase(b))for(e=f.length-1;e>=0;e--)if(f[e]==b)break;if(e>=0){for(c=f.length-1;c>=e;c--)d.end&&d.end(f[c]);f.length=
7
- e}}var c,h,f=[],j=a;for(f.last=function(){return f[f.length-1]};a;){h=!0;if(!f.last()||!q[f.last()]){if(a.indexOf("<\!--")===0)c=a.indexOf("--\>"),c>=0&&(d.comment&&d.comment(a.substring(4,c)),a=a.substring(c+3),h=!1);else if(B.test(a)){if(c=a.match(r))a=a.substring(c[0].length),c[0].replace(r,e),h=!1}else if(C.test(a)&&(c=a.match(s)))a=a.substring(c[0].length),c[0].replace(s,b),h=!1;h&&(c=a.indexOf("<"),h=c<0?a:a.substring(0,c),a=c<0?"":a.substring(c),d.chars&&d.chars(k(h)))}else a=a.replace(RegExp("(.*)<\\s*\\/\\s*"+
8
- f.last()+"[^>]*>","i"),function(b,a){a=a.replace(D,"$1").replace(E,"$1");d.chars&&d.chars(k(a));return""}),e("",f.last());if(a==j)throw"Parse Error: "+a;j=a}e()}function k(a){l.innerHTML=a.replace(/</g,"&lt;");return l.innerText||l.textContent||""}function t(a){return a.replace(/&/g,"&amp;").replace(F,function(a){return"&#"+a.charCodeAt(0)+";"}).replace(/</g,"&lt;").replace(/>/g,"&gt;")}function u(a){var d=!1,b=g.bind(a,a.push);return{start:function(a,c,h){a=g.lowercase(a);!d&&q[a]&&(d=a);!d&&v[a]==
9
- !0&&(b("<"),b(a),g.forEach(c,function(a,c){var e=g.lowercase(c);if(G[e]==!0&&(w[e]!==!0||a.match(H)))b(" "),b(c),b('="'),b(t(a)),b('"')}),b(h?"/>":">"))},end:function(a){a=g.lowercase(a);!d&&v[a]==!0&&(b("</"),b(a),b(">"));a==d&&(d=!1)},chars:function(a){d||b(t(a))}}}var s=/^<\s*([\w:-]+)((?:\s+[\w:-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)\s*>/,r=/^<\s*\/\s*([\w:-]+)[^>]*>/,A=/([\w:-]+)(?:\s*=\s*(?:(?:"((?:[^"])*)")|(?:'((?:[^'])*)')|([^>\s]+)))?/g,C=/^</,B=/^<\s*\//,D=/<\!--(.*?)--\>/g,
10
- E=/<!\[CDATA\[(.*?)]]\>/g,H=/^((ftp|https?):\/\/|mailto:|#)/,F=/([^\#-~| |!])/g,p=i("area,br,col,hr,img,wbr"),x=i("colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr"),y=i("rp,rt"),o=g.extend({},y,x),m=g.extend({},x,i("address,article,aside,blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5,h6,header,hgroup,hr,ins,map,menu,nav,ol,pre,script,section,table,ul")),n=g.extend({},y,i("a,abbr,acronym,b,bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s,samp,small,span,strike,strong,sub,sup,time,tt,u,var")),
11
- q=i("script,style"),v=g.extend({},p,m,n,o),w=i("background,cite,href,longdesc,src,usemap"),G=g.extend({},w,i("abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,scope,scrolling,shape,span,start,summary,target,title,type,valign,value,vspace,width")),l=document.createElement("pre");g.module("ngSanitize",[]).value("$sanitize",function(a){var d=[];
12
- z(a,u(d));return d.join("")});g.module("ngSanitize").directive("ngBindHtml",["$sanitize",function(a){return function(d,b,e){b.addClass("ng-binding").data("$binding",e.ngBindHtml);d.$watch(e.ngBindHtml,function(c){c=a(c);b.html(c||"")})}}]);g.module("ngSanitize").filter("linky",function(){var a=/((ftp|https?):\/\/|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s\.\;\,\(\)\{\}\<\>]/,d=/^mailto:/;return function(b){if(!b)return b;for(var e=b,c=[],h=u(c),f,g;b=e.match(a);)f=b[0],b[2]==b[3]&&(f="mailto:"+f),g=b.index,
13
- h.chars(e.substr(0,g)),h.start("a",{href:f}),h.chars(b[0].replace(d,"")),h.end("a"),e=e.substring(g+b[0].length);h.chars(e);return c.join("")}})})(window,window.angular);
6
+ (function(I,h){'use strict';function i(a){var d={},a=a.split(","),c;for(c=0;c<a.length;c++)d[a[c]]=!0;return d}function z(a,d){function c(a,b,c,f){b=h.lowercase(b);if(m[b])for(;e.last()&&n[e.last()];)g("",e.last());o[b]&&e.last()==b&&g("",b);(f=p[b]||!!f)||e.push(b);var j={};c.replace(A,function(a,b,d,c,g){j[b]=k(d||c||g||"")});d.start&&d.start(b,j,f)}function g(a,b){var c=0,g;if(b=h.lowercase(b))for(c=e.length-1;c>=0;c--)if(e[c]==b)break;if(c>=0){for(g=e.length-1;g>=c;g--)d.end&&d.end(e[g]);e.length=
7
+ c}}var b,f,e=[],j=a;for(e.last=function(){return e[e.length-1]};a;){f=!0;if(!e.last()||!q[e.last()]){if(a.indexOf("<\!--")===0)b=a.indexOf("--\>"),b>=0&&(d.comment&&d.comment(a.substring(4,b)),a=a.substring(b+3),f=!1);else if(B.test(a)){if(b=a.match(r))a=a.substring(b[0].length),b[0].replace(r,g),f=!1}else if(C.test(a)&&(b=a.match(s)))a=a.substring(b[0].length),b[0].replace(s,c),f=!1;f&&(b=a.indexOf("<"),f=b<0?a:a.substring(0,b),a=b<0?"":a.substring(b),d.chars&&d.chars(k(f)))}else a=a.replace(RegExp("(.*)<\\s*\\/\\s*"+
8
+ e.last()+"[^>]*>","i"),function(a,b){b=b.replace(D,"$1").replace(E,"$1");d.chars&&d.chars(k(b));return""}),g("",e.last());if(a==j)throw"Parse Error: "+a;j=a}g()}function k(a){l.innerHTML=a.replace(/</g,"&lt;");return l.innerText||l.textContent||""}function t(a){return a.replace(/&/g,"&amp;").replace(F,function(a){return"&#"+a.charCodeAt(0)+";"}).replace(/</g,"&lt;").replace(/>/g,"&gt;")}function u(a){var d=!1,c=h.bind(a,a.push);return{start:function(a,b,f){a=h.lowercase(a);!d&&q[a]&&(d=a);!d&&v[a]==
9
+ !0&&(c("<"),c(a),h.forEach(b,function(a,b){var d=h.lowercase(b);if(G[d]==!0&&(w[d]!==!0||a.match(H)))c(" "),c(b),c('="'),c(t(a)),c('"')}),c(f?"/>":">"))},end:function(a){a=h.lowercase(a);!d&&v[a]==!0&&(c("</"),c(a),c(">"));a==d&&(d=!1)},chars:function(a){d||c(t(a))}}}var s=/^<\s*([\w:-]+)((?:\s+[\w:-]+(?:\s*=\s*(?:(?:"[^"]*")|(?:'[^']*')|[^>\s]+))?)*)\s*(\/?)\s*>/,r=/^<\s*\/\s*([\w:-]+)[^>]*>/,A=/([\w:-]+)(?:\s*=\s*(?:(?:"((?:[^"])*)")|(?:'((?:[^'])*)')|([^>\s]+)))?/g,C=/^</,B=/^<\s*\//,D=/<\!--(.*?)--\>/g,
10
+ E=/<!\[CDATA\[(.*?)]]\>/g,H=/^((ftp|https?):\/\/|mailto:|tel:|#)/,F=/([^\#-~| |!])/g,p=i("area,br,col,hr,img,wbr"),x=i("colgroup,dd,dt,li,p,tbody,td,tfoot,th,thead,tr"),y=i("rp,rt"),o=h.extend({},y,x),m=h.extend({},x,i("address,article,aside,blockquote,caption,center,del,dir,div,dl,figure,figcaption,footer,h1,h2,h3,h4,h5,h6,header,hgroup,hr,ins,map,menu,nav,ol,pre,script,section,table,ul")),n=h.extend({},y,i("a,abbr,acronym,b,bdi,bdo,big,br,cite,code,del,dfn,em,font,i,img,ins,kbd,label,map,mark,q,ruby,rp,rt,s,samp,small,span,strike,strong,sub,sup,time,tt,u,var")),
11
+ q=i("script,style"),v=h.extend({},p,m,n,o),w=i("background,cite,href,longdesc,src,usemap"),G=h.extend({},w,i("abbr,align,alt,axis,bgcolor,border,cellpadding,cellspacing,class,clear,color,cols,colspan,compact,coords,dir,face,headers,height,hreflang,hspace,ismap,lang,language,nohref,nowrap,rel,rev,rows,rowspan,rules,scope,scrolling,shape,span,start,summary,target,title,type,valign,value,vspace,width")),l=document.createElement("pre");h.module("ngSanitize",[]).value("$sanitize",function(a){var d=[];
12
+ z(a,u(d));return d.join("")});h.module("ngSanitize").directive("ngBindHtml",["$sanitize",function(a){return function(d,c,g){c.addClass("ng-binding").data("$binding",g.ngBindHtml);d.$watch(g.ngBindHtml,function(b){b=a(b);c.html(b||"")})}}]);h.module("ngSanitize").filter("linky",function(){var a=/((ftp|https?):\/\/|(mailto:)?[A-Za-z0-9._%+-]+@)\S*[^\s\.\;\,\(\)\{\}\<\>]/,d=/^mailto:/;return function(c,g){if(!c)return c;var b,f=c,e=[],j=u(e),i,k,l={};if(h.isDefined(g))l.target=g;for(;b=f.match(a);)i=
13
+ b[0],b[2]==b[3]&&(i="mailto:"+i),k=b.index,j.chars(f.substr(0,k)),l.href=i,j.start("a",l),j.chars(b[0].replace(d,"")),j.end("a"),f=f.substring(k+b[0].length);j.chars(f);return e.join("")}})})(window,window.angular);