diff options
Diffstat (limited to 'xstatic/pkg/angular/data/angular-resource.js')
-rw-r--r-- | xstatic/pkg/angular/data/angular-resource.js | 555 |
1 files changed, 306 insertions, 249 deletions
diff --git a/xstatic/pkg/angular/data/angular-resource.js b/xstatic/pkg/angular/data/angular-resource.js index 7014984..7a5eac2 100644 --- a/xstatic/pkg/angular/data/angular-resource.js +++ b/xstatic/pkg/angular/data/angular-resource.js @@ -1,5 +1,5 @@ /** - * @license AngularJS v1.2.16 + * @license AngularJS v1.3.7 * (c) 2010-2014 Google, Inc. http://angularjs.org * License: MIT */ @@ -35,7 +35,7 @@ function lookupDottedPath(obj, path) { function shallowClearAndCopy(src, dst) { dst = dst || {}; - angular.forEach(dst, function(value, key){ + angular.forEach(dst, function(value, key) { delete dst[key]; }); @@ -78,6 +78,18 @@ function shallowClearAndCopy(src, dst) { * * Requires the {@link ngResource `ngResource`} module to be installed. * + * By default, trailing slashes will be stripped from the calculated URLs, + * which can pose problems with server backends that do not expect that + * behavior. This can be disabled by configuring the `$resourceProvider` like + * this: + * + * ```js + app.config(['$resourceProvider', function($resourceProvider) { + // Don't strip trailing slashes from calculated URLs + $resourceProvider.defaults.stripTrailingSlashes = false; + }]); + * ``` + * * @param {string} url A parametrized URL template with parameters prefixed by `:` as in * `/user/:username`. If you are using a URL with a port number (e.g. * `http://example.com:8080/api`), it will be respected. @@ -99,12 +111,14 @@ function shallowClearAndCopy(src, dst) { * Given a template `/path/:verb` and parameter `{verb:'greet', salutation:'Hello'}` results in * URL `/path/greet?salutation=Hello`. * - * If the parameter value is prefixed with `@` then the value of that parameter is extracted from - * the data object (useful for non-GET operations). + * If the parameter value is prefixed with `@` then the value for that parameter will be extracted + * from the corresponding property on the `data` object (provided when calling an action method). For + * example, if the `defaultParam` object is `{someParam: '@someProp'}` then the value of `someParam` + * will be `data.someProp`. * - * @param {Object.<Object>=} actions Hash with declaration of custom action that should extend + * @param {Object.<Object>=} actions Hash with declaration of custom actions that should extend * the default set of resource actions. The declaration should be created in the format of {@link - * ng.$http#usage_parameters $http.config}: + * ng.$http#usage $http.config}: * * {action1: {method:?, params:?, isArray:?, headers:?, ...}, * action2: {method:?, params:?, isArray:?, headers:?, ...}, @@ -114,8 +128,8 @@ function shallowClearAndCopy(src, dst) { * * - **`action`** – {string} – The name of action. This name becomes the name of the method on * your resource object. - * - **`method`** – {string} – HTTP request method. Valid methods are: `GET`, `POST`, `PUT`, - * `DELETE`, and `JSONP`. + * - **`method`** – {string} – Case insensitive HTTP method (e.g. `GET`, `POST`, `PUT`, + * `DELETE`, `JSONP`, etc). * - **`params`** – {Object=} – Optional set of pre-bound parameters for this action. If any of * the parameter value is a function, it will be executed every time when a param value needs to * be obtained for a request (unless the param was overridden). @@ -127,10 +141,16 @@ function shallowClearAndCopy(src, dst) { * `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` – * transform function or an array of such functions. The transform function takes the http * request body and headers and returns its transformed (typically serialized) version. + * By default, transformRequest will contain one function that checks if the request data is + * an object and serializes to using `angular.toJson`. To prevent this behavior, set + * `transformRequest` to an empty array: `transformRequest: []` * - **`transformResponse`** – * `{function(data, headersGetter)|Array.<function(data, headersGetter)>}` – * transform function or an array of such functions. The transform function takes the http * response body and headers and returns its transformed (typically deserialized) version. + * By default, transformResponse will contain one function that checks if the response looks like + * a JSON string and deserializes it using `angular.fromJson`. To prevent this behavior, set + * `transformResponse` to an empty array: `transformResponse: []` * - **`cache`** – `{boolean|Cache}` – If true, a default $http cache will be used to cache the * GET request, otherwise if a cache instance built with * {@link ng.$cacheFactory $cacheFactory}, this cache will be used for @@ -147,6 +167,14 @@ function shallowClearAndCopy(src, dst) { * `response` and `responseError`. Both `response` and `responseError` interceptors get called * with `http response` object. See {@link ng.$http $http interceptors}. * + * @param {Object} options Hash with custom settings that should extend the + * default `$resourceProvider` behavior. The only supported option is + * + * Where: + * + * - **`stripTrailingSlashes`** – {boolean} – If true then the trailing + * slashes from any calculated URL will be stripped. (Defaults to true.) + * * @returns {Object} A resource "class" object with methods for the default set of resource actions * optionally extended with custom `actions`. The default set contains these actions: * ```js @@ -295,20 +323,20 @@ function shallowClearAndCopy(src, dst) { * # Creating a custom 'PUT' request * In this example we create a custom method on our resource to make a PUT request * ```js - * var app = angular.module('app', ['ngResource', 'ngRoute']); + * var app = angular.module('app', ['ngResource', 'ngRoute']); * - * // Some APIs expect a PUT request in the format URL/object/ID - * // Here we are creating an 'update' method - * app.factory('Notes', ['$resource', function($resource) { + * // Some APIs expect a PUT request in the format URL/object/ID + * // Here we are creating an 'update' method + * app.factory('Notes', ['$resource', function($resource) { * return $resource('/notes/:id', null, * { * 'update': { method:'PUT' } * }); - * }]); + * }]); * - * // In our controller we get the ID from the URL using ngRoute and $routeParams - * // We pass in $routeParams and our Notes factory along with $scope - * app.controller('NotesCtrl', ['$scope', '$routeParams', 'Notes', + * // In our controller we get the ID from the URL using ngRoute and $routeParams + * // We pass in $routeParams and our Notes factory along with $scope + * app.controller('NotesCtrl', ['$scope', '$routeParams', 'Notes', function($scope, $routeParams, Notes) { * // First get a note object from the factory * var note = Notes.get({ id:$routeParams.id }); @@ -318,293 +346,322 @@ function shallowClearAndCopy(src, dst) { * Notes.update({ id:$id }, note); * * // This will PUT /notes/ID with the note object in the request payload - * }]); + * }]); * ``` */ angular.module('ngResource', ['ng']). - factory('$resource', ['$http', '$q', function($http, $q) { - - var DEFAULT_ACTIONS = { - 'get': {method:'GET'}, - 'save': {method:'POST'}, - 'query': {method:'GET', isArray:true}, - 'remove': {method:'DELETE'}, - 'delete': {method:'DELETE'} + provider('$resource', function() { + var provider = this; + + this.defaults = { + // Strip slashes by default + stripTrailingSlashes: true, + + // Default actions configuration + actions: { + 'get': {method: 'GET'}, + 'save': {method: 'POST'}, + 'query': {method: 'GET', isArray: true}, + 'remove': {method: 'DELETE'}, + 'delete': {method: 'DELETE'} + } }; - var noop = angular.noop, + + this.$get = ['$http', '$q', function($http, $q) { + + var noop = angular.noop, forEach = angular.forEach, extend = angular.extend, copy = angular.copy, isFunction = angular.isFunction; - /** - * We need our custom method because encodeURIComponent is too aggressive and doesn't follow - * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set (pchar) allowed in path - * segments: - * segment = *pchar - * pchar = unreserved / pct-encoded / sub-delims / ":" / "@" - * pct-encoded = "%" HEXDIG HEXDIG - * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" - * sub-delims = "!" / "$" / "&" / "'" / "(" / ")" - * / "*" / "+" / "," / ";" / "=" - */ - function encodeUriSegment(val) { - return encodeUriQuery(val, true). - replace(/%26/gi, '&'). - replace(/%3D/gi, '='). - replace(/%2B/gi, '+'); - } + /** + * We need our custom method because encodeURIComponent is too aggressive and doesn't follow + * http://www.ietf.org/rfc/rfc3986.txt with regards to the character set + * (pchar) allowed in path segments: + * segment = *pchar + * pchar = unreserved / pct-encoded / sub-delims / ":" / "@" + * pct-encoded = "%" HEXDIG HEXDIG + * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" + * sub-delims = "!" / "$" / "&" / "'" / "(" / ")" + * / "*" / "+" / "," / ";" / "=" + */ + function encodeUriSegment(val) { + return encodeUriQuery(val, true). + replace(/%26/gi, '&'). + replace(/%3D/gi, '='). + replace(/%2B/gi, '+'); + } - /** - * This method is intended for encoding *key* or *value* parts of query component. We need a - * custom method because encodeURIComponent is too aggressive and encodes stuff that doesn't - * have to be encoded per http://tools.ietf.org/html/rfc3986: - * query = *( pchar / "/" / "?" ) - * pchar = unreserved / pct-encoded / sub-delims / ":" / "@" - * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" - * pct-encoded = "%" HEXDIG HEXDIG - * sub-delims = "!" / "$" / "&" / "'" / "(" / ")" - * / "*" / "+" / "," / ";" / "=" - */ - function encodeUriQuery(val, pctEncodeSpaces) { - return encodeURIComponent(val). - replace(/%40/gi, '@'). - replace(/%3A/gi, ':'). - replace(/%24/g, '$'). - replace(/%2C/gi, ','). - replace(/%20/g, (pctEncodeSpaces ? '%20' : '+')); - } + /** + * This method is intended for encoding *key* or *value* parts of query component. We need a + * custom method because encodeURIComponent is too aggressive and encodes stuff that doesn't + * have to be encoded per http://tools.ietf.org/html/rfc3986: + * query = *( pchar / "/" / "?" ) + * pchar = unreserved / pct-encoded / sub-delims / ":" / "@" + * unreserved = ALPHA / DIGIT / "-" / "." / "_" / "~" + * pct-encoded = "%" HEXDIG HEXDIG + * sub-delims = "!" / "$" / "&" / "'" / "(" / ")" + * / "*" / "+" / "," / ";" / "=" + */ + function encodeUriQuery(val, pctEncodeSpaces) { + return encodeURIComponent(val). + replace(/%40/gi, '@'). + replace(/%3A/gi, ':'). + replace(/%24/g, '$'). + replace(/%2C/gi, ','). + replace(/%20/g, (pctEncodeSpaces ? '%20' : '+')); + } - function Route(template, defaults) { - this.template = template; - this.defaults = defaults || {}; - this.urlParams = {}; - } + function Route(template, defaults) { + this.template = template; + this.defaults = extend({}, provider.defaults, defaults); + this.urlParams = {}; + } - Route.prototype = { - setUrlParams: function(config, params, actionUrl) { - var self = this, + Route.prototype = { + setUrlParams: function(config, params, actionUrl) { + var self = this, url = actionUrl || self.template, val, encodedVal; - var urlParams = self.urlParams = {}; - forEach(url.split(/\W/), function(param){ - if (param === 'hasOwnProperty') { - throw $resourceMinErr('badname', "hasOwnProperty is not a valid parameter name."); - } - if (!(new RegExp("^\\d+$").test(param)) && param && - (new RegExp("(^|[^\\\\]):" + param + "(\\W|$)").test(url))) { - urlParams[param] = true; - } - }); - url = url.replace(/\\:/g, ':'); - - params = params || {}; - forEach(self.urlParams, function(_, urlParam){ - val = params.hasOwnProperty(urlParam) ? params[urlParam] : self.defaults[urlParam]; - if (angular.isDefined(val) && val !== null) { - encodedVal = encodeUriSegment(val); - url = url.replace(new RegExp(":" + urlParam + "(\\W|$)", "g"), function(match, p1) { - return encodedVal + p1; - }); - } else { - url = url.replace(new RegExp("(\/?):" + urlParam + "(\\W|$)", "g"), function(match, - leadingSlashes, tail) { - if (tail.charAt(0) == '/') { - return tail; - } else { - return leadingSlashes + tail; - } - }); - } - }); + var urlParams = self.urlParams = {}; + forEach(url.split(/\W/), function(param) { + if (param === 'hasOwnProperty') { + throw $resourceMinErr('badname', "hasOwnProperty is not a valid parameter name."); + } + if (!(new RegExp("^\\d+$").test(param)) && param && + (new RegExp("(^|[^\\\\]):" + param + "(\\W|$)").test(url))) { + urlParams[param] = true; + } + }); + url = url.replace(/\\:/g, ':'); + + params = params || {}; + forEach(self.urlParams, function(_, urlParam) { + val = params.hasOwnProperty(urlParam) ? params[urlParam] : self.defaults[urlParam]; + if (angular.isDefined(val) && val !== null) { + encodedVal = encodeUriSegment(val); + url = url.replace(new RegExp(":" + urlParam + "(\\W|$)", "g"), function(match, p1) { + return encodedVal + p1; + }); + } else { + url = url.replace(new RegExp("(\/?):" + urlParam + "(\\W|$)", "g"), function(match, + leadingSlashes, tail) { + if (tail.charAt(0) == '/') { + return tail; + } else { + return leadingSlashes + tail; + } + }); + } + }); - // strip trailing slashes and set the url - url = url.replace(/\/+$/, '') || '/'; - // then replace collapse `/.` if found in the last URL path segment before the query - // E.g. `http://url.com/id./format?q=x` becomes `http://url.com/id.format?q=x` - url = url.replace(/\/\.(?=\w+($|\?))/, '.'); - // replace escaped `/\.` with `/.` - config.url = url.replace(/\/\\\./, '/.'); + // strip trailing slashes and set the url (unless this behavior is specifically disabled) + if (self.defaults.stripTrailingSlashes) { + url = url.replace(/\/+$/, '') || '/'; + } + // then replace collapse `/.` if found in the last URL path segment before the query + // E.g. `http://url.com/id./format?q=x` becomes `http://url.com/id.format?q=x` + url = url.replace(/\/\.(?=\w+($|\?))/, '.'); + // replace escaped `/\.` with `/.` + config.url = url.replace(/\/\\\./, '/.'); - // set params - delegate param encoding to $http - forEach(params, function(value, key){ - if (!self.urlParams[key]) { - config.params = config.params || {}; - config.params[key] = value; - } - }); - } - }; + // set params - delegate param encoding to $http + forEach(params, function(value, key) { + if (!self.urlParams[key]) { + config.params = config.params || {}; + config.params[key] = value; + } + }); + } + }; - function resourceFactory(url, paramDefaults, actions) { - var route = new Route(url); - actions = extend({}, DEFAULT_ACTIONS, actions); + function resourceFactory(url, paramDefaults, actions, options) { + var route = new Route(url, options); - function extractParams(data, actionParams){ - var ids = {}; - actionParams = extend({}, paramDefaults, actionParams); - forEach(actionParams, function(value, key){ - if (isFunction(value)) { value = value(); } - ids[key] = value && value.charAt && value.charAt(0) == '@' ? - lookupDottedPath(data, value.substr(1)) : value; - }); - return ids; - } + actions = extend({}, provider.defaults.actions, actions); - function defaultResponseInterceptor(response) { - return response.resource; - } + function extractParams(data, actionParams) { + var ids = {}; + actionParams = extend({}, paramDefaults, actionParams); + forEach(actionParams, function(value, key) { + if (isFunction(value)) { value = value(); } + ids[key] = value && value.charAt && value.charAt(0) == '@' ? + lookupDottedPath(data, value.substr(1)) : value; + }); + return ids; + } + + function defaultResponseInterceptor(response) { + return response.resource; + } + + function Resource(value) { + shallowClearAndCopy(value || {}, this); + } + + Resource.prototype.toJSON = function() { + var data = extend({}, this); + delete data.$promise; + delete data.$resolved; + return data; + }; - function Resource(value){ - shallowClearAndCopy(value || {}, this); - } + forEach(actions, function(action, name) { + var hasBody = /^(POST|PUT|PATCH)$/i.test(action.method); - forEach(actions, function(action, name) { - var hasBody = /^(POST|PUT|PATCH)$/i.test(action.method); - - Resource[name] = function(a1, a2, a3, a4) { - var params = {}, data, success, error; - - /* jshint -W086 */ /* (purposefully fall through case statements) */ - switch(arguments.length) { - case 4: - error = a4; - success = a3; - //fallthrough - case 3: - case 2: - if (isFunction(a2)) { - if (isFunction(a1)) { - success = a1; - error = a2; - break; - } + Resource[name] = function(a1, a2, a3, a4) { + var params = {}, data, success, error; - success = a2; - error = a3; + /* jshint -W086 */ /* (purposefully fall through case statements) */ + switch (arguments.length) { + case 4: + error = a4; + success = a3; //fallthrough - } else { - params = a1; - data = a2; - success = a3; - break; - } - case 1: - if (isFunction(a1)) success = a1; - else if (hasBody) data = a1; - else params = a1; - break; - case 0: break; - default: - throw $resourceMinErr('badargs', - "Expected up to 4 arguments [params, data, success, error], got {0} arguments", - arguments.length); - } - /* jshint +W086 */ /* (purposefully fall through case statements) */ - - var isInstanceCall = this instanceof Resource; - var value = isInstanceCall ? data : (action.isArray ? [] : new Resource(data)); - var httpConfig = {}; - var responseInterceptor = action.interceptor && action.interceptor.response || - defaultResponseInterceptor; - var responseErrorInterceptor = action.interceptor && action.interceptor.responseError || - undefined; - - forEach(action, function(value, key) { - if (key != 'params' && key != 'isArray' && key != 'interceptor') { - httpConfig[key] = copy(value); + case 3: + case 2: + if (isFunction(a2)) { + if (isFunction(a1)) { + success = a1; + error = a2; + break; + } + + success = a2; + error = a3; + //fallthrough + } else { + params = a1; + data = a2; + success = a3; + break; + } + case 1: + if (isFunction(a1)) success = a1; + else if (hasBody) data = a1; + else params = a1; + break; + case 0: break; + default: + throw $resourceMinErr('badargs', + "Expected up to 4 arguments [params, data, success, error], got {0} arguments", + arguments.length); } - }); + /* jshint +W086 */ /* (purposefully fall through case statements) */ + + var isInstanceCall = this instanceof Resource; + var value = isInstanceCall ? data : (action.isArray ? [] : new Resource(data)); + var httpConfig = {}; + var responseInterceptor = action.interceptor && action.interceptor.response || + defaultResponseInterceptor; + var responseErrorInterceptor = action.interceptor && action.interceptor.responseError || + undefined; + + forEach(action, function(value, key) { + if (key != 'params' && key != 'isArray' && key != 'interceptor') { + httpConfig[key] = copy(value); + } + }); - if (hasBody) httpConfig.data = data; - route.setUrlParams(httpConfig, - extend({}, extractParams(data, action.params || {}), params), - action.url); + if (hasBody) httpConfig.data = data; + route.setUrlParams(httpConfig, + extend({}, extractParams(data, action.params || {}), params), + action.url); - var promise = $http(httpConfig).then(function(response) { - var data = response.data, + var promise = $http(httpConfig).then(function(response) { + var data = response.data, promise = value.$promise; - if (data) { - // Need to convert action.isArray to boolean in case it is undefined - // jshint -W018 - if (angular.isArray(data) !== (!!action.isArray)) { - throw $resourceMinErr('badcfg', 'Error in resource configuration. Expected ' + - 'response to contain an {0} but got an {1}', - action.isArray?'array':'object', angular.isArray(data)?'array':'object'); + if (data) { + // Need to convert action.isArray to boolean in case it is undefined + // jshint -W018 + if (angular.isArray(data) !== (!!action.isArray)) { + throw $resourceMinErr('badcfg', + 'Error in resource configuration for action `{0}`. Expected response to ' + + 'contain an {1} but got an {2}', name, action.isArray ? 'array' : 'object', + angular.isArray(data) ? 'array' : 'object'); + } + // jshint +W018 + if (action.isArray) { + value.length = 0; + forEach(data, function(item) { + if (typeof item === "object") { + value.push(new Resource(item)); + } else { + // Valid JSON values may be string literals, and these should not be converted + // into objects. These items will not have access to the Resource prototype + // methods, but unfortunately there + value.push(item); + } + }); + } else { + shallowClearAndCopy(data, value); + value.$promise = promise; + } } - // jshint +W018 - if (action.isArray) { - value.length = 0; - forEach(data, function(item) { - value.push(new Resource(item)); - }); - } else { - shallowClearAndCopy(data, value); - value.$promise = promise; - } - } - value.$resolved = true; + value.$resolved = true; - response.resource = value; + response.resource = value; - return response; - }, function(response) { - value.$resolved = true; + return response; + }, function(response) { + value.$resolved = true; - (error||noop)(response); + (error || noop)(response); - return $q.reject(response); - }); + return $q.reject(response); + }); - promise = promise.then( + promise = promise.then( function(response) { var value = responseInterceptor(response); - (success||noop)(value, response.headers); + (success || noop)(value, response.headers); return value; }, responseErrorInterceptor); - if (!isInstanceCall) { - // we are creating instance / collection - // - set the initial promise - // - return the instance / collection - value.$promise = promise; - value.$resolved = false; + if (!isInstanceCall) { + // we are creating instance / collection + // - set the initial promise + // - return the instance / collection + value.$promise = promise; + value.$resolved = false; - return value; - } + return value; + } - // instance call - return promise; - }; + // instance call + return promise; + }; - Resource.prototype['$' + name] = function(params, success, error) { - if (isFunction(params)) { - error = success; success = params; params = {}; - } - var result = Resource[name].call(this, params, this, success, error); - return result.$promise || result; - }; - }); + Resource.prototype['$' + name] = function(params, success, error) { + if (isFunction(params)) { + error = success; success = params; params = {}; + } + var result = Resource[name].call(this, params, this, success, error); + return result.$promise || result; + }; + }); - Resource.bind = function(additionalParamDefaults){ - return resourceFactory(url, extend({}, paramDefaults, additionalParamDefaults), actions); - }; + Resource.bind = function(additionalParamDefaults) { + return resourceFactory(url, extend({}, paramDefaults, additionalParamDefaults), actions); + }; - return Resource; - } + return Resource; + } - return resourceFactory; - }]); + return resourceFactory; + }]; + }); })(window, window.angular); |