intercooler
Version:
Making AJAX as easy as anchor tags
2 lines • 17.6 kB
JavaScript
/*! intercooler 0.2.0 2014-04-16 */
;var Intercooler=Intercooler||function(){function fp(a){return CryptoJS.SHA1(a).toString()}function levelPrefix(a){return a==_DEBUG?"IC DEBUG: ":a==_INFO?"IC INFO: ":a==_WARN?"IC WARN: ":a==_ERROR?"IC ERROR: ":"IC UNKNOWN: "}function log(a,b){var c=b||_INFO,d=_loggingLevel||_ERROR;_logger&&c>=d&&(null==_loggingGrep||_loggingGrep.test(a))&&_logger.log(levelPrefix(c),a)}function uuid(){var a=(new Date).getTime(),b="xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g,function(b){var c=(a+16*Math.random())%16|0;return a=Math.floor(a/16),("x"==b?c:7&c|8).toString(16)});return b}function icSelectorFor(a){return"[ic-id='"+a.attr("ic-id")+"']"}function findByICId(a){return $("[ic-id='"+a+"']")}function findById(a){return $("[id='"+a+"']")}function parseInterval(a){return log("POLL: Parsing interval string "+a,_DEBUG),"null"==a||"false"==a||""==a?null:a.lastIndexOf("ms")==a.length-2?parseInt(a.substr(0,a.length-2)):a.lastIndexOf("s")==a.length-1?1e3*parseInt(a.substr(0,a.length-1)):1e3}function getTarget(a){return a.attr("ic-target")?$(a.attr("ic-target")):a}function processHeaders(elt,xhr,pop){if(elt.trigger("ic.beforeHeaders",elt,xhr),xhr.getResponseHeader("X-IC-Refresh")){var pathsToRefresh=xhr.getResponseHeader("X-IC-Refresh").split(",");log("IC HEADER: refreshing "+pathsToRefresh,_DEBUG),$.each(pathsToRefresh,function(a,b){refreshDependencies(b.replace(/ /g,""),elt)})}if(xhr.getResponseHeader("X-IC-Script")&&(log("IC HEADER: evaling "+xhr.getResponseHeader("X-IC-Script"),_DEBUG),eval(xhr.getResponseHeader("X-IC-Script"))),xhr.getResponseHeader("X-IC-Redirect")&&(log("IC HEADER: redirecting to "+xhr.getResponseHeader("X-IC-Redirect"),_DEBUG),window.location=xhr.getResponseHeader("X-IC-Redirect")),"true"==xhr.getResponseHeader("X-IC-CancelPolling")&&cancelPolling(elt),xhr.getResponseHeader("X-IC-Open")&&(log("IC HEADER: opening "+xhr.getResponseHeader("X-IC-Open"),_DEBUG),window.open(xhr.getResponseHeader("X-IC-Open"))),xhr.getResponseHeader("X-IC-SetLocation")&&1!=pop&&(log("IC HEADER: pushing "+xhr.getResponseHeader("X-IC-SetLocation"),_DEBUG),_historySupport.pushUrl(xhr.getResponseHeader("X-IC-SetLocation"),elt)),xhr.getResponseHeader("X-IC-Transition")){log("IC HEADER: setting transition to "+xhr.getResponseHeader("X-IC-Transition"),_DEBUG);var target=getTarget(elt);target.data("ic-tmp-transition",xhr.getResponseHeader("X-IC-Transition"))}if(xhr.getResponseHeader("X-IC-Remove")&&(log("IC HEADER REMOVE COMMAND"),elt)){var target=getTarget(elt);log("IC REMOVING: "+target.html(),_DEBUG),isTransition(target,"none")?target.remove():target.fadeOut("fast",function(){target.remove()})}return elt.trigger("ic.afterHeaders",elt,xhr),!0}function handleTestResponse(a,b,c){var d=findSpinner(a);d.fadeIn("fast");var e={};c&&c.headers&&(e=c.headers);var f="";c&&("string"==typeof c||c instanceof String?f=c:("string"==typeof c.body||c.body instanceof String)&&(f=c.body)),processHeaders(a,{getResponseHeader:function(a){return e[a]}}),b(f,"",a),setTimeout(function(){d.fadeOut("fast")},800)}function beforeRequest(a){a.addClass("disabled")}function afterRequest(a){a.removeClass("disabled")}function replaceOrAddMethod(a,b){var c=/(&|^)_method=[^&]*/,d="&_method="+b;return c.test(a)?a.replace(c,d):a+"&"+d}function handleRemoteRequest(a,b,c,d,e){d=replaceOrAddMethod(d,b);for(var f=d.indexOf("&ic-handle-pop=true")>=0,g=0,h=_urlHandlers.length;h>g;g++){var i=_urlHandlers[g],j=null;if(null==i.url||new RegExp(i.url.replace(/\*/g,".*").replace(/\//g,"\\/")).test(c))return"GET"==b&&i.get&&(i.get&&(j=i.get(c,parseParams(d))),handleTestResponse(a,e,j)),"POST"==b&&(i.post&&(j=i.post(c,parseParams(d))),handleTestResponse(a,e,j)),"PUT"==b&&(i.put&&(j=i.put(c,parseParams(d))),handleTestResponse(a,e,j)),"DELETE"==b&&(i.delete&&(j=i.delete(c,parseParams(d))),handleTestResponse(a,e,j)),void 0}beforeRequest(a);var k=findSpinner(a);k.fadeIn("fast"),_remote.ajax({type:b,url:c,data:d,dataType:"text",beforeSend:function(){a.trigger("ic.beforeSend",a,d)},success:function(b,c,d){a.trigger("ic.success",a,b,c,d);var g=getTarget(a);g.data("ic-tmp-transition",a.attr("ic-transition")),processHeaders(a,d,f)&&e(b,c,a,d),g.data("ic-tmp-transition",null)},error:function(b,c,d){a.trigger("ic.error",a,b,c,d),log("An error occurred: "+d,_ERROR)},complete:function(){a.trigger("ic.complete",a,d),k.length>0?k.fadeOut("fast",function(){afterRequest(a)}):afterRequest(a)}})}function findSpinner(a){var b=null;if($(a).attr("ic-indicator"))b=$($(a).attr("ic-indicator")).first();else{var c=$(a).closest("[ic-indicator]");b=c.length>0?$(c.first().attr("ic-indicator")).first():$(a).find(".ic-indicator").first()}return b}function parseParams(a){var b,c=/([^&=]+)=?([^&]*)/g,d=function(a){return decodeURIComponent(a.replace(/\+/g," "))},e={};if(a)for("?"==a.substr(0,1)&&(a=a.substr(1));b=c.exec(a);){var f=d(b[1]),g=d(b[2]);void 0!==e[f]?($.isArray(e[f])||(e[f]=[e[f]]),e[f].push(g)):e[f]=g}return e}function processIncludes(a){var b="";return $(a).each(function(){b+="&"+$(this).serialize()}),b}function getParametersForElement(a){var b=getTarget(a),c="ic-request=true";return c+=a.closest("form").length>0?"&"+a.closest("form").serialize():"&"+a.serialize(),a.attr("id")&&(c+="&ic-element-id="+a.attr("id")),a.attr("name")&&(c+="&ic-element-name="+a.attr("name")),b.attr("ic-id")&&(c+="&ic-id="+b.attr("ic-id")),b.attr("ic-last-refresh")&&(c+="&ic-last-refresh="+b.attr("ic-last-refresh")),b.attr("ic-fingerprint")&&(c+="&ic-fingerprint="+b.attr("ic-fingerprint")),a.attr("ic-include")&&(c+=processIncludes(a.attr("ic-include"))),log("PARAMS: Returning parameters "+c+" for "+a),c}function maybeSetIntercoolerInfo(a){var b=getTarget(a);getIntercoolerId(b),maybeSetIntercoolerMetadata(b)}function updateIntercoolerMetaData(a){a.attr("ic-fingerprint",fp(a.text())),a.attr("ic-last-refresh",(new Date).getTime())}function maybeSetIntercoolerMetadata(a){a.attr("ic-fingerprint")||updateIntercoolerMetaData(a)}function getIntercoolerId(a){return a.attr("ic-id")||a.attr("ic-id",uuid()),a.attr("ic-id")}function withAttrs(a,b){$.each(a,function(a,c){b(c)})}function processSources(a){withAttrs(_SRC_ATTRS,function(b){$(a).is("["+b+"]")&&maybeSetIntercoolerInfo($(a)),$(a).find("["+b+"]").each(function(){maybeSetIntercoolerInfo($(this))})})}function startPolling(a){if(null==a.data("ic-poll-interval-id")){var b=parseInterval(a.attr("ic-poll"));if(null!=b){var c=icSelectorFor(a);log("POLL: Starting poll for element "+c,_DEBUG);var d=setInterval(function(){var b=$(c);a.trigger("ic.onPoll",b),0==b.length?(log("POLL: Clearing poll for element "+c,_DEBUG),clearTimeout(d)):updateElement(b)},b);a.data("ic-poll-interval-id",d)}}}function cancelPolling(a){null!=a.data("ic-poll-interval-id")&&clearTimeout(a.data("ic-poll-interval-id"))}function processPolling(a){$(a).is("[ic-poll]")&&(maybeSetIntercoolerInfo($(a)),startPolling(a)),$(a).find("[ic-poll]").each(function(){maybeSetIntercoolerInfo($(this)),startPolling($(this))})}function isDependent(a,b){return a&&b&&(0==b.indexOf(a)||0==a.indexOf(b))}function refreshDependencies(a,b){withAttrs(_SRC_ATTRS,function(c){$("["+c+"]").each(function(){isDependent(a,$(this).attr(c))?(null==b||$(b)[0]!=$(this)[0])&&updateElement($(this)):(isDependent(a,$(this).attr("ic-deps"))||"*"==$(this).attr("ic-deps"))&&(null==b||$(b)[0]!=$(this)[0])&&updateElement($(this))})})}function verbFor(a,b){return a.attr("ic-verb")?a.attr("ic-verb").toUpperCase():"ic-post-to"==b?"POST":"ic-put-to"==b?"PUT":"ic-delete-from"==b?"DELETE":"ic-get-from"==b?"GET":"POST"}function initButtonDestination(a,b){var c=$(a).attr(b);$(a).click(function(d){d.preventDefault(),handleRemoteRequest(a,verbFor(a,b),c,getParametersForElement(a),function(b){processICResponse(b,a),refreshDependencies(c)})})}function initInputDestination(a,b){var c=$(a).attr(b);$(a).change(function(){handleRemoteRequest(a,verbFor(a,b),c,getParametersForElement(a),function(b){processICResponse(b,a),refreshDependencies(c)})})}function initDestination(a,b){$(a).is("button, a, div, span")?initButtonDestination(a,b):$(a).is("input, select")&&initInputDestination(a,b)}function processDestinations(a){withAttrs(_DEST_ATTRS,function(b){$(a).is("["+b+"]")&&(maybeSetIntercoolerInfo($(a)),initDestination(a,b)),$(a).find("["+b+"]").each(function(){maybeSetIntercoolerInfo($(this)),initDestination($(this),b)})})}function isScrolledIntoView(a){var b=$(window).scrollTop(),c=b+$(window).height(),d=$(a).offset().top,e=d+$(a).height(),f=e>=b&&c>=d&&c>=e&&d>=b;return f}function handleLoadOn(a){$(a).attr("ic-load-on")&&("load"==$(a).attr("ic-load-on")?updateElement(a):"scrolled-into-view"==$(a).attr("ic-load-on")?(null==_scrollHandler&&(_scrollHandler=function(){$("[ic-load-on='scrolled-into-view']").each(function(){isScrolledIntoView($(this))&&1!=$(this).data("ic-scrolled-into-view-loaded")&&($(this).data("ic-scrolled-into-view-loaded",!0),updateElement($(this)))})},$(window).scroll(_scrollHandler)),setTimeout(function(){$(window).trigger("scroll")},100)):$(a).on($(a).attr("ic-load-on"),function(){updateElement(a)}))}function processLoadOn(a){handleLoadOn(a),$(a).find("[ic-load-on]").each(function(){handleLoadOn($(this))})}function processNodes(a){processSources(a),processPolling(a),processDestinations(a),processLoadOn(a)}function isTransition(a,b){return a.attr("ic-transition")==b||a.data("ic-tmp-transition")==b}function processICResponse(a,b){if(a&&/\S/.test(a)){log("IC RESPONSE: Received: "+a,_DEBUG);var c=getTarget(b),d=$("<div></div>").html(a);(fp(d.text())!=c.attr("ic-fingerprint")||"true"==c.attr("ic-always-update"))&&(isTransition(c,"none")?(c.html(a),updateIntercoolerMetaData(c),processNodes(c)):c.fadeOut("fast",function(){c.html(a),updateIntercoolerMetaData(c),processNodes(c),c.fadeIn("fast")})),d.remove()}}function updateElement(a){var b=a;if(b.attr("ic-src"))handleRemoteRequest(a,"GET",b.attr("ic-src"),getParametersForElement(b),function(a){processICResponse(a,b)});else if(b.attr("ic-prepend-from"))handleRemoteRequest(a,"GET",b.attr("ic-prepend-from"),getParametersForElement(b),function(a){var c=$(a);c.hide();var d=getTarget(b);if(log("target is "),log(d),d.prepend(c),c.fadeIn(),processNodes(c),d.attr("ic-limit-children")){var e=parseInt(b.attr("ic-limit-children"));b.children().length>e&&d.children().slice(e,d.children().length).remove()}});else if(b.attr("ic-append-from"))handleRemoteRequest(a,"GET",b.attr("ic-append-from"),getParametersForElement(b),function(a){var c=$(a);c.hide();var d=getTarget(b);if(d.append(c),c.fadeIn(),processNodes(c),d.attr("ic-limit-children")){var e=parseInt(b.attr("ic-limit-children"));d.children().length>e&&d.children().slice(0,d.children().length-e).remove()}});else if(b.attr("ic-style-src")){var c=b.attr("ic-style-src").split(":");handleRemoteRequest(a,"GET",c[1],getParametersForElement(b),function(a){b.css(c[0],a)})}else if(b.attr("ic-attr-src")){var d=b.attr("ic-attr-src").split(":");handleRemoteRequest(a,"GET",d[1],getParametersForElement(b),function(a){b.attr(d[0],a)})}}var _DEBUG=1,_INFO=2,_WARN=3,_ERROR=4,_SRC_ATTRS=["ic-src","ic-style-src","ic-attr-src","ic-prepend-from","ic-append-from"],_DEST_ATTRS=["ic-get-from","ic-post-to","ic-put-to","ic-delete-from"],_remote=$,_urlHandlers=[],_logger=window.console,_loggingLevel=null,_loggingGrep=null,_scrollHandler=null,CryptoJS=CryptoJS||function(a,b){var c={},d=c.lib={},e=function(){},f=d.Base={extend:function(a){e.prototype=this;var b=new e;return a&&b.mixIn(a),b.hasOwnProperty("init")||(b.init=function(){b.$super.init.apply(this,arguments)}),b.init.prototype=b,b.$super=this,b},create:function(){var a=this.extend();return a.init.apply(a,arguments),a},init:function(){},mixIn:function(a){for(var b in a)a.hasOwnProperty(b)&&(this[b]=a[b]);a.hasOwnProperty("toString")&&(this.toString=a.toString)},clone:function(){return this.init.prototype.extend(this)}},g=d.WordArray=f.extend({init:function(a,c){a=this.words=a||[],this.sigBytes=c!=b?c:4*a.length},toString:function(a){return(a||i).stringify(this)},concat:function(a){var b=this.words,c=a.words,d=this.sigBytes;if(a=a.sigBytes,this.clamp(),d%4)for(var e=0;a>e;e++)b[d+e>>>2]|=(c[e>>>2]>>>24-8*(e%4)&255)<<24-8*((d+e)%4);else if(65535<c.length)for(e=0;a>e;e+=4)b[d+e>>>2]=c[e>>>2];else b.push.apply(b,c);return this.sigBytes+=a,this},clamp:function(){var b=this.words,c=this.sigBytes;b[c>>>2]&=4294967295<<32-8*(c%4),b.length=a.ceil(c/4)},clone:function(){var a=f.clone.call(this);return a.words=this.words.slice(0),a},random:function(b){for(var c=[],d=0;b>d;d+=4)c.push(4294967296*a.random()|0);return new g.init(c,b)}}),h=c.enc={},i=h.Hex={stringify:function(a){var b=a.words;a=a.sigBytes;for(var c=[],d=0;a>d;d++){var e=b[d>>>2]>>>24-8*(d%4)&255;c.push((e>>>4).toString(16)),c.push((15&e).toString(16))}return c.join("")},parse:function(a){for(var b=a.length,c=[],d=0;b>d;d+=2)c[d>>>3]|=parseInt(a.substr(d,2),16)<<24-4*(d%8);return new g.init(c,b/2)}},j=h.Latin1={stringify:function(a){var b=a.words;a=a.sigBytes;for(var c=[],d=0;a>d;d++)c.push(String.fromCharCode(b[d>>>2]>>>24-8*(d%4)&255));return c.join("")},parse:function(a){for(var b=a.length,c=[],d=0;b>d;d++)c[d>>>2]|=(255&a.charCodeAt(d))<<24-8*(d%4);return new g.init(c,b)}},k=h.Utf8={stringify:function(a){try{return decodeURIComponent(escape(j.stringify(a)))}catch(b){throw Error("Malformed UTF-8 data")}},parse:function(a){return j.parse(unescape(encodeURIComponent(a)))}},l=d.BufferedBlockAlgorithm=f.extend({reset:function(){this._data=new g.init,this._nDataBytes=0},_append:function(a){"string"==typeof a&&(a=k.parse(a)),this._data.concat(a),this._nDataBytes+=a.sigBytes},_process:function(b){var c=this._data,d=c.words,e=c.sigBytes,f=this.blockSize,h=e/(4*f),h=b?a.ceil(h):a.max((0|h)-this._minBufferSize,0);if(b=h*f,e=a.min(4*b,e),b){for(var i=0;b>i;i+=f)this._doProcessBlock(d,i);i=d.splice(0,b),c.sigBytes-=e}return new g.init(i,e)},clone:function(){var a=f.clone.call(this);return a._data=this._data.clone(),a},_minBufferSize:0});d.Hasher=l.extend({cfg:f.extend(),init:function(a){this.cfg=this.cfg.extend(a),this.reset()},reset:function(){l.reset.call(this),this._doReset()},update:function(a){return this._append(a),this._process(),this},finalize:function(a){return a&&this._append(a),this._doFinalize()},blockSize:16,_createHelper:function(a){return function(b,c){return new a.init(c).finalize(b)}},_createHmacHelper:function(a){return function(b,c){return new m.HMAC.init(a,c).finalize(b)}}});var m=c.algo={};return c}(Math);!function(){var a=CryptoJS,b=a.lib,c=b.WordArray,d=b.Hasher,e=[],b=a.algo.SHA1=d.extend({_doReset:function(){this._hash=new c.init([1732584193,4023233417,2562383102,271733878,3285377520])},_doProcessBlock:function(a,b){for(var c=this._hash.words,d=c[0],f=c[1],g=c[2],h=c[3],i=c[4],j=0;80>j;j++){if(16>j)e[j]=0|a[b+j];else{var k=e[j-3]^e[j-8]^e[j-14]^e[j-16];e[j]=k<<1|k>>>31}k=(d<<5|d>>>27)+i+e[j],k=20>j?k+((f&g|~f&h)+1518500249):40>j?k+((f^g^h)+1859775393):60>j?k+((f&g|f&h|g&h)-1894007588):k+((f^g^h)-899497514),i=h,h=g,g=f<<30|f>>>2,f=d,d=k}c[0]=c[0]+d|0,c[1]=c[1]+f|0,c[2]=c[2]+g|0,c[3]=c[3]+h|0,c[4]=c[4]+i|0},_doFinalize:function(){var a=this._data,b=a.words,c=8*this._nDataBytes,d=8*a.sigBytes;return b[d>>>5]|=128<<24-d%32,b[(d+64>>>9<<4)+14]=Math.floor(c/4294967296),b[(d+64>>>9<<4)+15]=c,a.sigBytes=4*b.length,this._process(),this._hash},clone:function(){var a=d.clone.call(this);return a._hash=this._hash.clone(),a}});a.SHA1=d._createHelper(b),a.HmacSHA1=d._createHmacHelper(b)}();var _historySupport={stateCache:null,popping:!1,getRestorationURL:function(a){return a.attr("ic-restore-from")?a.attr("ic-restore-from"):window.location.pathname+window.location.search+window.location.hash},onPageLoad:function(){if(_historySupport.stateCache={"ic-setlocation":!0,"restore-from":window.location.pathname+window.location.search+window.location.hash,timestamp:(new Date).getTime()},null==window.onpopstate||1!=window.onpopstate["ic-on-pop-state-handler"]){var a=window.onpopstate;window.onpopstate=function(b){_historySupport.handlePop(b)||a&&a(b)},window.onpopstate["ic-on-pop-state-handler"]=!0}},pushUrl:function(a,b){log("IC HISTORY: pushing location "+a,_DEBUG);var c=getTarget(b),d=c.attr("id");if(null==d)return log("To support history for a given element, you must have a valid id attribute on the element",_ERROR),void 0;_historySupport.initHistory(b);var e={"ic-setlocation":!0,"id-to-restore":d.toString(),"restore-from":a,timestamp:(new Date).getTime()};b.trigger("ic.pushUrl",c,e),window.history.pushState(e,"",a)},initHistory:function(a){if(_historySupport.stateCache){var b=getTarget(a),c=b.attr("id");_historySupport.stateCache["id-to-restore"]=c.toString(),window.history.replaceState(_historySupport.stateCache),_historySupport.stateCache=null}},handlePop:function(a){var b=a.state;if(b&&b["ic-setlocation"]){var c=findById(b["id-to-restore"]),d=getParametersForElement(c);return d+="&ic-handle-pop=true",handleRemoteRequest(c,"GET",b["restore-from"],d,function(a){c.trigger("ic.handlePop",c,a),processICResponse(a,c)}),!0}return!1}};return $(function(){processNodes("body"),_historySupport.onPageLoad()}),{refresh:function(a){return updateElement(a),Intercooler},addURLHandler:function(a){if(!a.url)throw"Handlers must include a URL pattern";return _urlHandlers.push(a),Intercooler},setRemote:function(a){return _remote=a,Intercooler},setLogger:function(a,b,c){return _logger=a,b&&(_loggingLevel=b),c&&(_loggingGrep=c),Intercooler},log:function(a,b){return log(a,b),Intercooler},setLogLevel:function(a){return _loggingLevel=a,Intercooler},logLevels:{DEBUG:_DEBUG,INFO:_INFO,WARNING:_WARN,ERROR:_ERROR}}}();