| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398 |
- // jQuery REST Client - v1.0.2 - https://github.com/jpillora/jquery.rest
- // Jaime Pillora <dev@jpillora.com> - MIT Copyright 2014
- (function(window,$,undefined) {'use strict';
- var Cache, Resource, Verb, defaultOpts, deleteWarning, encode64, error, inheritExtend, s, stringify, validateOpts, validateStr;
- error = function(msg) {
- throw new Error("ERROR: jquery.rest: " + msg);
- };
- s = function(n) {
- var t;
- t = "";
- while (n-- > 0) {
- t += " ";
- }
- return t;
- };
- encode64 = function(s) {
- if (!window.btoa) {
- error("You need a polyfill for 'btoa' to use basic auth.");
- }
- return window.btoa(s);
- };
- stringify = function(obj) {
- if (!window.JSON) {
- error("You need a polyfill for 'JSON' to use stringify.");
- }
- return window.JSON.stringify(obj);
- };
- inheritExtend = function(a, b) {
- var F;
- F = function() {};
- F.prototype = a;
- return $.extend(true, new F(), b);
- };
- validateOpts = function(options) {
- if (!(options && $.isPlainObject(options))) {
- return false;
- }
- $.each(options, function(name) {
- if (defaultOpts[name] === undefined) {
- return error("Unknown option: '" + name + "'");
- }
- });
- return null;
- };
- validateStr = function(name, str) {
- if ('string' !== $.type(str)) {
- return error("'" + name + "' must be a string");
- }
- };
- deleteWarning = function() {
- return alert('"delete()" has been deprecated. Please use "destroy()" or "del()" instead.');
- };
- defaultOpts = {
- url: '',
- cache: 0,
- request: function(resource, options) {
- return $.ajax(options);
- },
- isSingle: false,
- autoClearCache: true,
- cachableMethods: ['GET'],
- methodOverride: false,
- stringifyData: false,
- stripTrailingSlash: true,
- password: null,
- username: null,
- token: null,
- verbs: {
- 'create': 'POST',
- 'read': 'GET',
- 'update': 'PUT',
- 'destroy': 'DELETE'
- },
- ajax: {
- dataType: 'json'
- }
- };
- Cache = (function() {
- function Cache(parent) {
- this.parent = parent;
- this.c = {};
- }
- Cache.prototype.valid = function(date) {
- var diff;
- diff = new Date().getTime() - date.getTime();
- return diff <= this.parent.opts.cache * 1000;
- };
- Cache.prototype.key = function(obj) {
- var key,
- _this = this;
- key = "";
- $.each(obj, function(k, v) {
- return key += k + "=" + ($.isPlainObject(v) ? "{" + _this.key(v) + "}" : v) + "|";
- });
- return key;
- };
- Cache.prototype.get = function(key) {
- var result;
- result = this.c[key];
- if (!result) {
- return;
- }
- if (this.valid(result.created)) {
- return result.data;
- }
- };
- Cache.prototype.put = function(key, data) {
- return this.c[key] = {
- created: new Date(),
- data: data
- };
- };
- Cache.prototype.clear = function(regexp) {
- var _this = this;
- if (regexp) {
- return $.each(this.c, function(k) {
- if (k.match(regexp)) {
- return delete _this.c[k];
- }
- });
- } else {
- return this.c = {};
- }
- };
- return Cache;
- })();
- Verb = (function() {
- function Verb(name, method, options, parent) {
- this.name = name;
- this.method = method;
- if (options == null) {
- options = {};
- }
- this.parent = parent;
- validateStr('name', this.name);
- validateStr('method', this.method);
- validateOpts(options);
- if (this.parent[this.name]) {
- error("Cannot add Verb: '" + name + "' already exists");
- }
- this.method = method.toUpperCase();
- if (!options.url) {
- options.url = '';
- }
- this.opts = inheritExtend(this.parent.opts, options);
- this.root = this.parent.root;
- this.custom = !defaultOpts.verbs[this.name];
- this.call = $.proxy(this.call, this);
- this.call.instance = this;
- }
- Verb.prototype.call = function() {
- var data, url, _ref;
- _ref = this.parent.extractUrlData(this.method, arguments), url = _ref.url, data = _ref.data;
- if (this.custom) {
- url += this.opts.url || this.name;
- }
- return this.parent.ajax.call(this, this.method, url, data);
- };
- Verb.prototype.show = function(d) {
- return console.log(s(d) + this.name + ": " + this.method);
- };
- return Verb;
- })();
- Resource = (function() {
- function Resource(nameOrUrl, options, parent) {
- if (options == null) {
- options = {};
- }
- validateOpts(options);
- if (parent && parent instanceof Resource) {
- this.name = nameOrUrl;
- validateStr('name', this.name);
- this.constructChild(parent, options);
- } else {
- this.url = nameOrUrl || '';
- validateStr('url', this.url);
- this.constructRoot(options);
- }
- }
- Resource.prototype.constructRoot = function(options) {
- this.opts = inheritExtend(defaultOpts, options);
- this.root = this;
- this.expectedIds = 0;
- this.urlNoId = this.url;
- this.cache = new Cache(this);
- this.parent = null;
- return this.name = this.opts.name || 'ROOT';
- };
- Resource.prototype.constructChild = function(parent, options) {
- this.parent = parent;
- validateStr('name', this.name);
- if (!(this.parent instanceof Resource)) {
- this.error("Invalid parent");
- }
- if (this.parent[this.name]) {
- this.error("'" + name + "' already exists");
- }
- if (!options.url) {
- options.url = '';
- }
- this.opts = inheritExtend(this.parent.opts, options);
- this.opts.isSingle = 'isSingle' in options && options.isSingle;
- this.root = this.parent.root;
- this.urlNoId = this.parent.url + ("" + (this.opts.url || this.name) + "/");
- this.url = this.urlNoId;
- this.expectedIds = this.parent.expectedIds;
- if (!this.opts.isSingle) {
- this.expectedIds += 1;
- this.url += ":ID_" + this.expectedIds + "/";
- }
- $.each(this.opts.verbs, $.proxy(this.addVerb, this));
- if (this.destroy) {
- this.del = this.destroy;
- return this["delete"] = deleteWarning;
- }
- };
- Resource.prototype.error = function(msg) {
- return error("Cannot add Resource: " + msg);
- };
- Resource.prototype.add = function(name, options) {
- return this[name] = new Resource(name, options, this);
- };
- Resource.prototype.addVerb = function(name, method, options) {
- return this[name] = new Verb(name, method, options, this).call;
- };
- Resource.prototype.show = function(d) {
- if (d == null) {
- d = 0;
- }
- if (d > 25) {
- error("Plugin Bug! Recursion Fail");
- }
- if (this.name) {
- console.log(s(d) + this.name + ": " + this.url);
- }
- $.each(this, function(name, fn) {
- if ($.type(fn) === 'function' && fn.instance instanceof Verb && name !== 'del') {
- return fn.instance.show(d + 1);
- }
- });
- $.each(this, function(name, res) {
- if (name !== "parent" && name !== "root" && res instanceof Resource) {
- return res.show(d + 1);
- }
- });
- return null;
- };
- Resource.prototype.toString = function() {
- return this.name;
- };
- Resource.prototype.extractUrlData = function(name, args) {
- var arg, canUrl, canUrlNoId, data, i, id, ids, msg, params, providedIds, t, url, _i, _j, _len, _len1;
- ids = [];
- data = null;
- params = null;
- for (_i = 0, _len = args.length; _i < _len; _i++) {
- arg = args[_i];
- t = $.type(arg);
- if (t === 'string' || t === 'number') {
- ids.push(arg);
- } else if (t === 'object' && data === null) {
- data = arg;
- } else if (t === 'object' && params === null) {
- params = arg;
- } else {
- error(("Invalid argument: " + arg + " (" + t + ").") + " Must be strings or ints (IDs) followed by one optional object and one optional query params object.");
- }
- }
- providedIds = ids.length;
- canUrl = name !== 'create';
- canUrlNoId = name !== 'update' && name !== 'delete';
- url = null;
- if (canUrl && providedIds === this.expectedIds) {
- url = this.url;
- }
- if (canUrlNoId && providedIds === this.expectedIds - 1) {
- url = this.urlNoId;
- }
- if (url === null) {
- if (canUrlNoId) {
- msg = this.expectedIds - 1;
- }
- if (canUrl) {
- msg = (msg ? msg + ' or ' : '') + this.expectedIds;
- }
- error("Invalid number of ID arguments, required " + msg + ", provided " + providedIds);
- }
- for (i = _j = 0, _len1 = ids.length; _j < _len1; i = ++_j) {
- id = ids[i];
- url = url.replace(new RegExp("\/:ID_" + (i + 1) + "\/"), "/" + id + "/");
- }
- if (params) {
- url += "?" + ($.param(params));
- }
- return {
- url: url,
- data: data
- };
- };
- Resource.prototype.ajax = function(method, url, data) {
- var ajaxOpts, encoded, escapedUrl, headers, key, req, useCache,
- _this = this;
- if (!method) {
- error("method missing");
- }
- if (!url) {
- error("url missing");
- }
- headers = {};
- if (this.opts.username && this.opts.password) {
- encoded = encode64(this.opts.username + ":" + this.opts.password);
- headers['Authorization'] = "Basic " + encoded;
- }
- if (this.opts.token) {
- headers['Authorization'] = "Bearer " + this.opts.token;
- }
- if (data && this.opts.stringifyData && (method !== 'GET' && method !== 'HEAD')) {
- data = stringify(data);
- headers['Content-Type'] = "application/json";
- }
- if (this.opts.methodOverride && (method !== 'GET' && method !== 'HEAD' && method !== 'POST')) {
- headers['X-HTTP-Method-Override'] = method;
- method = 'POST';
- }
- if (this.opts.stripTrailingSlash) {
- url = url.replace(/\/$/, "");
- }
- ajaxOpts = {
- url: url,
- type: method,
- headers: headers
- };
- if (data) {
- ajaxOpts.data = data;
- }
- ajaxOpts = $.extend(true, {}, this.opts.ajax, ajaxOpts);
- useCache = this.opts.cache && $.inArray(method, this.opts.cachableMethods) >= 0;
- if (useCache) {
- key = this.root.cache.key(ajaxOpts);
- req = this.root.cache.get(key);
- if (req) {
- return req;
- }
- }
- if (this.opts.cache && this.opts.autoClearCache && $.inArray(method, this.opts.cachableMethods) === -1) {
- escapedUrl = url.replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1");
- this.root.cache.clear(new RegExp(escapedUrl));
- }
- req = this.opts.request(this.parent, ajaxOpts);
- if (useCache) {
- req.done(function() {
- return _this.root.cache.put(key, req);
- });
- }
- return req;
- };
- return Resource;
- })();
- Resource.defaults = defaultOpts;
- $.RestClient = Resource;
- }.call(this,window,jQuery));
|