123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768 |
- (function(window, angular, undefined) {'use strict';
- var $resourceMinErr = angular.$$minErr('$resource');
- var MEMBER_NAME_REGEX = /^(\.[a-zA-Z_$@][0-9a-zA-Z_$@]*)+$/;
- function isValidDottedPath(path) {
- return (path != null && path !== '' && path !== 'hasOwnProperty' &&
- MEMBER_NAME_REGEX.test('.' + path));
- }
- function lookupDottedPath(obj, path) {
- if (!isValidDottedPath(path)) {
- throw $resourceMinErr('badmember', 'Dotted member path "@{0}" is invalid.', path);
- }
- var keys = path.split('.');
- for (var i = 0, ii = keys.length; i < ii && angular.isDefined(obj); i++) {
- var key = keys[i];
- obj = (obj !== null) ? obj[key] : undefined;
- }
- return obj;
- }
- function shallowClearAndCopy(src, dst) {
- dst = dst || {};
- angular.forEach(dst, function(value, key) {
- delete dst[key];
- });
- for (var key in src) {
- if (src.hasOwnProperty(key) && !(key.charAt(0) === '$' && key.charAt(1) === '$')) {
- dst[key] = src[key];
- }
- }
- return dst;
- }
- angular.module('ngResource', ['ng']).
- provider('$resource', function() {
- var PROTOCOL_AND_DOMAIN_REGEX = /^https?:\/\/[^\/]*/;
- var provider = this;
- this.defaults = {
-
- stripTrailingSlashes: true,
-
- actions: {
- 'get': {method: 'GET'},
- 'save': {method: 'POST'},
- 'query': {method: 'GET', isArray: true},
- 'remove': {method: 'DELETE'},
- 'delete': {method: 'DELETE'}
- }
- };
- this.$get = ['$http', '$log', '$q', '$timeout', function($http, $log, $q, $timeout) {
- var noop = angular.noop,
- forEach = angular.forEach,
- extend = angular.extend,
- copy = angular.copy,
- isFunction = angular.isFunction;
-
- function encodeUriSegment(val) {
- return encodeUriQuery(val, true).
- replace(/%26/gi, '&').
- replace(/%3D/gi, '=').
- replace(/%2B/gi, '+');
- }
-
- 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 = extend({}, provider.defaults, defaults);
- this.urlParams = {};
- }
- Route.prototype = {
- setUrlParams: function(config, params, actionUrl) {
- var self = this,
- url = actionUrl || self.template,
- val,
- encodedVal,
- protocolAndDomain = '';
- 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] = {
- isQueryParamValue: (new RegExp("\\?.*=:" + param + "(?:\\W|$)")).test(url)
- };
- }
- });
- url = url.replace(/\\:/g, ':');
- url = url.replace(PROTOCOL_AND_DOMAIN_REGEX, function(match) {
- protocolAndDomain = match;
- return '';
- });
- params = params || {};
- forEach(self.urlParams, function(paramInfo, urlParam) {
- val = params.hasOwnProperty(urlParam) ? params[urlParam] : self.defaults[urlParam];
- if (angular.isDefined(val) && val !== null) {
- if (paramInfo.isQueryParamValue) {
- encodedVal = encodeUriQuery(val, true);
- } else {
- 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;
- }
- });
- }
- });
-
- if (self.defaults.stripTrailingSlashes) {
- url = url.replace(/\/+$/, '') || '/';
- }
-
-
- url = url.replace(/\/\.(?=\w+($|\?))/, '.');
-
- config.url = protocolAndDomain + url.replace(/\/\\\./, '/.');
-
- forEach(params, function(value, key) {
- if (!self.urlParams[key]) {
- config.params = config.params || {};
- config.params[key] = value;
- }
- });
- }
- };
- function resourceFactory(url, paramDefaults, actions, options) {
- var route = new Route(url, options);
- actions = extend({}, provider.defaults.actions, actions);
- 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;
- };
- forEach(actions, function(action, name) {
- var hasBody = /^(POST|PUT|PATCH)$/i.test(action.method);
- var numericTimeout = action.timeout;
- var cancellable = angular.isDefined(action.cancellable) ? action.cancellable :
- (options && angular.isDefined(options.cancellable)) ? options.cancellable :
- provider.defaults.cancellable;
- if (numericTimeout && !angular.isNumber(numericTimeout)) {
- $log.debug('ngResource:\n' +
- ' Only numeric values are allowed as `timeout`.\n' +
- ' Promises are not supported in $resource, because the same value would ' +
- 'be used for multiple requests. If you are looking for a way to cancel ' +
- 'requests, you should use the `cancellable` option.');
- delete action.timeout;
- numericTimeout = null;
- }
- Resource[name] = function(a1, a2, a3, a4) {
- var params = {}, data, success, error;
-
- switch (arguments.length) {
- case 4:
- error = a4;
- success = a3;
-
- case 3:
- case 2:
- if (isFunction(a2)) {
- if (isFunction(a1)) {
- success = a1;
- error = a2;
- break;
- }
- success = a2;
- error = a3;
-
- } 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);
- }
-
- 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;
- var timeoutDeferred;
- var numericTimeoutPromise;
- forEach(action, function(value, key) {
- switch (key) {
- default:
- httpConfig[key] = copy(value);
- break;
- case 'params':
- case 'isArray':
- case 'interceptor':
- case 'cancellable':
- break;
- }
- });
- if (!isInstanceCall && cancellable) {
- timeoutDeferred = $q.defer();
- httpConfig.timeout = timeoutDeferred.promise;
- if (numericTimeout) {
- numericTimeoutPromise = $timeout(timeoutDeferred.resolve, numericTimeout);
- }
- }
- 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;
- if (data) {
-
-
- 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} (Request: {3} {4})', name, action.isArray ? 'array' : 'object',
- angular.isArray(data) ? 'array' : 'object', httpConfig.method, httpConfig.url);
- }
-
- if (action.isArray) {
- value.length = 0;
- forEach(data, function(item) {
- if (typeof item === "object") {
- value.push(new Resource(item));
- } else {
-
-
-
- value.push(item);
- }
- });
- } else {
- var promise = value.$promise;
- shallowClearAndCopy(data, value);
- value.$promise = promise;
- }
- }
- response.resource = value;
- return response;
- }, function(response) {
- (error || noop)(response);
- return $q.reject(response);
- });
- promise['finally'](function() {
- value.$resolved = true;
- if (!isInstanceCall && cancellable) {
- value.$cancelRequest = angular.noop;
- $timeout.cancel(numericTimeoutPromise);
- timeoutDeferred = numericTimeoutPromise = httpConfig.timeout = null;
- }
- });
- promise = promise.then(
- function(response) {
- var value = responseInterceptor(response);
- (success || noop)(value, response.headers);
- return value;
- },
- responseErrorInterceptor);
- if (!isInstanceCall) {
-
-
-
- value.$promise = promise;
- value.$resolved = false;
- if (cancellable) value.$cancelRequest = timeoutDeferred.resolve;
- return value;
- }
-
- 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.bind = function(additionalParamDefaults) {
- return resourceFactory(url, extend({}, paramDefaults, additionalParamDefaults), actions);
- };
- return Resource;
- }
- return resourceFactory;
- }];
- });
- })(window, window.angular);
|