From 313378ad2905fc07be00183b2acc61284c1c2c39 Mon Sep 17 00:00:00 2001 From: wei <> Date: Sun, 18 Jun 2006 05:02:24 +0000 Subject: Add TCallbackTimer --- framework/Web/Javascripts/extended/base.js | 3 +- framework/Web/Javascripts/js/ajax.js | 16 ++- framework/Web/Javascripts/js/prado.js | 5 +- framework/Web/Javascripts/prado/activecontrols3.js | 97 +++++++++++++- framework/Web/Javascripts/prado/ajax3.js | 2 +- framework/Web/UI/ActiveControls/TCallbackTimer.php | 142 +++++++++++++++++++++ 6 files changed, 259 insertions(+), 6 deletions(-) create mode 100644 framework/Web/UI/ActiveControls/TCallbackTimer.php (limited to 'framework/Web') diff --git a/framework/Web/Javascripts/extended/base.js b/framework/Web/Javascripts/extended/base.js index d88f82db..cdb7958c 100644 --- a/framework/Web/Javascripts/extended/base.js +++ b/framework/Web/Javascripts/extended/base.js @@ -33,7 +33,7 @@ Class.extend = function(base, definition) Copyright 2006, Dean Edwards License: http://creativecommons.org/licenses/LGPL/2.1/ */ -/* + var Base = function() { if (arguments.length) { if (this == window) { // cast an object to this class @@ -134,7 +134,6 @@ Base.implement = function(_interface) { if (_interface instanceof Function) _interface = _interface.prototype; this.prototype.extend(_interface); }; -*/ /* * Signals and Slots for Prototype: Easy custom javascript events diff --git a/framework/Web/Javascripts/js/ajax.js b/framework/Web/Javascripts/js/ajax.js index fea7e573..c2fb8f82 100644 --- a/framework/Web/Javascripts/js/ajax.js +++ b/framework/Web/Javascripts/js/ajax.js @@ -200,4 +200,18 @@ this.onInit(options);},doCallback:function(event,options) {var element=Event.findElement(event,'LI');this.index=element.autocompleteIndex;this.selectEntry();this.hide();Event.fireEvent(this.element,"change");},getUpdatedChoices:function() {options=new Array(this.getToken(),"__TAutComplete_onSuggest__");Prado.Callback(this.options.EventTarget,options,null,this.options);},onComplete:function(request,boundary) {result=Prado.Element.extractContent(request.responseText,boundary);if(typeof(result)=="string"&&result.length>0) -this.updateChoices(result);}}); \ No newline at end of file +this.updateChoices(result);}});Prado.WebUI.TCallbackTimer=Base.extend({count:0,timeout:0,constructor:function(options) +{this.options=Object.extend({Interval:1,DecayRate:0},options||{}) +this.onComplete=this.options.onComplete;Prado.WebUI.TCallbackTimer.register(this);},startTimer:function() +{this.options.onComplete=this.onRequestComplete.bind(this);setTimeout(this.onTimerEvent.bind(this),200);},stopTimer:function() +{(this.onComplete||Prototype.emptyFunction).apply(this,arguments);this.options.onComplete=undefined;clearTimeout(this.timer);this.timer=undefined;this.count=0;},onTimerEvent:function() +{this.options.params=this.timeout/1000;new Prado.CallbackRequest(this.options.ID,this.options);},onRequestComplete:function() +{(this.onComplete||Prototype.emptyFunction).apply(this,arguments);this.timer=setTimeout(this.onTimerEvent.bind(this),this.getNewTimeout())},getNewTimeout:function() +{switch(this.options.DecayType) +{case'Exponential':t=(Math.exp(this.options.DecayRate*this.count*this.options.Interval))-1;break;case'Linear':t=this.options.DecayRate*this.count*this.options.Interval;break;case'Quadratic':t=this.options.DecayRate*this.count*this.count*this.options.Interval;break;case'Cubic':t=this.options.DecayRate*this.count*this.count*this.count*this.options.Interval;break;default:t=0;} +this.timeout=(t+this.options.Interval)*1000;this.count++;return parseInt(this.timeout);}},{timers:{},register:function(timer) +{this.timers[timer.options.ID]=timer;},start:function(id) +{if(this.timers[id]) +this.timers[id].startTimer();},stop:function(id) +{if(this.timers[id]) +this.timers[id].stopTimer();}}); \ No newline at end of file diff --git a/framework/Web/Javascripts/js/prado.js b/framework/Web/Javascripts/js/prado.js index 38160fee..2cd37002 100644 --- a/framework/Web/Javascripts/js/prado.js +++ b/framework/Web/Javascripts/js/prado.js @@ -15,7 +15,10 @@ Function.prototype.bindEvent=function() Class.extend=function(base,definition) {var component=Class.create();Object.extend(component.prototype,base.prototype);if(definition) Object.extend(component.prototype,definition);return component;} -Signal={throwErrors:true,MT:function(){return true},connect:function(obj1,func1,obj2,func2,options){var options=Object.extend({connectOnce:false},options||{});if(typeof func1!='string'||typeof func2!='string')return;var sigObj=obj1||window;var slotObj=obj2||window;var signame=func1+'__signal_';var slotsname=func1+'__slots_';if(!sigObj[signame]){var slotFunc=function(){var args=arguments;var result=sigObj[signame].apply(sigObj,args);sigObj[slotsname].each(function(slot){try{if(slot&&slot[0]){slot[0][slot[1]].apply(slot[0],args);}}catch(e){if(Signal.throwErrors)throw e;}});return result;};(function(){sigObj[slotsname]=$A([]);sigObj[signame]=sigObj[func1]||Signal.MT;sigObj[func1]=slotFunc;})();} +var Base=function(){if(arguments.length){if(this==window){Base.prototype.extend.call(arguments[0],arguments.callee.prototype);}else{this.extend(arguments[0]);}}};Base.version="1.0.2";Base.prototype={extend:function(source,value){var extend=Base.prototype.extend;if(arguments.length==2){var ancestor=this[source];if((ancestor instanceof Function)&&(value instanceof Function)&&ancestor.valueOf()!=value.valueOf()&&/\bbase\b/.test(value)){var method=value;value=function(){var previous=this.base;this.base=ancestor;var returnValue=method.apply(this,arguments);this.base=previous;return returnValue;};value.valueOf=function(){return method;};value.toString=function(){return String(method);};} +return this[source]=value;}else if(source){var _prototype={toSource:null};var _protected=["toString","valueOf"];if(Base._prototyping)_protected[2]="constructor";for(var i=0;(name=_protected[i]);i++){if(source[name]!=_prototype[name]){extend.call(this,name,source[name]);}} +for(var name in source){if(!_prototype[name]){extend.call(this,name,source[name]);}}} +return this;},base:function(){}};Base.extend=function(_instance,_static){var extend=Base.prototype.extend;if(!_instance)_instance={};Base._prototyping=true;var _prototype=new this;extend.call(_prototype,_instance);var constructor=_prototype.constructor;_prototype.constructor=this;delete Base._prototyping;var klass=function(){if(!Base._prototyping)constructor.apply(this,arguments);this.constructor=klass;};klass.prototype=_prototype;klass.extend=this.extend;klass.implement=this.implement;klass.toString=function(){return String(constructor);};extend.call(klass,_static);var object=constructor?klass:_prototype;if(object.init instanceof Function)object.init();return object;};Base.implement=function(_interface){if(_interface instanceof Function)_interface=_interface.prototype;this.prototype.extend(_interface);};Signal={throwErrors:true,MT:function(){return true},connect:function(obj1,func1,obj2,func2,options){var options=Object.extend({connectOnce:false},options||{});if(typeof func1!='string'||typeof func2!='string')return;var sigObj=obj1||window;var slotObj=obj2||window;var signame=func1+'__signal_';var slotsname=func1+'__slots_';if(!sigObj[signame]){var slotFunc=function(){var args=arguments;var result=sigObj[signame].apply(sigObj,args);sigObj[slotsname].each(function(slot){try{if(slot&&slot[0]){slot[0][slot[1]].apply(slot[0],args);}}catch(e){if(Signal.throwErrors)throw e;}});return result;};(function(){sigObj[slotsname]=$A([]);sigObj[signame]=sigObj[func1]||Signal.MT;sigObj[func1]=slotFunc;})();} var con=(sigObj[slotsname].length>0)?(options.connectOnce?!sigObj[slotsname].any(function(slot){return(slot[0]==slotObj&&slot[1]==func2)}):true):true;if(con){sigObj[slotsname].push([slotObj,func2]);}},connectOnce:function(obj1,func1,obj2,func2,options){Signal.connect(obj1,func1,obj2,func2,Object.extend(options||{},{connectOnce:true}))},disconnect:function(obj1,func1,obj2,func2,options){var options=Object.extend({disconnectAll:false},options||{});if(typeof func1!='string'||typeof func2!='string')return;var sigObj=obj1||window;var slotObj=obj2||window;var signame=func1+'__signal_';var slotsname=func1+'__slots_';if(sigObj[slotsname]){if(options.disconnectAll){sigObj[slotsname]=sigObj[slotsname].collect(function(slot){if(slot[0]==slotObj&&slot[1]==func2){slot[0]=null;return null;}else{return slot;}}).compact();}else{var idx=-1;sigObj[slotsname]=sigObj[slotsname].collect(function(slot,index){if(slot[0]==slotObj&&slot[1]==func2&&idx<0){idx=index;slot[0]=null;return null;}else{return slot;}}).compact();}}},disconnectAll:function(obj1,func1,obj2,func2,options){Signal.disconnect(obj1,func1,obj2,func2,Object.extend(options||{},{disconnectAll:true}))}} Object.extend(String.prototype,{gsub:function(pattern,replacement){var result='',source=this,match;replacement=arguments.callee.prepareReplacement(replacement);while(source.length>0){if(match=source.match(pattern)){result+=source.slice(0,match.index);result+=(replacement(match)||'').toString();source=source.slice(match.index+match[0].length);}else{result+=source,source='';}} return result;},sub:function(pattern,replacement,count){replacement=this.gsub.prepareReplacement(replacement);count=count===undefined?1:count;return this.gsub(pattern,function(match){if(--count<0)return match[0];return replacement(match);});},scan:function(pattern,iterator){this.gsub(pattern,iterator);return this;},truncate:function(length,truncation){length=length||30;truncation=truncation===undefined?'...':truncation;return this.length>length?this.slice(0,length-truncation.length)+truncation:this;},strip:function(){return this.replace(/^\s+/,'').replace(/\s+$/,'');},stripTags:function(){return this.replace(/<\/?[^>]+>/gi,'');},stripScripts:function(){return this.replace(new RegExp(Prototype.ScriptFragment,'img'),'');},extractScripts:function(){var matchAll=new RegExp(Prototype.ScriptFragment,'img');var matchOne=new RegExp(Prototype.ScriptFragment,'im');return(this.match(matchAll)||[]).map(function(scriptTag){return(scriptTag.match(matchOne)||['',''])[1];});},evalScripts:function(){return this.extractScripts().map(function(script){return eval(script)});},escapeHTML:function(){var div=document.createElement('div');var text=document.createTextNode(this);div.appendChild(text);return div.innerHTML;},unescapeHTML:function(){var div=document.createElement('div');div.innerHTML=this.stripTags();return div.childNodes[0]?div.childNodes[0].nodeValue:'';},toQueryParams:function(){var pairs=this.match(/^\??(.*)$/)[1].split('&');return pairs.inject({},function(params,pairString){var pair=pairString.split('=');params[pair[0]]=pair[1];return params;});},toArray:function(){return this.split('');},camelize:function(){var oStringList=this.split('-');if(oStringList.length==1)return oStringList[0];var camelizedString=this.indexOf('-')==0?oStringList[0].charAt(0).toUpperCase()+oStringList[0].substring(1):oStringList[0];for(var i=1,len=oStringList.length;i 0) this.updateChoices(result); } -}); \ No newline at end of file +}); + +/** + * Callback Timer class. + */ +Prado.WebUI.TCallbackTimer = Base.extend( +{ + count : 0, + timeout : 0, + + constructor : function(options) + { + this.options = Object.extend( + { + Interval : 1, + DecayRate : 0 + }, options || {}) + + this.onComplete = this.options.onComplete; + Prado.WebUI.TCallbackTimer.register(this); + }, + + startTimer : function() + { + this.options.onComplete = this.onRequestComplete.bind(this); + setTimeout(this.onTimerEvent.bind(this), 200); + }, + + stopTimer : function() + { + (this.onComplete || Prototype.emptyFunction).apply(this, arguments); + this.options.onComplete = undefined; + clearTimeout(this.timer); + this.timer = undefined; + this.count = 0; + }, + + onTimerEvent : function() + { + this.options.params = this.timeout/1000; + new Prado.CallbackRequest(this.options.ID, this.options); + }, + + onRequestComplete : function() + { + (this.onComplete || Prototype.emptyFunction).apply(this, arguments); + this.timer = setTimeout(this.onTimerEvent.bind(this), this.getNewTimeout()) + }, + + getNewTimeout : function() + { + switch(this.options.DecayType) + { + case 'Exponential': + t = (Math.exp(this.options.DecayRate*this.count*this.options.Interval))-1; + break; + case 'Linear': + t = this.options.DecayRate*this.count*this.options.Interval; + break; + case 'Quadratic': + t = this.options.DecayRate*this.count*this.count*this.options.Interval; + break; + case 'Cubic': + t = this.options.DecayRate*this.count*this.count*this.count*this.options.Interval; + break; + default : t = 0; + } + this.timeout = (t + this.options.Interval)*1000; + this.count++; + return parseInt(this.timeout); + } +}, +//class methods +{ + timers : {}, + + register : function(timer) + { + this.timers[timer.options.ID] = timer; + }, + + start : function(id) + { + if(this.timers[id]) + this.timers[id].startTimer(); + }, + + stop : function(id) + { + if(this.timers[id]) + this.timers[id].stopTimer(); + } +}); + + + diff --git a/framework/Web/Javascripts/prado/ajax3.js b/framework/Web/Javascripts/prado/ajax3.js index adf8534a..bae60d89 100644 --- a/framework/Web/Javascripts/prado/ajax3.js +++ b/framework/Web/Javascripts/prado/ajax3.js @@ -11,7 +11,7 @@ Object.extend(Ajax.Request.prototype, { var event = Ajax.Request.Events[readyState]; var transport = this.transport, json = this.getHeaderData(Prado.CallbackRequest.DATA_HEADER); - + if (event == 'Complete') { try diff --git a/framework/Web/UI/ActiveControls/TCallbackTimer.php b/framework/Web/UI/ActiveControls/TCallbackTimer.php new file mode 100644 index 00000000..7f1aa692 --- /dev/null +++ b/framework/Web/UI/ActiveControls/TCallbackTimer.php @@ -0,0 +1,142 @@ + + * @link http://www.pradosoft.com/ + * @copyright Copyright © 2006 PradoSoft + * @license http://www.pradosoft.com/license/ + * @version $Revision: $ : $ + * @package System.Web.UI.ActiveControls + */ + +/** + * TCallbackTimer class. + * + * TCallbackTimer sends callback request every {@link setInterval Interval} seconds. + * Upon each callback request, the {@link onCallback OnCallback} event is raised. + * + * The intervals between each request can be increased when the browser is inactive + * by changing the {@link setDecayRate DecayRate} to a positive number. The + * default decay rate, {@link setDecayType DecayType}, is linear and can be changed to + * 'Exponential', 'Linear', 'Quadratic' or 'Cubic'. + * + * @author Wei Zhuo + * @version : $ Mon Jun 19 21:29:42 EST 2006 $ + * @package System.Web.UI.ActiveControls + * @since 3.0 + */ +class TCallbackTimer extends TCallback +{ + /** + * @return float seconds between callback requests. Default is 1 second. + */ + public function getInterval() + { + return $this->getViewState('Interval', 1); + } + + /** + * @param float seconds between callback requests, must be a positive number, default is 1 second. + */ + public function setInterval($value) + { + $interval = TPropertyValue::ensureFloat($value); + if($interval <= 0) + throw new TConfigurationException('callback_interval_be_positive', $this->getID()); + $this->setViewState('Interval', $interval, 1); + } + + /** + * Gets the decay rate between callbacks. Default is 0; + * @return float decay rate between callbacks. + */ + public function getDecayRate() + { + return $this->getViewState('Decay', 0); + } + + /** + * Sets the decay rate between callback. Default is 0; + * @param float decay rate between callbacks. + */ + public function setDecayRate($value) + { + $decay = TPropertyValue::ensureFloat($value); + if($decay < 0) + throw new TConfigurationException('callback_decay_be_not_negative', $this->getID()); + $this->setViewState('Decay', $decay); + } + + /** + * @param string Decay type, allows 'Exponential', 'Linear', 'Quadratic' and 'Cubic'. Default is 'Linear'. + */ + public function setDecayType($value) + { + $this->setViewState('DecayType', TPropertyValue::ensureEnum($value, + 'Exponential', 'Linear', 'Quadratic', 'Cubic'), 'Linear'); + } + + /** + * @return string decay type, default is 'Linear', valid types are 'Exponential', 'Linear', 'Quadratic' and 'Cubic'. + */ + public function getDecayType() + { + return $this->getViewState('DecayType', 'Linear'); + } + + /** + * Registers the javascript code to start the timer. + */ + public function startTimer() + { + $id = $this->getClientID(); + $code = "Prado.WebUI.TCallbackTimer.start('{$id}');"; + $cs = $this->getPage()->getClientScript(); + $cs->registerEndScript("{$id}:start", $code); + } + + /** + * Registers the javascript code to stop the timer. + */ + public function stopTimer() + { + $id = $this->getClientID(); + $code = "Prado.WebUI.TCallbackTimer.stop('{$id}');"; + $cs = $this->getPage()->getClientScript(); + $cs->registerEndScript("{$id}:stop", $code); + } + + /** + * @return array list of timer options for client-side. + */ + protected function getTimerOptions() + { + $options['ID'] = $this->getClientID(); + $options['Interval'] = $this->getInterval(); + $options['DecayRate'] = $this->getDecayRate(); + $options['DecayType'] = $this->getDecayType(); + return $options; + } + + /** + * Registers the javascript code for initializing the active control. + * @param THtmlWriter the renderer. + */ + public function render($writer) + { + parent::render($writer); + $this->getActiveControl()->registerCallbackClientScript( + $this->getClientClassName(), $this->getTimerOptions()); + } + + /** + * @return string corresponding javascript class name for this TActiveButton. + */ + protected function getClientClassName() + { + return 'Prado.WebUI.TCallbackTimer'; + } +} + +?> \ No newline at end of file -- cgit v1.2.3