angular-rails-engine 1.0.7.0 → 1.1.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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);