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');
}
}
|