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,472 @@
1
+ /**
2
+ * @license AngularJS v1.1.2
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 `save`, `remove` and `delete` actions are available on it as
93
+ * methods with the `$` prefix. This allows you to easily perform CRUD operations (create, read,
94
+ * 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
+ * @example
120
+ *
121
+ * # Credit card resource
122
+ *
123
+ * <pre>
124
+ // Define CreditCard class
125
+ var CreditCard = $resource('/user/:userId/card/:cardId',
126
+ {userId:123, cardId:'@id'}, {
127
+ charge: {method:'POST', params:{charge:true}}
128
+ });
129
+
130
+ // We can retrieve a collection from the server
131
+ var cards = CreditCard.query(function() {
132
+ // GET: /user/123/card
133
+ // server returns: [ {id:456, number:'1234', name:'Smith'} ];
134
+
135
+ var card = cards[0];
136
+ // each item is an instance of CreditCard
137
+ expect(card instanceof CreditCard).toEqual(true);
138
+ card.name = "J. Smith";
139
+ // non GET methods are mapped onto the instances
140
+ card.$save();
141
+ // POST: /user/123/card/456 {id:456, number:'1234', name:'J. Smith'}
142
+ // server returns: {id:456, number:'1234', name: 'J. Smith'};
143
+
144
+ // our custom method is mapped as well.
145
+ card.$charge({amount:9.99});
146
+ // POST: /user/123/card/456?amount=9.99&charge=true {id:456, number:'1234', name:'J. Smith'}
147
+ });
148
+
149
+ // we can create an instance as well
150
+ var newCard = new CreditCard({number:'0123'});
151
+ newCard.name = "Mike Smith";
152
+ newCard.$save();
153
+ // POST: /user/123/card {number:'0123', name:'Mike Smith'}
154
+ // server returns: {id:789, number:'01234', name: 'Mike Smith'};
155
+ expect(newCard.id).toEqual(789);
156
+ * </pre>
157
+ *
158
+ * The object returned from this function execution is a resource "class" which has "static" method
159
+ * for each action in the definition.
160
+ *
161
+ * Calling these methods invoke `$http` on the `url` template with the given `method`, `params` and `headers`.
162
+ * When the data is returned from the server then the object is an instance of the resource type and
163
+ * all of the non-GET methods are available with `$` prefix. This allows you to easily support CRUD
164
+ * operations (create, read, update, delete) on server-side data.
165
+
166
+ <pre>
167
+ var User = $resource('/user/:userId', {userId:'@id'});
168
+ var user = User.get({userId:123}, function() {
169
+ user.abc = true;
170
+ user.$save();
171
+ });
172
+ </pre>
173
+ *
174
+ * It's worth noting that the success callback for `get`, `query` and other method gets passed
175
+ * in the response that came from the server as well as $http header getter function, so one
176
+ * could rewrite the above example and get access to http headers as:
177
+ *
178
+ <pre>
179
+ var User = $resource('/user/:userId', {userId:'@id'});
180
+ User.get({userId:123}, function(u, getResponseHeaders){
181
+ u.abc = true;
182
+ u.$save(function(u, putResponseHeaders) {
183
+ //u => saved user object
184
+ //putResponseHeaders => $http header getter
185
+ });
186
+ });
187
+ </pre>
188
+
189
+ * # Buzz client
190
+
191
+ Let's look at what a buzz client created with the `$resource` service looks like:
192
+ <doc:example>
193
+ <doc:source jsfiddle="false">
194
+ <script>
195
+ function BuzzController($resource) {
196
+ this.userId = 'googlebuzz';
197
+ this.Activity = $resource(
198
+ 'https://www.googleapis.com/buzz/v1/activities/:userId/:visibility/:activityId/:comments',
199
+ {alt:'json', callback:'JSON_CALLBACK'},
200
+ {get:{method:'JSONP', params:{visibility:'@self'}}, replies: {method:'JSONP', params:{visibility:'@self', comments:'@comments'}}}
201
+ );
202
+ }
203
+
204
+ BuzzController.prototype = {
205
+ fetch: function() {
206
+ this.activities = this.Activity.get({userId:this.userId});
207
+ },
208
+ expandReplies: function(activity) {
209
+ activity.replies = this.Activity.replies({userId:this.userId, activityId:activity.id});
210
+ }
211
+ };
212
+ BuzzController.$inject = ['$resource'];
213
+ </script>
214
+
215
+ <div ng-controller="BuzzController">
216
+ <input ng-model="userId"/>
217
+ <button ng-click="fetch()">fetch</button>
218
+ <hr/>
219
+ <div ng-repeat="item in activities.data.items">
220
+ <h1 style="font-size: 15px;">
221
+ <img src="{{item.actor.thumbnailUrl}}" style="max-height:30px;max-width:30px;"/>
222
+ <a href="{{item.actor.profileUrl}}">{{item.actor.name}}</a>
223
+ <a href ng-click="expandReplies(item)" style="float: right;">Expand replies: {{item.links.replies[0].count}}</a>
224
+ </h1>
225
+ {{item.object.content | html}}
226
+ <div ng-repeat="reply in item.replies.data.items" style="margin-left: 20px;">
227
+ <img src="{{reply.actor.thumbnailUrl}}" style="max-height:30px;max-width:30px;"/>
228
+ <a href="{{reply.actor.profileUrl}}">{{reply.actor.name}}</a>: {{reply.content | html}}
229
+ </div>
230
+ </div>
231
+ </div>
232
+ </doc:source>
233
+ <doc:scenario>
234
+ </doc:scenario>
235
+ </doc:example>
236
+ */
237
+ angular.module('ngResource', ['ng']).
238
+ factory('$resource', ['$http', '$parse', function($http, $parse) {
239
+ var DEFAULT_ACTIONS = {
240
+ 'get': {method:'GET'},
241
+ 'save': {method:'POST'},
242
+ 'query': {method:'GET', isArray:true},
243
+ 'remove': {method:'DELETE'},
244
+ 'delete': {method:'DELETE'}
245
+ };
246
+ var noop = angular.noop,
247
+ forEach = angular.forEach,
248
+ extend = angular.extend,
249
+ copy = angular.copy,
250
+ isFunction = angular.isFunction,
251
+ getter = function(obj, path) {
252
+ return $parse(path)(obj);
253
+ };
254
+
255
+ /**
256
+ * We need our custom method because encodeURIComponent is too aggressive and doesn't follow
257
+ * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path
258
+ * segments:
259
+ * segment = *pchar
260
+ * pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
261
+ * pct-encoded = "%" HEXDIG HEXDIG
262
+ * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
263
+ * sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
264
+ * / "*" / "+" / "," / ";" / "="
265
+ */
266
+ function encodeUriSegment(val) {
267
+ return encodeUriQuery(val, true).
268
+ replace(/%26/gi, '&').
269
+ replace(/%3D/gi, '=').
270
+ replace(/%2B/gi, '+');
271
+ }
272
+
273
+
274
+ /**
275
+ * This method is intended for encoding *key* or *value* parts of query component. We need a custom
276
+ * method becuase encodeURIComponent is too agressive and encodes stuff that doesn't have to be
277
+ * encoded per http://tools.ietf.org/html/rfc3986:
278
+ * query = *( pchar / "/" / "?" )
279
+ * pchar = unreserved / pct-encoded / sub-delims / ":" / "@"
280
+ * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~"
281
+ * pct-encoded = "%" HEXDIG HEXDIG
282
+ * sub-delims = "!" / "$" / "&" / "'" / "(" / ")"
283
+ * / "*" / "+" / "," / ";" / "="
284
+ */
285
+ function encodeUriQuery(val, pctEncodeSpaces) {
286
+ return encodeURIComponent(val).
287
+ replace(/%40/gi, '@').
288
+ replace(/%3A/gi, ':').
289
+ replace(/%24/g, '$').
290
+ replace(/%2C/gi, ',').
291
+ replace((pctEncodeSpaces ? null : /%20/g), '+');
292
+ }
293
+
294
+ function Route(template, defaults) {
295
+ this.template = template = template + '#';
296
+ this.defaults = defaults || {};
297
+ var urlParams = this.urlParams = {};
298
+ forEach(template.split(/\W/), function(param){
299
+ if (param && template.match(new RegExp("[^\\\\]:" + param + "\\W"))) {
300
+ urlParams[param] = true;
301
+ }
302
+ });
303
+ this.template = template.replace(/\\:/g, ':');
304
+ }
305
+
306
+ Route.prototype = {
307
+ url: function(params) {
308
+ var self = this,
309
+ url = this.template,
310
+ val,
311
+ encodedVal;
312
+
313
+ params = params || {};
314
+ forEach(this.urlParams, function(_, urlParam){
315
+ val = params.hasOwnProperty(urlParam) ? params[urlParam] : self.defaults[urlParam];
316
+ if (angular.isDefined(val) && val !== null) {
317
+ encodedVal = encodeUriSegment(val);
318
+ url = url.replace(new RegExp(":" + urlParam + "(\\W)", "g"), encodedVal + "$1");
319
+ } else {
320
+ url = url.replace(new RegExp("(\/?):" + urlParam + "(\\W)", "g"), function(match,
321
+ leadingSlashes, tail) {
322
+ if (tail.charAt(0) == '/') {
323
+ return tail;
324
+ } else {
325
+ return leadingSlashes + tail;
326
+ }
327
+ });
328
+ }
329
+ });
330
+ url = url.replace(/\/?#$/, '');
331
+ var query = [];
332
+ forEach(params, function(value, key){
333
+ if (!self.urlParams[key]) {
334
+ query.push(encodeUriQuery(key) + '=' + encodeUriQuery(value));
335
+ }
336
+ });
337
+ query.sort();
338
+ url = url.replace(/\/*$/, '');
339
+ return url + (query.length ? '?' + query.join('&') : '');
340
+ }
341
+ };
342
+
343
+
344
+ function ResourceFactory(url, paramDefaults, actions) {
345
+ var route = new Route(url);
346
+
347
+ actions = extend({}, DEFAULT_ACTIONS, actions);
348
+
349
+ function extractParams(data, actionParams){
350
+ var ids = {};
351
+ actionParams = extend({}, paramDefaults, actionParams);
352
+ forEach(actionParams, function(value, key){
353
+ if (isFunction(value)) { value = value(); }
354
+ ids[key] = value.charAt && value.charAt(0) == '@' ? getter(data, value.substr(1)) : value;
355
+ });
356
+ return ids;
357
+ }
358
+
359
+ function Resource(value){
360
+ copy(value || {}, this);
361
+ }
362
+
363
+ forEach(actions, function(action, name) {
364
+ action.method = angular.uppercase(action.method);
365
+ var hasBody = action.method == 'POST' || action.method == 'PUT' || action.method == 'PATCH';
366
+ Resource[name] = function(a1, a2, a3, a4) {
367
+ var params = {};
368
+ var data;
369
+ var success = noop;
370
+ var error = null;
371
+ switch(arguments.length) {
372
+ case 4:
373
+ error = a4;
374
+ success = a3;
375
+ //fallthrough
376
+ case 3:
377
+ case 2:
378
+ if (isFunction(a2)) {
379
+ if (isFunction(a1)) {
380
+ success = a1;
381
+ error = a2;
382
+ break;
383
+ }
384
+
385
+ success = a2;
386
+ error = a3;
387
+ //fallthrough
388
+ } else {
389
+ params = a1;
390
+ data = a2;
391
+ success = a3;
392
+ break;
393
+ }
394
+ case 1:
395
+ if (isFunction(a1)) success = a1;
396
+ else if (hasBody) data = a1;
397
+ else params = a1;
398
+ break;
399
+ case 0: break;
400
+ default:
401
+ throw "Expected between 0-4 arguments [params, data, success, error], got " +
402
+ arguments.length + " arguments.";
403
+ }
404
+
405
+ var value = this instanceof Resource ? this : (action.isArray ? [] : new Resource(data));
406
+ var httpConfig = {};
407
+
408
+ forEach(action, function(value, key) {
409
+ if (key != 'params' && key != 'isArray' ) {
410
+ httpConfig[key] = copy(value);
411
+ }
412
+ });
413
+ httpConfig.data = data;
414
+ httpConfig.url = route.url(extend({}, extractParams(data, action.params || {}), params))
415
+
416
+ $http(httpConfig).then(function(response) {
417
+ var data = response.data;
418
+
419
+ if (data) {
420
+ if (action.isArray) {
421
+ value.length = 0;
422
+ forEach(data, function(item) {
423
+ value.push(new Resource(item));
424
+ });
425
+ } else {
426
+ copy(data, value);
427
+ }
428
+ }
429
+ (success||noop)(value, response.headers);
430
+ }, error);
431
+
432
+ return value;
433
+ };
434
+
435
+
436
+ Resource.prototype['$' + name] = function(a1, a2, a3) {
437
+ var params = extractParams(this),
438
+ success = noop,
439
+ error;
440
+
441
+ switch(arguments.length) {
442
+ case 3: params = a1; success = a2; error = a3; break;
443
+ case 2:
444
+ case 1:
445
+ if (isFunction(a1)) {
446
+ success = a1;
447
+ error = a2;
448
+ } else {
449
+ params = a1;
450
+ success = a2 || noop;
451
+ }
452
+ case 0: break;
453
+ default:
454
+ throw "Expected between 1-3 arguments [params, success, error], got " +
455
+ arguments.length + " arguments.";
456
+ }
457
+ var data = hasBody ? this : undefined;
458
+ Resource[name].call(this, params, data, success, error);
459
+ };
460
+ });
461
+
462
+ Resource.bind = function(additionalParamDefaults){
463
+ return ResourceFactory(url, extend({}, paramDefaults, additionalParamDefaults), actions);
464
+ };
465
+
466
+ return Resource;
467
+ }
468
+
469
+ return ResourceFactory;
470
+ }]);
471
+
472
+ })(window, window.angular);