You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1 lines
14 KiB
1 lines
14 KiB
!function(e,t,r,n){"use strict";var t=void 0!==t&&t.Math==Math?t:"undefined"!=typeof self&&self.Math==Math?self:Function("return this")();e.api=e.fn.api=function(r){var n,o=e(e.isFunction(this)?t:this),i=o.selector||"",s=(new Date).getTime(),a=[],u=arguments[0],c="string"==typeof u,d=[].slice.call(arguments,1);return o.each(function(){var o,l,g,f,p,m=e.isPlainObject(r)?e.extend(!0,{},e.fn.api.settings,r):e.extend({},e.fn.api.settings),v=m.namespace,b=m.metadata,h=m.selector,y=m.error,q=m.className,R="."+v,x="module-"+v,S=e(this),A=S.closest(h.form),k=m.stateContext?e(m.stateContext):S,T=this,P=k[0],j=S.data(x);p={initialize:function(){c||p.bind.events(),p.instantiate()},instantiate:function(){p.verbose("Storing instance of module",p),j=p,S.data(x,j)},destroy:function(){p.verbose("Destroying previous module for",T),S.removeData(x).off(R)},bind:{events:function(){var e=p.get.event();e?(p.verbose("Attaching API events to element",e),S.on(e+R,p.event.trigger)):"now"==m.on&&(p.debug("Querying API endpoint immediately"),p.query())}},decode:{json:function(e){if(void 0!==e&&"string"==typeof e)try{e=JSON.parse(e)}catch(e){}return e}},read:{cachedResponse:function(e){var r;return void 0===t.Storage?void p.error(y.noStorage):(r=sessionStorage.getItem(e),p.debug("Using cached response",e,r),r=p.decode.json(r))}},write:{cachedResponse:function(r,n){return n&&""===n?void p.debug("Response empty, not caching",n):void 0===t.Storage?void p.error(y.noStorage):(e.isPlainObject(n)&&(n=JSON.stringify(n)),sessionStorage.setItem(r,n),void p.verbose("Storing cached response for url",r,n))}},query:function(){if(p.is.disabled())return void p.debug("Element is disabled API request aborted");if(p.is.loading()){if(!m.interruptRequests)return void p.debug("Cancelling request, previous request is still pending");p.debug("Interrupting previous request"),p.abort()}if(m.defaultData&&e.extend(!0,m.urlData,p.get.defaultData()),m.serializeForm&&(m.data=p.add.formData(m.data)),!1===(l=p.get.settings()))return p.cancelled=!0,void p.error(y.beforeSend);if(p.cancelled=!1,!(g=p.get.templatedURL())&&!p.is.mocked())return void p.error(y.missingURL);if((g=p.add.urlData(g))||p.is.mocked()){if(l.url=m.base+g,o=e.extend(!0,{},m,{type:m.method||m.type,data:void 0,url:m.base+g,beforeSend:m.beforeXHR,success:function(){},failure:function(){},complete:function(){}}),p.debug("Querying URL",o.url),p.verbose("Using AJAX settings",o),"local"===m.cache&&p.read.cachedResponse(g))return p.debug("Response returned from local cache"),p.request=p.create.request(),void p.request.resolveWith(P,[p.read.cachedResponse(g)]);m.throttle?m.throttleFirstRequest||p.timer?(p.debug("Throttling request",m.throttle),clearTimeout(p.timer),p.timer=setTimeout(function(){p.timer&&delete p.timer,p.debug("Sending throttled request",void 0,o.method),p.send.request()},m.throttle)):(p.debug("Sending request",void 0,o.method),p.send.request(),p.timer=setTimeout(function(){},m.throttle)):(p.debug("Sending request",void 0,o.method),p.send.request())}},should:{removeError:function(){return!0===m.hideError||"auto"===m.hideError&&!p.is.form()}},is:{disabled:function(){return S.filter(h.disabled).length>0},expectingJSON:function(){return"json"===m.dataType||"jsonp"===m.dataType},form:function(){return S.is("form")||k.is("form")},mocked:function(){return m.mockResponse||m.mockResponseAsync||m.response||m.responseAsync},input:function(){return S.is("input")},loading:function(){return!!p.request&&"pending"==p.request.state()},abortedRequest:function(e){return e&&void 0!==e.readyState&&0===e.readyState?(p.verbose("XHR request determined to be aborted"),!0):(p.verbose("XHR request was not aborted"),!1)},validResponse:function(t){return p.is.expectingJSON()&&e.isFunction(m.successTest)?(p.debug("Checking JSON returned success",m.successTest,t),m.successTest(t)?(p.debug("Response passed success test",t),!0):(p.debug("Response failed success test",t),!1)):(p.verbose("Response is not JSON, skipping validation",m.successTest,t),!0)}},was:{cancelled:function(){return p.cancelled||!1},succesful:function(){return p.request&&"resolved"==p.request.state()},failure:function(){return p.request&&"rejected"==p.request.state()},complete:function(){return p.request&&("resolved"==p.request.state()||"rejected"==p.request.state())}},add:{urlData:function(t,r){var n,o;return t&&(n=t.match(m.regExp.required),o=t.match(m.regExp.optional),r=r||m.urlData,n&&(p.debug("Looking for required URL variables",n),e.each(n,function(n,o){var i=-1!==o.indexOf("$")?o.substr(2,o.length-3):o.substr(1,o.length-2),s=e.isPlainObject(r)&&void 0!==r[i]?r[i]:void 0!==S.data(i)?S.data(i):void 0!==k.data(i)?k.data(i):r[i];if(void 0===s)return p.error(y.requiredParameter,i,t),t=!1,!1;p.verbose("Found required variable",i,s),s=m.encodeParameters?p.get.urlEncodedValue(s):s,t=t.replace(o,s)})),o&&(p.debug("Looking for optional URL variables",n),e.each(o,function(n,o){var i=-1!==o.indexOf("$")?o.substr(3,o.length-4):o.substr(2,o.length-3),s=e.isPlainObject(r)&&void 0!==r[i]?r[i]:void 0!==S.data(i)?S.data(i):void 0!==k.data(i)?k.data(i):r[i];void 0!==s?(p.verbose("Optional variable Found",i,s),t=t.replace(o,s)):(p.verbose("Optional variable not found",i),t=-1!==t.indexOf("/"+o)?t.replace("/"+o,""):t.replace(o,""))}))),t},formData:function(t){var r,n=void 0!==e.fn.serializeObject,o=n?A.serializeObject():A.serialize();return t=t||m.data,r=e.isPlainObject(t),r?n?(p.debug("Extending existing data with form data",t,o),t=e.extend(!0,{},t,o)):(p.error(y.missingSerialize),p.debug("Cant extend data. Replacing data with form data",t,o),t=o):(p.debug("Adding form data",o),t=o),t}},send:{request:function(){p.set.loading(),p.request=p.create.request(),p.is.mocked()?p.mockedXHR=p.create.mockedXHR():p.xhr=p.create.xhr(),m.onRequest.call(P,p.request,p.xhr)}},event:{trigger:function(e){p.query(),"submit"!=e.type&&"click"!=e.type||e.preventDefault()},xhr:{always:function(){},done:function(t,r,n){var o=this,i=(new Date).getTime()-f,s=m.loadingDuration-i,a=!!e.isFunction(m.onResponse)&&(p.is.expectingJSON()?m.onResponse.call(o,e.extend(!0,{},t)):m.onResponse.call(o,t));s=s>0?s:0,a&&(p.debug("Modified API response in onResponse callback",m.onResponse,a,t),t=a),s>0&&p.debug("Response completed early delaying state change by",s),setTimeout(function(){p.is.validResponse(t)?p.request.resolveWith(o,[t,n]):p.request.rejectWith(o,[n,"invalid"])},s)},fail:function(e,t,r){var n=this,o=(new Date).getTime()-f,i=m.loadingDuration-o;i=i>0?i:0,i>0&&p.debug("Response completed early delaying state change by",i),setTimeout(function(){p.is.abortedRequest(e)?p.request.rejectWith(n,[e,"aborted",r]):p.request.rejectWith(n,[e,"error",t,r])},i)}},request:{done:function(e,t){p.debug("Successful API Response",e),"local"===m.cache&&g&&(p.write.cachedResponse(g,e),p.debug("Saving server response locally",p.cache)),m.onSuccess.call(P,e,S,t)},complete:function(e,t){var r,n;p.was.succesful()?(n=e,r=t):(r=e,n=p.get.responseFromXHR(r)),p.remove.loading(),m.onComplete.call(P,n,S,r)},fail:function(e,t,r){var n=p.get.responseFromXHR(e),i=p.get.errorFromRequest(n,t,r);if("aborted"==t)return p.debug("XHR Aborted (Most likely caused by page navigation or CORS Policy)",t,r),m.onAbort.call(P,t,S,e),!0;"invalid"==t?p.debug("JSON did not pass success test. A server-side error has most likely occurred",n):"error"==t&&void 0!==e&&(p.debug("XHR produced a server error",t,r),200!=e.status&&void 0!==r&&""!==r&&p.error(y.statusMessage+r,o.url),m.onError.call(P,i,S,e)),m.errorDuration&&"aborted"!==t&&(p.debug("Adding error state"),p.set.error(),p.should.removeError()&&setTimeout(p.remove.error,m.errorDuration)),p.debug("API Request failed",i,e),m.onFailure.call(P,n,S,e)}}},create:{request:function(){return e.Deferred().always(p.event.request.complete).done(p.event.request.done).fail(p.event.request.fail)},mockedXHR:function(){var t,r,n,o=m.mockResponse||m.response,i=m.mockResponseAsync||m.responseAsync;return n=e.Deferred().always(p.event.xhr.complete).done(p.event.xhr.done).fail(p.event.xhr.fail),o?(e.isFunction(o)?(p.debug("Using specified synchronous callback",o),r=o.call(P,l)):(p.debug("Using settings specified response",o),r=o),n.resolveWith(P,[r,!1,{responseText:r}])):e.isFunction(i)&&(t=function(e){p.debug("Async callback returned response",e),e?n.resolveWith(P,[e,!1,{responseText:e}]):n.rejectWith(P,[{responseText:e},!1,!1])},p.debug("Using specified async response callback",i),i.call(P,l,t)),n},xhr:function(){var t;return t=e.ajax(o).always(p.event.xhr.always).done(p.event.xhr.done).fail(p.event.xhr.fail),p.verbose("Created server request",t,o),t}},set:{error:function(){p.verbose("Adding error state to element",k),k.addClass(q.error)},loading:function(){p.verbose("Adding loading state to element",k),k.addClass(q.loading),f=(new Date).getTime()}},remove:{error:function(){p.verbose("Removing error state from element",k),k.removeClass(q.error)},loading:function(){p.verbose("Removing loading state from element",k),k.removeClass(q.loading)}},get:{responseFromXHR:function(t){return!!e.isPlainObject(t)&&(p.is.expectingJSON()?p.decode.json(t.responseText):t.responseText)},errorFromRequest:function(t,r,n){return e.isPlainObject(t)&&void 0!==t.error?t.error:void 0!==m.error[r]?m.error[r]:n},request:function(){return p.request||!1},xhr:function(){return p.xhr||!1},settings:function(){var t;return t=m.beforeSend.call(P,m),t&&(void 0!==t.success&&(p.debug("Legacy success callback detected",t),p.error(y.legacyParameters,t.success),t.onSuccess=t.success),void 0!==t.failure&&(p.debug("Legacy failure callback detected",t),p.error(y.legacyParameters,t.failure),t.onFailure=t.failure),void 0!==t.complete&&(p.debug("Legacy complete callback detected",t),p.error(y.legacyParameters,t.complete),t.onComplete=t.complete)),void 0===t&&p.error(y.noReturnedValue),!1===t?t:void 0!==t?e.extend(!0,{},t):e.extend(!0,{},m)},urlEncodedValue:function(e){var r=t.decodeURIComponent(e),n=t.encodeURIComponent(e);return r!==e?(p.debug("URL value is already encoded, avoiding double encoding",e),e):(p.verbose("Encoding value using encodeURIComponent",e,n),n)},defaultData:function(){var t={};return e.isWindow(T)||(p.is.input()?t.value=S.val():p.is.form()||(t.text=S.text())),t},event:function(){return e.isWindow(T)||"now"==m.on?(p.debug("API called without element, no events attached"),!1):"auto"==m.on?S.is("input")?void 0!==T.oninput?"input":void 0!==T.onpropertychange?"propertychange":"keyup":S.is("form")?"submit":"click":m.on},templatedURL:function(e){if(e=e||S.data(b.action)||m.action||!1,g=S.data(b.url)||m.url||!1)return p.debug("Using specified url",g),g;if(e){if(p.debug("Looking up url for action",e,m.api),void 0===m.api[e]&&!p.is.mocked())return void p.error(y.missingAction,m.action,m.api);g=m.api[e]}else p.is.form()&&(g=S.attr("action")||k.attr("action")||!1,p.debug("No url or action specified, defaulting to form action",g));return g}},abort:function(){var e=p.get.xhr();e&&"resolved"!==e.state()&&(p.debug("Cancelling API request"),e.abort())},reset:function(){p.remove.error(),p.remove.loading()},setting:function(t,r){if(p.debug("Changing setting",t,r),e.isPlainObject(t))e.extend(!0,m,t);else{if(void 0===r)return m[t];e.isPlainObject(m[t])?e.extend(!0,m[t],r):m[t]=r}},internal:function(t,r){if(e.isPlainObject(t))e.extend(!0,p,t);else{if(void 0===r)return p[t];p[t]=r}},debug:function(){!m.silent&&m.debug&&(m.performance?p.performance.log(arguments):(p.debug=Function.prototype.bind.call(console.info,console,m.name+":"),p.debug.apply(console,arguments)))},verbose:function(){!m.silent&&m.verbose&&m.debug&&(m.performance?p.performance.log(arguments):(p.verbose=Function.prototype.bind.call(console.info,console,m.name+":"),p.verbose.apply(console,arguments)))},error:function(){m.silent||(p.error=Function.prototype.bind.call(console.error,console,m.name+":"),p.error.apply(console,arguments))},performance:{log:function(e){var t,r,n;m.performance&&(t=(new Date).getTime(),n=s||t,r=t-n,s=t,a.push({Name:e[0],Arguments:[].slice.call(e,1)||"","Execution Time":r})),clearTimeout(p.performance.timer),p.performance.timer=setTimeout(p.performance.display,500)},display:function(){var t=m.name+":",r=0;s=!1,clearTimeout(p.performance.timer),e.each(a,function(e,t){r+=t["Execution Time"]}),t+=" "+r+"ms",i&&(t+=" '"+i+"'"),(void 0!==console.group||void 0!==console.table)&&a.length>0&&(console.groupCollapsed(t),console.table?console.table(a):e.each(a,function(e,t){console.log(t.Name+": "+t["Execution Time"]+"ms")}),console.groupEnd()),a=[]}},invoke:function(t,r,o){var i,s,a,u=j;return r=r||d,o=T||o,"string"==typeof t&&void 0!==u&&(t=t.split(/[\. ]/),i=t.length-1,e.each(t,function(r,n){var o=r!=i?n+t[r+1].charAt(0).toUpperCase()+t[r+1].slice(1):t;if(e.isPlainObject(u[o])&&r!=i)u=u[o];else{if(void 0!==u[o])return s=u[o],!1;if(!e.isPlainObject(u[n])||r==i)return void 0!==u[n]?(s=u[n],!1):(p.error(y.method,t),!1);u=u[n]}})),e.isFunction(s)?a=s.apply(o,r):void 0!==s&&(a=s),e.isArray(n)?n.push(a):void 0!==n?n=[n,a]:void 0!==a&&(n=a),s}},c?(void 0===j&&p.initialize(),p.invoke(u)):(void 0!==j&&j.invoke("destroy"),p.initialize())}),void 0!==n?n:this},e.api.settings={name:"API",namespace:"api",debug:!1,verbose:!1,performance:!0,api:{},cache:!0,interruptRequests:!0,on:"auto",stateContext:!1,loadingDuration:0,hideError:"auto",errorDuration:2e3,encodeParameters:!0,action:!1,url:!1,base:"",urlData:{},defaultData:!0,serializeForm:!1,throttle:0,throttleFirstRequest:!0,method:"get",data:{},dataType:"json",mockResponse:!1,mockResponseAsync:!1,response:!1,responseAsync:!1,beforeSend:function(e){return e},beforeXHR:function(e){},onRequest:function(e,t){},onResponse:!1,onSuccess:function(e,t){},onComplete:function(e,t){},onFailure:function(e,t){},onError:function(e,t){},onAbort:function(e,t){},successTest:!1,error:{beforeSend:"The before send function has aborted the request",error:"There was an error with your request",exitConditions:"API Request Aborted. Exit conditions met",JSONParse:"JSON could not be parsed during error handling",legacyParameters:"You are using legacy API success callback names",method:"The method you called is not defined",missingAction:"API action used but no url was defined",missingSerialize:"jquery-serialize-object is required to add form data to an existing data object",missingURL:"No URL specified for api event",noReturnedValue:"The beforeSend callback must return a settings object, beforeSend ignored.",noStorage:"Caching responses locally requires session storage",parseError:"There was an error parsing your request",requiredParameter:"Missing a required URL parameter: ",statusMessage:"Server gave an error: ",timeout:"Your request timed out"},regExp:{required:/\{\$*[A-z0-9]+\}/g,optional:/\{\/\$*[A-z0-9]+\}/g},className:{loading:"loading",error:"error"},selector:{disabled:".disabled",form:"form"},metadata:{action:"action",url:"url"}}}(jQuery,window,document);
|