summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitattributes4
-rw-r--r--HISTORY5
-rw-r--r--demos/blog/protected/.htaccess1
-rw-r--r--demos/composer/protected/.htaccess1
-rw-r--r--demos/personal/protected/.htaccess1
-rw-r--r--demos/quickstart/protected/pages/Controls/Samples/TDropDownList/Home.page14
-rw-r--r--demos/quickstart/protected/pages/Controls/Samples/TListBox/Home.page14
-rw-r--r--framework/Web/Javascripts/js/validator.js6
-rw-r--r--framework/Web/Javascripts/prado/validation3.js19
-rw-r--r--framework/Web/THttpRequest.php3
-rw-r--r--framework/Web/UI/THtmlWriter.php1
-rw-r--r--framework/Web/UI/WebControls/TDropDownList.php7
-rw-r--r--framework/Web/UI/WebControls/TListBox.php7
-rw-r--r--framework/Web/UI/WebControls/TListControl.php35
-rw-r--r--framework/Web/UI/WebControls/TRadioButton.php84
-rw-r--r--framework/Web/UI/WebControls/TRangeValidator.php59
-rw-r--r--tests/FunctionalTests/validators/protected/pages/StringRangeValidator.page12
17 files changed, 233 insertions, 40 deletions
diff --git a/.gitattributes b/.gitattributes
index 2d8f049d..1347c5c2 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -599,6 +599,7 @@ buildscripts/texbuilder/time-tracker/pages.php -text
buildscripts/texbuilder/time-tracker/preface.tex -text
buildscripts/texbuilder/time-tracker/time-tracker.tex -text
demos/blog/index.php -text
+demos/blog/protected/.htaccess -text
demos/blog/protected/Common/BlogDataModule.php -text
demos/blog/protected/Common/BlogErrorHandler.php -text
demos/blog/protected/Common/BlogException.php -text
@@ -666,6 +667,7 @@ demos/blog/themes/Summer/style.css -text
demos/blog/themes/Winter/style.css -text
demos/composer/index.php -text
demos/composer/index2.php -text
+demos/composer/protected/.htaccess -text
demos/composer/protected/pages/ClassDefinition.php -text
demos/composer/protected/pages/Home.page -text
demos/composer/protected/pages/Home.php -text
@@ -683,6 +685,7 @@ demos/helloworld/protected/.htaccess -text
demos/helloworld/protected/pages/Home.page -text
demos/helloworld/protected/pages/Home.php -text
demos/personal/index.php -text
+demos/personal/protected/.htaccess -text
demos/personal/protected/Pages/Home.page -text
demos/personal/protected/Pages/Home.php -text
demos/personal/protected/Pages/Layout.php -text
@@ -1986,6 +1989,7 @@ tests/FunctionalTests/validators/protected/pages/RangeValidatorString.page -text
tests/FunctionalTests/validators/protected/pages/RegularExpressionValidator.page -text
tests/FunctionalTests/validators/protected/pages/RequiredFieldValidator.page -text
tests/FunctionalTests/validators/protected/pages/RequiredListValidator.page -text
+tests/FunctionalTests/validators/protected/pages/StringRangeValidator.page -text
tests/FunctionalTests/validators/protected/pages/ValidationSummary.page -text
tests/FunctionalTests/validators/protected/pages/config.xml -text
tests/FunctionalTests/validators/tests/ButtonTestCase.php -text
diff --git a/HISTORY b/HISTORY
index 16f45c0a..b11a10bc 100644
--- a/HISTORY
+++ b/HISTORY
@@ -14,18 +14,23 @@ Version 3.0.3 August 6, 2006
============================
BUG: Ticket#264 - Typos in some exception throw statements (Knut)
BUG: Ticket#268 - THttpResponse.redirect() may fail for some browsers (Qiang)
+BUG: Ticket#297 - THttpRequest::constructUrl() encoding bug about array GET parameters (Qiang)
BUG: TDataGrid may complain getting ItemType on a non-object if the grid is not data-bound (Qiang)
BUG: TCheckBox.Value should be converted to string (Qiang)
CHG: Ticket#206 - TBaseValidator.OnValidate is raised only when the validator is visible (Qiang)
+ENH: Ticket#178 - Added TRadioButton.UniqueGroupName property (Qiang)
ENH: Ticket#220 - TClientScripts method to import custom javascript files (Wei)
ENH: Ticket#225 - TRadioButton::getRadioButtonsInGroup() added (Wei)
ENH: Ticket#223 - Use TRequiredFieldValidator for TRadioButtons with GroupName property (Wei)
+ENH: StringLength, multi-byte, check in TRangeValidator (Wei)
+ENH: Ticket#263 - TListBox and TDropDownList support optgroup now (Qiang)
ENH: Ticket#277 - Added TControl.CustomData property (Qiang)
ENH: Ticket#287 - TControl::broadcastEvent() may raise events now (Qiang)
ENH: Ticket#292 - Added THttpRequest::parseUrl() so that it is easier to be extended (Qiang)
ENH: Better URL 'Path' format (Qiang)
NEW: Added TStyleSheet (Wei)
+
Version 3.0.2 July 2, 2006
==========================
BUG: Ticket#182 - List and validator controls cause problem in child classes (Qiang)
diff --git a/demos/blog/protected/.htaccess b/demos/blog/protected/.htaccess
new file mode 100644
index 00000000..e0198322
--- /dev/null
+++ b/demos/blog/protected/.htaccess
@@ -0,0 +1 @@
+deny from all
diff --git a/demos/composer/protected/.htaccess b/demos/composer/protected/.htaccess
new file mode 100644
index 00000000..e0198322
--- /dev/null
+++ b/demos/composer/protected/.htaccess
@@ -0,0 +1 @@
+deny from all
diff --git a/demos/personal/protected/.htaccess b/demos/personal/protected/.htaccess
new file mode 100644
index 00000000..e0198322
--- /dev/null
+++ b/demos/personal/protected/.htaccess
@@ -0,0 +1 @@
+deny from all
diff --git a/demos/quickstart/protected/pages/Controls/Samples/TDropDownList/Home.page b/demos/quickstart/protected/pages/Controls/Samples/TDropDownList/Home.page
index 90dc4a3c..1b0b82d9 100644
--- a/demos/quickstart/protected/pages/Controls/Samples/TDropDownList/Home.page
+++ b/demos/quickstart/protected/pages/Controls/Samples/TDropDownList/Home.page
@@ -184,6 +184,20 @@ Dropdown list causing validation:
</td>
</tr>
+<tr>
+<td class="samplenote">
+Dropdown list with option groups:
+</td>
+<td class="sampleaction">
+<com:TDropDownList>
+ <com:TListItem Value="value 1" Text="item 1" Attributes.Group="group 1"/>
+ <com:TListItem Value="value 2" Text="item 2" Attributes.Group="group 1"/>
+ <com:TListItem Value="value 3" Text="item 3" Attributes.Group="group 2"/>
+ <com:TListItem Value="value 4" Text="item 4" Attributes.Group="group 2"/>
+</com:TDropDownList>
+</td>
+</tr>
+
</table>
</com:TContent> \ No newline at end of file
diff --git a/demos/quickstart/protected/pages/Controls/Samples/TListBox/Home.page b/demos/quickstart/protected/pages/Controls/Samples/TListBox/Home.page
index 9f9bf162..7b729588 100644
--- a/demos/quickstart/protected/pages/Controls/Samples/TListBox/Home.page
+++ b/demos/quickstart/protected/pages/Controls/Samples/TListBox/Home.page
@@ -255,6 +255,20 @@ List box causing validation:
</td>
</tr>
+<tr>
+<td class="samplenote">
+List box with option groups:
+</td>
+<td class="sampleaction">
+<com:TListBox>
+ <com:TListItem Value="value 1" Text="item 1" Attributes.Group="group 1"/>
+ <com:TListItem Value="value 2" Text="item 2" Attributes.Group="group 1"/>
+ <com:TListItem Value="value 3" Text="item 3" Attributes.Group="group 2"/>
+ <com:TListItem Value="value 4" Text="item 4" Attributes.Group="group 2"/>
+</com:TListBox>
+</td>
+</tr>
+
</table>
</com:TContent> \ No newline at end of file
diff --git a/framework/Web/Javascripts/js/validator.js b/framework/Web/Javascripts/js/validator.js
index 8869ab9e..5e896aa1 100644
--- a/framework/Web/Javascripts/js/validator.js
+++ b/framework/Web/Javascripts/js/validator.js
@@ -175,7 +175,11 @@ return true;switch(this.options.Operator)
return true;}});Prado.WebUI.TRangeValidator=Class.extend(Prado.WebUI.TBaseValidator,{evaluateIsValid:function()
{var value=this.getValidationValue();if(value.length<=0)
return true;if(typeof(this.options.DataType)=="undefined")
-this.options.DataType="String";var min=this.convert(this.options.DataType,this.options.MinValue||null);var max=this.convert(this.options.DataType,this.options.MaxValue||null);value=this.convert(this.options.DataType,value);if(value==null)
+this.options.DataType="String";if(this.options.DataType!="StringLength")
+{var min=this.convert(this.options.DataType,this.options.MinValue||null);var max=this.convert(this.options.DataType,this.options.MaxValue||null);value=this.convert(this.options.DataType,value);}
+else
+{var min=this.options.MinValue||0;var max=this.options.MaxValue||Number.POSITIVE_INFINITY;value=value.length;}
+if(value==null)
return false;var valid=true;if(min!=null)
valid=valid&&value>=min;if(max!=null)
valid=valid&&value<=max;return valid;}});Prado.WebUI.TRegularExpressionValidator=Class.extend(Prado.WebUI.TBaseValidator,{evaluateIsValid:function()
diff --git a/framework/Web/Javascripts/prado/validation3.js b/framework/Web/Javascripts/prado/validation3.js
index 9535f8c5..1dba23da 100644
--- a/framework/Web/Javascripts/prado/validation3.js
+++ b/framework/Web/Javascripts/prado/validation3.js
@@ -1113,11 +1113,20 @@ Prado.WebUI.TRangeValidator = Class.extend(Prado.WebUI.TBaseValidator,
return true;
if(typeof(this.options.DataType) == "undefined")
this.options.DataType = "String";
-
- var min = this.convert(this.options.DataType, this.options.MinValue || null);
- var max = this.convert(this.options.DataType, this.options.MaxValue || null);
- value = this.convert(this.options.DataType, value);
-
+
+ if(this.options.DataType != "StringLength")
+ {
+ var min = this.convert(this.options.DataType, this.options.MinValue || null);
+ var max = this.convert(this.options.DataType, this.options.MaxValue || null);
+ value = this.convert(this.options.DataType, value);
+ }
+ else
+ {
+ var min = this.options.MinValue || 0;
+ var max = this.options.MaxValue || Number.POSITIVE_INFINITY;
+ value = value.length;
+ }
+
if(value == null)
return false;
diff --git a/framework/Web/THttpRequest.php b/framework/Web/THttpRequest.php
index 323a4b7c..01827f33 100644
--- a/framework/Web/THttpRequest.php
+++ b/framework/Web/THttpRequest.php
@@ -475,7 +475,7 @@ class THttpRequest extends TApplicationComponent implements IteratorAggregate,Ar
{
$name=urlencode($name.'[]');
foreach($value as $v)
- $url.=$amp.$name.'='.$v;
+ $url.=$amp.$name.'='.urlencode($v);
}
else
$url.=$amp.urlencode($name).'='.urlencode($value);
@@ -547,6 +547,7 @@ class THttpRequest extends TApplicationComponent implements IteratorAggregate,Ar
$getVariables[$serviceID]=$path;
else
$getVariables[$path]='';
+ $index++;
}
}
return $getVariables;
diff --git a/framework/Web/UI/THtmlWriter.php b/framework/Web/UI/THtmlWriter.php
index 0243d365..1dddfd1d 100644
--- a/framework/Web/UI/THtmlWriter.php
+++ b/framework/Web/UI/THtmlWriter.php
@@ -75,6 +75,7 @@ class THtmlWriter extends TApplicationComponent implements ITextWriter
'onchange'=>true,
'src'=>true,
'title'=>true,
+ 'label'=>true,
'value'=>true
);
/**
diff --git a/framework/Web/UI/WebControls/TDropDownList.php b/framework/Web/UI/WebControls/TDropDownList.php
index 860fe69c..04f3780c 100644
--- a/framework/Web/UI/WebControls/TDropDownList.php
+++ b/framework/Web/UI/WebControls/TDropDownList.php
@@ -21,6 +21,13 @@ Prado::using('System.Web.UI.WebControls.TListControl');
* TDropDownList displays a dropdown list on a Web page.
* It inherits all properties and events from {@link TListControl}.
*
+ * Since v3.0.3, TDropDownList starts to support optgroup. To specify an option group for
+ * a list item, set a Group attribute with it,
+ * <code>
+ * $listitem->Attributes->Group="Group Name";
+ * // or <com:TListItem Attributes.Group="Group Name" .../> in template
+ * </code>
+ *
* @author Qiang Xue <qiang.xue@gmail.com>
* @version $Revision: $ $Date: $
* @package System.Web.UI.WebControls
diff --git a/framework/Web/UI/WebControls/TListBox.php b/framework/Web/UI/WebControls/TListBox.php
index 972ebbcb..79b73fb6 100644
--- a/framework/Web/UI/WebControls/TListBox.php
+++ b/framework/Web/UI/WebControls/TListBox.php
@@ -24,6 +24,13 @@ Prado::using('System.Web.UI.WebControls.TListControl');
* The property {@link setRows Rows} specifies how many rows of options are visible
* at a time. See {@link TListControl} for inherited properties.
*
+ * Since v3.0.3, TListBox starts to support optgroup. To specify an option group for
+ * a list item, set a Group attribute with it,
+ * <code>
+ * $listitem->Attributes->Group="Group Name";
+ * // or <com:TListItem Attributes.Group="Group Name" .../> in template
+ * </code>
+ *
* @author Qiang Xue <qiang.xue@gmail.com>
* @version $Revision: $ $Date: $
* @package System.Web.UI.WebControls
diff --git a/framework/Web/UI/WebControls/TListControl.php b/framework/Web/UI/WebControls/TListControl.php
index bd883590..8c1537b0 100644
--- a/framework/Web/UI/WebControls/TListControl.php
+++ b/framework/Web/UI/WebControls/TListControl.php
@@ -643,24 +643,53 @@ abstract class TListControl extends TDataBoundControl
if($this->_items)
{
$writer->writeLine();
+ $previousGroup=null;
foreach($this->_items as $item)
{
if($item->getEnabled())
{
- if($item->getSelected())
- $writer->addAttribute('selected','selected');
- $writer->addAttribute('value',$item->getValue());
if($item->getHasAttributes())
{
+ $group=$item->getAttributes()->remove('Group');
+ if($group!==$previousGroup)
+ {
+ if($previousGroup!==null)
+ {
+ $writer->renderEndTag();
+ $writer->writeLine();
+ $previousGroup=null;
+ }
+ if($group!==null)
+ {
+ $writer->addAttribute('label',$group);
+ $writer->renderBeginTag('optgroup');
+ $writer->writeLine();
+ $previousGroup=$group;
+ }
+ }
foreach($item->getAttributes() as $name=>$value)
$writer->addAttribute($name,$value);
}
+ else if($previousGroup!==null)
+ {
+ $writer->renderEndTag();
+ $writer->writeLine();
+ $previousGroup=null;
+ }
+ if($item->getSelected())
+ $writer->addAttribute('selected','selected');
+ $writer->addAttribute('value',$item->getValue());
$writer->renderBeginTag('option');
$writer->write(THttpUtility::htmlEncode($item->getText()));
$writer->renderEndTag();
$writer->writeLine();
}
}
+ if($previousGroup!==null)
+ {
+ $writer->renderEndTag();
+ $writer->writeLine();
+ }
}
}
diff --git a/framework/Web/UI/WebControls/TRadioButton.php b/framework/Web/UI/WebControls/TRadioButton.php
index 244244cb..9b6786aa 100644
--- a/framework/Web/UI/WebControls/TRadioButton.php
+++ b/framework/Web/UI/WebControls/TRadioButton.php
@@ -68,6 +68,10 @@ class TRadioButton extends TCheckBox
*/
private $_globalID;
/**
+ * @var string previous UniqueID (used to calculate UniqueGroup)
+ */
+ private $_previousUniqueID=null;
+ /**
* @var string the name used to fetch radiobutton post data
*/
private $_uniqueGroupName=null;
@@ -140,12 +144,64 @@ class TRadioButton extends TCheckBox
}
/**
- * Sets the name of the group that the radio button belongs to
+ * Sets the name of the group that the radio button belongs to.
+ * The group is unique among the control's naming container.
* @param string the group name
+ * @see setUniqueGroupName
*/
public function setGroupName($value)
{
$this->setViewState('GroupName',$value,'');
+ $this->_uniqueGroupName=null;
+ }
+
+ /**
+ * @return string the name used to fetch radiobutton post data
+ */
+ public function getUniqueGroupName()
+ {
+ if(($groupName=$this->getViewState('UniqueGroupName',''))!=='')
+ return $groupName;
+ else if(($uniqueID=$this->getUniqueID())!==$this->_previousUniqueID || $this->_uniqueGroupName===null)
+ {
+ $groupName=$this->getGroupName();
+ $this->_previousUniqueID=$uniqueID;
+ if($uniqueID!=='')
+ {
+ if(($pos=strrpos($uniqueID,TControl::ID_SEPARATOR))!==false)
+ {
+ if($groupName!=='')
+ $groupName=substr($uniqueID,0,$pos+1).$groupName;
+ else if($this->getNamingContainer() instanceof TRadioButtonList)
+ $groupName=substr($uniqueID,0,$pos);
+ }
+ if($groupName==='')
+ $groupName=$uniqueID;
+ }
+ $this->_uniqueGroupName=$groupName;
+ }
+ return $this->_uniqueGroupName;
+ }
+
+ /**
+ * Sets the unique group name that the radio button belongs to.
+ * A unique group is a radiobutton group unique among the whole page hierarchy,
+ * while the {@link setGroupName GroupName} specifies a group that is unique
+ * among the control's naming container only.
+ * For example, each cell of a {@link TDataGrid} is a naming container.
+ * If you specify {@link setGroupName GroupName} for a radiobutton in a cell,
+ * it groups together radiobutton within a cell, but not the other, even though
+ * they have the same {@link setGroupName GroupName}.
+ * On the contratry, if {@link setUniqueGroupName UniqueGroupName} is used instead,
+ * it will group all appropriate radio buttons on the whole page hierarchy.
+ * Note, when both {@link setUniqueGroupName UniqueGroupName} and
+ * {@link setGroupName GroupName}, the former takes precedence.
+ * @param string the group name
+ * @see setGroupName
+ */
+ public function setUniqueGroupName($value)
+ {
+ $this->setViewState('UniqueGroupName',$value,'');
}
/**
@@ -178,32 +234,6 @@ class TRadioButton extends TCheckBox
}
/**
- * @return string the name used to fetch radiobutton post data
- */
- private function getUniqueGroupName()
- {
- if($this->_uniqueGroupName===null)
- {
- $groupName=$this->getGroupName();
- $uniqueID=$this->getUniqueID();
- if($uniqueID!=='')
- {
- if(($pos=strrpos($uniqueID,TControl::ID_SEPARATOR))!==false)
- {
- if($groupName!=='')
- $groupName=substr($uniqueID,0,$pos+1).$groupName;
- else if($this->getNamingContainer() instanceof TRadioButtonList)
- $groupName=substr($uniqueID,0,$pos);
- }
- if($groupName==='')
- $groupName=$uniqueID;
- }
- $this->_uniqueGroupName=$groupName;
- }
- return $this->_uniqueGroupName;
- }
-
- /**
* Renders a radiobutton input element.
* @param THtmlWriter the writer for the rendering purpose
* @param string checkbox id
diff --git a/framework/Web/UI/WebControls/TRangeValidator.php b/framework/Web/UI/WebControls/TRangeValidator.php
index 9d23eb5e..b54a1684 100644
--- a/framework/Web/UI/WebControls/TRangeValidator.php
+++ b/framework/Web/UI/WebControls/TRangeValidator.php
@@ -34,6 +34,13 @@ Prado::using('System.Web.UI.WebControls.TBaseValidator');
* by {@link TSimpleDateFormatter}. If the property is not set,
* the GNU date syntax is assumed.
* - <b>String</b> A string data type.
+ * - <b>StringLength</b> check for string length.
+ *
+ * The TRangeValidator allows a special DataType "StringLength" that
+ * can be used to verify minimum and maximum string length. The
+ * {@link setCharset Charset} property can be used to force a particular
+ * charset for comparison. Otherwise, the application charset is used and is
+ * defaulted as UTF-8.
*
* @author Qiang Xue <qiang.xue@gmail.com>
* @version $Revision: $ $Date: $
@@ -96,13 +103,14 @@ class TRangeValidator extends TBaseValidator
}
/**
- * Sets the data type (Integer, Float, Date, String) that the values being
- * compared are converted to before the comparison is made.
+ * Sets the data type (Integer, Float, Date, String, StringLength) that the
+ * values being compared are converted to before the comparison is made.
* @param string the data type
*/
public function setDataType($value)
{
- $this->setViewState('DataType',TPropertyValue::ensureEnum($value,'Integer','Float','Date','String'),'String');
+ $this->setViewState('DataType',TPropertyValue::ensureEnum(
+ $value,'Integer','Float','Date','String', 'StringLength'),'String');
}
/**
@@ -123,6 +131,22 @@ class TRangeValidator extends TBaseValidator
}
/**
+ * @param string charset for string length comparison.
+ */
+ public function setCharset($value)
+ {
+ $this->setViewState('Charset', $value, '');
+ }
+
+ /**
+ * @return string charset for string length comparison.
+ */
+ public function getCharset()
+ {
+ return $this->getViewState('Charset', '');
+ }
+
+ /**
* This method overrides the parent's implementation.
* The validation succeeds if the input data is within the range.
* The validation always succeeds if the input data is empty.
@@ -142,6 +166,8 @@ class TRangeValidator extends TBaseValidator
return $this->isValidFloat($value);
case 'Date':
return $this->isValidDate($value);
+ case 'StringLength':
+ return $this->isValidStringLength($value);
default:
return $this->isValidString($value);
}
@@ -238,6 +264,33 @@ class TRangeValidator extends TBaseValidator
$valid=$valid && (strcmp($value,$maxValue)<=0);
return $valid;
}
+
+ /**
+ * @param string string for comparision
+ * @return boolean true if min and max string length are satisfied.
+ */
+ protected function isValidStringLength($value)
+ {
+ $minValue=$this->getMinValue();
+ $maxValue=$this->getMaxValue();
+
+ $valid=true;
+ $charset = $this->getCharset();
+ if($charset==='')
+ {
+ $app= $this->getApplication()->getGlobalization();
+ $charset = $app ? $app->getCharset() : null;
+ if(!$charset)
+ $charset = 'UTF-8';
+ }
+
+ $length = iconv_strlen($value, $charset);
+ if($minValue!=='')
+ $valid = $valid && $length >= intval($minValue);
+ if($maxValue!=='')
+ $valid = $valid && $length <= intval($maxValue);
+ return $valid;
+ }
/**
* Returns an array of javascript validator options.
diff --git a/tests/FunctionalTests/validators/protected/pages/StringRangeValidator.page b/tests/FunctionalTests/validators/protected/pages/StringRangeValidator.page
new file mode 100644
index 00000000..14f63801
--- /dev/null
+++ b/tests/FunctionalTests/validators/protected/pages/StringRangeValidator.page
@@ -0,0 +1,12 @@
+<com:TContent ID="Content">
+
+ <com:TTextBox ID="text1" />
+ <com:TRangeValidator
+ ControlToValidate="text1"
+ MinValue="5"
+ MaxValue="7"
+ DataType="StringLength"
+ ErrorMessage="String length must be between 5 and 7" />
+ <com:TButton Text="Submit!" />
+
+</com:TContent> \ No newline at end of file