angular-gem 1.1.2 → 1.1.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (29) hide show
  1. data/README.md +9 -2
  2. data/Rakefile +86 -19
  3. data/lib/angular-gem/version.rb +1 -1
  4. data/lib/generators/angular/resource_helpers.rb +13 -13
  5. data/test/dummy/log/test.log +1 -3
  6. data/test/dummy/tmp/cache/assets/{DF8/FD0/sprockets%2F87b01decd5c7fd3c6f174b8cba0d810f → D65/250/sprockets%2F54a960d46bb0b354e8bd46fa03f5e0e4} +0 -0
  7. data/test/dummy/tmp/cache/assets/{D73/C00/sprockets%2Fa3620dc4bbd0562669b546e9c58eede4 → D6A/FB0/sprockets%2F92721e9941b77adcfdfba3d060622de2} +0 -0
  8. data/test/dummy/tmp/cache/assets/E07/040/sprockets%2Ff55b8ce9d0f28ce36b768a1c7aeb2ef3 +0 -0
  9. data/test/test_helper.rb +3 -0
  10. data/vendor/assets/javascripts/1.0.5/angular-1.0.5.js +14733 -0
  11. data/vendor/assets/javascripts/1.0.5/angular-resource-1.0.5.js +445 -0
  12. data/vendor/assets/javascripts/1.0.5/angular-sanitize-1.0.5.js +535 -0
  13. data/{test/dummy/tmp/cache/assets/CF7/120/sprockets%2Fd6adf41113c67a57c4a1330845ba0d08 → vendor/assets/javascripts/1.1.2/angular-1.1.2.js} +0 -0
  14. data/vendor/assets/javascripts/1.1.2/angular-resource-1.1.2.js +472 -0
  15. data/vendor/assets/javascripts/1.1.2/angular-sanitize-1.1.2.js +556 -0
  16. data/{test/dummy/tmp/cache/assets/CD5/C60/sprockets%2F4348b099c4aadda10262e757261e0f81 → vendor/assets/javascripts/1.1.3/angular-1.1.3.js} +0 -0
  17. data/vendor/assets/javascripts/1.1.3/angular-resource-1.1.3.js +507 -0
  18. data/vendor/assets/javascripts/1.1.3/angular-sanitize-1.1.3.js +556 -0
  19. data/vendor/assets/javascripts/angular-resource-unstable.js +507 -0
  20. data/vendor/assets/javascripts/angular-resource.js +23 -50
  21. data/vendor/assets/javascripts/angular-sanitize-unstable.js +556 -0
  22. data/vendor/assets/javascripts/angular-sanitize.js +4 -25
  23. data/{test/dummy/tmp/cache/assets/CE3/300/sprockets%2Fc11999ba09d72e745355212e48bc72dd → vendor/assets/javascripts/angular-unstable.js} +0 -0
  24. data/vendor/assets/javascripts/angular.js +305 -454
  25. metadata +53 -21
  26. data/test/dummy/tmp/cache/assets/D71/060/sprockets%2Fc434a3f93ecb87049eb12e766005fede +0 -0
  27. data/test/dummy/tmp/cache/assets/D79/F40/sprockets%2F9088cfe323d1b81dd526e6a9e3ed358c +0 -0
  28. data/test/dummy/tmp/cache/assets/D9E/830/sprockets%2Fbb7eb0f50f1afed5705594e9d812b8d0 +0 -0
  29. data/test/dummy/tmp/cache/assets/DD4/250/sprockets%2Feaa70f0d0954a5edffe77c9ca1e93860 +0 -0
