297 lines
9.4 KiB
JavaScript
297 lines
9.4 KiB
JavaScript
/**
|
|
* smartupdater - jQuery Plugin
|
|
*
|
|
* Version - 4.0.beta
|
|
* Copyright (c) 2010 - 2011 Vadim Kiryukhin
|
|
* vkiryukhin @ gmail.com
|
|
*
|
|
* http://www.eslinstructor.net/smartupdater/
|
|
*
|
|
* Dual licensed under the MIT and GPL licenses:
|
|
* http://www.opensource.org/licenses/mit-license.php
|
|
* http://www.gnu.org/licenses/gpl.html
|
|
*
|
|
* USAGE:
|
|
*
|
|
* $("#myObject").smartupdater({
|
|
* url : "foo.php"
|
|
* }, function (data) {
|
|
* //process data here;
|
|
* }
|
|
* );
|
|
*
|
|
* Public functions:
|
|
* $("#myObject").smartupdater("stop")
|
|
* $("#myObject").smartupdater("restart");
|
|
* $("#myObject").smartupdater("setTimeout",timeout);
|
|
* $("#myObject").smartupdater("alterUrl"[,"foo.php"[,data]]);
|
|
* $("#myObject").smartupdater("alterCallback"[, foo]);
|
|
*
|
|
* Public Attributes:
|
|
* var status = $("#myObject").smartupdater("getState");
|
|
* var timeout = $("#myObject").smartupdater("getTimeout");
|
|
*
|
|
**/
|
|
|
|
(function($) {
|
|
|
|
|
|
var methods = {
|
|
|
|
init : function( options, callback) {
|
|
return this.each(function () {
|
|
var elem = this,
|
|
es = {};
|
|
|
|
elem.settings = jQuery.extend(true,{
|
|
url : '', // see jQuery.ajax for details
|
|
type : 'get', // see jQuery.ajax for details
|
|
data : '', // see jQuery.ajax for details
|
|
dataType : 'text', // see jQuery.ajax for details
|
|
|
|
minTimeout : 60000, // 1 minute
|
|
maxFailedRequests : 10, // max. number of consecutive ajax failures
|
|
maxFailedRequestsCb : false, // falure callback function
|
|
httpCache : false, // http cache
|
|
rCallback : false, // remote callback functions
|
|
selfStart : true, // start automatically after initializing
|
|
smartStop : { active: false, //disabled by default
|
|
monitorTimeout: 2500, // 2.5 seconds
|
|
minHeight: 1, // 1px
|
|
minWidth: 1 // 1px
|
|
}
|
|
|
|
}, options);
|
|
|
|
elem.smartupdaterStatus = {state:'',timeout:0};
|
|
|
|
es = elem.settings;
|
|
|
|
es.prevContent = '';
|
|
es.failedRequests = 0;
|
|
es.etag = '0';
|
|
es.lastModified = '0';
|
|
es.callback = callback;
|
|
es.origReq = {url:es.url,data:es.data,callback:callback};
|
|
es.stopFlag = false;
|
|
|
|
|
|
function start() {
|
|
|
|
/* check if element has been deleted and clean it up */
|
|
if(!$(elem).parents('body').length) {
|
|
clearInterval(elem.smartupdaterStatus.smartStop);
|
|
clearTimeout(elem.settings.h);
|
|
elem = {};
|
|
return;
|
|
}
|
|
|
|
$.ajax({
|
|
url : es.url,
|
|
type : es.type,
|
|
data : es.data,
|
|
dataType: es.dataType,
|
|
cache : false, // MUST be set to false to prevent IE caching issue.
|
|
|
|
success: function (data, statusText, xhr) {
|
|
|
|
var dataNotModified = false,
|
|
rCallback = false,
|
|
xSmart = jQuery.parseJSON(xhr.getResponseHeader("X-Smartupdater")),
|
|
xhrEtag, xhrLM;
|
|
|
|
if(xSmart) { // remote control
|
|
|
|
/* remote timeout */
|
|
es.minTimeout = xSmart.timeout ? xSmart.timeout : es.minTimeout;
|
|
|
|
/* remote callback */
|
|
rCallback = xSmart.callback ? xSmart.callback : false;
|
|
}
|
|
|
|
if(es.httpCache) { // http cache process here
|
|
|
|
xhrEtag = xhr.getResponseHeader("ETag");
|
|
xhrLM = xhr.getResponseHeader("Last-Modified");
|
|
|
|
dataNotModified = (es.etag == xhrEtag || es.lastModified == xhrLM) ? true : false;
|
|
es.etag = xhrEtag ? xhrEtag : es.etag;
|
|
es.lastModified = xhrLM ? xhrLM : es.lastModified;
|
|
}
|
|
|
|
if ( dataNotModified ||
|
|
es.prevContent == xhr.responseText ||
|
|
xhr.status == 304 ) { // data is not changed
|
|
|
|
if(!es.stopFlag) {
|
|
clearTimeout(es.h);
|
|
es.h = setTimeout(start, es.minTimeout);
|
|
}
|
|
|
|
} else { // data is changed
|
|
|
|
/* cache response data */
|
|
es.prevContent = xhr.responseText;
|
|
|
|
/* reset timeout */
|
|
if(!es.stopFlag) {
|
|
clearTimeout(es.h);
|
|
es.h = setTimeout(start, es.minTimeout);
|
|
}
|
|
|
|
/* run callback function */
|
|
if(es.rCallback && rCallback && es.rCallback.search(rCallback) != -1) {
|
|
window[rCallback](data);
|
|
} else {
|
|
es.callback(data);
|
|
}
|
|
}
|
|
|
|
elem.smartupdaterStatus.timeout = es.minTimeout;
|
|
es.failedRequests = 0;
|
|
},
|
|
|
|
error: function(xhr, textStatus, errorThrown) {
|
|
if ( ++es.failedRequests < es.maxFailedRequests ) {
|
|
|
|
/* increment falure counter and reset timeout */
|
|
if(!es.stopFlag) {
|
|
clearTimeout(es.h);
|
|
es.h = setTimeout(start, es.minTimeout);
|
|
elem.smartupdaterStatus.timeout = es.minTimeout;
|
|
}
|
|
|
|
} else {
|
|
|
|
/* stop smartupdater */
|
|
clearTimeout(es.h);
|
|
elem.smartupdaterStatus.state = 'OFF';
|
|
if( typeof(es.maxFailedRequestsCb)==='function') {
|
|
es.maxFailedRequestsCb(xhr, textStatus, errorThrown);
|
|
}
|
|
}
|
|
},
|
|
|
|
beforeSend: function(xhr, settings) {
|
|
|
|
if(es.httpCache) {
|
|
|
|
/* set http cache-related headers */
|
|
xhr.setRequestHeader("If-None-Match", es.etag );
|
|
xhr.setRequestHeader("If-Modified-Since", es.lastModified );
|
|
}
|
|
|
|
/* Feedback: Smartupdater sends it's current timeout to server */
|
|
xhr.setRequestHeader("X-Smartupdater", '{"timeout":"'+elem.smartupdaterStatus.timeout+'"}');
|
|
}
|
|
});
|
|
|
|
elem.smartupdaterStatus.state = 'ON';
|
|
}
|
|
|
|
es.fnStart = start;
|
|
|
|
if(es.selfStart) {
|
|
start();
|
|
}
|
|
|
|
if(es.smartStop.active) {
|
|
|
|
elem.smartupdaterStatus.smartStop = setInterval(function(){
|
|
|
|
// check if object has been deleted
|
|
if(!$(elem).parents('body').length) {
|
|
clearInterval(elem.smartupdaterStatus.smartStop);
|
|
clearTimeout(elem.settings.h);
|
|
elem = {};
|
|
return;
|
|
}
|
|
|
|
var $elem = $(elem);
|
|
var width = $elem.width(),
|
|
height = $elem.height(),
|
|
hidden = $elem.is(":hidden");
|
|
|
|
//element has been expanded, so smartupdater should be re-started.
|
|
if(!hidden && height > es.smartStop.minHeight && width > es.smartStop.minWidth
|
|
&& elem.smartupdaterStatus.state=="OFF") {
|
|
$elem.smartupdater("restart");
|
|
} else
|
|
//element has been minimized, so smartupdater should be stopped.
|
|
if( (hidden || height <= es.smartStop.minHeight || width <= es.smartStop.minWidth)
|
|
&& elem.smartupdaterStatus.state=="ON") {
|
|
$elem.smartupdater("stop");
|
|
|
|
}
|
|
|
|
},es.smartStop.monitorTimeout);
|
|
}
|
|
|
|
});
|
|
|
|
},// init()
|
|
|
|
stop : function () {
|
|
return this.each(function () {
|
|
this.settings.stopFlag = true;
|
|
clearTimeout(this.settings.h);
|
|
this.smartupdaterStatus.state = 'OFF';
|
|
});
|
|
},
|
|
|
|
restart : function () {
|
|
return this.each(function () {
|
|
this.settings.stopFlag = false;
|
|
clearTimeout(this.settings.h);
|
|
this.settings.failedRequests = 0;
|
|
this.settings.etag = "0";
|
|
this.settings.lastModified = "0";
|
|
this.settings.fnStart();
|
|
})
|
|
},
|
|
|
|
setTimeout : function (period) {
|
|
return this.each(function () {
|
|
clearTimeout(this.settings.h);
|
|
this.settings.minTimeout = period;
|
|
this.settings.fnStart();
|
|
});
|
|
},
|
|
|
|
alterCallback : function (callback) {
|
|
return this.each(function () {
|
|
this.settings.callback = callback ? callback : this.settings.origReq.callback;
|
|
});
|
|
},
|
|
|
|
alterUrl : function (url,data) {
|
|
return this.each(function () {
|
|
this.settings.url = url ? url : this.settings.origReq.url;
|
|
this.settings.data = data ? data : this.settings.origReq.data;
|
|
});
|
|
},
|
|
|
|
getTimeout : function () {
|
|
return this[0].smartupdaterStatus.timeout;
|
|
},
|
|
|
|
getState : function () {
|
|
return this[0].smartupdaterStatus.state;
|
|
}
|
|
|
|
}; //methods
|
|
|
|
jQuery.fn.smartupdater = function (options, callback) {
|
|
|
|
if ( methods[options] ) {
|
|
return methods[ options ].apply( this, Array.prototype.slice.call( arguments, 1 ));
|
|
} else if ( typeof options === 'object' || ! method ) {
|
|
return methods.init.apply( this, arguments );
|
|
} else {
|
|
$.error( 'Method ' + options + ' does not exist on jQuery.tooltip' );
|
|
}
|
|
};
|
|
|
|
|
|
})(jQuery);
|