diff options
42 files changed, 619 insertions, 403 deletions
| @@ -10,6 +10,18 @@ NEW: TSessionPageStatePersister (Qiang)  NEW: SQLMap (Wei)  NEW: TFeedService, TRssFeedDocument (Knut, Qiang) +Version 3.0.4 September 3, 2006 +=============================== +BUG: Fixed a bug that would prevent from using <prop:> tag in skins (Qiang) +BUG: Fixed a typo in TControl::setCustomData() (Qiang) +ENH: Ticket#336 - Speed up TSqliteCache with LIMIT SQL clause (Qiang) +ENH: TListControl.SelectedValues and SelectedIndices can now be set before databinding (Qiang) +ENH: Upgrade Scriptaculous javascript library to 1.6.2 (Wei) +ENH: Cells in TDataGrid rows can now be accessed via the corresponding column IDs (Qiang) +ENH: Input controls in some datagrid columns can now be accessed in a named fashion (Qiang) +CHG: Unify all client-side javascript event handler syntax. (Wei) +CHG: Added more conditions in the requirement checker (Qiang) +CHG: TControl::findControlsByType() now only returns objects of the specified type (Qiang)  Version 3.0.3 August 6, 2006  ============================  BUG: Ticket#264 - Typos in some exception throw statements (Knut) @@ -13,6 +13,17 @@ if you want to upgrade from version A to version C and there is  version B between A and C, you need to following the instructions
  for both A and B.
 +Upgrading from v3.0.3
 +---------------------
 +- This change affects existing client-side javascript handlers such as
 +  <com:TRequiredFieldValidator ClientSide.OnSuccess="xxx" />
 +  All ClientSide javascript event handlers (such as ClientSide.OnSuccess)
 +  are by default wrapped within the function block.
 +       function(sender, parameter){ // handler code }
 +  You may override this behaviour by providing your own javascript statement block
 +  as "javascript:MyHandlerFunction", e.g. ClientSide.OnSuccess="javascript:MyHandlerFunction"
 +  or ClientSide.OnSuccess="javascript:function(validator,sender){ ... }"
 +
  Upgrading from v3.0.2
  ---------------------
 @@ -42,45 +53,6 @@ Upgrading from v3.0.0  - TControl::onBubbleEvent() has been changed to TControl::bubbleEvent().
    This change only affects user controls that override this method.
 -Upgrading from v3.0.0 RC2
 --------------------------
 -- Template comment tag is changed from <! ... !> to <!-- ... --!>
 -- Remember to clean up 'assets' directory of your PRADO application
 -  as Javascript libraries were updated and client-side validators rewritten.
 -
 -
 -Upgrading from v3.0.0 RC1
 --------------------------
 -- !!! Expressions appeared in a template are now evaluated in PreRender
 -  stage. Previously, for template expressions, they are evaluated during
 -  rendering stage, while for property expressions, they are done right
 -  after the controls are constructed.
 -- !!! The context of the expressions appeared in a template is changed
 -  to the template control. Previously, it is the component/control
 -  associated with the expression.
 -- !!! List controls databound with integer-indexed arrays will have
 -  the integers as their list item values. Previously, it used the array
 -  values as the list item values.
 -
 -
 -Upgrading from v3.0.0 beta
 ---------------------------
 -- THttpSession.UseCustomStorage replaces the previous Storage.
 -- Pagers in TDataGrid are now enclosed within panels. The event indicating
 -  their creation is changed to OnPagerCreated instead of OnItemCreated.
 -- TTextHighlighter.EnableCopyCode defaults to false now.
 -- THtmlArea default toolbar and size are modified.
 -- TTarFileExtrator is moved to System.IO
 -  Cache classes are moved to System.Caching
 -  TXmlDocument is moved to System.Xml
 -  TLogger, TLogRouter, TDataFieldAccessor, TSimpleDateFormatter are moved to System.Util
 -
 -
 -Upgrading from v3.0.0 alpha
 ----------------------------
 -All event names must start with 'On'.
 -
 -
  Upgrading from v2.x and v1.x
  ----------------------------
  PRADO v3.x is not backward compatible with v2.x and v1.x.
 @@ -135,6 +135,7 @@      </copy>      <copy file="buildscripts/classtree/DWExtensionReadme.txt" tofile="${build.src.dir}/editors/Dreamweaver/readme.txt" /> +    <copy file="framework/pradolite.php" tofile="${build.src.dir}/framework/pradolite.php" />      <echo>Changing file permissions...</echo>      <chmod mode="0777"> diff --git a/buildscripts/classtree/build.php b/buildscripts/classtree/build.php index c0b5ba35..351a0d28 100644 --- a/buildscripts/classtree/build.php +++ b/buildscripts/classtree/build.php @@ -9,6 +9,7 @@ $exclusions=array(  //	'prado.php',
  	'pradolite.php',
  //	'PradoBase.php',
 +	'prado-cli.php',
  	'clientscripts.php',
  	'.svn',
  	'/I18N/core',
 diff --git a/demos/blog/protected/Pages/Posts/ListPost.page b/demos/blog/protected/Pages/Posts/ListPost.page index 1371a5ab..c3f1ba25 100644 --- a/demos/blog/protected/Pages/Posts/ListPost.page +++ b/demos/blog/protected/Pages/Posts/ListPost.page @@ -25,7 +25,7 @@  	<prop:ItemTemplate>
  <div class="post">
  <div class="post-title">
 -<%# $this->DataItem->Title %>
 +<%# htmlentities($this->DataItem->Title,ENT_QUOTES,'UTF-8') %>
  </div>
  <div class="post-time">
  <%# date('l, F j, Y \a\t h:i:s a',$this->DataItem->CreateTime) %>
 diff --git a/demos/blog/protected/Pages/Posts/ViewPost.page b/demos/blog/protected/Pages/Posts/ViewPost.page index c48b8537..7d9c208d 100644 --- a/demos/blog/protected/Pages/Posts/ViewPost.page +++ b/demos/blog/protected/Pages/Posts/ViewPost.page @@ -2,7 +2,7 @@  <div class="post">
  <div class="post-title">
 -<%= $this->CurrentPost->Title %>
 +<%= htmlentities($this->CurrentPost->Title,ENT_QUOTES,'UTF-8') %>
  </div>
  <div class="post-time">
  <com:TLabel
 diff --git a/demos/quickstart/protected/pages/Controls/Samples/TClientSideValidator/Home.page b/demos/quickstart/protected/pages/Controls/Samples/TClientSideValidator/Home.page index e96e7c12..2bfb1a28 100644 --- a/demos/quickstart/protected/pages/Controls/Samples/TClientSideValidator/Home.page +++ b/demos/quickstart/protected/pages/Controls/Samples/TClientSideValidator/Home.page @@ -4,16 +4,16 @@  	<com:TTextBox ID="text1" />
  	<com:TRequiredFieldValidator
  		ID="validator1"
 -		ControlToValidate="text1" 
 +		ControlToValidate="text1"
  		ErrorMessage="Text 1 is required" />
  	<div>
  	<com:TCheckBox ID="check1" Text="More..." />
  	</div>
 -	
 -	<com:TPanel ID="panel1" Style="display:none" > 
 +
 +	<com:TPanel ID="panel1" Style="display:none" >
  		<com:TLabel ForControl="text2" Text="Text 2:" />
  		<com:TTextBox ID="text2" />
 -		
 +
  	<com:TRequiredFieldValidator
  		ID="validator2"
  		ControlToValidate="text2"
 @@ -21,14 +21,14 @@  		OnPreRender="validate2_onPostValidate"
  		ErrorMessage="Text 2 is required">
  	<prop:ClientSide.OnValidate>
 -		validator.enabled = $("<%= $this->check1->ClientID %>").checked;
 +		sender.enabled = $("<%= $this->check1->ClientID %>").checked;
  	</prop:ClientSide.OnValidate>
 -	</com:TRequiredFieldValidator>	
 -	
 +	</com:TRequiredFieldValidator>
 +
  	</com:TPanel>
 -	
 +
  	<com:TButton ID="button1" Text="Submit!" />
 -	
 +
  	<com:TClientScript>
  	Event.OnLoad(function()
  	{
 diff --git a/demos/quickstart/protected/pages/Controls/Samples/TDataGrid/Sample3.page b/demos/quickstart/protected/pages/Controls/Samples/TDataGrid/Sample3.page index 2864de46..96affa4a 100644 --- a/demos/quickstart/protected/pages/Controls/Samples/TDataGrid/Sample3.page +++ b/demos/quickstart/protected/pages/Controls/Samples/TDataGrid/Sample3.page @@ -23,16 +23,19 @@  	>
  	<com:TBoundColumn
 +		ID="BookTitleColumn"
  		HeaderText="Book Title"
  		HeaderStyle.Width="400px"
  		DataField="title"
  		/>
  	<com:TBoundColumn
 +		ID="PublisherColumn"
  		HeaderText="Publisher"
  		HeaderStyle.Width="150px"
  		DataField="publisher"
  		/>
  	<com:TBoundColumn
 +		ID="PriceColumn"
  		ItemStyle.HorizontalAlign="Right"
  		ItemStyle.Wrap="false"
  		ItemStyle.Font.Italic="false"
 @@ -43,10 +46,11 @@  		DataFormatString="$%.2f"
  		/>
  	<com:TCheckBoxColumn
 +		ID="InStockColumn"
  		HeaderText="In-stock"
  		DataField="instock"
  		/>
 -	<com:TTemplateColumn HeaderText="Rating">
 +	<com:TTemplateColumn ID="RatingColumn" HeaderText="Rating">
  		<prop:ItemTemplate>
  		<img src="images/star<%#$this->Parent->DataItem['rating']%>.gif" alt="" />
  		</prop:ItemTemplate>
 @@ -70,6 +74,7 @@  		ItemStyle.Font.Italic="false"
  		/>
  	<com:TButtonColumn
 +		ID="DeleteColumn"
  		HeaderText="Delete"
  		HeaderStyle.Width="50px"
  		ItemStyle.HorizontalAlign="Center"
 diff --git a/demos/quickstart/protected/pages/Controls/Samples/TDataGrid/Sample3.php b/demos/quickstart/protected/pages/Controls/Samples/TDataGrid/Sample3.php index 6d8c0085..69a164c6 100644 --- a/demos/quickstart/protected/pages/Controls/Samples/TDataGrid/Sample3.php +++ b/demos/quickstart/protected/pages/Controls/Samples/TDataGrid/Sample3.php @@ -138,13 +138,13 @@ class Sample3 extends TPage  		if($item->ItemType==='EditItem')
  		{
  			// set column width of textboxes
 -			$item->Cells[0]->Controls[0]->Columns=40;
 -			$item->Cells[2]->Controls[0]->Columns=5;
 +			$item->BookTitleColumn->TextBox->Columns=40;
 +			$item->PriceColumn->TextBox->Columns=5;
  		}
  		if($item->ItemType==='Item' || $item->ItemType==='AlternatingItem' || $item->ItemType==='EditItem')
  		{
  			// add an aleart dialog to delete buttons
 -			$item->Cells[6]->Controls[0]->Attributes->onclick='if(!confirm(\'Are you sure?\')) return false;';
 +			$item->DeleteColumn->Button->Attributes->onclick='if(!confirm(\'Are you sure?\')) return false;';
  		}
  	}
 @@ -160,11 +160,11 @@ class Sample3 extends TPage  		$item=$param->Item;
  		$this->updateBook(
  			$this->DataGrid->DataKeys[$item->ItemIndex],	// ISBN
 -			$item->Cells[0]->Controls[0]->Text,				// title
 -			$item->Cells[1]->Controls[0]->Text,				// publisher
 -			$item->Cells[2]->Controls[0]->Text,				// price
 -			$item->Cells[3]->Controls[0]->Checked,			// instock
 -			$item->Cells[4]->Rating->SelectedValue			// rating
 +			$item->BookTitleColumn->TextBox->Text,			// title
 +			$item->PublisherColumn->TextBox->Text,			// publisher
 +			$item->PriceColumn->TextBox->Text,				// price
 +			$item->InStockColumn->CheckBox->Checked,		// instock
 +			$item->RatingColumn->Rating->SelectedValue		// rating
  			);
  		$this->DataGrid->EditItemIndex=-1;
  		$this->DataGrid->DataSource=$this->Data;
 diff --git a/demos/quickstart/protected/pages/Controls/Validation.page b/demos/quickstart/protected/pages/Controls/Validation.page index 2241f346..119749db 100644 --- a/demos/quickstart/protected/pages/Controls/Validation.page +++ b/demos/quickstart/protected/pages/Controls/Validation.page @@ -160,7 +160,7 @@ The summary can be displayed as a list, a bulleted list, or a single paragraph b  		<li>The <tt>OnError</tt> event is raised after the validator fails validation.</li>
  	</ul>
  	The corresponding events for the client side is available as sub-properties
 -	of the <tt>ClientSide</tt> property of the validator. 
 +	of the <tt>ClientSide</tt> property of the validator.
  </p>
  <p>The following example pop-up a message saying "hello" when the validator fails on the client-side.
  <com:TTextHighlighter Language="prado" CssClass="source">
 @@ -172,18 +172,19 @@ The summary can be displayed as a list, a bulleted list, or a single paragraph b  </com:TTextHighlighter>
  The resulting client-side event callback function is of the following form.
  <com:TTextHighlighter Language="javascript" CssClass="source">
 -function onErrorHandler(validator, sender)
 +function onErrorHandler(sender, parameter)
  {
  	alert("hello");
  }
  </com:TTextHighlighter>
 -Where <tt>validator</tt> is the current client-side validator and <tt>sender</tt>
 +Where <tt>sender</tt> is the current client-side validator and <tt>parameter</tt>
  is the control that invoked the validator.
  </p>
  <h3>Conditional Validation Example</h3>
  <p>
  The following example show the use of client-side and server side validator events. The example
 -demonstrates conditional validation. 
 +demonstrates conditional validation.
  <com:RunBar PagePath="Controls.Samples.TClientSideValidator.Home" />
  </p>
 +
  </com:TContent>
\ No newline at end of file diff --git a/framework/Caching/TSqliteCache.php b/framework/Caching/TSqliteCache.php index b94b39fe..acf42906 100644 --- a/framework/Caching/TSqliteCache.php +++ b/framework/Caching/TSqliteCache.php @@ -117,7 +117,7 @@ class TSqliteCache extends TCache  		$error='';
  		if(($this->_db=new SQLiteDatabase($this->_file,0666,$error))===false)
  			throw new TConfigurationException('sqlitecache_connection_failed',$error);
 -		if(($res=$this->_db->query('SELECT * FROM sqlite_master WHERE tbl_name=\''.self::CACHE_TABLE.'\' AND type=\'table\''))!=false)
 +		if(($res=$this->_db->query('SELECT * FROM sqlite_master WHERE tbl_name=\''.self::CACHE_TABLE.'\' AND type=\'table\' LIMIT 1'))!=false)
  		{
  			if($res->numRows()===0)
  			{
 @@ -161,7 +161,7 @@ class TSqliteCache extends TCache  	 */
  	protected function getValue($key)
  	{
 -		$sql='SELECT value FROM '.self::CACHE_TABLE.' WHERE key=\''.$key.'\' AND (expire=0 OR expire>'.time().')';
 +		$sql='SELECT value FROM '.self::CACHE_TABLE.' WHERE key=\''.$key.'\' AND (expire=0 OR expire>'.time().') LIMIT 1';
  		if(($ret=$this->_db->query($sql))!=false && ($row=$ret->fetch(SQLITE_ASSOC))!==false)
  			return $row['value'];
  		else
 diff --git a/framework/Exceptions/messages.txt b/framework/Exceptions/messages.txt index 89dcb799..13e1152f 100644 --- a/framework/Exceptions/messages.txt +++ b/framework/Exceptions/messages.txt @@ -165,6 +165,7 @@ control_stylesheet_applied				= StyleSheet skin has already been applied to {0}.  control_id_nonunique					= {0}.ID '{1}' is not unique among all controls under the same naming container.
  templatecontrol_mastercontrol_invalid	= Master control must be of type TTemplateControl or a child class.
 +templatecontrol_mastercontrol_required	= Control '{0}' requires a master control since the control uses TContent.
  templatecontrol_contentid_duplicated	= TContent ID '{0}' is duplicated.
  templatecontrol_placeholderid_duplicated= TContentPlaceHolder ID '{0}' is duplicated.
  templatecontrol_directive_invalid		= {0}.{1} can only accept a static text string through a template directive.
 @@ -192,6 +193,7 @@ listcontrol_selection_invalid			= {0} has an invalid selection that is set befor  listcontrol_selectedindex_invalid		= {0}.SelectedIndex has an invalid value {1}.
  listcontrol_selectedvalue_invalid		= {0}.SelectedValue has an invalid value '{1}'.
  listcontrol_expression_invalid			= {0} is evaluating an invalid expression '{1}' : {2}
 +listcontrol_multiselect_unsupported		= {0} does not support multiselection.
  label_associatedcontrol_invalid			= TLabel.AssociatedControl '{0}' cannot be found.
 diff --git a/framework/Web/Javascripts/TJavaScript.php b/framework/Web/Javascripts/TJavaScript.php index 0f6414ec..e48de8f4 100644 --- a/framework/Web/Javascripts/TJavaScript.php +++ b/framework/Web/Javascripts/TJavaScript.php @@ -89,7 +89,7 @@ class TJavaScript  		else
  			return strtr($js,array("\t"=>'\t',"\n"=>'\n',"\r"=>'\r','"'=>'\"','\''=>'\\\'','\\'=>'\\\\'));
  	}
 -	
 +
  	/**
  	 * @return string considers the string as raw javascript function code
  	 */
 @@ -98,16 +98,16 @@ class TJavaScript  		if(self::isFunction($js))
  			return $js;
  		else
 -			return 'javascript:'.$js; 
 +			return 'javascript:'.$js;
  	}
 -	
 +
  	/**
  	 * @return boolean true if string is raw javascript function code, i.e., if
  	 * the string begins with <tt>javascript:</tt>
  	 */
  	public static function isFunction($js)
  	{
 -		return preg_match('/^\s*javascript:/', $js);
 +		return preg_match('/^\s*javascript:/i', $js);
  	}
  	/**
 @@ -124,9 +124,9 @@ class TJavaScript  	 *
  	 * For higher complexity data structures use {@link jsonEncode} and {@link jsonDecode}
  	 * to serialize and unserialize.
 -	 * 
 +	 *
  	 * Note: strings begining with <tt>javascript:</tt> will be considered as
 -	 * raw javascript code and no encoding of that string will be enforced. 
 +	 * raw javascript code and no encoding of that string will be enforced.
  	 *
  	 * @param mixed PHP variable to be encoded
  	 * @param boolean whether the output is a map or a list.
 diff --git a/framework/Web/Javascripts/datepicker/datepicker.js b/framework/Web/Javascripts/datepicker/datepicker.js index 4525c1ba..5fff5f0f 100644 --- a/framework/Web/Javascripts/datepicker/datepicker.js +++ b/framework/Web/Javascripts/datepicker/datepicker.js @@ -10,41 +10,41 @@ Object.extend(Prado.WebUI.TDatePicker,  		var year=now.getFullYear();
  		var month=now.getMonth();
  		var day=1;
 -		
 +
  		var month_list = this.getMonthListControl(control);
  	 	var day_list = this.getDayListControl(control);
  	 	var year_list = this.getYearListControl(control);
 -		
 +
  		var day = day_list ? $F(day_list) : 1;
  		var month = month_list ? $F(month_list) : now.getMonth();
  		var year = year_list ? $F(year_list) : now.getFullYear();
 -		
 +
  		return new Date(year,month,day, 0, 0, 0);
  	},
 -	
 +
  	getYearListControl : function(control)
  	{
  		return $(control.id+"_year");
  	},
 -	
 +
  	getMonthListControl : function(control)
  	{
  		return $(control.id+"_month");
  	},
 -	
 +
  	getDayListControl : function(control)
  	{
  		return $(control.id+"_day");
  	}
  });
 -Prado.WebUI.TDatePicker.prototype = 
 +Prado.WebUI.TDatePicker.prototype =
  {
  	MonthNames : [	"January",		"February",		"March",	"April",
  		"May",			"June",			"July",		"August",
  		"September",	"October",		"November",	"December"
  	],
 -	AbbreviatedMonthNames : ["Jan", "Feb", "Mar", "Apr", "May", 
 +	AbbreviatedMonthNames : ["Jan", "Feb", "Mar", "Apr", "May",
  						"Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
  	ShortWeekDayNames : ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ],
 @@ -52,20 +52,20 @@ Prado.WebUI.TDatePicker.prototype =  	Format : "yyyy-MM-dd",
  	FirstDayOfWeek : 1, // 0 for sunday
 -	
 +
  	ClassName : "TDatePicker",
  	FromYear : 2000, UpToYear: 2015,
 -	
 +
  	initialize : function(options)
  	{
  		this.options = options || [];
 -		this.control = $(options.ID);	
 +		this.control = $(options.ID);
  		this.dateSlot = new Array(42);
  		this.weekSlot = new Array(6);
  		this.minimalDaysInFirstWeek	= 4;
  		this.selectedDate = this.newDate();
 -		
 +
  		//which element to trigger to show the calendar
  		if(this.options.Trigger)
  		{
 @@ -77,45 +77,45 @@ Prado.WebUI.TDatePicker.prototype =  			this.trigger  = this.control;
  			var triggerEvent = this.options.TriggerEvent || "focus";
  		}
 -		
 +
  		Object.extend(this,options);
 -		
 +
  		Event.observe(this.trigger, triggerEvent, this.show.bindEvent(this));
 -	
 +
  	},
  	create : function()
  	{
  		if(typeof(this._calDiv) != "undefined")
  			return;
 -			
 +
  		var div;
  		var table;
  		var tbody;
  		var tr;
  		var td;
 -	
 +
  		// Create the top-level div element
  		this._calDiv = document.createElement("div");
  		this._calDiv.className = this.ClassName;
 -		this._calDiv.style.display = "none";		
 +		this._calDiv.style.display = "none";
  		this._calDiv.style.position = "absolute"
 -		
 +
  		// header div
  		div = document.createElement("div");
  		div.className = "calendarHeader";
  		this._calDiv.appendChild(div);
 -		
 +
  		table = document.createElement("table");
  		table.style.cellSpacing = 0;
  		div.appendChild(table);
 -		
 +
  		tbody = document.createElement("tbody");
  		table.appendChild(tbody);
 -		
 +
  		tr = document.createElement("tr");
  		tbody.appendChild(tr);
 -		
 +
  		// Previous Month Button
  		td = document.createElement("td");
  		var previousMonth = document.createElement("input");
 @@ -124,11 +124,11 @@ Prado.WebUI.TDatePicker.prototype =  		previousMonth.value = "<<";
  		td.appendChild(previousMonth);
  		tr.appendChild(td);
 -		
 -		
 -		
 +
 +
 +
  		//
 -		// Create the month drop down 
 +		// Create the month drop down
  		//
  		td = document.createElement("td");
  		tr.appendChild(td);
 @@ -144,9 +144,9 @@ Prado.WebUI.TDatePicker.prototype =  	        this._monthSelect.appendChild(opt);
  	    }
  		td.appendChild(this._monthSelect);
 -		
 -		// 
 +
 +		//
  		// Create the year drop down
  		//
  		td = document.createElement("td");
 @@ -163,8 +163,8 @@ Prado.WebUI.TDatePicker.prototype =  			this._yearSelect.appendChild(opt);
  		}
  		td.appendChild(this._yearSelect);
 -		
 -		
 +
 +
  		td = document.createElement("td");
  		var nextMonth = document.createElement("input");
  		nextMonth.className = "nextMonthButton button";
 @@ -172,26 +172,26 @@ Prado.WebUI.TDatePicker.prototype =  		nextMonth.value = ">>";
  		td.appendChild(nextMonth);
  		tr.appendChild(td);
 -		
 +
  		// Calendar body
  		div = document.createElement("div");
  		div.className = "calendarBody";
  		this._calDiv.appendChild(div);
  		var calendarBody = div;
 -		
 -		// Create the inside of calendar body	
 -		
 +
 +		// Create the inside of calendar body
 +
  		var text;
  		table = document.createElement("table");
  		table.align="center";
  		table.className = "grid";
 -	
 +
  	    div.appendChild(table);
  		var thead = document.createElement("thead");
  		table.appendChild(thead);
  		tr = document.createElement("tr");
  		thead.appendChild(tr);
 -		
 +
  		for(i=0; i < 7; ++i) {
  			td = document.createElement("th");
  			text = document.createTextNode(this.ShortWeekDayNames[(i+this.FirstDayOfWeek)%7]);
 @@ -199,11 +199,11 @@ Prado.WebUI.TDatePicker.prototype =  			td.className = "weekDayHead";
  			tr.appendChild(td);
  		}
 -		
 +
  		// Date grid
  		tbody = document.createElement("tbody");
  		table.appendChild(tbody);
 -		
 +
  		for(week=0; week<6; ++week) {
  			tr = document.createElement("tr");
  			tbody.appendChild(tr);
 @@ -220,13 +220,13 @@ Prado.WebUI.TDatePicker.prototype =  				tmp.value = -1;
  				tmp.data = text;
  				this.dateSlot[(week*7)+day] = tmp;
 -				
 +
  				Event.observe(td, "mouseover", this.hover.bindEvent(this));
  				Event.observe(td, "mouseout", this.hover.bindEvent(this));
 -				
 +
  			}
  		}
 -		
 +
  		// Calendar Footer
  		div = document.createElement("div");
  		div.className = "calendarFooter";
 @@ -251,18 +251,18 @@ Prado.WebUI.TDatePicker.prototype =  		}
  		this.control.parentNode.appendChild(this._calDiv);
 -		
 +
  		this.update();
  		this.updateHeader();
 -		
 +
  		this.ieHack(true);
 -		// IE55+ extension		
 +		// IE55+ extension
  		previousMonth.hideFocus = true;
  		nextMonth.hideFocus = true;
  		todayButton.hideFocus = true;
  		// end IE55+ extension
 -		
 +
  		// hook up events
  		Event.observe(previousMonth, "click", this.prevMonth.bindEvent(this));
  		Event.observe(nextMonth, "click", this.nextMonth.bindEvent(this));
 @@ -272,18 +272,18 @@ Prado.WebUI.TDatePicker.prototype =  		Event.observe(this._yearSelect, "change", this.yearSelect.bindEvent(this));
  		// ie6 extension
 -		Event.observe(this._calDiv, "mousewheel", this.mouseWheelChange.bindEvent(this));		
 -		
 +		Event.observe(this._calDiv, "mousewheel", this.mouseWheelChange.bindEvent(this));
 +
  		Event.observe(calendarBody, "click", this.selectDate.bindEvent(this));
 -		
 +
  		Prado.Element.focus(this.control);
 -				
 +
  	},
 -	
 -	ieHack : function(cleanup) 
 +
 +	ieHack : function(cleanup)
  	{
  		// IE hack
 -		if(this.iePopUp) 
 +		if(this.iePopUp)
  		{
  			this.iePopUp.style.display = "block";
  			this.iePopUp.style.top = (this._calDiv.offsetTop -1 ) + "px";
 @@ -299,7 +299,7 @@ Prado.WebUI.TDatePicker.prototype =  		if(!this.showing) return;
  		if (!ev) ev = document.parentWindow.event;
  		var kc = ev.keyCode != null ? ev.keyCode : ev.charCode;
 -		
 +
  		if(kc == Event.KEY_RETURN || kc == Event.KEY_SPACEBAR || kc == Event.KEY_TAB)
  		{
  			this.setSelectedDate(this.selectedDate);
 @@ -310,8 +310,8 @@ Prado.WebUI.TDatePicker.prototype =  		{
  			Event.stop(ev); this.hide();
  		}
 -				
 -		var getDaysPerMonth = function (nMonth, nYear) 
 +
 +		var getDaysPerMonth = function (nMonth, nYear)
  		{
  			nMonth = (nMonth + 12) % 12;
  	        var days= [31,28,31,30,31,30,31,31,30,31,30,31];
 @@ -355,43 +355,43 @@ Prado.WebUI.TDatePicker.prototype =  			else
  				d -= 604800000; // -7 days
  		}
 -		else if (kc == Event.KEY_DOWN) 
 +		else if (kc == Event.KEY_DOWN)
  		{
  			if(ev.ctrlKey || ev.shiftKey) // +1 year
  			{
  				current.setDate( Math.min(current.getDate(), getDaysPerMonth(current.getMonth(),current.getFullYear() + 1)) ); // no need to catch dec -> jan for the year
  				d = current.setFullYear( current.getFullYear() + 1 );
  			}
 -			else 
 +			else
  				d += 7 * 24 * 61 * 60 * 1000; // +7 days
  		}
  		this.setSelectedDate(d);
 -		Event.stop(ev);	
 +		Event.stop(ev);
  	},
 -	
 +
  	selectDate : function(ev)
  	{
  		var el = Event.element(ev);
  		while (el.nodeType != 1)
  			el = el.parentNode;
 -		
 +
  		while (el != null && el.tagName && el.tagName.toLowerCase() != "td")
  			el = el.parentNode;
 -			
 +
  		// if no td found, return
  		if (el == null || el.tagName == null || el.tagName.toLowerCase() != "td")
  			return;
 -			
 +
  		var d = this.newDate(this.selectedDate);
  		var n = Number(el.firstChild.data);
  		if (isNaN(n) || n <= 0 || n == null)
  			return;
 -					
 +
  		d.setDate(n);
  		this.setSelectedDate(d);
  		this.hide();
  	},
 -	
 +
  	selectToday : function()
  	{
  		if(this.selectedDate.toISODate() == this.newDate().toISODate())
 @@ -399,36 +399,36 @@ Prado.WebUI.TDatePicker.prototype =  		this.setSelectedDate(this.newDate());
  	},
 -	
 +
  	clearSelection : function()
  	{
  		this.setSelectedDate(this.newDate());
  		this.hide();
  	},
 -	
 +
  	monthSelect : function(ev)
  	{
  		this.setMonth(Form.Element.getValue(Event.element(ev)));
  	},
 -	
 +
  	yearSelect : function(ev)
  	{
  		this.setYear(Form.Element.getValue(Event.element(ev)));
  	},
 -	
 +
  	// ie6 extension
 -	mouseWheelChange : function (e) 
 +	mouseWheelChange : function (e)
  	{
  		if (e == null) e = document.parentWindow.event;
  		var n = - e.wheelDelta / 120;
  		var d = this.newDate(this.selectedDate);
  		var m = d.getMonth() + n;
  		this.setMonth(m);
 -			
 +
  		return false;
  	},
 -	onChange : function() 
 +	onChange : function()
  	{
  		if(this.options.InputMode == "TextBox")
  		{
 @@ -459,7 +459,7 @@ Prado.WebUI.TDatePicker.prototype =  			Event.fireEvent(day || month || year, "change");
  		}
  	},
 -	
 +
  	formatDate : function()
  	{
  		return this.selectedDate ? this.selectedDate.SimpleFormat(this.Format,this) : '';
 @@ -474,52 +474,52 @@ Prado.WebUI.TDatePicker.prototype =  		return new Date(date.getFullYear(), date.getMonth(), date.getDate(), 0,0,0);
  	},
 -	setSelectedDate : function(date) 
 +	setSelectedDate : function(date)
  	{
  		if (date == null)
  			return;
  		this.selectedDate = this.newDate(date);
 -	
 +
  		this.updateHeader();
  		this.update();
  		if (typeof(this.onChange) == "function")
 -			this.onChange();
 +			this.onChange(this, date);
  	},
 -	getElement : function() 
 +	getElement : function()
  	{
  		return this._calDiv;
  	},
 -	getSelectedDate : function () 
 +	getSelectedDate : function ()
  	{
  		return this.selectedDate == null ? null : this.newDate(this.selectedDate);
  	},
 -	
 -	setYear : function(year) 
 +
 +	setYear : function(year)
  	{
  		var d = this.newDate(this.selectedDate);
  		d.setFullYear(year);
  		this.setSelectedDate(d);
  	},
 -	setMonth : function (month) 
 +	setMonth : function (month)
  	{
  		var d = this.newDate(this.selectedDate);
  		d.setMonth(month);
  		this.setSelectedDate(d);
  	},
 -	nextMonth : function () 
 +	nextMonth : function ()
  	{
  		this.setMonth(this.selectedDate.getMonth()+1);
  	},
 -	prevMonth : function () 
 +	prevMonth : function ()
  	{
  		this.setMonth(this.selectedDate.getMonth()-1);
  	},
 -	
 +
  	getDatePickerOffsetHeight : function()
  	{
  		if(this.options.InputMode == "TextBox")
 @@ -529,27 +529,27 @@ Prado.WebUI.TDatePicker.prototype =  		if(control) return control.offsetHeight;
  		var control = Prado.WebUI.TDatePicker.getMonthListControl(this.control);
 -		if(control) return control.offsetHeight;		
 +		if(control) return control.offsetHeight;
  		var control = Prado.WebUI.TDatePicker.getYearListControl(this.control);
 -		if(control) return control.offsetHeight;	
 +		if(control) return control.offsetHeight;
  		return 0;
  	},
 -	
 -	show : function() 
 +
 +	show : function()
  	{
  		this.create();
 -			
 +
  		if(!this.showing)
  		{
  			var pos = Position.positionedOffset(this.control);
 -						
 +
  			pos[1] += this.getDatePickerOffsetHeight();
 -			
 +
  			this._calDiv.style.display = "block";
  			this._calDiv.style.top = (pos[1]-1) + "px";
  			this._calDiv.style.left = pos[0] + "px";
 -			
 +
  			this.ieHack(false);
  			this.documentClickEvent = this.hideOnClick.bindEvent(this);
  			this.documentKeyDownEvent = this.keyPressed.bindEvent(this);
 @@ -560,7 +560,7 @@ Prado.WebUI.TDatePicker.prototype =  				this.selectedDate = date;
  				this.setSelectedDate(date);
  			}
 -			Event.observe(document,"keydown", this.documentKeyDownEvent); 
 +			Event.observe(document,"keydown", this.documentKeyDownEvent);
  			this.showing = true;
  		}
  	},
 @@ -572,7 +572,7 @@ Prado.WebUI.TDatePicker.prototype =  		else
  			return Prado.WebUI.TDatePicker.getDropDownDate(this.control);
  	},
 -	
 +
  	//hide the calendar when clicked outside any calendar
  	hideOnClick : function(ev)
  	{
 @@ -585,12 +585,12 @@ Prado.WebUI.TDatePicker.prototype =  			within = within || el == this.trigger;
  			within = within || el == this.control;
  			if(within) break;
 -			el = el.parentNode;			
 +			el = el.parentNode;
  		}
  		while(el);
  		if(!within) this.hide();
  	},
 -	
 +
  	hide : function()
  	{
 @@ -599,28 +599,28 @@ Prado.WebUI.TDatePicker.prototype =  			this._calDiv.style.display = "none";
  			if(this.iePopUp)
  				this.iePopUp.style.display = "none";
 -			this.showing = false;	
 -			Event.stopObserving(document.body, "click", this.documentClickEvent);	
 -			Event.stopObserving(document,"keydown", this.documentKeyDownEvent); 
 -		}	
 +			this.showing = false;
 +			Event.stopObserving(document.body, "click", this.documentClickEvent);
 +			Event.stopObserving(document,"keydown", this.documentKeyDownEvent);
 +		}
  	},
 -	
 -	update : function() 
 +
 +	update : function()
  	{
  		// Calculate the number of days in the month for the selected date
  		var date = this.selectedDate;
  		var today = (this.newDate()).toISODate();
 -		
 +
  		var selected = date.toISODate();
  		var d1 = new Date(date.getFullYear(), date.getMonth(), 1);
  		var d2 = new Date(date.getFullYear(), date.getMonth()+1, 1);
  		var monthLength = Math.round((d2 - d1) / (24 * 60 * 60 * 1000));
 -		
 +
  		// Find out the weekDay index for the first of this month
  		var firstIndex = (d1.getDay() - this.FirstDayOfWeek) % 7 ;
  	    if (firstIndex < 0)
  	    	firstIndex += 7;
 -		
 +
  		var index = 0;
  		while (index < firstIndex) {
  			this.dateSlot[index].value = -1;
 @@ -628,7 +628,7 @@ Prado.WebUI.TDatePicker.prototype =  			this.dateSlot[index].data.parentNode.className = "empty";
  			index++;
  		}
 -	        
 +
  	    for (i = 1; i <= monthLength; i++, index++) {
  			var slot = this.dateSlot[index];
  			var slotNode = slot.data.parentNode;
 @@ -645,18 +645,18 @@ Prado.WebUI.TDatePicker.prototype =  			}
  			d1 = new Date(d1.getFullYear(), d1.getMonth(), d1.getDate()+1);
  		}
 -		
 +
  		var lastDateIndex = index;
 -	        
 +
  	    while(index < 42) {
  			this.dateSlot[index].value = -1;
  			this.dateSlot[index].data.data = String.fromCharCode(160);
  			this.dateSlot[index].data.parentNode.className = "empty";
  			++index;
  		}
 -		
 +
  	},
 -	
 +
  	hover : function(ev)
  	{
  		if(Event.element(ev).tagName)
 @@ -667,7 +667,7 @@ Prado.WebUI.TDatePicker.prototype =  				Event.element(ev).removeClassName("hover");
  		}
  	},
 -	
 +
  	updateHeader : function () {
  		var options = this._monthSelect.options;
 @@ -678,7 +678,7 @@ Prado.WebUI.TDatePicker.prototype =  				options[i].selected = true;
  			}
  		}
 -		
 +
  		options = this._yearSelect.options;
  		var year = this.selectedDate.getFullYear();
  		for(var i=0; i < options.length; ++i) {
 @@ -687,8 +687,8 @@ Prado.WebUI.TDatePicker.prototype =  				options[i].selected = true;
  			}
  		}
 -	
 +
  	}
 -	
 -	
 +
 +
  };
\ No newline at end of file diff --git a/framework/Web/Javascripts/effects/controls.js b/framework/Web/Javascripts/effects/controls.js index de0261ed..ea5ce6ea 100644 --- a/framework/Web/Javascripts/effects/controls.js +++ b/framework/Web/Javascripts/effects/controls.js @@ -33,6 +33,9 @@  // useful when one of the tokens is \n (a newline), as it   // allows smart autocompletion after linebreaks. +if(typeof Effect == 'undefined') +  throw("controls.js requires including script.aculo.us' effects.js library"); +  var Autocompleter = {}  Autocompleter.Base = function() {};  Autocompleter.Base.prototype = { @@ -94,7 +97,7 @@ Autocompleter.Base.prototype = {    },    fixIEOverlapping: function() { -    Position.clone(this.update, this.iefix); +    Position.clone(this.update, this.iefix, {setTop:(!this.update.style.height)});      this.iefix.style.zIndex = 1;      this.update.style.zIndex = 2;      Element.show(this.iefix); @@ -202,11 +205,13 @@ Autocompleter.Base.prototype = {    markPrevious: function() {      if(this.index > 0) this.index--        else this.index = this.entryCount-1; +    this.getEntry(this.index).scrollIntoView(true);    },    markNext: function() {      if(this.index < this.entryCount-1) this.index++        else this.index = 0; +    this.getEntry(this.index).scrollIntoView(false);    },    getEntry: function(index) { @@ -531,7 +536,7 @@ Ajax.InPlaceEditor.prototype = {      Element.hide(this.element);      this.createForm();      this.element.parentNode.insertBefore(this.form, this.element); -    Field.scrollFreeActivate(this.editField); +    if (!this.options.loadTextURL) Field.scrollFreeActivate(this.editField);      // stop the event to avoid a page refresh in Safari      if (evt) {        Event.stop(evt); @@ -636,6 +641,7 @@ Ajax.InPlaceEditor.prototype = {      Element.removeClassName(this.form, this.options.loadingClassName);      this.editField.disabled = false;      this.editField.value = transport.responseText.stripTags(); +    Field.scrollFreeActivate(this.editField);    },    onclickCancel: function() {      this.onComplete(); diff --git a/framework/Web/Javascripts/effects/dragdrop.js b/framework/Web/Javascripts/effects/dragdrop.js index be2a30f5..1528eced 100644 --- a/framework/Web/Javascripts/effects/dragdrop.js +++ b/framework/Web/Javascripts/effects/dragdrop.js @@ -5,6 +5,9 @@  /*--------------------------------------------------------------------------*/ +if(typeof Effect == 'undefined') +  throw("dragdrop.js requires including script.aculo.us' effects.js library"); +  var Droppables = {    drops: [], @@ -204,21 +207,31 @@ var Draggables = {  /*--------------------------------------------------------------------------*/  var Draggable = Class.create(); +Draggable._revertCache = {}; +Draggable._dragging    = {}; +  Draggable.prototype = {    initialize: function(element) {      var options = Object.extend({        handle: false,        starteffect: function(element) { -        element._opacity = Element.getOpacity(element);  +        element._opacity = Element.getOpacity(element); +        Draggable._dragging[element] = true;          new Effect.Opacity(element, {duration:0.2, from:element._opacity, to:0.7});         },        reverteffect: function(element, top_offset, left_offset) {          var dur = Math.sqrt(Math.abs(top_offset^2)+Math.abs(left_offset^2))*0.02; -        element._revert = new Effect.Move(element, { x: -left_offset, y: -top_offset, duration: dur}); +        Draggable._revertCache[element] = +          new Effect.Move(element, { x: -left_offset, y: -top_offset, duration: dur, +            queue: {scope:'_draggable', position:'end'} +          });        },        endeffect: function(element) { -        var toOpacity = typeof element._opacity == 'number' ? element._opacity : 1.0 -        new Effect.Opacity(element, {duration:0.2, from:0.7, to:toOpacity});  +        var toOpacity = typeof element._opacity == 'number' ? element._opacity : 1.0; +        new Effect.Opacity(element, {duration:0.2, from:0.7, to:toOpacity,  +          queue: {scope:'_draggable', position:'end'}, +          afterFinish: function(){ Draggable._dragging[element] = false } +        });         },        zindex: 1000,        revert: false, @@ -264,6 +277,8 @@ Draggable.prototype = {    },    initDrag: function(event) { +    if(typeof Draggable._dragging[this.element] != undefined && +      Draggable._dragging[this.element]) return;      if(Event.isLeftClick(event)) {            // abort on form elements, fixes a Firefox issue        var src = Event.element(event); @@ -274,9 +289,9 @@ Draggable.prototype = {          src.tagName=='BUTTON' ||          src.tagName=='TEXTAREA')) return; -      if(this.element._revert) { -        this.element._revert.cancel(); -        this.element._revert = null; +      if(Draggable._revertCache[this.element]) { +        Draggable._revertCache[this.element].cancel(); +        Draggable._revertCache[this.element] = null;        }        var pointer = [Event.pointerX(event), Event.pointerY(event)]; @@ -442,6 +457,7 @@ Draggable.prototype = {    },    startScrolling: function(speed) { +    if(!(speed[0] || speed[1])) return;      this.scrollSpeed = [speed[0]*this.options.scrollSpeed,speed[1]*this.options.scrollSpeed];      this.lastScrolled = new Date();      this.scrollInterval = setInterval(this.scroll.bind(this), 10); @@ -708,7 +724,7 @@ var Sortable = {      if(!Element.isParent(dropon, element)) {        var index; -      var children = Sortable.findElements(dropon, {tag: droponOptions.tag}); +      var children = Sortable.findElements(dropon, {tag: droponOptions.tag, only: droponOptions.only});        var child = null;        if(children) { @@ -869,7 +885,7 @@ var Sortable = {      if (options.tree) {        return Sortable.tree(element, arguments[1]).children.map( function (item) { -        return [name + Sortable._constructIndex(item) + "=" +  +        return [name + Sortable._constructIndex(item) + "[id]=" +                   encodeURIComponent(item.id)].concat(item.children.map(arguments.callee));        }).flatten().join('&');      } else { diff --git a/framework/Web/Javascripts/effects/effects.js b/framework/Web/Javascripts/effects/effects.js index 0864323e..1f3d50bb 100644 --- a/framework/Web/Javascripts/effects/effects.js +++ b/framework/Web/Javascripts/effects/effects.js @@ -105,6 +105,9 @@ Array.prototype.call = function() {  var Effect = {    tagifyText: function(element) { +    if(typeof Builder == 'undefined') +      throw("Effect.tagifyText requires including script.aculo.us' builder.js library"); +            var tagifyStyle = 'position:relative';      if(/MSIE/.test(navigator.userAgent)) tagifyStyle += ';zoom:1';      element = $(element); @@ -161,9 +164,8 @@ var Effect2 = Effect; // deprecated  Effect.Transitions = {} -Effect.Transitions.linear = function(pos) { -  return pos; -} +Effect.Transitions.linear = Prototype.K; +  Effect.Transitions.sinoidal = function(pos) {    return (-Math.cos(pos*Math.PI)/2) + 0.5;  } @@ -353,7 +355,7 @@ Object.extend(Object.extend(Effect.Opacity.prototype, Effect.Base.prototype), {    initialize: function(element) {      this.element = $(element);      // make this work on IE on elements without 'layout' -    if(/MSIE/.test(navigator.userAgent) && (!this.element.hasLayout)) +    if(/MSIE/.test(navigator.userAgent) && (!this.element.currentStyle.hasLayout))        this.element.setStyle({zoom: 1});      var options = Object.extend({        from: this.element.getOpacity() || 0.0, @@ -393,8 +395,8 @@ Object.extend(Object.extend(Effect.Move.prototype, Effect.Base.prototype), {    },    update: function(position) {      this.element.setStyle({ -      left: this.options.x  * position + this.originalLeft + 'px', -      top:  this.options.y  * position + this.originalTop  + 'px' +      left: Math.round(this.options.x  * position + this.originalLeft) + 'px', +      top:  Math.round(this.options.y  * position + this.originalTop)  + 'px'      });    }  }); @@ -433,7 +435,7 @@ Object.extend(Object.extend(Effect.Scale.prototype, Effect.Base.prototype), {      this.originalLeft = this.element.offsetLeft;      var fontSize = this.element.getStyle('font-size') || '100%'; -    ['em','px','%'].each( function(fontSizeType) { +    ['em','px','%','pt'].each( function(fontSizeType) {        if(fontSize.indexOf(fontSizeType)>0) {          this.fontSize     = parseFloat(fontSize);          this.fontSizeType = fontSizeType; @@ -462,8 +464,8 @@ Object.extend(Object.extend(Effect.Scale.prototype, Effect.Base.prototype), {    },    setDimensions: function(height, width) {      var d = {}; -    if(this.options.scaleX) d.width = width + 'px'; -    if(this.options.scaleY) d.height = height + 'px'; +    if(this.options.scaleX) d.width = Math.round(width) + 'px'; +    if(this.options.scaleY) d.height = Math.round(height) + 'px';      if(this.options.scaleFromCenter) {        var topd  = (height - this.dims[0])/2;        var leftd = (width  - this.dims[1])/2; @@ -589,7 +591,7 @@ Effect.Puff = function(element) {  Effect.BlindUp = function(element) {    element = $(element);    element.makeClipping(); -  return new Effect.Scale(element, 0,  +  return new Effect.Scale(element, 0,      Object.extend({ scaleContent: false,         scaleX: false,         restoreAfterFinish: true, @@ -604,28 +606,27 @@ Effect.BlindUp = function(element) {  Effect.BlindDown = function(element) {    element = $(element);    var elementDimensions = element.getDimensions(); -  return new Effect.Scale(element, 100,  -    Object.extend({ scaleContent: false,  -      scaleX: false, -      scaleFrom: 0, -      scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, -      restoreAfterFinish: true, -      afterSetup: function(effect) { -        effect.element.makeClipping(); -        effect.element.setStyle({height: '0px'}); -        effect.element.show();  -      },   -      afterFinishInternal: function(effect) { -        effect.element.undoClipping(); -      } -    }, arguments[1] || {}) -  ); +  return new Effect.Scale(element, 100, Object.extend({  +    scaleContent: false,  +    scaleX: false, +    scaleFrom: 0, +    scaleMode: {originalHeight: elementDimensions.height, originalWidth: elementDimensions.width}, +    restoreAfterFinish: true, +    afterSetup: function(effect) { +      effect.element.makeClipping(); +      effect.element.setStyle({height: '0px'}); +      effect.element.show();  +    },   +    afterFinishInternal: function(effect) { +      effect.element.undoClipping(); +    } +  }, arguments[1] || {}));  }  Effect.SwitchOff = function(element) {    element = $(element);    var oldOpacity = element.getInlineOpacity(); -  return new Effect.Appear(element, {  +  return new Effect.Appear(element, Object.extend({      duration: 0.4,      from: 0,      transition: Effect.Transitions.flicker, @@ -645,7 +646,7 @@ Effect.SwitchOff = function(element) {          }        })      } -  }); +  }, arguments[1] || {}));  }  Effect.DropOut = function(element) { @@ -729,7 +730,7 @@ Effect.SlideDown = function(element) {      }, arguments[1] || {})    );  } -   +  Effect.SlideUp = function(element) {    element = $(element);    element.cleanWhitespace(); diff --git a/framework/Web/Javascripts/effects/slider.js b/framework/Web/Javascripts/effects/slider.js index c0f1fc01..696992ca 100644 --- a/framework/Web/Javascripts/effects/slider.js +++ b/framework/Web/Javascripts/effects/slider.js @@ -64,7 +64,12 @@ Control.Slider.prototype = {      this.alignY = parseInt(this.options.alignY || '0');      this.trackLength = this.maximumOffset() - this.minimumOffset(); -    this.handleLength = this.isVertical() ? this.handles[0].offsetHeight : this.handles[0].offsetWidth; + +    this.handleLength = this.isVertical() ?  +      (this.handles[0].offsetHeight != 0 ?  +        this.handles[0].offsetHeight : this.handles[0].style.height.replace(/px$/,"")) :  +      (this.handles[0].offsetWidth != 0 ? this.handles[0].offsetWidth :  +        this.handles[0].style.width.replace(/px$/,""));      this.active   = false;      this.dragging = false; @@ -137,8 +142,8 @@ Control.Slider.prototype = {    },    setValue: function(sliderValue, handleIdx){      if(!this.active) { -      this.activeHandle    = this.handles[handleIdx]; -      this.activeHandleIdx = handleIdx; +      this.activeHandleIdx = handleIdx || 0; +      this.activeHandle    = this.handles[this.activeHandleIdx];        this.updateStyles();      }      handleIdx = handleIdx || this.activeHandleIdx || 0; @@ -180,8 +185,11 @@ Control.Slider.prototype = {      return(this.isVertical() ? this.alignY : this.alignX);    },    maximumOffset: function(){ -    return(this.isVertical() ? -      this.track.offsetHeight - this.alignY : this.track.offsetWidth - this.alignX); +    return(this.isVertical() ?  +      (this.track.offsetHeight != 0 ? this.track.offsetHeight : +        this.track.style.height.replace(/px$/,"")) - this.alignY :  +      (this.track.offsetWidth != 0 ? this.track.offsetWidth :  +        this.track.style.width.replace(/px$/,"")) - this.alignY);    },      isVertical:  function(){      return (this.axis == 'vertical'); @@ -217,7 +225,8 @@ Control.Slider.prototype = {          var handle = Event.element(event);          var pointer  = [Event.pointerX(event), Event.pointerY(event)]; -        if(handle==this.track) { +        var track = handle; +        if(track==this.track) {            var offsets  = Position.cumulativeOffset(this.track);             this.event = event;            this.setValue(this.translateToValue(  diff --git a/framework/Web/Javascripts/prado/ajax.js b/framework/Web/Javascripts/prado/ajax.js index 06c3d741..4f1c1ec9 100644 --- a/framework/Web/Javascripts/prado/ajax.js +++ b/framework/Web/Javascripts/prado/ajax.js @@ -1,4 +1,4 @@ -/** 
 +/**
   * Prado AJAX service. The default service provider is JPSpan.
   */
  Prado.AJAX = { Service : 'Prototype' };
 @@ -11,10 +11,10 @@ Prado.AJAX.EvalScript = function(output)  	var match = new RegExp(Ajax.Updater.ScriptFragment, 'img');
  	var scripts  = output.match(match);
 -	if (scripts) 
 +	if (scripts)
  	{
  		match = new RegExp(Ajax.Updater.ScriptFragment, 'im');
 -		setTimeout((function() 
 +		setTimeout((function()
  		{
  			for (var i = 0; i < scripts.length; i++)
  				eval(scripts[i].match(match)[1]);
 @@ -27,21 +27,21 @@ Prado.AJAX.EvalScript = function(output)   * AJAX service request using Prototype's AJAX request class.
   */
  Prado.AJAX.Request = Class.create();
 -Prado.AJAX.Request.prototype = Object.extend(Ajax.Request.prototype, 
 +Prado.AJAX.Request.prototype = Object.extend(Ajax.Request.prototype,
  {
  	/**
  	 * Evaluate the respond JSON data, override parent implementing.
  	 * If default eval fails, try parsing the JSON data (slower).
  	 */
 -	evalJSON: function() 
 +	evalJSON: function()
  	{
 -		try 
 +		try
  		{
  			var json = this.transport.getResponseHeader('X-JSON'), object;
  			object = eval(json);
  			return object;
 -		} 
 -		catch (e) 
 +		}
 +		catch (e)
  		{
  			if(isString(json))
  			{
 @@ -49,15 +49,15 @@ Prado.AJAX.Request.prototype = Object.extend(Ajax.Request.prototype,  			}
  		}
  	},
 -	
 +
  	respondToReadyState: function(readyState) {
      var event = Ajax.Request.Events[readyState];
      var transport = this.transport, json = this.evalJSON();
 -	
 +
  	if(event == 'Complete' && transport.status)
      	Ajax.Responders.dispatch('on' + transport.status, this, transport, json);
 -    	
 +
     (this.options['on' + event] || Prototype.emptyFunction)(transport, json);
      Ajax.Responders.dispatch('on' + event, this, transport, json);
 @@ -66,15 +66,15 @@ Prado.AJAX.Request.prototype = Object.extend(Ajax.Request.prototype,         || this.options['on' + (this.responseIsSuccess() ? 'Success' : 'Failure')]
         || Prototype.emptyFunction)(transport, json);
 - 
 +
      /* Avoid memory leak in MSIE: clean up the oncomplete event handler */
      if (event == 'Complete')
        this.transport.onreadystatechange = Prototype.emptyFunction;
    }
 -  	
 +
  });
 -Prado.AJAX.Error = function(e, code) 
 +Prado.AJAX.Error = function(e, code)
  {
      e.name = 'Prado.AJAX.Error';
      e.code = code;
 @@ -85,7 +85,7 @@ Prado.AJAX.Error = function(e, code)   * Post data builder, serialize the data using JSON.
   */
  Prado.AJAX.RequestBuilder = Class.create();
 -Prado.AJAX.RequestBuilder.prototype = 
 +Prado.AJAX.RequestBuilder.prototype =
  {
  	initialize : function()
  	{
 @@ -96,13 +96,13 @@ Prado.AJAX.RequestBuilder.prototype =  	{
  		return Prado.AJAX.JSON.stringify(data);
  	},
 -	build : function(data) 
 +	build : function(data)
  	{
  		var sep = '';
 -        for ( var argName in data) 
 +        for ( var argName in data)
  		{
  			if(isFunction(data[argName])) continue;
 -            try 
 +            try
  			{
                  this.body += sep + argName + '=';
                  this.body += encodeURIComponent(this.encode(data[argName]));
 @@ -110,9 +110,9 @@ Prado.AJAX.RequestBuilder.prototype =                  throw Prado.AJAX.Error(e, 1006);
              }
              sep = '&';
 -        }        
 +        }
      },
 -	
 +
  	getAll : function()
  	{
  		this.build(this.data);
 @@ -141,7 +141,7 @@ Prado.AJAX.RemoteObject.Request.prototype = Object.extend(Prado.AJAX.Request.pro  	},
  	/**
 -	 * Call the remote object, 
 +	 * Call the remote object,
  	 * @param string the remote server url
  	 * @param array additional arguments
  	 */
 @@ -165,7 +165,7 @@ Prado.AJAX.RemoteObject.Request.prototype = Object.extend(Prado.AJAX.Request.pro  /**
   * Base proxy class for Prado RemoteObjects via AJAX.
 - * e.g. 
 + * e.g.
   * <code>
   *	var TestObject1 = Class.create();
   *	TestObject1.prototype = Object.extend(new Prado.AJAX.RemoteObject(),
 @@ -182,18 +182,18 @@ Prado.AJAX.RemoteObject.Request.prototype = Object.extend(Prado.AJAX.Request.pro   *		}
   *	});
   *</code>
 - * And client usage, 
 + * And client usage,
   * <code>
   *	var test1 = new TestObject1(); //create new remote object
   *	test1.method1(); //call the method, no onComplete hook
   *
   *  var onComplete = { method1 : function(result){ alert(result) } };
   *  //create new remote object with onComplete callback
 - *  var test2 = new TestObject1(onComplete); 
 + *  var test2 = new TestObject1(onComplete);
   *  test2.method1(); //call it, on success, onComplete's method1 is called.
   * </code>
   */
 -Prado.AJAX.RemoteObject.prototype = 
 +Prado.AJAX.RemoteObject.prototype =
  {
  	baseInitialize : function(handlers, options)
  	{
 @@ -207,11 +207,11 @@ Prado.AJAX.RemoteObject.prototype =  		this.__callback = method;
  		return this.__service.invokeRemoteObject(url+"/"+method, args);
  	},
 -	
 +
  	__onSuccess : function(transport, json)
  	{
  		if(this.__handlers[this.__callback])
 -			this.__handlers[this.__callback](json, transport.responseText);		
 +			this.__handlers[this.__callback](json, transport.responseText);
  	}
  };
 @@ -224,12 +224,12 @@ Prado.AJAX.Exception =  	 * Server returns 505 exception. Just log it.
  	 */
  	"on505" : function(request, transport, e)
 -	{		
 +	{
  		var msg = 'HTTP '+transport.status+" with response";
  		Logger.error(msg, transport.responseText);
  		Logger.exception(e);
  	},
 -	
 +
  	onComplete : function(request, transport, e)
  	{
  		if(transport.status != 505)
 @@ -265,8 +265,8 @@ Prado.AJAX.Exception =  //Add HTTP exception respones when logger is enabled.
  Event.OnLoad(function()
 -{ 
 -	if(typeof Logger != "undefined") 
 +{
 +	if(typeof Logger != "undefined")
  	{
  		Logger.exception = Prado.AJAX.Exception.logException;
  		Ajax.Responders.register(Prado.AJAX.Exception);
 @@ -274,7 +274,7 @@ Event.OnLoad(function()  });
  /**
 - * Prado Callback service that provides component intergration, 
 + * Prado Callback service that provides component intergration,
   * viewstate (read only), and automatic form data serialization.
   * Usage: <code>new Prado.AJAX.Callback('MyPage.MyComponentID.raiseCallbackEvent', options)</code>
   * These classes should be called by the components developers.
 @@ -283,7 +283,7 @@ Event.OnLoad(function()  Prado.AJAX.Callback = Class.create();
  Prado.AJAX.Callback.prototype = Object.extend(new Prado.AJAX.RemoteObject(),
  {
 -	
 +
  	/**
  	 * Create and request a new Prado callback service.
  	 * @param string|element the callback ID, must be of the form, <t>ClassName.ComponentID.MethodName</t>
 @@ -294,14 +294,14 @@ Prado.AJAX.Callback.prototype = Object.extend(new Prado.AJAX.RemoteObject(),  	{
  		if(!isString(ID) && typeof(ID.id) != "undefined")
  			ID = ID.id;
 -		if(!isString(ID)) 
 +		if(!isString(ID))
  			throw new Error('A Control ID must be specified');
  		this.baseInitialize(this, options);
  		this.options = options || [];
  		this.__service.post.data['__ID'] = ID;
  		this.requestCallback();
  	},
 -	
 +
  	/**
  	 * Get form data for components that implements IPostBackHandler.
  	 */
 @@ -313,7 +313,7 @@ Prado.AJAX.Callback.prototype = Object.extend(new Prado.AJAX.RemoteObject(),  		{
  			var id = IDs[i];
  			if(id.indexOf("[]") > -1)
 -				this.__service.post.data['__data'][id] = 
 +				this.__service.post.data['__data'][id] =
  					this.collectArrayPostData(id);
  			else if(isObject($(id)))
  				this.__service.post.data['__data'][id] = $F(id);
 @@ -325,12 +325,12 @@ Prado.AJAX.Callback.prototype = Object.extend(new Prado.AJAX.RemoteObject(),  		var elements = document.getElementsByName(name);
  		var data = [];
  		$A(elements).each(function(el)
 -		{ 
 -			if($F(el)) data.push($F(el)); 
 +		{
 +			if($F(el)) data.push($F(el));
  		});
  		return data;
  	},
 -	
 +
  	/**
  	 * Prepares and calls the AJAX request.
  	 * Collects the data from components that implements IPostBackHandler
 @@ -377,7 +377,7 @@ Prado.AJAX.Callback.Action =  /**
 - * Returns false if validation required and validates to false, 
 + * Returns false if validation required and validates to false,
   * returns true otherwise.
   * @return boolean true if validation passes.
   */
 @@ -406,20 +406,22 @@ Prado.AJAX.Callback.IDs = [];  /**
   * Simple AJAX callback interface, suitable for inline javascript.
   * e.g., <code><a href="..." onclick="Prado.Callback('..', 'Hello');">Click me</a></code>
 - * @param string callback ID
 - * @param array parameters to pass to the callback service
 + * @param {String} callback ID
 + * @param {Array} parameters to pass to the callback service
 + * @param {Function} on callback success handler method
 + * @param {Object} additional callback options
   */
  Prado.Callback = function(ID, params, onSuccess, options)
  {
 -	var callback =  
 +	var callback =
  	{
  		'params' : [params] || [],
 -		'onSuccess' : onSuccess || Prototype.emptyFunction, 
 +		'onSuccess' : onSuccess || Prototype.emptyFunction,
  		'CausesValidation' : true
  	};
  	Object.extend(callback, options || {});
 -	
 +
  	new Prado.AJAX.Callback(ID, callback);
  	return false;
  }
\ No newline at end of file diff --git a/framework/Web/UI/TClientScriptManager.php b/framework/Web/UI/TClientScriptManager.php index d1f3f457..504cfb40 100644 --- a/framework/Web/UI/TClientScriptManager.php +++ b/framework/Web/UI/TClientScriptManager.php @@ -623,13 +623,12 @@ abstract class TClientSideOptions extends TComponent  	/**  	 * Ensure that the javascript statements are wrapped in a javascript -	 * function block. Default has no wrapping. Override this method to -	 * customize the wrapping javascript function block. +	 * function block as <code>function(sender, parameter){ //code }</code>.  	 */  	protected function ensureFunction($javascript)  	{ -		return $javascript; +		return "function(sender, parameter){ {$javascript} }";  	}  } -?> +?>
\ No newline at end of file diff --git a/framework/Web/UI/TControl.php b/framework/Web/UI/TControl.php index 4e9361aa..a347b0ba 100644 --- a/framework/Web/UI/TControl.php +++ b/framework/Web/UI/TControl.php @@ -941,7 +941,7 @@ class TControl extends TApplicationComponent implements IRenderable, IBindable  		{
  			foreach($this->_rf[self::RF_CONTROLS] as $control)
  			{
 -				if($control instanceof $type)
 +				if(is_object($control) && get_class($control)===$type)
  					$controls[]=$control;
  				if(($control instanceof TControl) && $control->getHasControls())
  					$controls=array_merge($controls,$control->findControlsByType($type));
 diff --git a/framework/Web/UI/TTemplateControl.php b/framework/Web/UI/TTemplateControl.php index 3bbe52c5..7d1f2d7e 100644 --- a/framework/Web/UI/TTemplateControl.php +++ b/framework/Web/UI/TTemplateControl.php @@ -235,6 +235,8 @@ class TTemplateControl extends TCompositeControl  			foreach($this->_contents as $id=>$content)
  				$master->injectContent($id,$content);
  		}
 +		else if(!empty($this->_contents))
 +			throw new TConfigurationException('templatecontrol_mastercontrol_required',get_class($this));
  		parent::initRecursive($namingContainer);
  	}
  }
 diff --git a/framework/Web/UI/TThemeManager.php b/framework/Web/UI/TThemeManager.php index 245f8049..1d80d0c5 100644 --- a/framework/Web/UI/TThemeManager.php +++ b/framework/Web/UI/TThemeManager.php @@ -292,10 +292,10 @@ class TTheme extends TApplicationComponent implements ITheme  					$template=new TTemplate(file_get_contents($themePath.'/'.$file),$themePath,$themePath.'/'.$file);
  					foreach($template->getItems() as $skin)
  					{
 -						if($skin[0]!==-1)
 -							throw new TConfigurationException('theme_control_nested',$skin[1],dirname($themePath));
 -						else if(!isset($skin[2]))  // a text string, ignored
 +						if(!isset($skin[2]))  // a text string, ignored
  							continue;
 +						else if($skin[0]!==-1)
 +							throw new TConfigurationException('theme_control_nested',$skin[1],dirname($themePath));
  						$type=$skin[1];
  						$id=isset($skin[2]['skinid'])?$skin[2]['skinid']:0;
  						unset($skin[2]['skinid']);
 diff --git a/framework/Web/UI/WebControls/TBaseValidator.php b/framework/Web/UI/WebControls/TBaseValidator.php index ff026b49..a6d044ff 100644 --- a/framework/Web/UI/WebControls/TBaseValidator.php +++ b/framework/Web/UI/WebControls/TBaseValidator.php @@ -85,7 +85,7 @@ abstract class TBaseValidator extends TLabel implements IValidator  	 */  	private $_registered=false;  	/** -	 * @var TClientSideValidatorOptions validator client-script options. +	 * @var TValidatorClientSide validator client-script options.  	 */  	private $_clientSide;  	/** @@ -167,7 +167,7 @@ abstract class TBaseValidator extends TLabel implements IValidator  		$options['ControlCssClass'] = $this->getControlCssClass();  		$options['ControlType'] = $this->getClientControlClass($control); -		 +  		//get date format from date picker target control  		if($control instanceof TDatePicker)  			$options['DateFormat'] = $control->getDateFormat(); @@ -194,7 +194,7 @@ abstract class TBaseValidator extends TLabel implements IValidator  	}  	/** -	 * Gets the TClientSideValidatorOptions that allows modification of the client- +	 * Gets the TValidatorClientSide that allows modification of the client-  	 * side validator events.  	 *  	 * The client-side validator supports the following events. @@ -207,21 +207,21 @@ abstract class TBaseValidator extends TLabel implements IValidator  	 *  	 * You can attach custom javascript code to each of these events  	 * -	 * @return TClientSideValidatorOptions javascript validator event options. +	 * @return TValidatorClientSide javascript validator event options.  	 */  	public function getClientSide()  	{  		if(is_null($this->_clientSide)) -			$this->_clientSide = $this->createClientSideOptions(); +			$this->_clientSide = $this->createClientSide();  		return $this->_clientSide;  	}  	/** -	 * @return TClientSideValidatorOptions javascript validator event options. +	 * @return TValidatorClientSide javascript validator event options.  	 */ -	protected function createClientSideOptions() +	protected function createClientSide()  	{ -		return new TClientSideValidatorOptions; +		return new TValidatorClientSide;  	}  	/** @@ -568,11 +568,11 @@ abstract class TBaseValidator extends TLabel implements IValidator  }  /** - * TClientSideValidatorOptions class. + * TValidatorClientSide class.   *   * Client-side validator events can be modified through the {@link   * TBaseValidator::getClientSide ClientSide} property of a validator. The - * subproperties of ClientSide are those of the TClientSideValidatorOptions + * subproperties of ClientSide are those of the TValidatorClientSide   * properties. The client-side validator supports the following events.   *   * The <tt>OnValidate</tt> event is raise before the validator validation @@ -590,7 +590,7 @@ abstract class TBaseValidator extends TLabel implements IValidator   * @package System.Web.UI.WebControls   * @since 3.0   */ -class TClientSideValidatorOptions extends TClientSideOptions +class TValidatorClientSide extends TClientSideOptions  {  	/**  	 * @return string javascript code for client-side OnValidate event. @@ -659,10 +659,8 @@ class TClientSideValidatorOptions extends TClientSideOptions  	 */  	public function getObserveChanges()  	{ -		if(($option=$this->getOption('ObserveChanges'))!==null) -			return $option; -		else -			return true; +		$changes = $this->getOption('ObserveChanges'); +		return is_null($changes) ? true : $changes;  	}  	/** @@ -678,4 +676,4 @@ class TClientSideValidatorOptions extends TClientSideOptions  	}  } -?>
\ No newline at end of file +?> diff --git a/framework/Web/UI/WebControls/TBoundColumn.php b/framework/Web/UI/WebControls/TBoundColumn.php index 5975ec02..26fad32b 100644 --- a/framework/Web/UI/WebControls/TBoundColumn.php +++ b/framework/Web/UI/WebControls/TBoundColumn.php @@ -26,6 +26,15 @@ Prado::using('System.Web.UI.WebControls.TDataGridColumn');   * If {@link setReadOnly ReadOnly} is false, TBoundColumn will display cells in edit mode
   * with textboxes. Otherwise, a static text is displayed.
   *
 + * When a datagrid row is in edit mode, the textbox control in the TBoundColumn
 + * can be accessed by one of the following two methods:
 + * <code>
 + * $datagridItem->BoundColumnID->TextBox
 + * $datagridItem->BoundColumnID->Controls[0]
 + * </code>
 + * The second method is possible because the textbox control created within the
 + * datagrid cell is the first child.
 + *
   * @author Qiang Xue <qiang.xue@gmail.com>
   * @version $Revision: $  $Date: $
   * @package System.Web.UI.WebControls
 @@ -103,6 +112,7 @@ class TBoundColumn extends TDataGridColumn  				{
  					$textBox=Prado::createComponent('System.Web.UI.WebControls.TTextBox');
  					$cell->getControls()->add($textBox);
 +					$cell->registerObject('TextBox',$textBox);
  					$control=$textBox;
  				}
  				if(($dataField=$this->getDataField())!=='')
 diff --git a/framework/Web/UI/WebControls/TButtonColumn.php b/framework/Web/UI/WebControls/TButtonColumn.php index 20844f14..fdcf58d3 100644 --- a/framework/Web/UI/WebControls/TButtonColumn.php +++ b/framework/Web/UI/WebControls/TButtonColumn.php @@ -39,6 +39,14 @@ Prado::using('System.Web.UI.WebControls.TImageButton');   * The buttons' <b>CausesValidation</b> and <b>ValidationGroup</b> property values
   * are determined by the column's corresponding properties.
   *
 + * The buttons in the column can be accessed by one of the following two methods:
 + * <code>
 + * $datagridItem->ButtonColumnID->Button
 + * $datagridItem->ButtonColumnID->Controls[0]
 + * </code>
 + * The second method is possible because the button control created within the
 + * datagrid cell is the first child.
 + *
   * @author Qiang Xue <qiang.xue@gmail.com>
   * @version $Revision: $  $Date: $
   * @package System.Web.UI.WebControls
 @@ -238,6 +246,7 @@ class TButtonColumn extends TDataGridColumn  			if($this->getDataTextField()!=='' || ($buttonType==='ImageButton' && $this->getDataImageUrlField()!==''))
  				$button->attachEventHandler('OnDataBinding',array($this,'dataBindColumn'));
  			$cell->getControls()->add($button);
 +			$cell->registerObject('Button',$button);
  		}
  	}
 diff --git a/framework/Web/UI/WebControls/TCheckBoxColumn.php b/framework/Web/UI/WebControls/TCheckBoxColumn.php index 4df1e695..d7fac8cf 100644 --- a/framework/Web/UI/WebControls/TCheckBoxColumn.php +++ b/framework/Web/UI/WebControls/TCheckBoxColumn.php @@ -28,6 +28,15 @@ Prado::using('System.Web.UI.WebControls.TCheckBox');   * TCheckBoxColumn will display an enabled checkbox provided the cells are
   * in edit mode. Otherwise, the checkboxes will be disabled to prevent from editting.
   *
 + * The checkbox control in the TCheckBoxColumn can be accessed by one of
 + * the following two methods:
 + * <code>
 + * $datagridItem->CheckBoxColumnID->CheckBox
 + * $datagridItem->CheckBoxColumnID->Controls[0]
 + * </code>
 + * The second method is possible because the checkbox control created within the
 + * datagrid cell is the first child.
 + *
   * @author Qiang Xue <qiang.xue@gmail.com>
   * @version $Revision: $  $Date: $
   * @package System.Web.UI.WebControls
 @@ -87,6 +96,7 @@ class TCheckBoxColumn extends TDataGridColumn  				$checkBox->setEnabled(false);
  			$cell->setHorizontalAlign('Center');
  			$cell->getControls()->add($checkBox);
 +			$cell->registerObject('CheckBox',$checkBox);
  			if($this->getDataField()!=='')
  				$checkBox->attachEventHandler('OnDataBinding',array($this,'dataBindColumn'));
  		}
 diff --git a/framework/Web/UI/WebControls/TDataGrid.php b/framework/Web/UI/WebControls/TDataGrid.php index e27f6ead..ad30ff3f 100644 --- a/framework/Web/UI/WebControls/TDataGrid.php +++ b/framework/Web/UI/WebControls/TDataGrid.php @@ -1075,6 +1075,11 @@ class TDataGrid extends TBaseDataList implements INamingContainer  				$cell=new TTableHeaderCell;
  			else
  				$cell=new TTableCell;
 +			if(($id=$column->getID())!=='')
 +			{
 +				$cell->setID($id);
 +				$item->registerObject($id,$cell);
 +			}
  			$column->initializeCell($cell,$index,$itemType);
  			$cells->add($cell);
  			$index++;
 diff --git a/framework/Web/UI/WebControls/TDatePicker.php b/framework/Web/UI/WebControls/TDatePicker.php index 001c7c46..0c3e0b9a 100644 --- a/framework/Web/UI/WebControls/TDatePicker.php +++ b/framework/Web/UI/WebControls/TDatePicker.php @@ -19,8 +19,6 @@ Prado::using('System.Web.UI.WebControls.TTextBox');   *
   * TDatePicker class.
   *
 - * Be aware, this control is EXPERIMENTAL and is not stablized yet.
 - *
   * TDatePicker displays a text box for date input purpose.
   * When the text box receives focus, a calendar will pop up and users can
   * pick up from it a date that will be automatically entered into the text box.
 @@ -69,14 +67,18 @@ Prado::using('System.Web.UI.WebControls.TTextBox');  class TDatePicker extends TTextBox
  {
  	/**
 +	 * @var TDatePickerClientScript validator client-script options.
 +	 */
 +	private $_clientScript;
 +		/**
  	 * AutoPostBack is not supported.
  	 */
  	public function setAutoPostBack($value)
  	{
  		throw new TNotSupportedException('tdatepicker_autopostback_unsupported',
 -			get_class($this)); 
 +			get_class($this));
  	}
 -	
 +
  	/**
  	 * @return string the format of the date string
  	 */
 @@ -278,7 +280,7 @@ class TDatePicker extends TTextBox  	{
  		return $this->getText();
  	}
 -	
 +
  	/**
  	 * @param string date string
  	 */
 @@ -288,6 +290,31 @@ class TDatePicker extends TTextBox  	}
  	/**
 +	 * Gets the TDatePickerClientScript to set the TDatePicker event handlers.
 +	 *
 +	 * The date picker on the client-side supports the following events.
 +	 * # <tt>OnDateChanged</tt> -- raised when the date is changed.
 +	 *
 +	 * You can attach custom javascript code to each of these events
 +	 *
 +	 * @return TDatePickerClientScript javascript validator event options.
 +	 */
 +	public function getClientSide()
 +	{
 +		if(is_null($this->_clientScript))
 +			$this->_clientScript = $this->createClientScript();
 +		return $this->_clientScript;
 +	}
 +
 +	/**
 +	 * @return TDatePickerClientScript javascript validator event options.
 +	 */
 +	protected function createClientScript()
 +	{
 +		return new TDatePickerClientScript;
 +	}
 +
 +	/**
  	 * Returns the value to be validated.
  	 * This methid is required by IValidatable interface.
  	 * @return integer the value of the property to be validated.
 @@ -394,7 +421,7 @@ class TDatePicker extends TTextBox  			$year = intval($values[$key.'$year']);
  		else
  			$year = $date['year'];
 -		
 +
  		$date = @mktime(0, 0, 0, $month, $day, $year);
  		$pattern = $this->getDateFormat();
 @@ -421,6 +448,9 @@ class TDatePicker extends TTextBox  			$options['Trigger'] = $this->getDatePickerButtonID();
  		$options = array_merge($options, $this->getCulturalOptions());
 +		if(!is_null($this->_clientScript))
 +			$options = array_merge($options,
 +				$this->_clientScript->getOptions()->toArray());
  		return $options;
  	}
 @@ -583,7 +613,7 @@ class TDatePicker extends TTextBox  		$writer->addAttribute('name', $this->getUniqueID().'$month');
  		$writer->addAttribute('class', 'datepicker_month_options');
  		if($this->getReadOnly() || !$this->getEnabled(true))
 -			$writer->addAttribute('disabled', 'disabled');		
 +			$writer->addAttribute('disabled', 'disabled');
  		$writer->renderBeginTag('select');
  		$this->renderDropDownListOptions($writer,
  					$this->getLocalizedMonthNames($info), $selected-1);
 @@ -604,8 +634,8 @@ class TDatePicker extends TTextBox  		switch($formatter->getMonthPattern())
  		{
  			case 'MMM': return $info->getAbbreviatedMonthNames();
 -			case 'MM': 
 -				$array = array(); 
 +			case 'MM':
 +				$array = array();
  				for($i=1;$i<=12;$i++)
  						$array[$i-1] = $i < 10 ? '0'.$i : $i;
  				return $array;
 @@ -629,7 +659,7 @@ class TDatePicker extends TTextBox  		$writer->addAttribute('id', $this->getClientID().'_year');
  		$writer->addAttribute('name', $this->getUniqueID().'$year');
  		if($this->getReadOnly() || !$this->getEnabled(true))
 -			$writer->addAttribute('disabled', 'disabled');		
 +			$writer->addAttribute('disabled', 'disabled');
  		$writer->renderBeginTag('select');
  		$writer->addAttribute('class', 'datepicker_year_options');
  		$this->renderDropDownListOptions($writer, $years, $selected);
 @@ -705,7 +735,7 @@ class TDatePicker extends TTextBox  		else
  			throw new TConfigurationException('datepicker_calendarstyle_invalid',$style);
  	}
 -	
 +
  	/**
  	 * Publish the spacer.gif for IE iframe source.
  	 * @return string the URL for the spacer.gif.
 @@ -739,16 +769,54 @@ class TDatePicker extends TTextBox  		{
  			$cs = $this->getPage()->getClientScript();
  			$cs->registerPradoScript("datepicker");
 -			
 +
  			if(!$cs->isEndScriptRegistered('TDatePicker.spacer'))
  			{
  				$spacer = $this->publishIFrameSpacer();
  				$code = "Prado.WebUI.TDatePicker.spacer = '$spacer';";
  				$cs->registerEndScript('TDatePicker.spacer', $code);
  			}
 -			$cs->registerPostBackControl('Prado.WebUI.TDatePicker', $this->getDatePickerOptions());
 +
 +			$options = TJavaScript::encode($this->getDatePickerOptions());
 +			$code = "new Prado.WebUI.TDatePicker($options);";
 +			$cs->registerEndScript("prado:".$this->getClientID(), $code);
  		}
  	}
  }
 +/**
 + * TDatePickerClientScript class.
 + *
 + * Client-side date picker event {@link setOnDateChanged OnDateChanged}
 + * can be modified through the {@link TDatePicker:: getClientSide ClientSide}
 + * property of a date picker.
 + *
 + * The <tt>OnDateChanged</tt> event is raise when the date picker's date
 + * is changed.
 + *
 + * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
 + * @version $Revision: $  $Date: $
 + * @package System.Web.UI.WebControls
 + * @since 3.0.4
 + */
 +class TDatePickerClientScript extends TClientSideOptions
 +{
 +	/**
 +	 * Javascript code to execute when the date picker's date is changed.
 +	 * @param string javascript code
 +	 */
 +	public function setOnDateChanged($javascript)
 +	{
 +		$this->setFunction('OnDateChanged', $javascript);
 +	}
 +
 +	/**
 +	 * @return string javascript code to execute when the date picker's date is changed.
 +	 */
 +	public function getOnDateChanged()
 +	{
 +		return $this->getOption('OnDateChanged');
 +	}
 +}
 +
  ?>
 diff --git a/framework/Web/UI/WebControls/TEditCommandColumn.php b/framework/Web/UI/WebControls/TEditCommandColumn.php index 65e389bd..c742ef11 100644 --- a/framework/Web/UI/WebControls/TEditCommandColumn.php +++ b/framework/Web/UI/WebControls/TEditCommandColumn.php @@ -38,6 +38,14 @@ Prado::using('System.Web.UI.WebControls.TDataGridColumn');   * properties affect the corresponding properties of the edit and update buttons.
   * The cancel button does not cause validation by default.
   *
 + * The command buttons in the column can be accessed by one of the following methods:
 + * <code>
 + * $datagridItem->ButtonColumnID->EditButton (or UpdateButton, CancelButton)
 + * $datagridItem->ButtonColumnID->Controls[0]
 + * </code>
 + * The second method is possible because the button control created within the
 + * datagrid cell is the first child.
 + *
   * @author Qiang Xue <qiang.xue@gmail.com>
   * @version $Revision: $  $Date: $
   * @package System.Web.UI.WebControls
 @@ -154,13 +162,21 @@ class TEditCommandColumn extends TDataGridColumn  	{
  		parent::initializeCell($cell,$columnIndex,$itemType);
  		if($itemType===TDataGrid::IT_ITEM || $itemType===TDataGrid::IT_ALTERNATINGITEM || $itemType===TDataGrid::IT_SELECTEDITEM)
 -			$cell->getControls()->add($this->createButton('Edit',$this->getEditText(),false,''));
 +		{
 +			$button=$this->createButton('Edit',$this->getEditText(),false,'');
 +			$cell->getControls()->add($button);
 +			$cell->registerObject('EditButton',$button);
 +		}
  		else if($itemType===TDataGrid::IT_EDITITEM)
  		{
  			$controls=$cell->getControls();
 -			$controls->add($this->createButton('Update',$this->getUpdateText(),$this->getCausesValidation(),$this->getValidationGroup()));
 +			$button=$this->createButton('Update',$this->getUpdateText(),$this->getCausesValidation(),$this->getValidationGroup());
 +			$controls->add($button);
 +			$cell->registerObject('UpdateButton',$button);
  			$controls->add(' ');
 -			$controls->add($this->createButton('Cancel',$this->getCancelText(),false,''));
 +			$button=$this->createButton('Cancel',$this->getCancelText(),false,'');
 +			$controls->add($button);
 +			$cell->registerObject('CancelButton',$button);
  		}
  	}
 diff --git a/framework/Web/UI/WebControls/THyperLinkColumn.php b/framework/Web/UI/WebControls/THyperLinkColumn.php index 9fc1e3d2..b8dbb607 100644 --- a/framework/Web/UI/WebControls/THyperLinkColumn.php +++ b/framework/Web/UI/WebControls/THyperLinkColumn.php @@ -36,6 +36,14 @@ Prado::using('System.Web.UI.WebControls.THyperLink');   * The same rule applies to {@link setNavigateUrl NavigateUrl} and
   * {@link setDataNavigateUrlField DataNavigateUrlField} properties.
   *
 + * The hyperlinks in the column can be accessed by one of the following two methods:
 + * <code>
 + * $datagridItem->HyperLinkColumnID->HyperLink
 + * $datagridItem->HyperLinkColumnID->Controls[0]
 + * </code>
 + * The second method is possible because the hyperlink control created within the
 + * datagrid cell is the first child.
 + *
   * @author Qiang Xue <qiang.xue@gmail.com>
   * @version $Revision: $  $Date: $
   * @package System.Web.UI.WebControls
 @@ -178,6 +186,7 @@ class THyperLinkColumn extends TDataGridColumn  			if($this->getDataTextField()!=='' || $this->getDataNavigateUrlField()!=='')
  				$link->attachEventHandler('OnDataBinding',array($this,'dataBindColumn'));
  			$cell->getControls()->add($link);
 +			$cell->registerObject('HyperLink',$link);
  		}
  	}
 diff --git a/framework/Web/UI/WebControls/TListControl.php b/framework/Web/UI/WebControls/TListControl.php index 8c1537b0..76c59903 100644 --- a/framework/Web/UI/WebControls/TListControl.php +++ b/framework/Web/UI/WebControls/TListControl.php @@ -94,6 +94,8 @@ abstract class TListControl extends TDataBoundControl  	 */
  	private $_cachedSelectedIndex=-1;
  	private $_cachedSelectedValue=null;
 +	private $_cachedSelectedIndices=null;
 +	private $_cachedSelectedValues=null;
  	/**
  	 * @return string tag name of the list control
 @@ -213,20 +215,34 @@ abstract class TListControl extends TDataBoundControl  		// so we make them be effective now
  		if($this->_cachedSelectedValue!==null)
  		{
 -			$index=$items->findIndexByValue($this->_cachedSelectedValue);
 -			if($index===-1 || ($this->_cachedSelectedIndex!==-1 && $this->_cachedSelectedIndex!==$index))
 -				throw new TInvalidDataValueException('listcontrol_selection_invalid',get_class($this));
 -			$this->setSelectedIndex($index);
 -			$this->_cachedSelectedValue=null;
 -			$this->_cachedSelectedIndex=-1;
 +			$this->setSelectedValue($this->_cachedSelectedValue);
 +			$this->resetCachedSelections();
  		}
  		else if($this->_cachedSelectedIndex!==-1)
  		{
  			$this->setSelectedIndex($this->_cachedSelectedIndex);
 -			$this->_cachedSelectedIndex=-1;
 +			$this->resetCachedSelections();
 +		}
 +		else if($this->_cachedSelectedValues!==null)
 +		{
 +			$this->setSelectedValues($this->_cachedSelectedValues);
 +			$this->resetCachedSelections();
 +		}
 +		else if($this->_cachedSelectedIndices!==null)
 +		{
 +			$this->setSelectedIndices($this->_cachedSelectedIndices);
 +			$this->resetCachedSelections();
  		}
  	}
 +	private function resetCachedSelections()
 +	{
 +		$this->_cachedSelectedValue=null;
 +		$this->_cachedSelectedIndex=-1;
 +		$this->_cachedSelectedValues=null;
 +		$this->_cachedSelectedIndices=null;
 +	}
 +
  	/**
  	 * Creates a collection object to hold list items.
  	 * This method may be overriden to create a customized collection.
 @@ -461,16 +477,22 @@ abstract class TListControl extends TDataBoundControl  	 */
  	public function setSelectedIndices($indices)
  	{
 -		if($this->_items)
 +		if($this->getIsMultiSelect())
  		{
 -			$this->clearSelection();
 -			$n=$this->_items->getCount();
 -			foreach($indices as $index)
 +			if($this->_items)
  			{
 -				if($index>=0 && $index<$n)
 -					$this->_items->itemAt($index)->setSelected(true);
 +				$this->clearSelection();
 +				$n=$this->_items->getCount();
 +				foreach($indices as $index)
 +				{
 +					if($index>=0 && $index<$n)
 +						$this->_items->itemAt($index)->setSelected(true);
 +				}
  			}
 +			$this->_cachedSelectedIndices=$indices;
  		}
 +		else
 +			throw new TNotSupportedException('listcontrol_multiselect_unsupported',get_class($this));
  		if($this->getAdapter() instanceof IListControlAdapter)
  			$this->getAdapter()->setSelectedIndices($indices);
 @@ -544,20 +566,26 @@ abstract class TListControl extends TDataBoundControl  	 */
  	public function setSelectedValues($values)
  	{
 -		if($this->_items)
 +		if($this->getIsMultiSelect())
  		{
 -			$this->clearSelection();
 -			$lookup=array();
 -			foreach($this->_items as $item)
 -				$lookup[$item->getValue()]=$item;
 -			foreach($values as $value)
 +			if($this->_items)
  			{
 -				if(isset($lookup["$value"]))
 -					$lookup["$value"]->setSelected(true);
 -		    	else
 -		    		throw new TInvalidDataValueException('listcontrol_selectedvalue_invalid',get_class($this),$value);
 +				$this->clearSelection();
 +				$lookup=array();
 +				foreach($this->_items as $item)
 +					$lookup[$item->getValue()]=$item;
 +				foreach($values as $value)
 +				{
 +					if(isset($lookup["$value"]))
 +						$lookup["$value"]->setSelected(true);
 +			    	else
 +			    		throw new TInvalidDataValueException('listcontrol_selectedvalue_invalid',get_class($this),$value);
 +				}
  			}
 +			$this->_cachedSelectedValues=$values;
  		}
 +		else
 +			throw new TNotSupportedException('listcontrol_multiselect_unsupported',get_class($this));
  		if($this->getAdapter() instanceof IListControlAdapter)
  			$this->getAdapter()->setSelectedValues($values);
 diff --git a/framework/Web/UI/WebControls/TValidationSummary.php b/framework/Web/UI/WebControls/TValidationSummary.php index cfb57c5b..796a62f0 100644 --- a/framework/Web/UI/WebControls/TValidationSummary.php +++ b/framework/Web/UI/WebControls/TValidationSummary.php @@ -40,7 +40,7 @@ class TValidationSummary extends TWebControl  	 * @var TClientSideValidationSummaryOptions validation client side options.
  	 */
  	private $_clientSide;
 -	
 +
  	/**
  	 * Constructor.
  	 * This method sets the foreground color to red.
 @@ -232,7 +232,7 @@ class TValidationSummary extends TWebControl  		if($this->getEnableClientScript() && !$cs->isEndScriptRegistered($scriptKey))
  		{
  			$manager['FormID'] = $formID;
 -			$options = TJavaScript::encode($manager); 
 +			$options = TJavaScript::encode($manager);
  			$cs->registerPradoScript('validator');
  			$cs->registerEndScript($scriptKey, "new Prado.ValidationManager({$options});");
  		}
 @@ -262,7 +262,7 @@ class TValidationSummary extends TWebControl  		$options['Refresh'] = $this->getAutoUpdate();
  		$options['ValidationGroup'] =  $this->getValidationGroup();
  		$options['Display'] = $this->getDisplay();
 -		
 +
  		if(!is_null($this->_clientSide))
  			$options = array_merge($options,$this->_clientSide->getOptions()->toArray());
 @@ -279,7 +279,7 @@ class TValidationSummary extends TWebControl  			$this->_clientSide = $this->createClientScript();
  		return $this->_clientSide;
  	}
 -	
 +
  	/**
  	 * @return TClientSideValidationSummaryOptions javascript validation summary
  	 * event options.
 @@ -388,20 +388,20 @@ class TValidationSummary extends TWebControl  /**
   * TClientSideValidationSummaryOptions class.
 - * 
 + *
   * Client-side validation summary events such as {@link setOnHideSummary
   * OnHideSummary} and {@link setOnShowSummary OnShowSummary} can be modified
   * through the {@link TBaseValidator:: getClientSide ClientSide} property of a
   * validation summary.
 - * 
 + *
   * The <tt>OnHideSummary</tt> event is raise when the validation summary
   * requests to hide the messages.
 - * 
 + *
   * The <tt>OnShowSummary</tt> event is raised when the validation summary
   * requests to show the messages.
 - * 
 + *
   * See the quickstart documentation for further details.
 - * 
 + *
   * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
   * @version $Revision: $  $Date: $
   * @package System.Web.UI.WebControls
 @@ -416,7 +416,7 @@ class TClientSideValidationSummaryOptions extends TClientSideOptions  	{
  		return $this->getOption('OnHideSummary');	
  	}
 -	
 +
  	/**
  	 * Client-side OnHideSummary validation summary event is raise when all the
  	 * validators are valid. This will override the default client-side
 @@ -427,7 +427,7 @@ class TClientSideValidationSummaryOptions extends TClientSideOptions  	{
  		$this->setFunction('OnHideSummary', $javascript);
  	}
 -	
 +
  	/**
  	 * Client-side OnShowSummary event is raise when one or more validators are
  	 * not valid. This will override the default client-side validation summary
 @@ -438,7 +438,7 @@ class TClientSideValidationSummaryOptions extends TClientSideOptions  	{
  		$this->setFunction('OnShowSummary', $javascript);
  	}
 -	
 +
  	/**
  	 * @return string javascript code for client-side OnShowSummary event.
  	 */
 @@ -460,4 +460,4 @@ class TClientSideValidationSummaryOptions extends TClientSideOptions  	}	
  }
 -?>
\ No newline at end of file +?>
 @@ -7,7 +7,7 @@  <body>
  <h1>PRADO Framework for PHP 5 </h1>
 -<p>Version 3.0.3, August 6, 2006<br>
 +<p>Version 3.0.4, September 3, 2006<br>
  Copyright© 2004-2006 by <a href="http://www.pradosoft.com/">PradoSoft</a><br>
  All Rights Reserved.
  </p>
 @@ -46,6 +46,7 @@ The installation is done! You will see the following subdirectories,    to reside in a Web directory.</li>
    <li>demos - contains several demo applications.</li>
    <li>docs - contains tutorials and documentation.</li>
 +  <li>editors - contains editor support for PRADO.</li>
    <li>requirements - contains a requirement checker script that can check if your
    system can run PRADO applications.</li>
  </ul>
 diff --git a/requirements/index.php b/requirements/index.php index fb58dfce..432f5332 100644 --- a/requirements/index.php +++ b/requirements/index.php @@ -59,6 +59,21 @@ $requirements = array(  		class_exists("DOMDocument",false),
  		'DOM extension check',
  		'DOM extension required'),
 +    array(
 +        true,
 +        extension_loaded("SPL"),
 +        'SPL extension check',
 +        'SPL extension required'),
 +    array(
 +        true,
 +        extension_loaded("CType"),
 +        'CType extension check',
 +        'CType extension required'),
 +    array(
 +        true,
 +        extension_loaded("pcre"),
 +        'PCRE extension check',
 +        'PCRE extension required'),
  	array(
  		false,
  		function_exists("iconv"),
 diff --git a/requirements/messages-bg.txt b/requirements/messages-bg.txt index e1be6b5d..aaf1ba56 100644 --- a/requirements/messages-bg.txt +++ b/requirements/messages-bg.txt @@ -24,4 +24,10 @@ SCRIPT_FILENAME required		= $_SERVER["SCRIPT_FILENAME"] трябва да ука  $_SERVER["REQUEST_URI"] check		= Проверка за $_SERVER["REQUEST_URI"]
  REQUEST_URI required			= $_SERVER["REQUEST_URI"] или $_SERVER["QUERY_STRING"] трябва да е достъпен за да е възможно анализирането на потребителските заявки.
  $_SERVER["PATH_INFO"] check		= Проверка за $_SERVER["PATH_INFO"]
 -PATH_INFO required			= $_SERVER["PATH_INFO"] или $_SERVER["PHP_SELF"] и $_SERVER["SCRIPT_NAME"] се изискват за да се определи URL информацията за пътя.
\ No newline at end of file +PATH_INFO required			= $_SERVER["PATH_INFO"] или $_SERVER["PHP_SELF"] и $_SERVER["SCRIPT_NAME"] се изискват за да се определи URL информацията за пътя.
 +SPL extension check					= Проверка за SPL разширението
 +SPL extension required				= DOM разширението е задължително за PRADO.
 +CType extension check				= Проверка за CType разширението
 +CType extension required			= CType разширението е задължително за PRADO.
 +PCRE extension check				= Проверка за PCRE разширението
 +PCRE extension required				= PCRE разширението е задължително за PRADO.
 diff --git a/requirements/messages-zh.txt b/requirements/messages-zh.txt index 6ee6e2c4..eb25d760 100644 --- a/requirements/messages-zh.txt +++ b/requirements/messages-zh.txt @@ -27,3 +27,9 @@ $_SERVER["REQUEST_URI"] check = $_SERVER["REQUEST_URI"]检查  REQUEST_URI required = $_SERVER["REQUEST_URI"]或$_SERVER["QUERY_STRING"]是必须的。如果它们都不存在,用户请求将无法被正确解析。
  $_SERVER["PATH_INFO"] check = $_SERVER["PATH_INFO"]检查
  PATH_INFO required = $_SERVER["PATH_INFO"]或$_SERVER["PHP_SELF"]和$_SERVER["SCRIPT_NAME"]是必须的。如果它们都不存在,URL的pathinfo将无法被正确解析。
 +SPL extension check = SPL模块检查
 +SPL extension required = SPL模块是必须的。
 +CType extension check = CType模块检查
 +CType extension required = CType模块是必须的。
 +PCRE extension check = PCRE模块检查
 +PCRE extension required = PCRE模块是必须的。
 diff --git a/requirements/messages.txt b/requirements/messages.txt index 5c1a1364..47bb888f 100644 --- a/requirements/messages.txt +++ b/requirements/messages.txt @@ -27,3 +27,9 @@ $_SERVER["REQUEST_URI"] check		= $_SERVER["REQUEST_URI"] check  REQUEST_URI required				= Either $_SERVER["REQUEST_URI"] or $_SERVER["QUERY_STRING"] must be available for resolving user requests.
  $_SERVER["PATH_INFO"] check			= $_SERVER["PATH_INFO"] check
  PATH_INFO required					= $_SERVER["PATH_INFO"] or $_SERVER["PHP_SELF"] and $_SERVER["SCRIPT_NAME"] are required for determining URL pathinfo.
 +SPL extension check					= SPL extension check
 +SPL extension required				= SPL extension is required by PRADO.
 +CType extension check				= CType extension check
 +CType extension required			= CType extension is required by PRADO.
 +PCRE extension check				= PCRE extension check
 +PCRE extension required				= PCRE extension is required by PRADO.
 diff --git a/tests/FunctionalTests/features/protected/pages/ValidatorEffects.page b/tests/FunctionalTests/features/protected/pages/ValidatorEffects.page index 7fca0f56..e01b542e 100644 --- a/tests/FunctionalTests/features/protected/pages/ValidatorEffects.page +++ b/tests/FunctionalTests/features/protected/pages/ValidatorEffects.page @@ -4,43 +4,43 @@  <fieldset id="quickRegistration">
  	<legend>Create New Account</legend>
 -<com:TClientScript UsingPradoScripts="effects,logger" />
 +<com:TClientScript PradoScripts="effects,logger" />
  <div class="username">
 -	Username: 
 +	Username:
  	<com:TTextBox ID="Username" />
  	<com:TRequiredFieldValidator
  		ID="UsernameVal"
  		ControlToValidate="Username"
 -		ValidationGroup="registration" 
 +		ValidationGroup="registration"
  		ControlCssClass="required"
  		Display="Dynamic"
  		ErrorMessage="a username is required.">
  	<prop:ClientSide.OnError>
 -		Effect.Shake(validator.control);
 -		Effect.Appear(validator.message);
 +		Effect.Shake(sender.control);
 +		Effect.Appear(sender.message);
  	</prop:ClientSide.OnError>
  	<prop:ClientSide.OnSuccess>
 -		Effect.Fade(validator.message);
 +		Effect.Fade(sender.message);
  	</prop:ClientSide.OnSuccess>
 -	</com:TRequiredFieldValidator>		
 +	</com:TRequiredFieldValidator>
  </div>
  <div class="password">
  	Password
  	<com:TTextBox ID="Password" TextMode="Password" />
 -	<!-- alternate synatx : see 
 +	<!-- alternate synatx : see
  	http://encytemedia.com/blog/articles/2006/03/07/prototype-gets-some-serious-syntactic-sugar
  	-->
  <com:TRequiredFieldValidator
  	ID="PasswordVal"
  	ControlToValidate="Password"
 -	ValidationGroup="registration" 
 +	ValidationGroup="registration"
  	ControlCssClass="required"
  	Display="Dynamic"
 -	ClientSide.OnError="validator.message.visualEffect('appear')"
 -	ClientSide.OnSuccess="validator.message.visualEffect('fade')"
 -	ErrorMessage="a password is required." />	
 -</div>	
 +	ClientSide.OnError="sender.message.visualEffect('appear')"
 +	ClientSide.OnSuccess="sender.message.visualEffect('fade')"
 +	ErrorMessage="a password is required." />
 +</div>
  <div class="create">
  	<com:TButton ID="Create" ValidationGroup="registration" Text="Create New Account"/>
  </div>
 @@ -54,7 +54,7 @@  <div class="username">
  	Login Name:
  	<com:TTextBox ID="UserID" />
 -		
 +
  	<com:TRequiredFieldValidator
  		ID="UserVal1"
  		ControlToValidate="UserID"
 @@ -78,26 +78,26 @@  <com:TButton ID="login" ValidationGroup="signin" CssClass="button" Text="Sign In" />
  <div class="validation">
 -	<com:TValidationSummary 
 +	<com:TValidationSummary
  		ID="summary2"
  		ValidationGroup="signin"
  		Display="Dynamic"
 -		ClientSide.OnHideSummary="Effect.Squish(summary.messages)"
 +		ClientSide.OnHideSummary="Effect.Squish(sender.messages)"
  		HeaderText="<p>You could not login because</p>">
  	<prop:ClientSide.OnShowSummary>
 -		Effect.Appear(summary.messages)
 -		Effect.Shake(summary.messages,{ queue: 'end'})
 -	</prop:ClientSide.OnShowSummary>	
 +		Effect.Appear(sender.messages)
 +		Effect.Shake(sender.messages,{ queue: 'end'})
 +	</prop:ClientSide.OnShowSummary>
  	</com:TValidationSummary>
  </div>
  </fieldset>
 -<com:TLinkButton ID="linkButton1" 
 -	Text="Click Me" 
 +<com:TLinkButton ID="linkButton1"
 +	Text="Click Me"
  	OnClick="linkButton1_Clicked">
  	<prop:Attributes.onclick>
 -	if(!confirm('<%= Prado::localize("Confirm Delete") %>')) 
 +	if(!confirm('<%= Prado::localize("Confirm Delete") %>'))
  		return false;
  	</prop:Attributes.onclick>
  </com:TLinkButton>
 diff --git a/tests/FunctionalTests/quickstart/Controls/DataGrid3TestCase.php b/tests/FunctionalTests/quickstart/Controls/DataGrid3TestCase.php index 4f53a38e..39a5aba6 100644 --- a/tests/FunctionalTests/quickstart/Controls/DataGrid3TestCase.php +++ b/tests/FunctionalTests/quickstart/Controls/DataGrid3TestCase.php @@ -10,16 +10,16 @@ class DataGrid3TestCase extends SeleniumTestCase  		$this->verifyTextPresent("Design Patterns: Elements of Reusable Object-Oriented Software", "");
  		$this->verifyTextPresent("Addison-Wesley Professional", "");
  		$this->verifyTextPresent("$47.04", "");
 -		$this->verifyAttribute('ctl0_body_DataGrid_ctl2_ctl7@checked','regexp:true|checked');
 -		$this->verifyAttribute('ctl0_body_DataGrid_ctl2_ctl7@disabled','regexp:true|disabled');
 +		$this->verifyAttribute('ctl0_body_DataGrid_ctl2_ctl1@checked','regexp:true|checked');
 +		$this->verifyAttribute('ctl0_body_DataGrid_ctl2_ctl1@disabled','regexp:true|disabled');
  		//$this->verifyElementPresent("//img[@src='images/star5.gif']",'');
  		// edit the 2nd row
 -		$this->clickAndWait("id=ctl0_body_DataGrid_ctl2_ctl8", "");
 -		$this->type("ctl0\$body\$DataGrid\$ctl2\$ctl7", "Design Pattern: Elements of Reusable Object-Oriented Software");
 -		$this->type("ctl0\$body\$DataGrid\$ctl2\$ctl8", "Addison Wesley Professional");
 -		$this->type("ctl0\$body\$DataGrid\$ctl2\$ctl9", "\$57.04");
 -		$this->click("//input[@name='ctl0\$body\$DataGrid\$ctl2\$ctl10']", "");
 +		$this->clickAndWait("id=ctl0_body_DataGrid_ctl2_ctl2", "");
 +		$this->type("ctl0\$body\$DataGrid\$ctl2\$ctl1", "Design Pattern: Elements of Reusable Object-Oriented Software");
 +		$this->type("ctl0\$body\$DataGrid\$ctl2\$ctl2", "Addison Wesley Professional");
 +		$this->type("ctl0\$body\$DataGrid\$ctl2\$ctl3", "\$57.04");
 +		$this->click("//input[@name='ctl0\$body\$DataGrid\$ctl2\$ctl4']", "");
  		$this->select("ctl0\$body\$DataGrid\$ctl2\$Rating", "label=1");
  		$this->clickAndWait("link=Save", "");
 @@ -27,23 +27,23 @@ class DataGrid3TestCase extends SeleniumTestCase  		$this->verifyTextPresent("Design Pattern: Elements of Reusable Object-Oriented Software", "");
  		$this->verifyTextPresent("Addison Wesley Professional", "");
  		$this->verifyTextPresent("$57.04", "");
 -		$this->verifyAttribute('ctl0_body_DataGrid_ctl2_ctl7@checked','regexp:false|null');
 -		$this->verifyAttribute('ctl0_body_DataGrid_ctl2_ctl7@disabled','regexp:true|disabled');
 +		$this->verifyAttribute('ctl0_body_DataGrid_ctl2_ctl1@checked','regexp:false|null');
 +		$this->verifyAttribute('ctl0_body_DataGrid_ctl2_ctl1@disabled','regexp:true|disabled');
  		//$this->verifyElementPresent("//img[@src='images/star1.gif']",'');
  		// verify cancel editting the 3rd row
 -		$this->clickAndWait("id=ctl0_body_DataGrid_ctl3_ctl8", "");
 +		$this->clickAndWait("id=ctl0_body_DataGrid_ctl3_ctl2", "");
  		$this->clickAndWait("link=Cancel", "");
  		$this->verifyTextPresent("Design Patterns Explained : A New Perspective on Object-Oriented Design", "");
  		// verify deleting
 -		$this->clickAndWait("id=ctl0_body_DataGrid_ctl3_ctl9", "");
 +		$this->clickAndWait("id=ctl0_body_DataGrid_ctl3_ctl3", "");
  		$this->verifyConfirmation("Are you sure?");
  		$this->verifyTextNotPresent("Design Patterns Explained : A New Perspective on Object-Oriented Design", "");
  		$this->verifyTextPresent("Extreme Programming Explained : Embrace Change",'');
  		$this->chooseCancelOnNextConfirmation();
 -		$this->click("id=ctl0_body_DataGrid_ctl6_ctl9", "");
 +		$this->click("id=ctl0_body_DataGrid_ctl6_ctl3", "");
  		$this->verifyConfirmation("Are you sure?");
  		$this->verifyTextPresent("Extreme Programming Explained : Embrace Change",'');
  	}
 diff --git a/tests/FunctionalTests/tickets/protected/pages/Ticket278.page b/tests/FunctionalTests/tickets/protected/pages/Ticket278.page index 75aed4d9..e7341bcc 100644 --- a/tests/FunctionalTests/tickets/protected/pages/Ticket278.page +++ b/tests/FunctionalTests/tickets/protected/pages/Ticket278.page @@ -4,16 +4,16 @@  	<com:TTextBox ID="text1" />
  	<com:TRequiredFieldValidator
  		ID="validator1"
 -		ControlToValidate="text1" 
 +		ControlToValidate="text1"
  		ErrorMessage="Text 1 is required" />
  	<div>
  	<com:TCheckBox ID="check1" Text="More..." />
  	</div>
 -	
 -	<com:TPanel ID="panel1" Style="display:none" > 
 +
 +	<com:TPanel ID="panel1" Style="display:none" >
  		<com:TLabel ForControl="text2" Text="Text 2:" />
  		<com:TTextBox ID="text2" />
 -		
 +
  	<com:TRequiredFieldValidator
  		ID="validator2"
  		ControlToValidate="text2"
 @@ -21,14 +21,14 @@  		OnPreRender="validate2_onPostValidate"
  		ErrorMessage="Text 2 is required">
  	<prop:ClientSide.OnValidate>
 -		validator.enabled = $("<%= $this->check1->ClientID %>").checked;
 +		sender.enabled = $("<%= $this->check1->ClientID %>").checked;
  	</prop:ClientSide.OnValidate>
 -	</com:TRequiredFieldValidator>	
 -	
 +	</com:TRequiredFieldValidator>
 +
  	</com:TPanel>
 -	
 +
  	<com:TButton ID="button1" Text="Submit!" />
 -	
 +
  	<com:TClientScript>
  	Event.OnLoad(function()
  	{
 diff --git a/tests/FunctionalTests/tickets/tests/Ticket274TestCase.php b/tests/FunctionalTests/tickets/tests/Ticket274TestCase.php index ae976a7f..6a5ae0ff 100644 --- a/tests/FunctionalTests/tickets/tests/Ticket274TestCase.php +++ b/tests/FunctionalTests/tickets/tests/Ticket274TestCase.php @@ -9,15 +9,15 @@ class Ticket274TestCase extends SeleniumTestCase  		$this->assertTitle('Verifying Ticket 274');
  		$this->assertNotVisible($base.'validator1');
  		$this->assertNotVisible($base.'validator2');
 -		
 -		$this->click($base.'button1');		
 +
 +		$this->clickAndWait($base.'button1');
  		$this->assertVisible($base.'validator1');
  		$this->assertNotVisible($base.'validator2');
 -		
 +
  		$this->type($base.'MyDate', 'asd');
 -		$this->click($base.'button1');
 +		$this->clickAndWait($base.'button1');
  		$this->assertVisible($base.'validator1');
 -		$this->assertNotVisible($base.'validator2');		
 +		$this->assertNotVisible($base.'validator2');
  	}
  }
 | 