@@ -0,0 +1,507 @@
1
+ /**
2
+ * @license AngularJS v1.1.3
3
+ * (c) 2010-2012 Google, Inc. http://angularjs.org
4
+ * License: MIT
5
+ */
6
+ (function(window, angular, undefined) {
7
+ 'use strict';
8
+
9
+ /**
10
+ * @ngdoc overview
11
+ * @name ngResource
12
+ * @description
13
+ */
14
+
15
+ /**
16
+ * @ngdoc object
17
+ * @name ngResource.$resource
18
+ * @requires $http
19
+ *
20
+ * @description
21
+ * A factory which creates a resource object that lets you interact with
22
+ * [RESTful](http://en.wikipedia.org/wiki/Representational_State_Transfer) server-side data sources.
23
+ *
24
+ * The returned resource object has action methods which provide high-level behaviors without
25
+ * the need to interact with the low level {@link ng.$http $http} service.
26
+ *
27
+ * @param {string} url A parameterized URL template with parameters prefixed by `:` as in
28
+ * `/user/:username`. If you are using a URL with a port number (e.g.
29
+ * `http://example.com:8080/api`), you'll need to escape the colon character before the port
30
+ * number, like this: `$resource('http://example.com\\:8080/api')`.
31
+ *
32
+ * @param {Object=} paramDefaults Default values for `url` parameters. These can be overridden in
33
+ * `actions` methods. If any of the parameter value is a function, it will be executed every time
34
+ * when a param value needs to be obtained for a request (unless the param was overriden).
35
+ *
36
+ * Each key value in the parameter object is first bound to url template if present and then any
37
+ * excess keys are appended to the url search query after the `?`.
38
+ *
39
+ * Given a template `/path/:verb` and parameter `{verb:'greet', salutation:'Hello'}` results in
40
+ * URL `/path/greet?salutation=Hello`.
41
+ *
42
+ * If the parameter value is prefixed with `@` then the value of that parameter is extracted from
43
+ * the data object (useful for non-GET operations).
44
+ *
45
+ * @param {Object.<Object>=} actions Hash with declaration of custom action that should extend the
46
+ * default set of resource actions. The declaration should be created in the format of {@link
47
+ * ng.$http#Parameters $http.config}:
48
+ *
49
+ * {action1: {method:?, params:?, isArray:?, headers:?, ...},
50
+ * action2: {method:?, params:?, isArray:?, headers:?, ...},
51
+ * ...}
52
+ *
53
+ * Where:
54
+ *
55
+ * - **`action`** – {string} – The name of action. This name becomes the name of the method on your
56
+ * resource object.
57
+ * - **`method`** – {string} – HTTP request method. Valid methods are: `GET`, `POST`, `PUT`, `DELETE`,
58
+ * and `JSONP`.
59
+ * - **`params`** – {Object=} – Optional set of pre-bound parameters for this action. If any of the
60
+ * parameter value is a function, it will be executed every time when a param value needs to be
61
+ * obtained for a request (unless the param was overriden).
62
+ * - **`isArray`** – {boolean=} – If true then the returned object for this action is an array, see
63
+ * `returns` section.
64
+ * - **`transformRequest`** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –
65
+ * transform function or an array of such functions. The transform function takes the http
66
+ * request body and headers and returns its transformed (typically serialized) version.
67
+ * - **`transformResponse`** – `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` –
68
+ * transform function or an array of such functions. The transform function takes the http
69
+ * response body and headers and returns its transformed (typically deserialized) version.
70
+ * - **`cache`** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the
71
+ * GET request, otherwise if a cache instance built with
72
+ * {@link ng.$cacheFactory $cacheFactory}, this cache will be used for
73
+ * caching.
74
+ * - **`timeout`** – `{number}` – timeout in milliseconds.
75
+ * - **`withCredentials`** - `{boolean}` - whether to to set the `withCredentials` flag on the
76
+ * XHR object. See {@link https://developer.mozilla.org/en/http_access_control#section_5
77
+ * requests with credentials} for more information.
78
+ * - **`responseType`** - `{string}` - see {@link
79
+ * https://developer.mozilla.org/en-US/docs/DOM/XMLHttpRequest#responseType requestType}.
80
+ *
81
+ * @returns {Object} A resource "class" object with methods for the default set of resource actions
82
+ * optionally extended with custom `actions`. The default set contains these actions:
83
+ *
84
+ * { 'get': {method:'GET'},
85
+ * 'save': {method:'POST'},
86
+ * 'query': {method:'GET', isArray:true},
87
+ * 'remove': {method:'DELETE'},
88
+ * 'delete': {method:'DELETE'} };
89
+ *
90
+ * Calling these methods invoke an {@link ng.$http} with the specified http method,
91
+ * destination and parameters. When the data is returned from the server then the object is an
92
+ * instance of the resource class. The actions `save`, `remove` and `delete` are available on it
93
+ * as methods with the `$` prefix. This allows you to easily perform CRUD operations (create,
94
+ * read, update, delete) on server-side data like this:
95
+ * <pre>
96
+ var User = $resource('/user/:userId', {userId:'@id'});
97
+ var user = User.get({userId:123}, function() {
98
+ user.abc = true;
99
+ user.$save();
100
+ });
101
+ </pre>
102
+ *
103
+ * It is important to realize that invoking a $resource object method immediately returns an
104
+ * empty reference (object or array depending on `isArray`). Once the data is returned from the
105
+ * server the existing reference is populated with the actual data. This is a useful trick since
106
+ * usually the resource is assigned to a model which is then rendered by the view. Having an empty
107
+ * object results in no rendering, once the data arrives from the server then the object is
108
+ * populated with the data and the view automatically re-renders itself showing the new data. This
109
+ * means that in most case one never has to write a callback function for the action methods.
110
+ *
111
+ * The action methods on the class object or instance object can be invoked with the following
112
+ * parameters:
113
+ *
114
+ * - HTTP GET "class" actions: `Resource.action([parameters], [success], [error])`
115
+ * - non-GET "class" actions: `Resource.action([parameters], postData, [success], [error])`
116
+ * - non-GET instance actions: `instance.$action([parameters], [success], [error])`
117
+ *
118
+ *
119
+ * The Resource instances and collection have these additional properties:
120
+ *
121
+ * - `$then`: the `then` method of a {@link ng.$q promise} derived from the underlying
122
+ * {@link ng.$http $http} call.
123
+ *
124
+ * The success callback for the `$then` method will be resolved if the underlying `$http` requests
125
+ * succeeds.
126
+ *
127
+ * The success callback is called with a single object which is the {@link ng.$http http response}
128
+ * object extended with a new property `resource`. This `resource` property is a reference to the
129
+ * result of the resource action — resource object or array of resources.
130
+ *
131
+ * The error callback is called with the {@link ng.$http http response} object when an http
132
+ * error occurs.
133
+ *
134
+ * - `$resolved`: true if the promise has been resolved (either with success or rejection);
135
+ * Knowing if the Resource has been resolved is useful in data-binding.
136
+ *
137
+ * @example
138
+ *
139
+ * # Credit card resource
140
+ *
141
+ * <pre>
142
+ // Define CreditCard class
143
+ var CreditCard = $resource('/user/:userId/card/:cardId',
144
+ {userId:123, cardId:'@id'}, {
145
+ charge: {method:'POST', params:{charge:true}}
146
+ });
147
+
148
+ // We can retrieve a collection from the server
149
+ var cards = CreditCard.query(function() {
150
+ // GET: /user/123/card
151
+ // server returns: [ {id:456, number:'1234', name:'Smith'} ];
152
+
153
+ var card = cards[0];
154
+ // each item is an instance of CreditCard
155
+ expect(card instanceof CreditCard).toEqual(true);
156
+ card.name = "J. Smith";
157
+ // non GET methods are mapped onto the instances
158
+ card.$save();
159
+ // POST: /user/123/card/456 {id:456, number:'1234', name:'J. Smith'}
160
+ // server returns: {id:456, number:'1234', name: 'J. Smith'};
161
+
162
+ // our custom method is mapped as well.
163
+ card.$charge({amount:9.99});
164
+ // POST: /user/123/card/456?amount=9.99&charge=true {id:456, number:'1234', name:'J. Smith'}
165
+ });
166
+
167
+ // we can create an instance as well
168
+ var newCard = new CreditCard({number:'0123'});
169
+ newCard.name = "Mike Smith";
170
+ newCard.$save();
171
+ // POST: /user/123/card {number:'0123', name:'Mike Smith'}
172
+ // server returns: {id:789, number:'01234', name: 'Mike Smith'};
173
+ expect(newCard.id).toEqual(789);
174
+ * </pre>
175
+ *
176
+ * The object returned from this function execution is a resource "class" which has "static" method
177
+ * for each action in the definition.
178
+ *
179
+ * Calling these methods invoke `$http` on the `url` template with the given `method`, `params` and `headers`.
180
+ * When the data is returned from the server then the object is an instance of the resource type and
181
+ * all of the non-GET methods are available with `$` prefix. This allows you to easily support CRUD
182
+ * operations (create, read, update, delete) on server-side data.
183
+
184
+ <pre>
185
+ var User = $resource('/user/:userId', {userId:'@id'});
186
+ var user = User.get({userId:123}, function() {
187
+ user.abc = true;
188
+ user.$save();
189
+ });
190
+ </pre>
191
+ *
192
+ * It's worth noting that the success callback for `get`, `query` and other method gets passed
193
+ * in the response that came from the server as well as $http header getter function, so one
194
+ * could rewrite the above example and get access to http headers as:
195
+ *
196
+ <pre>
197
+ var User = $resource('/user/:userId', {userId:'@id'});
198
+ User.get({userId:123}, function(u, getResponseHeaders){
199
+ u.abc = true;
200
+ u.$save(function(u, putResponseHeaders) {
201
+ //u => saved user object
202
+ //putResponseHeaders => $http header getter
203
+ });
204
+ });
205
+ </pre>
206
+
207
+ * # Buzz client
208
+
209
+ Let's look at what a buzz client created with the `$resource` service looks like:
210
+ <doc:example>
211
+ <doc:source jsfiddle="false">
212
+ <script>
213
+ function BuzzController($resource) {
214
+ this.userId = 'googlebuzz';
215
+ this.Activity = $resource(
216
+ 'https://www.googleapis.com/buzz/v1/activities/:userId/:visibility/:activityId/:comments',
217
+ {alt:'json', callback:'JSON_CALLBACK'},
218
+ {get:{method:'JSONP', params:{visibility:'@self'}}, replies: {method:'JSONP', params:{visibility:'@self', comments:'@comments'}}}
219
+ );
220
+ }
221
+
222
+ BuzzController.prototype = {
223
+ fetch: function() {
224
+ this.activities = this.Activity.get({userId:this.userId});
225
+ },
226
+ expandReplies: function(activity) {
227
+ activity.replies = this.Activity.replies({userId:this.userId, activityId:activity.id});
228
+ }
229
+ };
230
+ BuzzController.$inject = ['$resource'];
231
+ </script>
232
+
233
+ <div ng-controller="BuzzController">
234
+ <input ng-model="userId"/>
235
+ <button ng-click="fetch()">fetch</button>
236
+ <hr/>
237
+ <div ng-repeat="item in activities.data.items">
238
+ <h1 style="font-size: 15px;">
239
+ <img src="{{item.actor.thumbnailUrl}}" style="max-height:30px;max-width:30px;"/>
240
+ <a href="{{item.actor.profileUrl}}">{{item.actor.name}}</a>
241
+ <a href ng-click="expandReplies(item)" style="float: right;">Expand replies: {{item.links.replies[0].count}}</a>
242
+ </h1>
243
+ {{item.object.content | html}}
244
+ <div ng-repeat="reply in item.replies.data.items" style="margin-left: 20px;">
245
+ <img src="{{reply.actor.thumbnailUrl}}" style="max-height:30px;max-width:30px;"/>
246
+ <a href="{{reply.actor.profileUrl}}">{{reply.actor.name}}</a>: {{reply.content | html}}
247
+ </div>
248
+ </div>
249
+ </div>
250
+ </doc:source>
251
+ <doc:scenario>
252
+ </doc:scenario>
253
+ </doc:example>
254
+ */
255
+ angular.module('ngResource', ['ng']).
256
+ factory('$resource', ['$http', '$parse', function($http, $parse) {
257
+ var DEFAULT_ACTIONS = {
258
+ 'get': {method:'GET'},
259
+ 'save': {method:'POST'},
260
+ 'query': {method:'GET', isArray:true},
261
+ 'remove': {method:'DELETE'},
262
+ 'delete': {method:'DELETE'}
263
+ };
264
+ var noop = angular.noop,
265
+ forEach = angular.forEach,
266
+ extend = angular.extend,
267
+ copy = angular.copy,
268
+ isFunction = angular.isFunction,
269
+ getter = function(obj, path) {
270
+ return $parse(path)(obj);
271
+ };
272
+
273
+ /**
274
+ * We need our custom method because encodeURIComponent is too aggressive and doesn't follow
275
+ * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path
276
+ * segments:
277
+ * segment = *pchar
278
+ * pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
279
+ * pct-encoded = "%" HEXDIG HEXDIG
280
+ * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
281
+ * sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
282
+ * / "*" / "+" / "," / ";" / "="
283
+ */
284
+ function encodeUriSegment(val) {
285
+ return encodeUriQuery(val, true).
286
+ replace(/%26/gi, '&').
287
+ replace(/%3D/gi, '=').
288
+ replace(/%2B/gi, '+');
289
+ }
290
+
291
+
292
+ /**
293
+ * This method is intended for encoding *key* or *value* parts of query component. We need a custom
294
+ * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be
295
+ * encoded per http://tools.ietf.org/html/rfc3986:
296
+ * query = *( pchar / "/" / "?" )
297
+ * pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
298
+ * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
299
+ * pct-encoded = "%" HEXDIG HEXDIG
300
+ * sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
301
+ * / "*" / "+" / "," / ";" / "="
302
+ */
303
+ function encodeUriQuery(val, pctEncodeSpaces) {
304
+ return encodeURIComponent(val).
305
+ replace(/%40/gi, '@').
306
+ replace(/%3A/gi, ':').
307
+ replace(/%24/g, '$').
308
+ replace(/%2C/gi, ',').
309
+ replace((pctEncodeSpaces ? null : /%20/g), '+');
310
+ }
311
+
312
+ function Route(template, defaults) {
313
+ this.template = template = template + '#';
314
+ this.defaults = defaults || {};
315
+ var urlParams = this.urlParams = {};
316
+ forEach(template.split(/\W/), function(param){
317
+ if (param && (new RegExp("(^|[^\\\\]):" + param + "\\W").test(template))) {
318
+ urlParams[param] = true;
319
+ }
320
+ });
321
+ this.template = template.replace(/\\:/g, ':');
322
+ }
323
+
324
+ Route.prototype = {
325
+ setUrlParams: function(config, params) {
326
+ var self = this,
327
+ url = this.template,
328
+ val,
329
+ encodedVal;
330
+
331
+ params = params || {};
332
+ forEach(this.urlParams, function(_, urlParam){
333
+ val = params.hasOwnProperty(urlParam) ? params[urlParam] : self.defaults[urlParam];
334
+ if (angular.isDefined(val) && val !== null) {
335
+ encodedVal = encodeUriSegment(val);
336
+ url = url.replace(new RegExp(":" + urlParam + "(\\W)", "g"), encodedVal + "$1");
337
+ } else {
338
+ url = url.replace(new RegExp("(\/?):" + urlParam + "(\\W)", "g"), function(match,
339
+ leadingSlashes, tail) {
340
+ if (tail.charAt(0) == '/') {
341
+ return tail;
342
+ } else {
343
+ return leadingSlashes + tail;
344
+ }
345
+ });
346
+ }
347
+ });
348
+
349
+ // set the url
350
+ config.url = url.replace(/\/?#$/, '').replace(/\/*$/, '');
351
+
352
+ // set params - delegate param encoding to $http
353
+ forEach(params, function(value, key){
354
+ if (!self.urlParams[key]) {
355
+ config.params = config.params || {};
356
+ config.params[key] = value;
357
+ }
358
+ });
359
+ }
360
+ };
361
+
362
+
363
+ function ResourceFactory(url, paramDefaults, actions) {
364
+ var route = new Route(url);
365
+
366
+ actions = extend({}, DEFAULT_ACTIONS, actions);
367
+
368
+ function extractParams(data, actionParams){
369
+ var ids = {};
370
+ actionParams = extend({}, paramDefaults, actionParams);
371
+ forEach(actionParams, function(value, key){
372
+ if (isFunction(value)) { value = value(); }
373
+ ids[key] = value.charAt && value.charAt(0) == '@' ? getter(data, value.substr(1)) : value;
374
+ });
375
+ return ids;
376
+ }
377
+
378
+ function Resource(value){
379
+ copy(value || {}, this);
380
+ }
381
+
382
+ forEach(actions, function(action, name) {
383
+ action.method = angular.uppercase(action.method);
384
+ var hasBody = action.method == 'POST' || action.method == 'PUT' || action.method == 'PATCH';
385
+ Resource[name] = function(a1, a2, a3, a4) {
386
+ var params = {};
387
+ var data;
388
+ var success = noop;
389
+ var error = null;
390
+ var promise;
391
+
392
+ switch(arguments.length) {
393
+ case 4:
394
+ error = a4;
395
+ success = a3;
396
+ //fallthrough
397
+ case 3:
398
+ case 2:
399
+ if (isFunction(a2)) {
400
+ if (isFunction(a1)) {
401
+ success = a1;
402
+ error = a2;
403
+ break;
404
+ }
405
+
406
+ success = a2;
407
+ error = a3;
408
+ //fallthrough
409
+ } else {
410
+ params = a1;
411
+ data = a2;
412
+ success = a3;
413
+ break;
414
+ }
415
+ case 1:
416
+ if (isFunction(a1)) success = a1;
417
+ else if (hasBody) data = a1;
418
+ else params = a1;
419
+ break;
420
+ case 0: break;
421
+ default:
422
+ throw "Expected between 0-4 arguments [params, data, success, error], got " +
423
+ arguments.length + " arguments.";
424
+ }
425
+
426
+ var value = this instanceof Resource ? this : (action.isArray ? [] : new Resource(data));
427
+ var httpConfig = {},
428
+ promise;
429
+
430
+ forEach(action, function(value, key) {
431
+ if (key != 'params' && key != 'isArray' ) {
432
+ httpConfig[key] = copy(value);
433
+ }
434
+ });
435
+ httpConfig.data = data;
436
+ route.setUrlParams(httpConfig, extend({}, extractParams(data, action.params || {}), params));
437
+
438
+ function markResolved() { value.$resolved = true; }
439
+
440
+ promise = $http(httpConfig);
441
+ value.$resolved = false;
442
+
443
+ promise.then(markResolved, markResolved);
444
+ value.$then = promise.then(function(response) {
445
+ var data = response.data;
446
+ var then = value.$then, resolved = value.$resolved;
447
+
448
+ if (data) {
449
+ if (action.isArray) {
450
+ value.length = 0;
451
+ forEach(data, function(item) {
452
+ value.push(new Resource(item));
453
+ });
454
+ } else {
455
+ copy(data, value);
456
+ value.$then = then;
457
+ value.$resolved = resolved;
458
+ }
459
+ }
460
+
461
+ (success||noop)(value, response.headers);
462
+
463
+ response.resource = value;
464
+ return response;
465
+ }, error).then;
466
+
467
+ return value;
468
+ };
469
+
470
+
471
+ Resource.prototype['$' + name] = function(a1, a2, a3) {
472
+ var params = extractParams(this),
473
+ success = noop,
474
+ error;
475
+
476
+ switch(arguments.length) {
477
+ case 3: params = a1; success = a2; error = a3; break;
478
+ case 2:
479
+ case 1:
480
+ if (isFunction(a1)) {
481
+ success = a1;
482
+ error = a2;
483
+ } else {
484
+ params = a1;
485
+ success = a2 || noop;
486
+ }
487
+ case 0: break;
488
+ default:
489
+ throw "Expected between 1-3 arguments [params, success, error], got " +
490
+ arguments.length + " arguments.";
491
+ }
492
+ var data = hasBody ? this : undefined;
493
+ Resource[name].call(this, params, data, success, error);
494
+ };
495
+ });
496
+
497
+ Resource.bind = function(additionalParamDefaults){
498
+ return ResourceFactory(url, extend({}, paramDefaults, additionalParamDefaults), actions);
499
+ };
500
+
501
+ return Resource;
502
+ }
503
+
504
+ return ResourceFactory;
505
+ }]);
506
+
507
+ })(window, window.angular);