diff options
Diffstat (limited to 'framework/Web/Javascripts')
| -rw-r--r-- | framework/Web/Javascripts/TJavaScript.php | 15 | ||||
| -rw-r--r-- | framework/Web/Javascripts/js/ajax.js | 53 | ||||
| -rw-r--r-- | framework/Web/Javascripts/js/prado.js | 4 | ||||
| -rw-r--r-- | framework/Web/Javascripts/js/validator.js | 3 | ||||
| -rw-r--r-- | framework/Web/Javascripts/prado/ajax3.js | 213 | ||||
| -rw-r--r-- | framework/Web/Javascripts/prado/validation3.js | 9 | 
6 files changed, 234 insertions, 63 deletions
| diff --git a/framework/Web/Javascripts/TJavaScript.php b/framework/Web/Javascripts/TJavaScript.php index 75fc2438..0f6414ec 100644 --- a/framework/Web/Javascripts/TJavaScript.php +++ b/framework/Web/Javascripts/TJavaScript.php @@ -24,6 +24,11 @@  class TJavaScript
  {
  	/**
 +	 * @var TJSON JSON decoder and encoder instance
 +	 */
 +	private static $_json;
 +	
 +	/**
  	 * Renders a list of javascript files
  	 * @param array URLs to the javascript files
  	 * @return string rendering result
 @@ -191,8 +196,9 @@ class TJavaScript  	 */
  	public static function jsonEncode($value)
  	{
 -		Prado::using('System.Web.Javascripts.TJSON');
 -		return TJSON::encode($value);
 +		if(is_null(self::$_json))
 +			self::$_json = Prado::createComponent('System.Web.Javascripts.TJSON');
 +		return self::$_json->encode($value);
  	}
  	/**
 @@ -203,8 +209,9 @@ class TJavaScript  	 */
  	public static function jsonDecode($value)
  	{
 -		Prado::using('System.Web.Javascripts.TJSON');
 -		return TJSON::decode($value);
 +		if(is_null(self::$_json))
 +			self::$_json = Prado::createComponent('System.Web.Javascripts.TJSON');
 +		return self::$_json->decode($value);
  	}
  }
 diff --git a/framework/Web/Javascripts/js/ajax.js b/framework/Web/Javascripts/js/ajax.js index 2b509d61..6ae737bf 100644 --- a/framework/Web/Javascripts/js/ajax.js +++ b/framework/Web/Javascripts/js/ajax.js @@ -20,28 +20,53 @@ this.transport=Ajax.getTransport();this.setOptions(options);var onComplete=this.  response=response.stripScripts();if(receiver){if(this.options.insertion){new this.options.insertion(receiver,response);}else{Element.update(receiver,response);}}  if(this.responseIsSuccess()){if(this.onComplete)  setTimeout(this.onComplete.bind(this),10);}}});Ajax.PeriodicalUpdater=Class.create();Ajax.PeriodicalUpdater.prototype=Object.extend(new Ajax.Base(),{initialize:function(container,url,options){this.setOptions(options);this.onComplete=this.options.onComplete;this.frequency=(this.options.frequency||2);this.decay=(this.options.decay||1);this.updater={};this.container=container;this.url=url;this.start();},start:function(){this.options.onComplete=this.updateComplete.bind(this);this.onTimerEvent();},stop:function(){this.updater.onComplete=undefined;clearTimeout(this.timer);(this.onComplete||Prototype.emptyFunction).apply(this,arguments);},updateComplete:function(request){if(this.options.decay){this.decay=(request.responseText==this.lastText?this.decay*this.options.decay:1);this.lastText=request.responseText;} -this.timer=setTimeout(this.onTimerEvent.bind(this),this.decay*this.frequency*1000);},onTimerEvent:function(){this.updater=new Ajax.Updater(this.container,this.url,this.options);}});Prado.Callback=Class.create();Object.extend(Prado.Callback,{FIELD_CALLBACK_TARGET:'PRADO_CALLBACK_TARGET',FIELD_CALLBACK_PARAMETER:'PRADO_CALLBACK_PARAMETER',PostDataLoaders:['PRADO_PAGESTATE'],Exception:{"on505":function(request,transport,data) -{var msg='HTTP '+transport.status+" with response";Logger.error(msg,transport.responseText);this.logException(data);},onComplete:function(request,transport,data) -{if(transport.status!=505) -{var msg='HTTP '+transport.status+" with response : \n";msg+=transport.responseText+"\n";msg+="Data : \n"+inspect(data);Logger.warn(msg);}},formatException:function(e) +this.timer=setTimeout(this.onTimerEvent.bind(this),this.decay*this.frequency*1000);},onTimerEvent:function(){this.updater=new Ajax.Updater(this.container,this.url,this.options);}});Object.extend(Ajax.Request.prototype,{respondToReadyState:function(readyState) +{var event=Ajax.Request.Events[readyState];var transport=this.transport,json=this.getHeaderData(Prado.CallbackRequest.DATA_HEADER);if(event=='Complete') +{Ajax.Responders.dispatch('on'+transport.status,this,transport,json);Prado.CallbackRequest.dispatchActions(this.getHeaderData(Prado.CallbackRequest.ACTION_HEADER));try{(this.options['on'+this.transport.status]||this.options['on'+(this.responseIsSuccess()?'Success':'Failure')]||Prototype.emptyFunction)(transport,json);}catch(e){this.dispatchException(e);} +if((this.header('Content-type')||'').match(/^text\/javascript/i)) +this.evalResponse();} +try{(this.options['on'+event]||Prototype.emptyFunction)(transport,json);Ajax.Responders.dispatch('on'+event,this,transport,json);}catch(e){this.dispatchException(e);} +if(event=='Complete') +this.transport.onreadystatechange=Prototype.emptyFunction;},getHeaderData:function(name) +{try +{var json=this.header(name);return eval('('+json+')');} +catch(e) +{if(typeof(json)=="string") +{Logger.info("using json") +return Prado.CallbackRequest.decode(json);}}}});Prado.CallbackRequest=Class.create();Object.extend(Prado.CallbackRequest,{FIELD_CALLBACK_TARGET:'PRADO_CALLBACK_TARGET',FIELD_CALLBACK_PARAMETER:'PRADO_CALLBACK_PARAMETER',PostDataLoaders:['PRADO_PAGESTATE'],DATA_HEADER:'X-PRADO-DATA',ACTION_HEADER:'X-PRADO-ACTIONS',ERROR_HEADER:'X-PRADO-ERROR',dispatchActions:function(actions) +{actions.each(this.__run);},__run:function(command) +{for(var method in command) +{if(command[method][0]) +{var id=command[method][0];if($(id)||id.indexOf("[]")>-1) +method.toFunction().apply(this,command[method]);else if(typeof(Logger)!="undefined") +{Logger.error("Error in executing callback response:","Unable to find HTML element with ID '"+id+"' before executing "+method+"().");}}}},Exception:{"on505":function(request,transport,data) +{var e=request.getHeaderData(Prado.CallbackRequest.ERROR_HEADER);Logger.error("Callback Server Error "+e.code,this.formatException(e));},'on200':function(request,transport,data) +{if(transport.status<500) +{var msg='HTTP '+transport.status+" with response : \n";msg+=transport.responseText+"\n";msg+="Data : \n"+inspect(data)+"\n";msg+="Actions : \n";request.getHeaderData(Prado.CallbackRequest.ACTION_HEADER).each(function(action) +{msg+=inspect(action)+"\n";}) +Logger.warn(msg);}},onException:function(e) +{Logger.error('Uncaught Callback Client Exception:',e);},formatException:function(e)  {var msg=e.type+" with message \""+e.message+"\"";msg+=" in "+e.file+"("+e.line+")\n";msg+="Stack trace:\n";var trace=e.trace;for(var i=0;i<trace.length;i++)  {msg+="  #"+i+" "+trace[i].file;msg+="("+trace[i].line+"): ";msg+=trace[i]["class"]+"->"+trace[i]["function"]+"()"+"\n";} -return msg;},logException:function(e) -{Logger.error("Callback Request Error "+e.code,this.formatException(e));}},encode:function(data) -{Prado.JSON.stringify(data);},decode:function(data) +msg+=e.version+" "+e.time+"\n";return msg;}},encode:function(data) +{return Prado.JSON.stringify(data);},decode:function(data)  {return Prado.JSON.parse(data);}})  Event.OnLoad(function()  {if(typeof Logger!="undefined") -Ajax.Responders.register(Prado.Callback.Exception);});Prado.Callback.prototype={url:window.location.href,options:{},id:null,parameters:null,initialize:function(id,parameters,onSuccess,options) -{this.options=options||{};this.id=id;this.parameters=parameters;var request={postBody:this._getPostData(),onSuccess:this._onSuccess.bind(this)} -Object.extend(this.options||{},request);new Ajax.Request(this.url,this.options);},_getPostData:function() -{var data={};Prado.Callback.PostDataLoaders.each(function(name) +Ajax.Responders.register(Prado.CallbackRequest.Exception);});Prado.CallbackRequest.prototype={url:window.location.href,options:{},id:null,request:null,initialize:function(id,options) +{this.options=options||{};this.id=id;var request={postBody:this._getPostData(),parameters:''} +Object.extend(this.options||{},request);if(this.options.CausesValidation!=false&&typeof(Prado.Validation)!="undefined") +{var form=this.options.Form||Prado.Validation.getForm();if(Prado.Validation.validate(form,this.options.ValidationGroup,this)==false) +return;} +this.request=new Ajax.Request(this.url,this.options);},_getPostData:function() +{var data={};Prado.CallbackRequest.PostDataLoaders.each(function(name)  {$A(document.getElementsByName(name)).each(function(element)  {var value=$F(element);if(typeof(value)!="undefined")  data[name]=value;})}) -if(typeof(this.parameters)!="undefined") -data[Prado.Callback.FIELD_CALLBACK_PARAMETER]=Prado.Callback.encode(this.parameters);data[Prado.Callback.FIELD_CALLBACK_TARGET]=this.id;return $H(data).toQueryString();},_onSuccess:function(response,transport,json) -{}} +if(typeof(this.options.params)!="undefined") +data[Prado.CallbackRequest.FIELD_CALLBACK_PARAMETER]=Prado.CallbackRequest.encode(this.options.params);data[Prado.CallbackRequest.FIELD_CALLBACK_TARGET]=this.id;return $H(data).toQueryString();}} +Prado.Callback=function(UniqueID,parameter,onSuccess,options) +{var callback={'params':parameter||'','onSuccess':onSuccess||Prototype.emptyFunction,'CausesValidation':true};Object.extend(callback,options||{});new Prado.CallbackRequest(UniqueID,callback);return false;}  Array.prototype.______array='______array';Prado.JSON={org:'http://www.JSON.org',copyright:'(c)2005 JSON.org',license:'http://www.crockford.com/JSON/license.html',stringify:function(arg){var c,i,l,s='',v;switch(typeof arg){case'object':if(arg){if(arg.______array=='______array'){for(i=0;i<arg.length;++i){v=this.stringify(arg[i]);if(s){s+=',';}  s+=v;}  return'['+s+']';}else if(typeof arg.toString!='undefined'){for(i in arg){v=arg[i];if(typeof v!='undefined'&&typeof v!='function'){v=this.stringify(v);if(s){s+=',';} diff --git a/framework/Web/Javascripts/js/prado.js b/framework/Web/Javascripts/js/prado.js index 498a6cf7..d80f984d 100644 --- a/framework/Web/Javascripts/js/prado.js +++ b/framework/Web/Javascripts/js/prado.js @@ -256,7 +256,7 @@ selection[method](isList?element:el,value);},click:function(element)  {var el=$(element);if(!el)return;if(document.createEvent)  {var evt=document.createEvent('HTMLEvents');evt.initEvent('click',true,true);el.dispatchEvent(evt);}  else if(el.fireEvent) -{el.fireEvent('onclick');if(typeof(el.onclick)=="function") +{el.fireEvent('onclick');if(isFunction(el.onclick))  el.onclick();}},setAttribute:function(element,attribute,value)  {var el=$(element);if(attribute=="disabled"&&value==false)  el.removeAttribute(attribute);else @@ -265,7 +265,7 @@ el.setAttribute(attribute,value);},setOptions:function(element,options)  {while(el.length>0)  el.remove(0);for(var i=0;i<options.length;i++)  el.options[el.options.length]=new Option(options[i][0],options[i][1]);}},focus:function(element) -{var obj=$(element);if(typeof(obj)!="undefined"&&typeof(obj.focus)!="undefined") +{var obj=$(element);if(isObject(obj)&&isdef(obj.focus))  setTimeout(function(){obj.focus();},100);return false;}}  Prado.Element.Selection={inputValue:function(el,value)  {switch(el.type.toLowerCase()) diff --git a/framework/Web/Javascripts/js/validator.js b/framework/Web/Javascripts/js/validator.js index 66b48866..41b40fcd 100644 --- a/framework/Web/Javascripts/js/validator.js +++ b/framework/Web/Javascripts/js/validator.js @@ -3,7 +3,8 @@ Prado.Validation=Class.create();Object.extend(Prado.Validation,{managers:{},vali  {if(this.managers[formID])  {return this.managers[formID].validate(groupID,invoker);}  else -{throw new Error("Form '"+form+"' is not registered with Prado.Validation");}},isValid:function(formID,groupID) +{throw new Error("Form '"+form+"' is not registered with Prado.Validation");}},getForm:function() +{var keys=$H(this.managers).keys();return keys[0];},isValid:function(formID,groupID)  {if(this.managers[formID])  return this.managers[formID].isValid(groupID);return true;},addValidator:function(formID,validator)  {if(this.managers[formID]) diff --git a/framework/Web/Javascripts/prado/ajax3.js b/framework/Web/Javascripts/prado/ajax3.js index ded63104..1cffbd73 100644 --- a/framework/Web/Javascripts/prado/ajax3.js +++ b/framework/Web/Javascripts/prado/ajax3.js @@ -1,27 +1,131 @@  /**
 + * Override Prototype's response implementation.
 + */
 +Object.extend(Ajax.Request.prototype,
 +{
 +	/**
 +	 * Customize the response, dispatch onXXX response code events, and
 +	 * tries to execute response actions (javascript statements).
 +	 */
 +	respondToReadyState : function(readyState) 
 +	{
 +	    var event = Ajax.Request.Events[readyState];
 +	    var transport = this.transport, json = this.getHeaderData(Prado.CallbackRequest.DATA_HEADER);
 +		
 +	    if (event == 'Complete') 
 +	    {
 +			Ajax.Responders.dispatch('on' + transport.status, this, transport, json);
 +			Prado.CallbackRequest.dispatchActions(this.getHeaderData(Prado.CallbackRequest.ACTION_HEADER));
 +	      
 +	      try {
 +	        (this.options['on' + this.transport.status]
 +	         || this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')]
 +	         || Prototype.emptyFunction)(transport, json);
 +	  	      } catch (e) {
 +	        this.dispatchException(e);
 +	      }
 +	      if ((this.header('Content-type') || '').match(/^text\/javascript/i))
 +	        this.evalResponse();
 +	    }
 +	    
 +	    try {
 +	      (this.options['on' + event] || Prototype.emptyFunction)(transport, json);
 +	      Ajax.Responders.dispatch('on' + event, this, transport, json);
 +	    } catch (e) {
 +	      this.dispatchException(e);
 +	    }
 +	    
 +	    /* Avoid memory leak in MSIE: clean up the oncomplete event handler */
 +	    if (event == 'Complete')
 +	      this.transport.onreadystatechange = Prototype.emptyFunction;
 +	},
 +	
 +	/**
 +	 * Gets header data assuming JSON encoding.
 +	 * @param string header name
 +	 * @return object header data as javascript structures.
 +	 */
 +	getHeaderData : function(name)
 +	{
 +		try 
 +		{
 +			var json = this.header(name);
 +			return eval('(' + json + ')');
 +		} 
 +		catch (e) 
 +		{
 +			if(typeof(json) == "string")
 +			{
 +				Logger.info("using json")
 +				return Prado.CallbackRequest.decode(json);
 +			}
 +		}
 +	}
 +});
 +
 +/**
   * Prado Callback client-side request handler.
   */
 -Prado.Callback = Class.create();
 +Prado.CallbackRequest = Class.create();
  /**
   * Static definitions.
   */
 -Object.extend(Prado.Callback,
 +Object.extend(Prado.CallbackRequest,
  {
  	/**
  	 * Callback request target POST field name.
  	 */
  	FIELD_CALLBACK_TARGET : 'PRADO_CALLBACK_TARGET',
 -	
  	/**
  	 * Callback request parameter POST field name.
  	 */
  	FIELD_CALLBACK_PARAMETER : 'PRADO_CALLBACK_PARAMETER',
 -	
  	/**
  	 * List of form fields that will be collected during callback.
  	 */
  	PostDataLoaders : ['PRADO_PAGESTATE'],
 +	/**
 +	 * Response data header name.
 +	 */
 +	DATA_HEADER : 'X-PRADO-DATA',
 +	/**
 +	 * Response javascript execution statement header name.
 +	 */
 +	ACTION_HEADER : 'X-PRADO-ACTIONS',
 +	/**
 +	 * Response errors/exceptions header name.
 +	 */
 +	ERROR_HEADER : 'X-PRADO-ERROR',
 +	
 +	/**
 +	 * Dispatch callback response actions.
 +	 */
 +	dispatchActions : function(actions)
 +	{
 +		actions.each(this.__run);
 +	},
 +	
 +	/**
 +	 * Prase and evaluate a Callback clien-side action
 +	 */
 +	__run : function(command)
 +	{
 +		for(var method in command)
 +		{
 +			if(command[method][0])
 +			{
 +				var id = command[method][0];
 +				if($(id) || id.indexOf("[]") > -1)
 +					method.toFunction().apply(this,command[method]);
 +				else if(typeof(Logger) != "undefined")
 +				{
 +					Logger.error("Error in executing callback response:", 
 +					"Unable to find HTML element with ID '"+id+"' before executing "+method+"().");		
 +				}
 +			}
 +		}
 +	},
  	/**
  	 * Respond to Prado Callback request exceptions.
 @@ -32,27 +136,40 @@ Object.extend(Prado.Callback,  		 * Server returns 505 exception. Just log it.
  		 */
  		"on505" : function(request, transport, data)
 -		{		
 -			var msg = 'HTTP '+transport.status+" with response";
 -			Logger.error(msg, transport.responseText);
 -			this.logException(data);
 +		{	
 +			var e = request.getHeaderData(Prado.CallbackRequest.ERROR_HEADER);
 +			Logger.error("Callback Server Error "+e.code, this.formatException(e));
  		},
  		/**
  		 * Callback OnComplete event,logs reponse and data to console.
  		 */
 -		onComplete : function(request, transport, data)
 +		'on200' : function(request, transport, data)
  		{
 -			if(transport.status != 505)
 +			if(transport.status < 500)
  			{
  				var msg = 'HTTP '+transport.status+" with response : \n";
  				msg += transport.responseText + "\n";
 -				msg += "Data : \n"+inspect(data);
 +				msg += "Data : \n"+inspect(data)+"\n";
 +				msg += "Actions : \n";
 +				request.getHeaderData(Prado.CallbackRequest.ACTION_HEADER).each(function(action)
 +				{
 +					msg += inspect(action)+"\n";
 +				})
 +				
  				Logger.warn(msg);
  			}
  		},
  		/**
 +		 * Uncaught exceptions during callback response.
 +		 */
 +		onException : function(e)
 +		{
 +			Logger.error('Uncaught Callback Client Exception:', e);
 +		},
 +	
 +		/**
  		 * Formats the exception message for display in console.
  		 */
  		formatException : function(e)
 @@ -67,15 +184,8 @@ Object.extend(Prado.Callback,  				msg += "("+trace[i].line+"): ";
  				msg += trace[i]["class"]+"->"+trace[i]["function"]+"()"+"\n";
  			}
 +			msg += e.version+" "+e.time+"\n";
  			return msg;
 -		},
 -	
 -		/**
 -		 * Log Callback response exceptions to console.
 -		 */
 -		logException : function(e)
 -		{
 -			Logger.error("Callback Request Error "+e.code, this.formatException(e));
  		}
  	},
 @@ -84,7 +194,7 @@ Object.extend(Prado.Callback,  	 */
  	encode : function(data)
  	{
 -		Prado.JSON.stringify(data);
 +		return Prado.JSON.stringify(data);
  	},
  	/**
 @@ -100,13 +210,13 @@ Object.extend(Prado.Callback,  Event.OnLoad(function()
  { 
  	if(typeof Logger != "undefined") 
 -		Ajax.Responders.register(Prado.Callback.Exception);
 +		Ajax.Responders.register(Prado.CallbackRequest.Exception);
  });
  /**
   * Create and prepare a new callback request.
   */
 -Prado.Callback.prototype = 
 +Prado.CallbackRequest.prototype = 
  {
  	/**
  	 * Callback URL, same url as the current page.
 @@ -124,27 +234,31 @@ Prado.Callback.prototype =  	id : null,
  	/**
 -	 * Callback parameters.
 +	 * Current callback request.
  	 */
 -	parameters : null,
 +	request : null,
  	/**
  	 * Prepare and inititate a callback request.
  	 */
 -	initialize : function(id, parameters, onSuccess, options)
 +	initialize : function(id, options)
  	{
  		this.options = options || {};	
  		this.id = id;
 -		this.parameters = parameters;
  		var request = 
  		{
  			postBody : this._getPostData(),
 -			onSuccess : this._onSuccess.bind(this)
 +			parameters : ''
  		}
  		Object.extend(this.options || {},request);
 -		
 -		new Ajax.Request(this.url, this.options);
 +		if(this.options.CausesValidation != false && typeof(Prado.Validation) != "undefined")
 +		{
 +			var form =  this.options.Form || Prado.Validation.getForm();
 +			if(Prado.Validation.validate(form,this.options.ValidationGroup,this) == false)
 +				return;
 +		}
 +		this.request = new Ajax.Request(this.url, this.options);
  	},
  	/**
 @@ -156,7 +270,7 @@ Prado.Callback.prototype =  	{
  		var data = {};
 -		Prado.Callback.PostDataLoaders.each(function(name)
 +		Prado.CallbackRequest.PostDataLoaders.each(function(name)
  		{
  			$A(document.getElementsByName(name)).each(function(element)
  			{
 @@ -165,17 +279,32 @@ Prado.Callback.prototype =  					data[name] = value;
  			})
  		})
 -		if(typeof(this.parameters) != "undefined")
 -			data[Prado.Callback.FIELD_CALLBACK_PARAMETER] = Prado.Callback.encode(this.parameters);
 -		data[Prado.Callback.FIELD_CALLBACK_TARGET] = this.id;
 +		if(typeof(this.options.params) != "undefined")
 +			data[Prado.CallbackRequest.FIELD_CALLBACK_PARAMETER] = Prado.CallbackRequest.encode(this.options.params);
 +		data[Prado.CallbackRequest.FIELD_CALLBACK_TARGET] = this.id;
  		return $H(data).toQueryString();
 -	},
 -	
 -	/**
 -	 * Dispatch a successfull response to the appropriate responders.
 -	 */
 -	_onSuccess : function(response, transport, json)
 -	{
 -		//Logger.info("asd");	
  	}
 -}
\ No newline at end of file +}
 +
 +/**
 + * Create a new callback request using default settings.
 + * @param string callback handler unique ID.
 + * @param mixed parameter to pass to callback handler on the server side.
 + * @param function client side onSuccess event handler.
 + * @param object additional request options.
 + * @return boolean always false.
 + */
 +Prado.Callback = function(UniqueID, parameter, onSuccess, options)
 +{
 +	var callback =  
 +	{
 +		'params' : parameter || '',
 +		'onSuccess' : onSuccess || Prototype.emptyFunction, 
 +		'CausesValidation' : true
 +	};
 +
 +	Object.extend(callback, options || {});
 +	
 +	new Prado.CallbackRequest(UniqueID, callback);
 +	return false;
 +}
 diff --git a/framework/Web/Javascripts/prado/validation3.js b/framework/Web/Javascripts/prado/validation3.js index 1f154fec..8becac70 100644 --- a/framework/Web/Javascripts/prado/validation3.js +++ b/framework/Web/Javascripts/prado/validation3.js @@ -90,6 +90,15 @@ Object.extend(Prado.Validation,  	},
  	/**
 +	 * @return string first form ID.
 +	 */
 +	getForm : function()
 +	{
 +		var keys = $H(this.managers).keys();
 +		return keys[0];
 +	},
 +	
 +	/**
  	 * Check if the validators are valid for a particular form (and group).
  	 * The validators states will not be changed.
  	 * The <tt>validate</tt> function should be called first. 
 | 
