summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitattributes2
-rw-r--r--HISTORY11
-rw-r--r--UPGRADE12
-rw-r--r--buildscripts/jsbuilder/build.php2
-rw-r--r--buildscripts/texbuilder/build.php9
-rw-r--r--demos/quickstart/protected/pages/Advanced/I18N.page124
-rw-r--r--demos/quickstart/protected/pages/Controls/DatePicker.page75
-rw-r--r--demos/quickstart/protected/pages/Controls/Literal.page6
-rw-r--r--demos/quickstart/protected/pages/Controls/Samples/TDatePicker/Home.page61
-rw-r--r--demos/quickstart/protected/pages/Controls/Standard.page4
-rw-r--r--demos/quickstart/protected/pages/Controls/Validation.page28
-rw-r--r--demos/quickstart/protected/pages/GettingStarted/AboutPrado.page8
-rw-r--r--framework/I18N/TDateFormat.php11
-rw-r--r--framework/I18N/core/DateFormat.php12
-rw-r--r--framework/I18N/core/NumberFormat.php7
-rw-r--r--framework/I18N/core/NumberFormatInfo.php18
-rw-r--r--framework/Web/Javascripts/js/validator.js50
-rw-r--r--framework/Web/Javascripts/prado/validation3.js71
-rw-r--r--framework/Web/UI/WebControls/TDataTypeValidator.php13
-rw-r--r--framework/Web/UI/WebControls/TListControlValidator.php132
-rw-r--r--framework/Web/UI/WebControls/TLiteral.php7
-rw-r--r--framework/Web/UI/WebControls/TTable.php2
-rw-r--r--tests/FunctionalTests/validators/tests/DataTypeValidatorTestCase.php49
23 files changed, 573 insertions, 141 deletions
diff --git a/.gitattributes b/.gitattributes
index 1f88e993..4af4a3fe 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -182,6 +182,7 @@ demos/quickstart/protected/pages/Controls/Samples/TDataList/Sample2.page -text
demos/quickstart/protected/pages/Controls/Samples/TDataList/Sample2.php -text
demos/quickstart/protected/pages/Controls/Samples/TDataTypeValidator/Home.page -text
demos/quickstart/protected/pages/Controls/Samples/TDataTypeValidator/Home.php -text
+demos/quickstart/protected/pages/Controls/Samples/TDatePicker/Home.page -text
demos/quickstart/protected/pages/Controls/Samples/TDropDownList/Home.page -text
demos/quickstart/protected/pages/Controls/Samples/TDropDownList/Home.php -text
demos/quickstart/protected/pages/Controls/Samples/TEmailAddressValidator/Home.page -text
@@ -1183,6 +1184,7 @@ tests/FunctionalTests/validators/tests/ButtonTestCase.php -text
tests/FunctionalTests/validators/tests/CheckBoxTestCase.php -text
tests/FunctionalTests/validators/tests/CompareValidatorTestCase.php -text
tests/FunctionalTests/validators/tests/CustomValidatorTestCase.php -text
+tests/FunctionalTests/validators/tests/DataTypeValidatorTestCase.php -text
tests/FunctionalTests/validators/tests/DatePickerTestCase.php -text
tests/FunctionalTests/validators/tests/ImageButtonTestCase.php -text
tests/FunctionalTests/validators/tests/LinkButtonTestCase.php -text
diff --git a/HISTORY b/HISTORY
index bf75c31a..f92ad992 100644
--- a/HISTORY
+++ b/HISTORY
@@ -1,7 +1,5 @@
Version 3.1.0 To be released
============================
-ENH: Format string in classes extending TDataGridColumn can now evaluate an expression (Qiang)
-ENH: Format string in classes extending TListControl can now evaluate an expression (Qiang)
NEW: TOutputCache (Qiang)
NEW: TQueue (Qiang)
NEW: TPageStateFormatter (Qiang)
@@ -10,6 +8,7 @@ NEW: SQLMap (Wei)
Version 3.0.0 May 1, 2006
=========================
+BUG: Ticket#70 - Javascript for TDataTypeValidator added (Wei)
BUG: Ticket#131 - TImageMap and TLinkButton continue to postback even client validator fails (Wei)
BUG: Ticket#135 - TBrowserLogRoute reports wrong timings (Qiang)
BUG: Ticket#137 - The JavasciptLogger does not work (Qiang)
@@ -18,12 +17,20 @@ BUG: Ticket#139 - TThemeManager::setBasePath() should understand an alias path (
BUG: Non-control components can now use expressions in their properties (Qiang)
BUG: TControl.Visible did not make use of overriden getVisible() (Qiang)
BUG: TWizard did not stop navigation upon a validation failure (Qiang)
+BUG: NumberFormat will now zero-fill numbers base on the pattern. (Wei)
ENH: TButton, TImageButton and TLinkButton now implement IButtonControl interface (Qiang)
ENH: TResponse::writeFile takes three additional parameters to allow sending memory data (Qiang)
ENH: TButtonColumn can now be a column of image buttons (Qiang)
+ENH: TLiteral will display body content if Text is empty (Qiang)
+ENH: Format string in classes extending TDataGridColumn can now evaluate an expression (Qiang)
+ENH: Format string in classes extending TListControl can now evaluate an expression (Qiang)
CHG: Rewrote client-side javascript validators, check your client-side validation behaviour (Wei)
CHG: Updated the javascript Prototype library, a few utilties functions REMOVED, may break your existing javascript code. (Wei)
CHG: Build javascript without compression, only comments are removed. (Wei)
+CHG: TDatePicker's date can be set using Date property, it value must be in same format as DateFormat, TimeStamp must be set as integer (wei)
+CHG: TSimpleDateFormatter::parse() now return an integer or null on parse error (Wei)
+NEW: TListControlValidator (Wei)
+
Version 3.0RC2 April 16, 2006
=============================
diff --git a/UPGRADE b/UPGRADE
index b9213eb8..20c91cc9 100644
--- a/UPGRADE
+++ b/UPGRADE
@@ -1,11 +1,11 @@
- Upgrading Instructions for PRADO Framework v3.0.0 RC2
- =====================================================
+ Upgrading Instructions for PRADO Framework v3.0.0
+ =================================================
!!!IMPORTANT!!!
After upgrading, remember to delete everything under
-your PRADO application's cache and runtime directories.
+your PRADO application's assets and runtime directories.
The following upgrading instructions are cumulative. That is,
@@ -14,6 +14,11 @@ version B between A and C, you need to following the instructions
for both A and B.
+Upgrading from v3.0.0 RC2
+-------------------------
+There should be no compatibility issues.
+
+
Upgrading from v3.0.0 RC1
-------------------------
- !!! Expressions appeared in a template are now evaluated in PreRender
@@ -27,6 +32,7 @@ Upgrading from v3.0.0 RC1
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.
diff --git a/buildscripts/jsbuilder/build.php b/buildscripts/jsbuilder/build.php
index 910f0394..cc41c963 100644
--- a/buildscripts/jsbuilder/build.php
+++ b/buildscripts/jsbuilder/build.php
@@ -166,7 +166,7 @@ foreach($libraries as $libFile => $sourceFiles)
echo "Saving file {$libFile}\n";
$builds++;
}
-if(preg_match('/doc*/', $argv[1]))
+if(isset($argv[1]) && preg_match('/doc*/', $argv[1]))
{
$files = "";
foreach($libraries as $lib)
diff --git a/buildscripts/texbuilder/build.php b/buildscripts/texbuilder/build.php
index 4988bccd..4e2d8be6 100644
--- a/buildscripts/texbuilder/build.php
+++ b/buildscripts/texbuilder/build.php
@@ -155,7 +155,12 @@ function include_figure($info, $filename)
function anchor($matches)
{
$page = get_current_path();
- return '\hypertarget{'.$page.'/'.$matches[1].'}{}';
+ return '\hypertarget{'.$page.'/'.strtolower($matches[1]).'}{}';
+}
+
+function texttt($matches)
+{
+ return '\texttt{'.str_replace(array('#','_'),array('\#','\_'), $matches[1]).'}';
}
function get_current_path()
@@ -222,7 +227,7 @@ function parse_html($page,$html)
//text modifiers
$html = preg_replace('/<b>([^<]*)<\/b>/', '\textbf{$1}', $html);
$html = preg_replace('/<i>([^<]*)<\/i>/', '\emph{$1}', $html);
- $html = preg_replace('/<tt>([^<]*)<\/tt>/', '\texttt{$1}', $html);
+ $html = preg_replace_callback('/<tt>([^<]*)<\/tt>/', 'texttt', $html);
//links
$html = preg_replace_callback('/<a[^>]+href="([^"]*)"[^>]*>([^<]*)<\/a>/',
diff --git a/demos/quickstart/protected/pages/Advanced/I18N.page b/demos/quickstart/protected/pages/Advanced/I18N.page
index f37e5cf6..4a220c4c 100644
--- a/demos/quickstart/protected/pages/Advanced/I18N.page
+++ b/demos/quickstart/protected/pages/Advanced/I18N.page
@@ -170,23 +170,145 @@ The time is {time}.
&lt;com:TDateFormat Value="12/01/2005" /&gt;
</com:TTextHighlighter>
-<p>There are of 4 localized date patterns and 4 localized time patterns. They can be used in any combination. If using a combined pattern, the first must be the date, followed by a space, and lastly the time pattern. For example, full date pattern with short time pattern.</p>
+<p>The <tt>Pattern</tt> property accepts 4 predefined localized date patterns and 4 predefined localized time patterns.
+<ul>
+ <li><tt>fulldate</tt></li>
+ <li><tt>longdate</tt></li>
+ <li><tt>mediumdate</tt></li>
+ <li><tt>shortdate</tt></li>
+ <li><tt>fulltime</tt></li>
+ <li><tt>longtime</tt></li>
+ <li><tt>mediumtime</tt></li>
+ <li><tt>shorttime</tt></li>
+</ul>
+The predefined can be used in any combination. If using a combined predefined pattern,
+the first pattern must be the date, followed by a space, and lastly the time pattern.
+For example, full date pattern with short time pattern. The actual ordering of the
+date-time and the actual pattern will be determine automatically from locale data specified
+by the <tt>Culture</tt> property.</p>
<com:TTextHighlighter Language="prado" CssClass="source">
&lt;com:TDateFormat Pattern="fulldate shorttime" /&gt;
</com:TTextHighlighter>
+<p>You can also specify a custom pattern using the following sub-patterns.
+The date/time format is specified by means of a string time pattern. In this pattern, all ASCII letters are reserved as pattern letters, which are defined as the following:
+<com:TTextHighlighter Language="text" CssClass="source">
+ Symbol Meaning Presentation Example
+ ------ ------- ------------ -------
+ G era designator (Text) AD
+ y year (Number) 1996
+ M month in year (Text &amp; Number) July &amp; 07
+ d day in month (Number) 10
+ h hour in am/pm (1~12) (Number) 12
+ H hour in day (0~23) (Number) 0
+ m minute in hour (Number) 30
+ s second in minute (Number) 55
+ E day of week (Text) Tuesday
+ D day in year (Number) 189
+ F day of week in month (Number) 2 (2nd Wed in July)
+ w week in year (Number) 27
+ W week in month (Number) 2
+ a am/pm marker (Text) PM
+ k hour in day (1~24) (Number) 24
+ K hour in am/pm (0~11) (Number) 0
+ z time zone (Time) Pacific Standard Time
+ ' escape for text (Delimiter) 'Date='
+ '' single quote (Literal) 'o''clock'
+</com:TTextHighlighter>
+</p>
+
+<p>The count of pattern letters determine the format.</p>
+
+<p>(Text): 4 letters uses full form, less than 4, use short or abbreviated form
+if it exists. (e.g., "EEEE" produces "Monday", "EEE" produces "Mon")</p>
+
+<p>(Number): the minimum number of digits. Shorter numbers are zero-padded
+ to this amount (e.g. if "m" produces "6", "mm" produces "06"). Year is
+ handled specially; that is, if the count of 'y' is 2, the Year will be
+ truncated to 2 digits. (e.g., if "yyyy" produces "1997", "yy" produces "97".)
+ Unlike other fields, fractional seconds are padded on the right with zero.</p>
+
+<p>(Text and Number): 3 or over, use text, otherwise use number. (e.g.,
+"M" produces "1", "MM" produces "01", "MMM" produces "Jan", and "MMMM"
+produces "January".)</p>
+
+<p>Any characters in the pattern that are not in the ranges of ['a'..'z']
+and ['A'..'Z'] will be treated as quoted text. For instance, characters
+like ':', '.', ' ', and '@' will appear in the resulting time text
+even they are not embraced within single quotes.</p>
+
+<p>Examples using the US locale:
+
+<com:TTextHighlighter Language="text" CssClass="source">
+Format Pattern Result
+-------------- -------
+"yyyy.MM.dd G 'at' HH:mm:ss" -&gt;&gt; 1996.07.10 AD at 15:08:56
+"EEE, MMM d, ''yy" -&gt;&gt; Wed, Jul 10, '96
+"h:mm a" -&gt;&gt; 12:08 PM
+"hh 'o''clock' a, z" -&gt;&gt; 12 o'clock PM, Pacific Daylight Time
+"K:mm a" -&gt;&gt; 0:00 PM
+"yyyy.MMMM.dd G hh:mm a" -&gt;&gt; 1996.July.10 AD 12:08 PM
+</com:TTextHighlighter>
+</p>
+
<p>If the <tt>Value</tt> property is not specified, the current date and time is used.</p>
<h2>TNumberFormat</h2>
<p>PRADO's Internationalization framework provide localized currency formatting and number formatting. Please note that the <tt>TNumberFormat</tt> component provides formatting only, it does not perform current conversion or exchange.</p>
+<p>Numbers can be formatted as currency, percentage, decimal or scientific
+numbers by specifying the <tt>Type</tt> attribute. The valid types are:
+<ul>
+ <li><tt>currency</tt></li>
+ <li><tt>percentage</tt></li>
+ <li><tt>decimal</tt></li>
+ <li><tt>scientific</tt></li>
+</ul>
+</p>
+
<com:TTextHighlighter Language="prado" CssClass="source">
&lt;com:TNumberFormat Type="currency" Value="100" /&gt;
</com:TTextHighlighter>
<p><tt>Culture</tt> and <tt>Currency</tt> properties may be specified to format locale specific numbers. </p>
+<p>If someone from US want to see sales figures from a store in
+Germany (say using the EURO currency), formatted using the german
+ currency, you would need to use the attribute <tt>Culture="de_DE"</tt> to get
+the currency right, e.g. 100,00$. The decimal and grouping separator is
+then also from the <tt>de_DE</tt> locale. This may lead to some confusion because
+people from US uses the "," (comma) as thousand separator. Therefore a <tt>Currency</tt>
+attribute is available, so that the output from the following example results in $100.00
+<com:TTextHighlighter Language="prado" CssClass="source">
+&lt;com:TNumberFormat Type="currency"
+ Culture="en_US" Currency="EUR" Value="100" /&gt;
+</com:TTextHighlighter>
+</p>
+
+<p>The <tt>Pattern</tt> property determines the number of digits, thousand grouping
+positions, the number of decimal points and the decimal position. The actual characters that
+are used to represent the decimal points and thousand points are culture specific
+and will change automatically according to the <tt>Culture</tt> property. The valid
+<tt>Pattern</tt> characters are:
+<ul>
+ <li><tt># (hash)</tt> - represents the optional digits</li>
+ <li><tt>0 (zero)</tt> - represents the mandatory digits, zero left filled</li>
+ <li><tt>. (full stop)</tt> - the position of the decimal point (only 1 decimal point is allowed)</li>
+ <li><tt>, (comma)</tt> - thousand point separation (up to 2 commas are allowed)</li>
+</ul>
+For example, consider the <tt>Value="1234567.12345"</tt> and
+with <tt>Culture="en_US"</tt> (which uses "," for thousand point separator and "." for decimal separators).
+<com:TTextHighlighter Language="text" CssClass="source">
+Pattern Output
+------- ------
+##,###.00 -&gt;&gt; 1,234,567.12
+##,###.## -&gt;&gt; 1,234,567.12345
+##,##.0000 -&gt;&gt; 1,23,45,67.1235
+##,###,##.0 -&gt;&gt; 12,345,67.1
+000,000,000.0 -&gt;&gt; 001,234,567.1
+</com:TTextHighlighter>
+</p>
<h2>TTranslateParameter</h2>
<p>Compound messages, i.e., string substitution, can be accomplished with <tt>TTranslateParameter</tt>.
diff --git a/demos/quickstart/protected/pages/Controls/DatePicker.page b/demos/quickstart/protected/pages/Controls/DatePicker.page
index 5425f2ab..17d28382 100644
--- a/demos/quickstart/protected/pages/Controls/DatePicker.page
+++ b/demos/quickstart/protected/pages/Controls/DatePicker.page
@@ -3,8 +3,81 @@
<h1>TDatePicker</h1>
<com:DocLink ClassPath="System.Web.UI.WebControls.TDatePicker" />
+<p><tt>TDatePicker</tt> 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.
+The format of the date string displayed in the text box is determined by
+the <tt>DateFormat</tt> property. Valid formats are the combination of the
+following tokens:
+
+<com:TTextHighlighter Language="text" CssClass="source">
+Character Format Pattern (en-US)
+---------------------------------------------------------------------
+ d day digit
+ dd padded day digit e.g. 01, 02
+ M month digit
+ MM padded month digit
+ MMM localized abbreviated month names, e.g. Mar, Apr
+ MMMM localized month name, e.g. March, April
+ yy 2 digit year
+ yyyy 4 digit year
+---------------------------------------------------------------------
+</com:TTextHighlighter>
+
+<p>
+The date of the date picker can be set using the <tt>Date</tt> or <tt>Timestamp</tt>
+properties. The <tt>Date</tt> property value must be in the same format as the pattern
+specified in the <tt>DateFormat</tt> property. The <tt>Timestamp</tt> property
+only accepts integers such as the Unix timestamp.
+</p>
+
<p>
-TBD
+TDatePicker has three <tt>Mode</tt> to show the date picker popup.
+ <ul>
+ <li><tt>Basic</tt> - Only shows a text input, focusing on the input shows the date picker.</li>
+ <li><tt>Button</tt> - Shows a button next to the text input, clicking on the button shows the date, button text can be by the <tt>ButtonText</tt> property.</li>
+ <li><tt>ImageButton</tt> - Shows an image next to the text input, clicking on the image shows the date picker, image source can be change through the <tt>ImageUrl</tt> property.</li>
+ </ul>
</p>
+<p>The <tt>CssClass</tt> property can be used to override the css class name
+for the date picker panel. The <tt>CalendarStyle</tt> property changes the overall calendar style.
+The following <tt>CalendarStyle</tt> values are available:
+ <ul>
+ <li><tt>default</tt> - The default calendar style.</li>
+ </ul>
+</p>
+
+<p>The <tt>InputMode</tt> property can be set to "TextBox" or "DropDownList" with
+default as "TextBox". In <tt>DropDownList</tt> mode, in addition to the popup date picker, three
+drop down list (day, month and year) are presented to select the date .
+When <tt>InputMode</tt> equals "DropDownList", the order and appearance of the date, month, and year
+will depend on the pattern specified in <tt>DateFormat</tt> property.
+</p>
+
+<p>The popup date picker can be hidden by specifying <tt>ShowCalendar</tt> as false. Much of the
+text of the popup date picker can be changed to a different language using the <tt>Culture</tt> property.
+</p>
+
+<p>The calendar picker year limit can be set using the <tt>FromYear</tt> and <tt>UpToYear</tt> properties
+where <tt>FromYear</tt> is the starting year and <tt>UpToYear</tt> is the last year selectable.
+The starting day of the week can be changed by the <tt>FirstDayOfWeek</tt> property, with 0 as Sunday, 1 as Monday, etc.
+</p>
+
+<p><b>Note 1:</b> If the <tt>InputMode</tt> is "TextBox", the <tt>DateFormat</tt> should
+only <b>NOT</b> contain <code>MMM</code> or <code>MMMM</code> patterns. The
+server side date parser will not be able to determine the correct date if <code>MMM</code> or
+<code>MMMM</code> are used. When <tt>InputMode</tt> equals "DropDownList", all patterns can be used.</p>
+
+<p><b>Note 2:</b> When the <tt>TDatePicker</tt> is used together
+with a validator, the <tt>DateFormat</tt> property of the validator must be equal to
+the <tt>DateFormat</tt> of the <tt>TDatePicker</tt> <b>AND</b> must set <tt>DataType</tt>="Date"
+on the validator to ensure correct validation. See
+<a href="?page=Controls.Validation#TCompareValidator">TCompareValidator</a>,
+<a href="?page=Controls.Validation#TDataTypeValidator">TDataTypeValidator</a> and
+<a href="?page=Controls.Validation#TRangeValidator">TRangeValidator</a>
+for details.</p>
+
+<com:RunBar PagePath="Controls.Samples.TDatePicker.Home" />
+
</com:TContent> \ No newline at end of file
diff --git a/demos/quickstart/protected/pages/Controls/Literal.page b/demos/quickstart/protected/pages/Controls/Literal.page
index d7b44aff..30a84880 100644
--- a/demos/quickstart/protected/pages/Controls/Literal.page
+++ b/demos/quickstart/protected/pages/Controls/Literal.page
@@ -5,7 +5,7 @@
<p>
<tt>TLiteral</tt> displays a static text on a Web page. <tt>TLiteral</tt> is similar to the <tt>TLabel</tt> control, except that the <tt>TLiteral</tt>
- * control does not allow child controls and has no style properties, such as <tt>BackColor</tt>, <tt>Font</tt>, etc.
+ * control has no style properties, such as <tt>BackColor</tt>, <tt>Font</tt>, etc.
</p>
<p>
@@ -13,6 +13,10 @@ The text displayed by <tt>TLiteral</tt> can be programmatically controlled by se
</p>
<p>
+<tt>TLiteral</tt> will render the contents enclosed within its component tag if <tt>Text</tt> is empty.
+</p>
+
+<p>
Be aware, if <tt>Encode</tt> is false, make sure <tt>Text</tt> does not contain unwanted characters that may bring security vulnerabilities.
</p>
diff --git a/demos/quickstart/protected/pages/Controls/Samples/TDatePicker/Home.page b/demos/quickstart/protected/pages/Controls/Samples/TDatePicker/Home.page
new file mode 100644
index 00000000..e563145d
--- /dev/null
+++ b/demos/quickstart/protected/pages/Controls/Samples/TDatePicker/Home.page
@@ -0,0 +1,61 @@
+<com:TContent ID="body">
+
+<h1>TDatePicker Samples</h1>
+
+<table class="sampletable">
+
+<tr>
+ <td class="samplenote">Default TDatePicker</td>
+ <td class="sampleaction">
+ <com:TDatePicker />
+ </td>
+</tr>
+
+<tr>
+ <td class="samplenote">Button Mode, <br />pre-selected date 20-10-2005</td>
+ <td class="sampleaction">
+ <com:TDatePicker Mode="Button" Date="20-10-2005"/>
+ </td>
+</tr>
+
+<tr>
+ <td class="samplenote">InputMode="DropDownList", <br />custom DateFormat="yyyy/MMM"</td>
+ <td class="sampleaction">
+ <com:TDatePicker DateFormat="yyyy/MMM" InputMode="DropDownList"/>
+ </td>
+</tr>
+
+<tr>
+ <td class="samplenote">InputMode="DropDownList", <br/>custom DateFormat="MMM/yyyy", <br/>Culture="fr"</td>
+ <td class="sampleaction">
+ <com:TDatePicker DateFormat="MMM/yyyy" Culture="fr" InputMode="DropDownList"/>
+ </td>
+</tr>
+
+
+<tr>
+ <td class="samplenote">Custom DateFormat="日期:yyyy年M月d日", <br/>culture="zh_CN", <br />ImageButton mode, <br />pre-selected using Timestamp=&lt;%= @strtotime("-1 year") %&gt;</td>
+ <td class="sampleaction">
+ <com:TDatePicker Mode="ImageButton" Culture="zh_CN"
+ DateFormat="日期:yyyy年M月d日"
+ Timestamp=<%= @strtotime("-1 year") %>/>
+ </td>
+</tr>
+
+<tr>
+ <td class="samplenote">Custom DateFormat="yyyy/MMMM/dd", <br />DropDownList, <br />pre-selected Date="2005/05/15"</td>
+ <td class="sampleaction">
+ <com:TDatePicker DateFormat="yyyy/MMMM/dd" Date="2005/05/15" InputMode="DropDownList"/>
+ </td>
+</tr>
+
+<tr>
+ <td class="samplenote">DropDownList, <br />pre-selected date Timestamp=&lt;%= @strtotime("-1 month") %&gt;</td>
+ <td class="sampleaction">
+ <com:TDatePicker InputMode="DropDownList" Timestamp=<%= @strtotime("-1 month") %>/>
+ </td>
+</tr>
+
+</table>
+
+</com:TContent> \ No newline at end of file
diff --git a/demos/quickstart/protected/pages/Controls/Standard.page b/demos/quickstart/protected/pages/Controls/Standard.page
index 9580a0d7..dfaee35b 100644
--- a/demos/quickstart/protected/pages/Controls/Standard.page
+++ b/demos/quickstart/protected/pages/Controls/Standard.page
@@ -15,7 +15,7 @@
<a href="?page=Controls.ColorPicker">TColorPicker</a> represents an input field taking color values via a color dialog.
</li>
- <li>*
+ <li>
<a href="?page=Controls.DatePicker">TDatePicker</a> represents an input field taking date values via a calendar dialog.
</li>
@@ -27,7 +27,7 @@
<a href="?page=Controls.FileUpload">TFileUpload</a> represents a file upload field. It allows users to upload a file to server.
</li>
- <li>
+ <li>*
<a href="?page=Controls.Head">THead</a> represents the &lt;head&gt; element on an HTML Web page. It is required by a PRADO page should it use themes.
</li>
diff --git a/demos/quickstart/protected/pages/Controls/Validation.page b/demos/quickstart/protected/pages/Controls/Validation.page
index 6fe87fd0..6d83af3d 100644
--- a/demos/quickstart/protected/pages/Controls/Validation.page
+++ b/demos/quickstart/protected/pages/Controls/Validation.page
@@ -26,14 +26,19 @@ Validators share a common set of properties, which are defined in the base class
<li><tt>Dynamic</tt> - the space for displaying the error message is NOT reserved. Therefore, showing up the error message will shift the layout of your page around (usually down).</li>
</ul>
</li>
+<li><tt>ControlCssClass</tt> - the Css class that is applied to the control being validated in case the validation fails.</li>
+<li><tt>FocusOnError</tt> - set focus at the validating place if the validation fails. Defaults to false.</li>
+<li><tt>FocusElementID</tt> - the ID of the HTML element that will receive focus if validation fails and <tt>FocusOnError</tt> is true.</li>
</ul>
+<a name="TRequiredFieldValidator"></a>
<h2>TRequiredFieldValidator</h2>
<p>
TRequiredFieldValidator ensures that the user enters some data in the specified input field. By default, TRequiredFieldValidator will check if the user input is empty or not. The validation fails if the input is empty. By setting <tt>InitialValue</tt>, the validator can check if the user input is different from <tt>InitialValue</tt>. If not, the validation fails.
</p>
<com:RunBar PagePath="Controls.Samples.TRequiredFieldValidator.Home" />
+<a name="TRegularExpressionValidator"></a>
<h2>TRegularExpressionValidator</h2>
<p>
TRegularExpressionValidator verifies the user input against a regular pattern. The validation fails if the input does not match the pattern. The regular expression can be specified by the <tt>RegularExpression</tt> property. Some commonly used regular expressions include:
@@ -58,7 +63,7 @@ Note, TRegularExpressionValidator only checks for nonempty user input. Use a TRe
</p>
<com:RunBar PagePath="Controls.Samples.TRegularExpressionValidator.Home" />
-<h2>TEmailAddressValidator</h2>
+<h2 id="TEmailAddressValidator">TEmailAddressValidator</h2>
<p>
TEmailAddressValidator verifies that the user input is a valid email address. The validator uses a regular expression to check if the input is in a valid email address format. If <tt>CheckMXRecord</tt> is true, the validator will also check whether the MX record indicated by the email address is valid, provided <tt>checkdnsrr()</tt> is available in the installed PHP.
</p>
@@ -66,7 +71,8 @@ TEmailAddressValidator verifies that the user input is a valid email address. Th
Note, if the input being validated is empty, TEmailAddressValidator will not do validation. Use a TRequiredFieldValidator to ensure the value is not empty.
</p>
<com:RunBar PagePath="Controls.Samples.TEmailAddressValidator.Home" />
-
+
+<a name="TCompareValidator"></a>
<h2>TCompareValidator</h2>
<p>
TCompareValidator compares the user input with a constant value specified by <tt>ValueToCompare</tt>, or another user input specified by <tt>ControlToCompare</tt>. The <tt>Operator</tt> property specifies how to compare the values, which includes <tt>Equal</tt>, <tt>NotEqual</tt>, <tt>GreaterThan</tt>, <tt>GreaterThanEqual</tt>, <tt>LessThan</tt> and <tt>LessThanEqual</tt>. Before comparison, the values being compared will be converted to the type specified by <tt>DataType</tt> listed as follows,
@@ -75,26 +81,40 @@ TCompareValidator compares the user input with a constant value specified by <tt
<li><tt>String</tt> - A string data type.</li>
<li><tt>Integer</tt> - A 32-bit signed integer data type.</li>
<li><tt>Float</tt> - A double-precision floating point number data type.</li>
-<li><tt>Currency</tt> - A decimal data type that can contain currency symbols.</li>
<li><tt>Date</tt> - A date data type. The date format can be specified by setting <tt>DateFormat</tt> property, which must be recognizable by <tt>TSimpleDateFormatter</tt>. If the property is not set, the GNU date syntax is assumed.</li>
</ul>
<p>
Note, if the input being validated is empty, TEmailAddressValidator will not do validation. Use a TRequiredFieldValidator to ensure the value is not empty.
</p>
+<p>
+<b>N.B.</b> If validating against a <a href="?page=Controls.DatePicker">TDatePicker</a> the <tt>DataType</tt> must be equal to "Date" and the <tt>DateFormat</tt> property of the validator must be equal to the <tt>DateFormat</tt> of the <a href="?page=Controls.DatePicker">TDatePicker</a>.
+</p>
<com:RunBar PagePath="Controls.Samples.TCompareValidator.Home" />
+<a name="TDataTypeValidator"></a>
<h2>TDataTypeValidator</h2>
<p>
TDataTypeValidator verifies if the input data is of specific type indicated by <tt>DataType</tt>. The data types that can be checked against are the same as those in TCompareValidator.
</p>
+<p>
+<b>N.B.</b> If validating against a <a href="?page=Controls.DatePicker">TDatePicker</a> the <tt>DataType</tt> must be equal to "Date" and the <tt>DateFormat</tt> property of the validator must be equal to the <tt>DateFormat</tt> of the <a href="?page=Controls.DatePicker">TDatePicker</a>.
+</p>
+
+
<com:RunBar PagePath="Controls.Samples.TDataTypeValidator.Home" />
+<a name="TRangeValidator"></a>
<h2>TRangeValidator</h2>
<p>
TRangeValidator verifies whether an input value is within a specified range. TRangeValidator uses three key properties to perform its validation. The <tt>MinValue</tt> and <tt>MaxValue</tt> properties specify the minimum and maximum values of the valid range. The <tt>DataType</tt> property specifies the data type of the value being validated. The value will be first converted into the specified type and then compare with the valid range. The data types that can be checked against are the same as those in TCompareValidator.
</p>
+<p>
+<b>N.B.</b> If validating against a <a href="?page=Controls.DatePicker">TDatePicker</a> the <tt>DataType</tt> must be equal to "Date" and the <tt>DateFormat</tt> property of the validator must be equal to the <tt>DateFormat</tt> of the <a href="?page=Controls.DatePicker">TDatePicker</a>.
+</p>
+
<com:RunBar PagePath="Controls.Samples.TRangeValidator.Home" />
+<a name="TCustomValidator"></a>
<h2>TCustomValidator</h2>
<p>
TCustomValidator performs user-defined validation (either server-side or client-side or both) on an input control.
@@ -118,7 +138,7 @@ function ValidationFunctionName(sender, parameter)
</com:TTextHighlighter>
<com:RunBar PagePath="Controls.Samples.TCustomValidator.Home" />
-
+<a name="TValidationSummary"></a>
<h2>TValidationSummary</h2>
<p>
TValidationSummary displays a summary of validation errors inline on a Web page, in a message box, or both.
diff --git a/demos/quickstart/protected/pages/GettingStarted/AboutPrado.page b/demos/quickstart/protected/pages/GettingStarted/AboutPrado.page
index 5ea7a1cf..6ac58b73 100644
--- a/demos/quickstart/protected/pages/GettingStarted/AboutPrado.page
+++ b/demos/quickstart/protected/pages/GettingStarted/AboutPrado.page
@@ -48,21 +48,21 @@ Without caching techniques, PRADO may not be suitable for developing extremely h
PRADO is described as a unique framework. Its uniqueness mainly lies in the component-based and event-driven programming paradigm that it tries to promote. Although this programming paradigm is not new in desktop application programming and not new in a few Web programming languages, PRADO is perhaps the first PHP framework enabling it.
</p>
<p>
-Most PHP frameworks are trying to establish a loose standard of organizing PHP programming, most preferably the MVC (model-view-controller) model. It is difficult to compare PRADO with these frameworks because they have different focuses. What we can say is, PRADO is more like a high-level language built upon PHP while those MVC frameworks stand for the best programming practices. Both aim to help developers to rapidly complete Web application development. The advantage of PRADO is its rich set of prebuilt powerful components and extreme reusability of the PRADO code, while the advantage of the MVC frameworks is the complete separation of model, view and controller, which greatly facilitates team integration.
+Most PHP frameworks are trying to establish a loose standard of organizing PHP programming, most preferably the MVC (model-view-controller) model. It is difficult to compare PRADO with these frameworks because they have different focuses. What we can say is, PRADO is more like a high-level language built upon PHP, while the MVC frameworks stand for the best programming practices. Both aim to help developers to rapidly complete Web application development. The advantage of PRADO is its rich set of prebuilt powerful components and extreme reusability of the PRADO code, while the advantage of the MVC frameworks is the complete separation of model, view and controller, which greatly facilitates team integration.
</p>
<h2>History of PRADO</h2>
<p>
-The very original inspiration of PRADO came from Apache Tapestry. During the design and implementation, I borrowed many ideas from Borland Delphi and Microsoft ASP.NET. The first version of PRADO came out in June 2004 and was written in PHP 4. Driven by the Zend PHP 5 coding contest, I rewrote PRADO in PHP 5, which proved to be a wise move, thanks to the new object model provided by PHP 5. PRADO won the grand prize in the Zend contest, earning high votes both from the public and from the judges' panel.
+The very original inspiration of PRADO came from Apache Tapestry. During the design and implementation, I borrowed many ideas from Borland Delphi and Microsoft ASP.NET. The first version of PRADO came out in June 2004 and was written in PHP 4. Driven by the Zend PHP 5 coding contest, I rewrote PRADO in PHP 5, which proved to be a wise move, thanks to the new object model provided by PHP 5. PRADO won the grand prize in the Zend contest, earning the highest votes from both the public and the judges' panel.
</p>
<p>
-In August 2004, PRADO was hosted on SourceForge as an open source project. Soon after, the project site <a href="http://www.xisc.com/">xisc.com</a> was announced to public. With the fantastic support of PRADO developer team and PRADO users, PRADO evolved to version 2.0 in mid 2005. In this version, Wei Zhuo contributed to PRADO with the excellent I18 and L10N support.
+In August 2004, PRADO started to be hosted on SourceForge as an open source project. Soon after, the project site <a href="http://www.xisc.com/">xisc.com</a> was announced to public. With the fantastic support of PRADO developer team and PRADO users, PRADO evolved to version 2.0 in mid 2005. In this version, Wei Zhuo contributed to PRADO with the excellent I18N and L10N support.
</p>
<p>
In May 2005, we decided to completely rewrite the PRADO framework to resolve a few fundamental issues found in version 2.0 and to catch up with some cool features available in Microsoft ASP.NET 2.0. After nearly a year's hard work with over 50,000 lines of new code, version 3.0 was finally made available in April 2006.
</p>
<p>
-Starting from version 3.0, significant efforts are allocated to ensure the quality and stability of PRADO. If we say PRADO v2.x and v1.x are proof-of-concept work, we can say PRADO 3.x grows up to a serious project that is suitable for business application development.
+Starting from version 3.0, significant efforts are allocated to ensure the quality and stability of PRADO. If we say PRADO v2.x and v1.x are proof-of-concept work, we can say PRADO 3.x has grown up to a project that is suitable for serious business application development.
</p>
</com:TContent> \ No newline at end of file
diff --git a/framework/I18N/TDateFormat.php b/framework/I18N/TDateFormat.php
index 8ebbce5e..0f5507ab 100644
--- a/framework/I18N/TDateFormat.php
+++ b/framework/I18N/TDateFormat.php
@@ -48,10 +48,9 @@ Prado::using('System.I18N.TI18NControl');
* if the Value property is not specified.
* - <b>Pattern</b>, string,
* <br>Gets or sets the formatting pattern. The predefined patterns are
- * 'full date', 'long date', 'medium date', 'short date', 'full time',
- * 'long time', 'medium time', and 'short time'. Custom patterns can
- * specified when the Pattern property does not match the predefined
- * patterns.
+ * 'fulldate', 'longdate', 'mediumdate', 'shortdate', 'fulltime',
+ * 'longtime', 'mediumtime', and 'shorttime'. Custom patterns can specified
+ * when the Pattern property does not match the predefined patterns.
*
* @author Xiang Wei Zhuo <weizhuo[at]gmail[dot]com>
* @version v1.0, last update on Sat Dec 11 15:25:11 EST 2004
@@ -69,7 +68,7 @@ class TDateFormat extends TI18NControl
* A set of pattern presets and their respective formatting shorthand.
* @var array
*/
- protected $patternPresets = array(
+ static private $_patternPresets = array(
'fulldate'=>'P','full'=>'P',
'longdate'=>'D','long'=>'d',
'mediumdate'=>'p','medium'=>'p',
@@ -132,7 +131,7 @@ class TDateFormat extends TI18NControl
protected function getPreset($string)
{
$string = strtolower($string);
- foreach($this->patternPresets as $pattern => $preset)
+ foreach(self::$_patternPresets as $pattern => $preset)
{
if($string == $pattern)
return $preset;
diff --git a/framework/I18N/core/DateFormat.php b/framework/I18N/core/DateFormat.php
index 9caca03b..142926f4 100644
--- a/framework/I18N/core/DateFormat.php
+++ b/framework/I18N/core/DateFormat.php
@@ -128,7 +128,12 @@ class DateFormat
if($pattern{0} == "'"
&& $pattern{strlen($pattern)-1} == "'")
{
- $tokens[$i] = preg_replace('/(^\')|(\'$)/','',$pattern);
+ $sub = preg_replace('/(^\')|(\'$)/','',$pattern);
+ $tokens[$i] = str_replace('``````','\'',$sub);
+ }
+ else if($pattern == '``````')
+ {
+ $tokens[$i] = '\'';
}
else
{
@@ -145,7 +150,7 @@ class DateFormat
throw new
Exception('function '.$function.' not found.');
}
- }
+ }
}
return I18N_toEncoding(implode('',$tokens), $charset);
@@ -269,6 +274,7 @@ class DateFormat
$token = null;
$text = false;
+ $pattern = preg_replace("/''/", '``````', $pattern);
for($i = 0; $i < strlen($pattern); $i++)
{
@@ -278,7 +284,7 @@ class DateFormat
}
else
{
- $tokens[] = str_replace("''","'",$token);
+ $tokens[] = str_replace("","'",$token);
$token = $pattern{$i};
}
diff --git a/framework/I18N/core/NumberFormat.php b/framework/I18N/core/NumberFormat.php
index bde87e65..d1184f86 100644
--- a/framework/I18N/core/NumberFormat.php
+++ b/framework/I18N/core/NumberFormat.php
@@ -63,7 +63,7 @@ require_once(dirname(__FILE__).'/util.php');
* $ja = new NumberFormat('ja_JP');
*
* //Japanese currency pattern, and using Japanese Yen symbol
- * $ja->format(123.14,'c','JPY'); //ï¿?123 (Yen 123)
+ * $ja->format(123.14,'c','JPY'); //�?123 (Yen 123)
* </code>
* For each culture, the symbol for each currency may be different.
*
@@ -166,12 +166,17 @@ class NumberFormat
$string = substr($string, 0, $dp);
$integer = '';
+
+ $digitSize = $this->formatInfo->getDigitSize();
+
+ $string = str_pad($string, $digitSize, '0',STR_PAD_LEFT);
$len = strlen($string);
$groupSeparator = $this->formatInfo->GroupSeparator;
$groupSize = $this->formatInfo->GroupSizes;
+
$firstGroup = true;
$multiGroup = is_int($groupSize[1]);
$count = 0;
diff --git a/framework/I18N/core/NumberFormatInfo.php b/framework/I18N/core/NumberFormatInfo.php
index 15b9ee5d..3531cc7f 100644
--- a/framework/I18N/core/NumberFormatInfo.php
+++ b/framework/I18N/core/NumberFormatInfo.php
@@ -324,6 +324,13 @@ class NumberFormatInfo
}
}
}
+
+ if(is_int($decimalPos))
+ $digitPattern = substr($pattern,0,$decimalPos);
+ else
+ $digitPattern = $pattern;
+
+ $digitPattern = preg_replace('/[^0]/','',$digitPattern);
$info['groupPos1'] = $groupPos1;
$info['groupSize1'] = $groupSize1;
@@ -331,6 +338,7 @@ class NumberFormatInfo
$info['groupSize2'] = $groupSize2;
$info['decimalPos'] = $decimalPos;
$info['decimalPoints'] = $decimalPoints;
+ $info['digitSize'] = strlen($digitPattern);
return $info;
}
@@ -365,6 +373,16 @@ class NumberFormatInfo
return $this->pattern['decimalPoints'] = $value;
}
+ function getDigitSize()
+ {
+ return $this->pattern['digitSize'];
+ }
+
+ function setDigitSize($value)
+ {
+ $this->pattern['digitSize'] = $value;
+ }
+
/**
* Gets the string to use as the decimal separator.
* @return string decimal separator.
diff --git a/framework/Web/Javascripts/js/validator.js b/framework/Web/Javascripts/js/validator.js
index 38d8a2a4..8659d2e9 100644
--- a/framework/Web/Javascripts/js/validator.js
+++ b/framework/Web/Javascripts/js/validator.js
@@ -353,7 +353,7 @@ validator.manager.updateSummary(validator.group);
this._isObserving[control.id+this.options.ID] = true;
}
},
-trim : function(value)
+_trim : function(value)
{
return typeof(value) == "string" ? value.trim() : "";
},
@@ -393,20 +393,20 @@ getValidationValue : function(control)
{
case 'TDatePicker':
if(control.type == "text")
- return this.trim($F(control));
+ return this._trim($F(control));
else
{
- this.observeDatePickerChanges();
+ this._observeDatePickerChanges();
return Prado.WebUI.TDatePicker.getDropDownDate(control).getTime();
}
default:
- if(this.isListControlType())
- return this.getFirstSelectedListValue();
+ if(this._isListControlType())
+ return this._getFirstSelectedListValue();
else
- return this.trim($F(control));
+ return this._trim($F(control));
}
},
-observeDatePickerChanges : function()
+_observeDatePickerChanges : function()
{
if(Prado.Browser().ie)
{
@@ -416,11 +416,11 @@ this.observeChanges(DatePicker.getMonthListControl(this.control));
this.observeChanges(DatePicker.getYearListControl(this.control));
}
},
-getSelectedValuesAndChecks : function(elements, initialValue)
+_getSelectedValuesAndChecks : function(elements, initialValue)
{
var checked = 0;
var values = [];
-var isSelected = this.isCheckBoxType(elements[0]) ? 'checked' : 'selected';
+var isSelected = this._isCheckBoxType(elements[0]) ? 'checked' : 'selected';
elements.each(function(element)
{
if(element[isSelected] && element.value != initialValue)
@@ -431,7 +431,7 @@ values.push(element.value);
});
return {'checks' : checked, 'values' : values};
},
-getListElements : function()
+_getListElements : function()
{
switch(this.options.ControlType)
{
@@ -440,7 +440,7 @@ var elements = [];
for(var i = 0; i < this.options.TotalItems; i++)
{
var element = $(this.options.ControlToValidate+"_"+i);
-if(this.isCheckBoxType(element))
+if(this._isCheckBoxType(element))
elements.push(element);
}
return elements;
@@ -457,7 +457,7 @@ default:
return [];
}
},
-isCheckBoxType : function(element)
+_isCheckBoxType : function(element)
{
if(element && element.type)
{
@@ -466,18 +466,18 @@ return type == "checkbox" || type == "radio";
}
return false;
},
-isListControlType : function()
+_isListControlType : function()
{
var list = ['TCheckBoxList', 'TRadioButtonList', 'TListBox'];
return list.include(this.options.ControlType);
},
-getFirstSelectedListValue : function()
+_getFirstSelectedListValue : function()
{
var initial = "";
if(typeof(this.options.InitialValue) != "undefined")
initial = this.options.InitialValue;
-var elements = this.getListElements();
-var selection = this.getSelectedValuesAndChecks(elements, initial);
+var elements = this._getListElements();
+var selection = this._getSelectedValuesAndChecks(elements, initial);
return selection.values.length > 0 ? selection.values[0] : initial;
}
}
@@ -493,7 +493,7 @@ return true;
else
{
var a = this.getValidationValue();
-var b = this.trim(this.options.InitialValue);
+var b = this._trim(this.options.InitialValue);
return(a != b);
}
}
@@ -595,16 +595,16 @@ Prado.WebUI.TListControlValidator = Class.extend(Prado.WebUI.TBaseValidator,
{
evaluateIsValid : function()
{
-var elements = this.getListElements();
+var elements = this._getListElements();
if(elements && elements.length <= 0)
return true;
this.observeListElements(elements);
-var selection = this.getSelectedValuesAndChecks(elements);
+var selection = this._getSelectedValuesAndChecks(elements);
return this.isValidList(selection.checks, selection.values);
},
observeListElements : function(elements)
{
-if(Prado.Browser().ie && this.isCheckBoxType(elements[0]))
+if(Prado.Browser().ie && this._isCheckBoxType(elements[0]))
{
var validator = this;
elements.each(function(element)
@@ -640,3 +640,13 @@ required = this.options.Required.split(/,\s*/);
return required;
}
});
+Prado.WebUI.TDataTypeValidator = Class.extend(Prado.WebUI.TBaseValidator,
+{
+evaluateIsValid : function()
+{
+var value = this.getValidationValue();
+if(value.length <= 0)
+return true;
+return this.convert(this.options.DataType, value) != null;
+}
+});
diff --git a/framework/Web/Javascripts/prado/validation3.js b/framework/Web/Javascripts/prado/validation3.js
index 4c189532..40472e7e 100644
--- a/framework/Web/Javascripts/prado/validation3.js
+++ b/framework/Web/Javascripts/prado/validation3.js
@@ -667,9 +667,9 @@ Prado.WebUI.TBaseValidator.prototype =
},
/**
- * @return string trims the string value, empty string if value is not string.
+ * @return string _trims the string value, empty string if value is not string.
*/
- trim : function(value)
+ _trim : function(value)
{
return typeof(value) == "string" ? value.trim() : "";
},
@@ -720,25 +720,26 @@ Prado.WebUI.TBaseValidator.prototype =
{
case 'TDatePicker':
if(control.type == "text")
- return this.trim($F(control));
+ return this._trim($F(control));
else
{
- this.observeDatePickerChanges();
+ this._observeDatePickerChanges();
return Prado.WebUI.TDatePicker.getDropDownDate(control).getTime();
}
default:
- if(this.isListControlType())
- return this.getFirstSelectedListValue();
+ if(this._isListControlType())
+ return this._getFirstSelectedListValue();
else
- return this.trim($F(control));
+ return this._trim($F(control));
}
},
/**
* Observe changes in the drop down list date picker, IE only.
+ * @private
*/
- observeDatePickerChanges : function()
+ _observeDatePickerChanges : function()
{
if(Prado.Browser().ie)
{
@@ -753,12 +754,13 @@ Prado.WebUI.TBaseValidator.prototype =
* Gets numeber selections and their values.
* @return object returns selected values in <tt>values</tt> property
* and number of selections in <tt>checks</tt> property.
+ * @private
*/
- getSelectedValuesAndChecks : function(elements, initialValue)
+ _getSelectedValuesAndChecks : function(elements, initialValue)
{
var checked = 0;
var values = [];
- var isSelected = this.isCheckBoxType(elements[0]) ? 'checked' : 'selected';
+ var isSelected = this._isCheckBoxType(elements[0]) ? 'checked' : 'selected';
elements.each(function(element)
{
if(element[isSelected] && element.value != initialValue)
@@ -774,8 +776,9 @@ Prado.WebUI.TBaseValidator.prototype =
* Gets an array of the list control item input elements, for TCheckBoxList
* checkbox inputs are returned, for TListBox HTML option elements are returned.
* @return array list control option elements.
+ * @private
*/
- getListElements : function()
+ _getListElements : function()
{
switch(this.options.ControlType)
{
@@ -784,7 +787,7 @@ Prado.WebUI.TBaseValidator.prototype =
for(var i = 0; i < this.options.TotalItems; i++)
{
var element = $(this.options.ControlToValidate+"_"+i);
- if(this.isCheckBoxType(element))
+ if(this._isCheckBoxType(element))
elements.push(element);
}
return elements;
@@ -804,8 +807,9 @@ Prado.WebUI.TBaseValidator.prototype =
/**
* @return boolean true if element is of checkbox or radio type.
+ * @private
*/
- isCheckBoxType : function(element)
+ _isCheckBoxType : function(element)
{
if(element && element.type)
{
@@ -817,8 +821,9 @@ Prado.WebUI.TBaseValidator.prototype =
/**
* @return boolean true if control to validate is of some of the TListControl type.
+ * @private
*/
- isListControlType : function()
+ _isListControlType : function()
{
var list = ['TCheckBoxList', 'TRadioButtonList', 'TListBox'];
return list.include(this.options.ControlType);
@@ -826,14 +831,15 @@ Prado.WebUI.TBaseValidator.prototype =
/**
* @return string gets the first selected list value, initial value if none found.
+ * @private
*/
- getFirstSelectedListValue : function()
+ _getFirstSelectedListValue : function()
{
var initial = "";
if(typeof(this.options.InitialValue) != "undefined")
initial = this.options.InitialValue;
- var elements = this.getListElements();
- var selection = this.getSelectedValuesAndChecks(elements, initial);
+ var elements = this._getListElements();
+ var selection = this._getSelectedValuesAndChecks(elements, initial);
return selection.values.length > 0 ? selection.values[0] : initial;
}
}
@@ -862,7 +868,7 @@ Prado.WebUI.TRequiredFieldValidator = Class.extend(Prado.WebUI.TBaseValidator,
else
{
var a = this.getValidationValue();
- var b = this.trim(this.options.InitialValue);
+ var b = this._trim(this.options.InitialValue);
return(a != b);
}
}
@@ -1099,13 +1105,13 @@ Prado.WebUI.TListControlValidator = Class.extend(Prado.WebUI.TBaseValidator,
*/
evaluateIsValid : function()
{
- var elements = this.getListElements();
+ var elements = this._getListElements();
if(elements && elements.length <= 0)
return true;
this.observeListElements(elements);
- var selection = this.getSelectedValuesAndChecks(elements);
+ var selection = this._getSelectedValuesAndChecks(elements);
return this.isValidList(selection.checks, selection.values);
},
@@ -1114,7 +1120,7 @@ Prado.WebUI.TListControlValidator = Class.extend(Prado.WebUI.TBaseValidator,
*/
observeListElements : function(elements)
{
- if(Prado.Browser().ie && this.isCheckBoxType(elements[0]))
+ if(Prado.Browser().ie && this._isCheckBoxType(elements[0]))
{
var validator = this;
elements.each(function(element)
@@ -1165,6 +1171,25 @@ Prado.WebUI.TListControlValidator = Class.extend(Prado.WebUI.TBaseValidator,
}
});
-
-
+/**
+ * TDataTypeValidator verifies if the input data is of the type specified
+ * by <tt>DataType</tt> option.
+ * The following data types are supported:
+ * - <b>Integer</b> A 32-bit signed integer data type.
+ * - <b>Float</b> A double-precision floating point number data type.
+ * - <b>Date</b> A date data type.
+ * - <b>String</b> A string data type.
+ * For <b>Date</b> type, the option <tt>DateFormat</tt>
+ * will be used to determine how to parse the date string.
+ */
+Prado.WebUI.TDataTypeValidator = Class.extend(Prado.WebUI.TBaseValidator,
+{
+ evaluateIsValid : function()
+ {
+ var value = this.getValidationValue();
+ if(value.length <= 0)
+ return true;
+ return this.convert(this.options.DataType, value) != null;
+ }
+});
diff --git a/framework/Web/UI/WebControls/TDataTypeValidator.php b/framework/Web/UI/WebControls/TDataTypeValidator.php
index d78be7bf..ebcaace7 100644
--- a/framework/Web/UI/WebControls/TDataTypeValidator.php
+++ b/framework/Web/UI/WebControls/TDataTypeValidator.php
@@ -99,6 +99,19 @@ class TDataTypeValidator extends TBaseValidator
}
/**
+ * Returns an array of javascript validator options.
+ * @return array javascript validator options.
+ */
+ protected function getClientScriptOptions()
+ {
+ $options = parent::getClientScriptOptions();
+ $options['DataType']=$this->getDataType();
+ if(($dateFormat=$this->getDateFormat())!=='')
+ $options['DateFormat']=$dateFormat;
+ return $options;
+ }
+
+ /**
* This method overrides the parent's implementation.
* The validation succeeds if the input data is of valid type.
* The validation always succeeds if ControlToValidate is not specified
diff --git a/framework/Web/UI/WebControls/TListControlValidator.php b/framework/Web/UI/WebControls/TListControlValidator.php
index 9264e891..0d0940ab 100644
--- a/framework/Web/UI/WebControls/TListControlValidator.php
+++ b/framework/Web/UI/WebControls/TListControlValidator.php
@@ -1,5 +1,4 @@
<?php
-
/**
* TListControlValidator class file
*
@@ -10,7 +9,7 @@
* @version $Revision: $ $Date: $
* @package System.Web.UI.WebControls
*/
-
+
/**
* Using TBaseValidator class
*/
@@ -18,9 +17,9 @@ Prado::using('System.Web.UI.WebControls.TBaseValidator');
/**
* TListControlValidator class.
- *
+ *
* TListControlValidator checks the number of selection and their values
- * for a <b>TListControl that allows multiple selection</b>.
+ * for a <b>TListControl that allows multiple selection</b>.
*
* You can specify the minimum or maximum (or both) number of selections
* required using the {@link setMinSelection MinSelection} and
@@ -37,9 +36,9 @@ Prado::using('System.Web.UI.WebControls.TBaseValidator');
* <com:TListItem Text="item3" Value="value3" />
* </com:TListBox>
*
- * <com:TRequiredListValidator
+ * <com:TRequiredListValidator
* ControlToValidate="listbox"
- * MinSelection="2"
+ * MinSelection="2"
* ErrorMessage="Please select at least 2" />
* </code>
* - "value1" must be selected <b>and</b> at least 1 other
@@ -47,14 +46,14 @@ Prado::using('System.Web.UI.WebControls.TBaseValidator');
* <com:TCheckBoxList ID="checkboxes">
* <com:TListItem Text="item1" Value="value1" />
* <com:TListItem Text="item2" Value="value2" />
- * <com:TListItem Text="item3" Value="value3" />
+ * <com:TListItem Text="item3" Value="value3" />
* </com:TCheckBoxList>
*
- * <com:TRequiredListValidator
+ * <com:TRequiredListValidator
* ControlToValidate="checkboxes"
* RequiredSelections="value1"
* MinSelection="2"
- * ErrorMessage="Please select 'item1' and at least 1 other" />
+ * ErrorMessage="Please select 'item1' and at least 1 other" />
* </code>
*
* @author Xiang Wei Zhuo <weizhuo[at]gmail.com>
@@ -63,112 +62,115 @@ Prado::using('System.Web.UI.WebControls.TBaseValidator');
* @since 3.0
*/
class TListControlValidator extends TBaseValidator
-{
+{
/**
- * @return int min number of selections
+ * @return integer min number of selections. Defaults to -1, meaning not set.
*/
- function getMinSelection()
+ public function getMinSelection()
{
- return $this->getViewState('MinSelection','');
+ return $this->getViewState('MinSelection',-1);
}
-
+
/**
- * @param int minimum number of selections.
+ * @param integer minimum number of selections.
*/
- function setMinSelection($value)
+ public function setMinSelection($value)
{
- $this->setViewState('MinSelection',$value,'');
+ if(($value=TPropertyValue::ensureInteger($value))<0)
+ $value=-1;
+ $this->setViewState('MinSelection',$value,-1);
}
-
+
/**
- * @return int max number of selections
+ * @return integer max number of selections. Defaults to -1, meaning not set.
*/
- function getMaxSelection()
+ public function getMaxSelection()
{
- return $this->getViewState('MaxSelection','');
+ return $this->getViewState('MaxSelection',-1);
}
-
+
/**
- * @param int max number of selections.
- */
- function setMaxSelection($value)
+ * @param integer max number of selections.
+ */
+ public function setMaxSelection($value)
{
- $this->setViewState('MaxSelection',$value,'');
+ if(($value=TPropertyValue::ensureInteger($value))<0)
+ $value=-1;
+ $this->setViewState('MaxSelection',$value,-1);
}
/**
* Get a comma separated list of required selected values.
- * @return string comma separated list of required values.
+ * @return string comma separated list of required values.
*/
- function getRequiredSelections()
+ public function getRequiredSelections()
{
return $this->getViewState('RequiredSelections','');
}
-
+
/**
* Set the list of required values, using aa comma separated list.
- * @param string comma separated list of required values.
+ * @param string comma separated list of required values.
*/
- function setRequiredSelections($value)
+ public function setRequiredSelections($value)
{
$this->setViewState('RequiredSelections',$value,'');
- }
-
+ }
+
/**
* This method overrides the parent's implementation.
* The validation succeeds if the input component changes its data
* from the InitialValue or the input component is not given.
* @return boolean whether the validation succeeds
*/
- public function evaluateIsValid()
- {
+ protected function evaluateIsValid()
+ {
$control=$this->getValidationTarget();
-
+
$exists = true;
- list($count, $values) = $this->getSelection($control);
+ $values = $this->getSelection($control);
+ $count = count($values);
$required = $this->getRequiredValues();
-
+
//if required, check the values
if(!empty($required))
{
- if(count($values) < count($required) )
+ if($count < count($required) )
return false;
foreach($required as $require)
$exists = $exists && in_array($require, $values);
}
-
+
$min = $this->getMinSelection();
$max = $this->getMaxSelection();
-
- if($min !== '' && $max !=- '')
- return $exists && $count >= intval($min) && $count <= intval($max);
- else if($min === '' && $max !== '')
- return $exists && $count <= intval($max);
- else if($min !== '' && $max === '')
- return $exists && $count >= intval($min);
- }
-
+
+ if($min !== -1 && $max !== -1)
+ return $exists && $count >= $min && $count <= $max;
+ else if($min === -1 && $max !== -1)
+ return $exists && $count <= $max;
+ else if($min !== -1 && $max === -1)
+ return $exists && $count >= $min;
+ else
+ return $exists;
+ }
+
/**
* @param TListControl control to validate
* @return array number of selected values and its values.
*/
protected function getSelection($control)
{
- $count = 0;
$values = array();
//get the data
foreach($control->getItems() as $item)
{
- if($item->getSelected())
- {
- $count++;
+ if($item->getSelected())
$values[] = $item->getValue();
- }
}
- return array($count, $values);
+ return $values;
}
-
+
/**
* @return array list of required values.
*/
@@ -180,7 +182,7 @@ class TListControlValidator extends TBaseValidator
$required = preg_split('/,\s*/', $string);
return $required;
}
-
+
/**
* Returns an array of javascript validator options.
* @return array javascript validator options.
@@ -189,26 +191,26 @@ class TListControlValidator extends TBaseValidator
{
$options = parent::getClientScriptOptions();
$control = $this->getValidationTarget();
-
+
if(!$control instanceof TListControl)
{
throw new TConfigurationException(
- 'tlistcontrolvalidator_invalid_control',
+ 'tlistcontrolvalidator_invalid_control',
$this->getID(),$this->getControlToValidate(), get_class($control));
}
-
+
$min = $this->getMinSelection();
$max = $this->getMaxSelection();
- if($min !== '')
- $options['Min']= intval($min);
- if($max !== '')
- $options['Max']= intval($max);
+ if($min !== -1)
+ $options['Min']= $min;
+ if($max !== -1)
+ $options['Max']= $max;
$required = $this->getRequiredSelections();
if(strlen($required) > 0)
$options['Required']= $required;
$options['TotalItems'] = $control->getItemCount();
return $options;
- }
+ }
}
?> \ No newline at end of file
diff --git a/framework/Web/UI/WebControls/TLiteral.php b/framework/Web/UI/WebControls/TLiteral.php
index 35888676..f335499f 100644
--- a/framework/Web/UI/WebControls/TLiteral.php
+++ b/framework/Web/UI/WebControls/TLiteral.php
@@ -15,11 +15,14 @@
*
* TLiteral displays a static text on the Web page.
* TLiteral is similar to the TLabel control, except that the TLiteral
- * control does not allow child controls and do not have style properties (e.g. BackColor, Font, etc.)
+ * control does not have style properties (e.g. BackColor, Font, etc.)
* You can programmatically control the text displayed in the control by setting
* the {@link setText Text} property. The text displayed may be HTML-encoded
* if the {@link setEncode Encode} property is set true (defaults to false).
*
+ * TLiteral will render the contents enclosed within its component tag
+ * if {@link setText Text} is empty.
+ *
* Note, if {@link setEncode Encode} is false, make sure {@link setText Text}
* does not contain unwanted characters that may bring security vulnerabilities.
*
@@ -76,6 +79,8 @@ class TLiteral extends TControl
else
$writer->write($text);
}
+ else
+ parent::renderContents($writer);
}
}
diff --git a/framework/Web/UI/WebControls/TTable.php b/framework/Web/UI/WebControls/TTable.php
index fe01649c..4fcbb6fb 100644
--- a/framework/Web/UI/WebControls/TTable.php
+++ b/framework/Web/UI/WebControls/TTable.php
@@ -45,7 +45,7 @@ Prado::using('System.Web.UI.WebControls.TTableRow');
* <com:TTableCell Text="content" />
* <com:TTableCell Text="content" />
* </com:TTableRow>
- * <com:TTable>
+ * </com:TTable>
* </code>
* The above can also be accomplished in code as follows,
* <code>
diff --git a/tests/FunctionalTests/validators/tests/DataTypeValidatorTestCase.php b/tests/FunctionalTests/validators/tests/DataTypeValidatorTestCase.php
new file mode 100644
index 00000000..1ca3de5d
--- /dev/null
+++ b/tests/FunctionalTests/validators/tests/DataTypeValidatorTestCase.php
@@ -0,0 +1,49 @@
+<?php
+/*
+ * Created on 25/04/2006
+ */
+
+class DataTypeValidatorTestCase extends SeleniumTestCase
+{
+ function test()
+ {
+ $base = "ctl0_Content_";
+ $this->open("validators/index.php?page=DataTypeValidator", "");
+ $this->verifyTextPresent("Data Type Validator Tests", "");
+ $this->clickAndWait("//input[@type='submit' and @value='submit!']", "");
+
+ $this->assertNotVisible("{$base}validator1");
+ $this->assertNotVisible("{$base}validator2");
+ $this->assertNotVisible("{$base}validator3");
+
+ $this->type("{$base}textbox1", "a");
+ $this->type("{$base}textbox2", "b");
+ $this->type("{$base}textbox3", "c");
+ $this->click("//input[@type='submit' and @value='submit!']", "");
+
+ $this->assertVisible("{$base}validator1");
+ $this->assertVisible("{$base}validator2");
+ $this->assertVisible("{$base}validator3");
+
+ $this->type("{$base}textbox1", "12");
+ $this->type("{$base}textbox2", "12.5");
+ $this->type("{$base}textbox3", "2/10/2005");
+ $this->clickAndWait("//input[@type='submit' and @value='submit!']", "");
+
+ $this->assertNotVisible("{$base}validator1");
+ $this->assertNotVisible("{$base}validator2");
+ $this->assertNotVisible("{$base}validator3");
+
+ $this->type("{$base}textbox1", "12.2");
+ $this->type("{$base}textbox2", "-12.5");
+ $this->type("{$base}textbox3", "2/13/2005");
+ $this->click("//input[@type='submit' and @value='submit!']", "");
+
+ $this->assertVisible("{$base}validator1");
+ $this->assertNotVisible("{$base}validator2");
+ $this->assertVisible("{$base}validator3");
+ }
+
+}
+
+?>