summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorxue <>2006-07-02 18:05:42 +0000
committerxue <>2006-07-02 18:05:42 +0000
commit7e002c23edc5fb5db70935591aa6adeda25fc7fb (patch)
tree846feb337405448cc1559c2e7b4ed6f85798e0c7
parent618293517861b69334cd470068199394120cd20a (diff)
Merge from 3.0 branch till 1224.
-rw-r--r--.gitattributes5
-rw-r--r--HISTORY6
-rw-r--r--demos/quickstart/protected/application.xml4
-rw-r--r--demos/quickstart/protected/comments/CommentList.php58
-rw-r--r--demos/quickstart/protected/comments/CommentList.tpl105
-rw-r--r--demos/quickstart/protected/comments/QuickStartComments.php175
-rw-r--r--demos/quickstart/protected/comments/comments.dbbin6144 -> 0 bytes
-rw-r--r--demos/quickstart/protected/controls/Layout.tpl1
-rw-r--r--framework/Util/TLogRouter.php4
-rw-r--r--framework/Web/Javascripts/colorpicker/colorpicker.js4
-rwxr-xr-xframework/Web/Javascripts/colorpicker/spacer.gifbin0 -> 43 bytes
-rw-r--r--framework/Web/Javascripts/datepicker/datepicker.js8
-rw-r--r--framework/Web/Javascripts/js/colorpicker.js4
-rw-r--r--framework/Web/Javascripts/js/datepicker.js6
-rw-r--r--framework/Web/UI/WebControls/TBaseValidator.php23
-rw-r--r--framework/Web/UI/WebControls/TCheckBox.php46
-rw-r--r--framework/Web/UI/WebControls/THtmlArea.php2
-rw-r--r--framework/Web/UI/WebControls/TRadioButton.php3
-rw-r--r--tests/FunctionalTests/index.php2
-rwxr-xr-xtests/FunctionalTests/tickets/protected/pages/Home.page3
-rwxr-xr-xtests/FunctionalTests/tickets/protected/pages/Home.php34
-rw-r--r--tests/FunctionalTests/tickets/protected/pages/Ticket200.page6
-rw-r--r--tests/FunctionalTests/tickets/protected/pages/Ticket200.php16
-rw-r--r--tests/FunctionalTests/tickets/protected/pages/Ticket202.page19
-rw-r--r--tests/FunctionalTests/tickets/protected/pages/Ticket205.page26
-rw-r--r--tests/FunctionalTests/tickets/protected/pages/Ticket205.php11
-rw-r--r--tests/FunctionalTests/tickets/protected/pages/Ticket207.page24
-rw-r--r--tests/FunctionalTests/tickets/protected/pages/Ticket227.page4
-rw-r--r--tests/FunctionalTests/tickets/protected/pages/Ticket246.page17
-rw-r--r--tests/FunctionalTests/tickets/tests/Ticket205TestCase.php23
-rw-r--r--tests/FunctionalTests/tickets/tests/Ticket207TestCase.php37
-rw-r--r--tests/FunctionalTests/tickets/tests/Ticket227TestCase.php12
-rw-r--r--tests/FunctionalTests/tickets/tests/Ticket246TestCase.php12
-rwxr-xr-xtests/FunctionalTests/validators/protected/pages/Home.page3
-rwxr-xr-xtests/FunctionalTests/validators/protected/pages/Home.php34
35 files changed, 359 insertions, 378 deletions
diff --git a/.gitattributes b/.gitattributes
index 04b42000..ea016ff1 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -696,10 +696,6 @@ demos/quickstart/index.php -text
demos/quickstart/index2.php -text
demos/quickstart/protected/.htaccess -text
demos/quickstart/protected/application.xml -text
-demos/quickstart/protected/comments/CommentList.php -text
-demos/quickstart/protected/comments/CommentList.tpl -text
-demos/quickstart/protected/comments/QuickStartComments.php -text
-demos/quickstart/protected/comments/comments.db -text
demos/quickstart/protected/controls/DocLink.php -text
demos/quickstart/protected/controls/Layout.php -text
demos/quickstart/protected/controls/Layout.tpl -text
@@ -1500,6 +1496,7 @@ framework/Web/Javascripts/colorpicker/colorpicker.js -text
framework/Web/Javascripts/colorpicker/default.css -text
framework/Web/Javascripts/colorpicker/hue.gif -text
framework/Web/Javascripts/colorpicker/slider.gif -text
+framework/Web/Javascripts/colorpicker/spacer.gif -text
framework/Web/Javascripts/colorpicker/target_black.gif -text
framework/Web/Javascripts/colorpicker/target_white.gif -text
framework/Web/Javascripts/datepicker/calendar.png -text
diff --git a/HISTORY b/HISTORY
index e3d35ac6..d2b8721f 100644
--- a/HISTORY
+++ b/HISTORY
@@ -13,11 +13,14 @@ Version 3.0.2 July 2, 2006
==========================
BUG: Ticket#182 - List and validator controls cause problem in child classes (Qiang)
BUG: Ticket#191 - Duplicated postbacks occur when using TButton with validators (Qiang)
+BUG: Ticket#207 - Validators ClientSide.OnError triggered twice (Wei)
BUG: Ticket#213 - PRADO Requirements Checker charset error (Qiang)
+BUG: Ticket#227 - Enabled property doesn't works with THtmlArea (Wei)
BUG: Ticket#234 - Postback target could be out of date (Qiang)
BUG: Ticket#239 - Ondeactivate handler for the first View of MultiView is always fired (Qiang)
BUG: Ticket#244 - redirect() needs absolute URL (Qiang)
BUG: Ticket#245 - getIsSecureConnection() is not working correctly (Qiang)
+BUG: Ticket#246 - TDatePicker wrong popup position in scrolled div (Wei)
BUG: Ticket#260 - Wrong value of a configuration option in setUseTransparentSessionID (Qiang)
CHG: ensureChildControls() is now invoked in TControl::initRecursive (Qiang)
CHG: Postback enabled control will always disable default client-side browser action. (Qiang)
@@ -28,12 +31,15 @@ ENH: Ticket#231 - Added TButton.ButtonType property to allow reset button (Qiang
ENH: Ticket#232 - Allow <%# %> and <%= %> embedded within property values (Qiang)
ENH: Ticket#256 - Datagrid columns can now be accessed via IDs (Qiang)
ENH: Ticket#257 - OnSelectedIndexChanged event of TDataList and TDataGrid now passes the original command parameter (Qiang)
+ENH: Ticket#262 - Added TCheckBox.Value property (Qiang)
ENH: TRepeater, TDataList and TDataGrid will store data indices in DataKeys if DataKeyField is not set. (Qiang)
ENH: Added TPageService.BasePageClass property (Qiang)
ENH: Added TDataGrid.EmptyTemplate property (Qiang)
ENH: Added paging feature to all TDataBoundControl-derived controls (Qiang)
+ENH: ClientSide.ObserveChanges="false" to only revalidate client side validator when control changes (Wei)
NEW: Added TPager (Qiang)
NEW: Added Dreamweaver taglib extension (Stanislav, Qiang)
+NEW: Prado Command line script to create a new project, see framework/prado-cli.php (Wei)
Version 3.0.1 June 4, 2006
==========================
diff --git a/demos/quickstart/protected/application.xml b/demos/quickstart/protected/application.xml
index 79ee4529..3e2374d8 100644
--- a/demos/quickstart/protected/application.xml
+++ b/demos/quickstart/protected/application.xml
@@ -16,12 +16,8 @@
</modules>
<paths>
<using namespace="Application.controls.*" />
- <using namespace="Application.comments.*" />
</paths>
<services>
<service id="page" class="TPageService" DefaultPage="GettingStarted.Introduction" />
</services>
- <parameters>
- <parameter id="enableNewComment" value="false" />
- </parameters>
</application> \ No newline at end of file
diff --git a/demos/quickstart/protected/comments/CommentList.php b/demos/quickstart/protected/comments/CommentList.php
deleted file mode 100644
index 3bfb7239..00000000
--- a/demos/quickstart/protected/comments/CommentList.php
+++ /dev/null
@@ -1,58 +0,0 @@
-<?php
-
-Prado::using('System.I18N.*');
-
-/**
- * CommentList class.
- *
- * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
- * @version : $ Sat May 27 17:53:15 AZOST 2006 $
- * @package Demo.Quickstart.comments
- * @since 3.0
- */
-class CommentList extends TTemplateControl
-{
- private $_exclude = array(
- 'Comments',
- 'Markdown',
- 'Search',
- 'GettingStarted.Introduction');
-
- private $_quickstart;
-
- public function onLoad($param)
- {
- parent::onLoad($param);
-
- $this->_quickstart = new QuickStartComments();
-
- $page = $this->getService()->getRequestedPagePath();
-
- $this->listComments($page);
- }
-
- protected function listComments($page)
- {
- $this->comments->setDataSource($this->_quickstart->getComments($page));
- $this->comments->dataBind();
- }
-
- public function addComment_Clicked($sender, $param)
- {
- $page = $this->getService()->getRequestedPagePath();
- $this->_quickstart->addNewComment($page,
- $this->email->getText(), $this->content->getText());
- $this->multiView1->setActiveViewIndex(1);
- }
-
- public function setVisible($value)
- {
- $page = $this->getService()->getRequestedPagePath();
- if(in_array($page, $this->_exclude))
- parent::setVisible(false);
- else
- parent::setVisible($value);
- }
-}
-
-?> \ No newline at end of file
diff --git a/demos/quickstart/protected/comments/CommentList.tpl b/demos/quickstart/protected/comments/CommentList.tpl
deleted file mode 100644
index 06cddd1e..00000000
--- a/demos/quickstart/protected/comments/CommentList.tpl
+++ /dev/null
@@ -1,105 +0,0 @@
-<div id="comments">
-
-<com:TRepeater ID="comments">
- <prop:HeaderTemplate>
- <h2 class="comment_header">Comments
- <com:TPlaceHolder Visible=<%$ enableNewComment %> >
- <span style="font-size:0.8em">( <a href="#add_comments">Add your comments</a> )</span>
- </com:TPlaceHolder>
- </h2>
- </prop:HeaderTemplate>
- <prop:ItemTemplate>
- <div class="comment_item comment_item<%# $this->ItemIndex%2 %>">
- <span class="number" id="comment_<%# $this->ItemIndex+1 %>"><%# $this->ItemIndex+1 %></span>
- <span class="email">
- <%# str_replace(array('@','.'),array(' at ',' dot '), strtoupper($this->DataItem['email'])) %>
- </span>
- <span class="date">
- <com:TDateFormat Value=<%# intval($this->DataItem['date_added']) %> />
- </span>
- <div class="comment">
- <com:TSafeHtml>
- <com:TMarkdown CssClass="source">
- <%# $this->DataItem['comment'] %>
- </com:TMarkdown>
- </com:TSafeHtml>
- </div>
- </div>
- </prop:ItemTemplate>
-</com:TRepeater>
-
-<com:TMultiView ID="multiView1" ActiveViewIndex="0" Visible=<%$ enableNewComment %> >
- <com:TView ID="view1">
- <div id="add_comments" class="add_comments">
- <h3>Post a comment</h3>
- <p><strong>Note:</strong>
- Please only use the comments in relation to this page for
- <ul>
- <li>questions/critcisms/suggestions on the documentation,</li>
- <li>small notes that can solve or clarify a particular problem or task.</li>
- </ul>
- If you experience errors please <a href="http://trac.pradosoft.com/newticket">file a ticket</a>
- or <a href="http://www.pradosoft.com/forum/">ask at the forum</a>.
- Please use the <a href="http://pradosoft.com/wiki/index.php/Main_Page">Prado wiki</a> for longer pieces and detailed solutions</a>.
- </p>
- <p>Comments will be periodically reviewed, integrated into the documentation and removed.
- You may use <a href="?page=Markdown">markdown syntax</a> in your comment. </p>
-
- <div class="comment_email">
- <com:TLabel ID="email_label" Text="Email:" ForControl="email"/>
- <com:TTextBox ID="email" />
- <com:TRequiredFieldValidator
- ControlToValidate="email"
- Display="Dynamic"
- ErrorMessage="An email address is required." />
- <com:TEmailAddressValidator
- ControlToValidate="email"
- CheckMXRecord="false"
- Display="Dynamic"
- ErrorMessage="Please provide your email address."/>
- </div>
- <div class="comment_content">
- <com:TLabel ID="content_label" Text="Comment:" ForControl="content"/>
- <com:TTextBox ID="content" TextMode="MultiLine"/>
- <div class="please_add">
- <com:TRequiredFieldValidator
- ControlToValidate="content"
- Display="Dynamic"
- ErrorMessage="Please add your comment." />
- </div>
- </div>
- <com:TPlaceHolder Visible=<%= strlen($this->content->Text) %> >
- <div class="comment_preview">
- <h3 style="margin:0">Preview comment</h3>
- <div class="comment">
- <com:TSafeHtml>
- <com:TMarkdown CssClass="source">
- <%= $this->content->Text %>
- </com:TMarkdown>
- </com:TSafeHtml>
- </div>
- </div>
- </com:TPlaceHolder>
- <div class="add_comment">
- <com:TButton ID="previewComment" Text="Preview Comment" />
- <com:TButton ID="addComment" Text="Add Comment" OnClick="addComment_Clicked"/>
- </div>
- </div>
- </com:TView>
- <com:TView ID="view2">
- <div class="comment_added">
- <div class="thank">Thank you, your comment is quequed for moderation.</div>
- <div class="comment_preview">
- <h3 style="margin:0">Preview comment</h3>
- <div class="comment">
- <com:TSafeHtml>
- <com:TMarkdown CssClass="source">
- <%= $this->content->Text %>
- </com:TMarkdown>
- </com:TSafeHtml>
- </div>
- </div>
- </div>
- </com:TView>
-</com:TMultiView>
-</div> \ No newline at end of file
diff --git a/demos/quickstart/protected/comments/QuickStartComments.php b/demos/quickstart/protected/comments/QuickStartComments.php
deleted file mode 100644
index 7b504caf..00000000
--- a/demos/quickstart/protected/comments/QuickStartComments.php
+++ /dev/null
@@ -1,175 +0,0 @@
-<?php
-
-/**
- * QuickStartComments class.
- *
- * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
- * @version : $ Sat May 27 16:49:19 AZOST 2006 $
- * @package Demos.QuickStart.comments
- * @since 3.0
- */
-class QuickStartComments
-{
- /**
- * @var string sqlite database source.
- */
- private $_database;
- /**
- * @var sqlite connection.
- */
- private $_connection;
-
- /**
- * Sets the sqlite comment database file.
- */
- public function __construct()
- {
- $this->_database = realpath(dirname(__FILE__).'/comments.db');
- }
-
- /**
- * Closed the database connection.
- */
- public function __destruct()
- {
- if(!is_null($this->_connection))
- sqlite_close($this->_connection);
- }
-
- /**
- * @return resource sqlite database connection.
- */
- protected function getConnection()
- {
- if(is_null($this->_connection))
- $this->_connection = sqlite_open($this->_database);
- return $this->_connection;
- }
-
- /**
- * Quote database input data.
- */
- protected function quote($value)
- {
- return sqlite_escape_string($value);
- }
-
- /**
- * Executes an sqlite query.
- * @param string SQL
- * @return mixed query results.
- */
- protected function query($sql)
- {
- return sqlite_query($this->getConnection(), $sql);
- }
-
- /**
- * Returns a row from the sqlite result.
- * @param resource sqlite result
- * @return array database record.
- */
- protected function fetch($resource)
- {
- if($resource !== false)
- return sqlite_fetch_array($resource);
- else
- return false;
- }
-
- /**
- * Fetch all the records for given SQL query.
- * @param string SQL query.
- * @return array result set.
- */
- protected function fetchAll($sql)
- {
- $rs = $this->query($sql);
- $rows = array();
- while($row = $this->fetch($rs))
- $rows[] = $row;
- return $rows;
- }
-
- /**
- * Returns all the comments for a given page.
- * @param string specific page comments
- * @return array list of comments
- */
- public function getComments($pageID)
- {
- $page = $this->quote($pageID);
- $sql = "SELECT * FROM comments WHERE page='$page' AND approved = 1 ORDER BY date_added ASC";
- return $this->fetchAll($sql);
- }
-
- /**
- * Adds a new comment for moderation.
- * @param string ID of the page to comment belongs
- * @param string email address of the commenter
- * @param string comment contents
- */
- public function addNewComment($pageID, $email, $comment)
- {
- $page = $this->quote($pageID);
- $email = $this->quote($email);
- $comment = $this->quote($comment);
- $date_added = time();
- $sql = <<<EOD
- INSERT INTO comments(page, email, comment, date_added)
- VALUES ('$page', '$email', '$comment', '$date_added')
-EOD;
- return $this->query($sql);
- }
-
- /**
- * Update an existing comment.
- * @param string comment ID
- * @param string page ID
- * @param string email address
- * @param string updated comment.
- */
- public function updateComment($commentID, $page, $email, $content)
- {
- $ID = intval($commentID);
- $email = $this->quote($email);
- $comment = $this->quote($content);
- $page = $this->quote($page);
- $sql = <<<EOD
- UPDATE comments SET
- email = '$email', comment = '$comment', page = '$page'
- WHERE id = $ID;
-EOD;
- $this->query($sql);
- }
-
- /**
- * Delete a comment.
- * @param string comment ID
- */
- public function deleteComment($commentID)
- {
- $ID = intval($commentID);
- $this->query("DELETE FROM comments WHERE id=$ID");
- }
-
- /**
- * @return array all the quequed comments.
- */
- public function getQuequedComments()
- {
- return $this->fetchAll("SELECT * FROM comments WHERE approved != 1");
- }
-
- /**
- * Approve a quequed comment.
- * @param string comment ID.
- */
- public function approveComment($commentID)
- {
- $ID = intval($commentID);
- $this->query("UPDATE comments SET approved = 1 WHERE id=$ID");
- }
-}
-
-?> \ No newline at end of file
diff --git a/demos/quickstart/protected/comments/comments.db b/demos/quickstart/protected/comments/comments.db
deleted file mode 100644
index b81d7123..00000000
--- a/demos/quickstart/protected/comments/comments.db
+++ /dev/null
Binary files differ
diff --git a/demos/quickstart/protected/controls/Layout.tpl b/demos/quickstart/protected/controls/Layout.tpl
index 733bf6e1..52ab5bc4 100644
--- a/demos/quickstart/protected/controls/Layout.tpl
+++ b/demos/quickstart/protected/controls/Layout.tpl
@@ -32,7 +32,6 @@
<div id="content">
<com:TContentPlaceHolder ID="body" />
</div>
-<com:CommentList Visible="true" />
</td>
</tr>
</table>
diff --git a/framework/Util/TLogRouter.php b/framework/Util/TLogRouter.php
index fe0d2964..a9d37b2f 100644
--- a/framework/Util/TLogRouter.php
+++ b/framework/Util/TLogRouter.php
@@ -22,8 +22,8 @@
* or an external configuration file specified by {@link setConfigFile ConfigFile}.
* The format is as follows,
* <code>
- * &lt;route class="TFileLogRoute" Categories="System.Web.UI" Levels="Warning" /&gt;
- * &lt;route class="TEmailLogRoute" Categories="Application" Levels="Fatal" Emails="admin@pradosoft.com" /&gt;
+ * <route class="TFileLogRoute" Categories="System.Web.UI" Levels="Warning" />
+ * <route class="TEmailLogRoute" Categories="Application" Levels="Fatal" Emails="admin@pradosoft.com" />
* </code>
* You can specify multiple routes with different filtering conditions and different
* targets, even if the routes are of the same type.
diff --git a/framework/Web/Javascripts/colorpicker/colorpicker.js b/framework/Web/Javascripts/colorpicker/colorpicker.js
index 06cfb037..acf5531c 100644
--- a/framework/Web/Javascripts/colorpicker/colorpicker.js
+++ b/framework/Web/Javascripts/colorpicker/colorpicker.js
@@ -68,7 +68,7 @@ Object.extend(Prado.WebUI.TColorPicker.prototype,
{
var constructor = mode == "Basic" ? "getBasicPickerContainer": "getFullPickerContainer"
this.element = this[constructor](this.options['ID'], this.options['Palette'])
- document.body.appendChild(this.element);
+ this.input.parentNode.appendChild(this.element);
this.element.style.display = "none";
if(Prado.Browser().ie)
@@ -90,7 +90,7 @@ Object.extend(Prado.WebUI.TColorPicker.prototype,
{
if(!this.showing)
{
- var pos = Position.cumulativeOffset(this.input);
+ var pos = Position.positionedOffset(this.input);
pos[1] += this.input.offsetHeight;
this.element.style.top = (pos[1]-1) + "px";
diff --git a/framework/Web/Javascripts/colorpicker/spacer.gif b/framework/Web/Javascripts/colorpicker/spacer.gif
new file mode 100755
index 00000000..fc256098
--- /dev/null
+++ b/framework/Web/Javascripts/colorpicker/spacer.gif
Binary files differ
diff --git a/framework/Web/Javascripts/datepicker/datepicker.js b/framework/Web/Javascripts/datepicker/datepicker.js
index 11bee07e..4525c1ba 100644
--- a/framework/Web/Javascripts/datepicker/datepicker.js
+++ b/framework/Web/Javascripts/datepicker/datepicker.js
@@ -247,10 +247,10 @@ Prado.WebUI.TDatePicker.prototype =
this.iePopUp.style.position = "absolute"
this.iePopUp.scrolling="no"
this.iePopUp.frameBorder="0"
- document.body.appendChild(this.iePopUp);
+ this.control.parentNode.appendChild(this.iePopUp);
}
- document.body.appendChild(this._calDiv);
+ this.control.parentNode.appendChild(this._calDiv);
this.update();
this.updateHeader();
@@ -542,8 +542,8 @@ Prado.WebUI.TDatePicker.prototype =
if(!this.showing)
{
- var pos = Position.cumulativeOffset(this.control);
-
+ var pos = Position.positionedOffset(this.control);
+
pos[1] += this.getDatePickerOffsetHeight();
this._calDiv.style.display = "block";
diff --git a/framework/Web/Javascripts/js/colorpicker.js b/framework/Web/Javascripts/js/colorpicker.js
index 47949239..8429b5e6 100644
--- a/framework/Web/Javascripts/js/colorpicker.js
+++ b/framework/Web/Javascripts/js/colorpicker.js
@@ -33,7 +33,7 @@ Event.observe(this.button,"click",this._buttonOnClick);Event.observe(this.input,
{var mode=this.options['Mode'];if(this.element==null)
{var constructor=mode=="Basic"?"getBasicPickerContainer":"getFullPickerContainer"
this.element=this[constructor](this.options['ID'],this.options['Palette'])
-document.body.appendChild(this.element);this.element.style.display="none";if(Prado.Browser().ie)
+this.input.parentNode.appendChild(this.element);this.element.style.display="none";if(Prado.Browser().ie)
{this.iePopUp=document.createElement('iframe');this.iePopUp.src=Prado.WebUI.TColorPicker.UIImages['button.gif'];this.iePopUp.style.position="absolute"
this.iePopUp.scrolling="no"
this.iePopUp.frameBorder="0"
@@ -42,7 +42,7 @@ if(mode=="Full")
this.initializeFullPicker();}
this.show(mode);},show:function(type)
{if(!this.showing)
-{var pos=Position.cumulativeOffset(this.input);pos[1]+=this.input.offsetHeight;this.element.style.top=(pos[1]-1)+"px";this.element.style.left=pos[0]+"px";this.element.style.display="block";this.ieHack(type);this._documentClickEvent=this.hideOnClick.bindEvent(this,type);this._documentKeyDownEvent=this.keyPressed.bindEvent(this,type);Event.observe(document.body,"click",this._documentClickEvent);Event.observe(document,"keydown",this._documentKeyDownEvent);this.showing=true;if(type=="Full")
+{var pos=Position.positionedOffset(this.input);pos[1]+=this.input.offsetHeight;this.element.style.top=(pos[1]-1)+"px";this.element.style.left=pos[0]+"px";this.element.style.display="block";this.ieHack(type);this._documentClickEvent=this.hideOnClick.bindEvent(this,type);this._documentKeyDownEvent=this.keyPressed.bindEvent(this,type);Event.observe(document.body,"click",this._documentClickEvent);Event.observe(document,"keydown",this._documentKeyDownEvent);this.showing=true;if(type=="Full")
{this.observeMouseMovement();var color=Rico.Color.createFromHex(this.input.value);this.inputs.oldColor.style.backgroundColor=color.asHex();this.setColor(color,true);}}},hide:function(event)
{if(this.showing)
{if(this.iePopUp)
diff --git a/framework/Web/Javascripts/js/datepicker.js b/framework/Web/Javascripts/js/datepicker.js
index 090f3cbd..bbf81293 100644
--- a/framework/Web/Javascripts/js/datepicker.js
+++ b/framework/Web/Javascripts/js/datepicker.js
@@ -22,8 +22,8 @@ div=document.createElement("div");div.className="calendarFooter";this._calDiv.ap
{this.iePopUp=document.createElement('iframe');this.iePopUp.src=Prado.WebUI.TDatePicker.spacer;this.iePopUp.style.position="absolute"
this.iePopUp.scrolling="no"
this.iePopUp.frameBorder="0"
-document.body.appendChild(this.iePopUp);}
-document.body.appendChild(this._calDiv);this.update();this.updateHeader();this.ieHack(true);previousMonth.hideFocus=true;nextMonth.hideFocus=true;todayButton.hideFocus=true;Event.observe(previousMonth,"click",this.prevMonth.bindEvent(this));Event.observe(nextMonth,"click",this.nextMonth.bindEvent(this));Event.observe(todayButton,"click",this.selectToday.bindEvent(this));Event.observe(this._monthSelect,"change",this.monthSelect.bindEvent(this));Event.observe(this._yearSelect,"change",this.yearSelect.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)
+this.control.parentNode.appendChild(this.iePopUp);}
+this.control.parentNode.appendChild(this._calDiv);this.update();this.updateHeader();this.ieHack(true);previousMonth.hideFocus=true;nextMonth.hideFocus=true;todayButton.hideFocus=true;Event.observe(previousMonth,"click",this.prevMonth.bindEvent(this));Event.observe(nextMonth,"click",this.nextMonth.bindEvent(this));Event.observe(todayButton,"click",this.selectToday.bindEvent(this));Event.observe(this._monthSelect,"change",this.monthSelect.bindEvent(this));Event.observe(this._yearSelect,"change",this.yearSelect.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)
{if(this.iePopUp)
{this.iePopUp.style.display="block";this.iePopUp.style.top=(this._calDiv.offsetTop-1)+"px";this.iePopUp.style.left=(this._calDiv.offsetLeft-1)+"px";this.iePopUp.style.width=Math.abs(this._calDiv.offsetWidth-2)+"px";this.iePopUp.style.height=(this._calDiv.offsetHeight+1)+"px";if(cleanup)this.iePopUp.style.display="none";}},keyPressed:function(ev)
{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)
@@ -92,7 +92,7 @@ this.onChange();},getElement:function()
{if(this.options.InputMode=="TextBox")
return this.control.offsetHeight;var control=Prado.WebUI.TDatePicker.getDayListControl(this.control);if(control)return control.offsetHeight;var control=Prado.WebUI.TDatePicker.getMonthListControl(this.control);if(control)return control.offsetHeight;var control=Prado.WebUI.TDatePicker.getYearListControl(this.control);if(control)return control.offsetHeight;return 0;},show:function()
{this.create();if(!this.showing)
-{var pos=Position.cumulativeOffset(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);Event.observe(document.body,"click",this.documentClickEvent);var date=this.getDateFromInput();if(date)
+{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);Event.observe(document.body,"click",this.documentClickEvent);var date=this.getDateFromInput();if(date)
{this.selectedDate=date;this.setSelectedDate(date);}
Event.observe(document,"keydown",this.documentKeyDownEvent);this.showing=true;}},getDateFromInput:function()
{if(this.options.InputMode=="TextBox")
diff --git a/framework/Web/UI/WebControls/TBaseValidator.php b/framework/Web/UI/WebControls/TBaseValidator.php
index a0801d4c..9366de62 100644
--- a/framework/Web/UI/WebControls/TBaseValidator.php
+++ b/framework/Web/UI/WebControls/TBaseValidator.php
@@ -124,7 +124,7 @@ abstract class TBaseValidator extends TLabel implements IValidator
}
/**
- * Adds attributes to renderer. Calls parent implementation and renders the
+ * Adds attributes to renderer. Calls parent implementation and renders the
* client control scripts.
* @param THtmlWriter the renderer
*/
@@ -237,7 +237,7 @@ abstract class TBaseValidator extends TLabel implements IValidator
$this->registerClientScriptValidator();
$this->updateControlCssClass();
}
-
+
/**
* Update the ControlToValidate component's css class depending
* if the ControlCssClass property is set, and whether this is valid.
@@ -635,6 +635,25 @@ class TClientSideValidatorOptions extends TClientSideOptions
}
/**
+ * @param boolean true to revalidate when the control to validate changes value.
+ */
+ public function setObserveChanges($value)
+ {
+ $this->setOption('ObserveChanges', TPropertyValue::ensureBoolean($value));
+ }
+
+ /**
+ * @return boolean true to observe changes.
+ */
+ public function getObserveChanges()
+ {
+ if(($option=$this->getOption('ObserveChanges'))!==null)
+ return $option;
+ else
+ return true;
+ }
+
+ /**
* Ensure the string is a valid javascript function. If the string begins
* with "javascript:" valid javascript function is assumed, otherwise the
* code block is enclosed with "function(validator, sender){ }" block.
diff --git a/framework/Web/UI/WebControls/TCheckBox.php b/framework/Web/UI/WebControls/TCheckBox.php
index 6fe562c9..04733f95 100644
--- a/framework/Web/UI/WebControls/TCheckBox.php
+++ b/framework/Web/UI/WebControls/TCheckBox.php
@@ -60,13 +60,10 @@ class TCheckBox extends TWebControl implements IPostBackDataHandler, IValidatabl
public function loadPostData($key,$values)
{
$checked=$this->getChecked();
- if(isset($values[$key])!=$checked)
- {
- $this->setChecked(!$checked);
- return true;
- }
- else
- return false;
+ if($newChecked=isset($values[$key]))
+ $this->setValue($values[$key]);
+ $this->setChecked($newChecked);
+ return $newChecked!==$checked;
}
/**
@@ -134,6 +131,22 @@ class TCheckBox extends TWebControl implements IPostBackDataHandler, IValidatabl
}
/**
+ * @return string the value of the checkbox. Defaults to empty.
+ */
+ public function getValue()
+ {
+ return $this->getViewState('Value','');
+ }
+
+ /**
+ * @param string the value of the checkbox
+ */
+ public function setValue($value)
+ {
+ $this->setViewState('Value',$value,'');
+ }
+
+ /**
* @return string the alignment (Left or Right) of the text caption, defaults to Right.
*/
public function getTextAlign()
@@ -309,13 +322,18 @@ class TCheckBox extends TWebControl implements IPostBackDataHandler, IValidatabl
*/
protected function getValueAttribute()
{
- $attributes=$this->getViewState('InputAttributes',null);
- if($attributes && $attributes->contains('value'))
- return $attributes->itemAt('value');
- else if($this->hasAttribute('value'))
- return $this->getAttribute('value');
+ if(($value=$this->getValue())!=='')
+ return $value;
else
- return '';
+ {
+ $attributes=$this->getViewState('InputAttributes',null);
+ if($attributes && $attributes->contains('value'))
+ return $attributes->itemAt('value');
+ else if($this->hasAttribute('value'))
+ return $this->getAttribute('value');
+ else
+ return '';
+ }
}
/**
@@ -345,7 +363,7 @@ class TCheckBox extends TWebControl implements IPostBackDataHandler, IValidatabl
if($clientID!=='')
$writer->addAttribute('id',$clientID);
$writer->addAttribute('type','checkbox');
- if(($value = $this->getValueAttribute()) !== '')
+ if(($value=$this->getValueAttribute())!=='')
$writer->addAttribute('value',$value);
if(!empty($onclick))
$writer->addAttribute('onclick',$onclick);
diff --git a/framework/Web/UI/WebControls/THtmlArea.php b/framework/Web/UI/WebControls/THtmlArea.php
index 09f8328c..2a1e311d 100644
--- a/framework/Web/UI/WebControls/THtmlArea.php
+++ b/framework/Web/UI/WebControls/THtmlArea.php
@@ -219,7 +219,7 @@ class THtmlArea extends TTextBox
*/
protected function addAttributesToRender($writer)
{
- if($this->getEnableVisualEdit())
+ if($this->getEnableVisualEdit() && $this->getEnabled(true))
{
$writer->addAttribute('id',$this->getClientID());
$this->registerEditorClientScript($writer);
diff --git a/framework/Web/UI/WebControls/TRadioButton.php b/framework/Web/UI/WebControls/TRadioButton.php
index bb3e0658..2bbdf22e 100644
--- a/framework/Web/UI/WebControls/TRadioButton.php
+++ b/framework/Web/UI/WebControls/TRadioButton.php
@@ -101,6 +101,9 @@ class TRadioButton extends TCheckBox
$this->setViewState('GroupName',$value,'');
}
+ /**
+ * @return string the value attribute to be rendered
+ */
protected function getValueAttribute()
{
if(($value=parent::getValueAttribute())==='')
diff --git a/tests/FunctionalTests/index.php b/tests/FunctionalTests/index.php
index ceba599a..c4b3123b 100644
--- a/tests/FunctionalTests/index.php
+++ b/tests/FunctionalTests/index.php
@@ -14,4 +14,4 @@ Prado Functional Test Suites
<li><a href="features.php">Tests of New Features</a> (<a href="features/index.php">list of new features</a>)</li>
</ul>
</body>
-</html> \ No newline at end of file
+</html>
diff --git a/tests/FunctionalTests/tickets/protected/pages/Home.page b/tests/FunctionalTests/tickets/protected/pages/Home.page
new file mode 100755
index 00000000..d4ac162c
--- /dev/null
+++ b/tests/FunctionalTests/tickets/protected/pages/Home.page
@@ -0,0 +1,3 @@
+<com:TContent ID="Content">
+<com:TBulletedList ID="List" DisplayMode="HyperLink"/>
+</com:TContent> \ No newline at end of file
diff --git a/tests/FunctionalTests/tickets/protected/pages/Home.php b/tests/FunctionalTests/tickets/protected/pages/Home.php
new file mode 100755
index 00000000..37804419
--- /dev/null
+++ b/tests/FunctionalTests/tickets/protected/pages/Home.php
@@ -0,0 +1,34 @@
+<?php
+
+class Home extends TPage
+{
+ public function onLoad($param)
+ {
+ parent::onLoad($param);
+ $list=$this->getPageList(dirname(__FILE__),'');
+ $this->List->DataSource=$list;
+ $this->List->dataBind();
+ }
+
+ protected function getPageList($directory,$basePath)
+ {
+ $list=array();
+ $folder=@opendir($directory);
+ while($entry=@readdir($folder))
+ {
+ if($entry[0]==='.')
+ continue;
+ else if(is_file($directory.'/'.$entry))
+ {
+ if(($page=basename($entry,'.page'))!==$entry && strpos($page,'.')===false)
+ $list['?page='.$basePath.$page]=$basePath.$page;
+ }
+ else
+ $list=array_merge($list,$this->getPageList($directory.'/'.$entry,$basePath.$entry.'.'));
+ }
+ closedir($folder);
+ return $list;
+ }
+}
+
+?> \ No newline at end of file
diff --git a/tests/FunctionalTests/tickets/protected/pages/Ticket200.page b/tests/FunctionalTests/tickets/protected/pages/Ticket200.page
new file mode 100644
index 00000000..76c60f40
--- /dev/null
+++ b/tests/FunctionalTests/tickets/protected/pages/Ticket200.page
@@ -0,0 +1,6 @@
+<com:TContent ID="Content">
+ <com:TLinkButton ID="linkButton1" Text="Click Me" OnClick="linkButton1_Clicked" />
+ <p style="height:500px"><br /></p>
+ <com:TLinkButton ID="linkButton2" Text="Click Me" OnClick="linkButton2_Clicked" />
+ <p style="height:500px"></br></p>
+</com:TContent> \ No newline at end of file
diff --git a/tests/FunctionalTests/tickets/protected/pages/Ticket200.php b/tests/FunctionalTests/tickets/protected/pages/Ticket200.php
new file mode 100644
index 00000000..a80a3b8a
--- /dev/null
+++ b/tests/FunctionalTests/tickets/protected/pages/Ticket200.php
@@ -0,0 +1,16 @@
+<?php
+
+class Ticket200 extends TPage
+{
+ function linkButton1_Clicked()
+ {
+
+ }
+
+ function linkButton2_Clicked()
+ {
+
+ }
+}
+
+?> \ No newline at end of file
diff --git a/tests/FunctionalTests/tickets/protected/pages/Ticket202.page b/tests/FunctionalTests/tickets/protected/pages/Ticket202.page
new file mode 100644
index 00000000..ae984c2d
--- /dev/null
+++ b/tests/FunctionalTests/tickets/protected/pages/Ticket202.page
@@ -0,0 +1,19 @@
+<%@ MasterPage="" %>
+<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" >
+
+<com:THead ID="Head">
+ <meta http-equiv="content-language" content="en"/>
+ <meta http-equiv="Expires" content="0">
+</com:THead>
+
+<body>
+<com:TForm>
+<com:TTextBox MaxLength="50" />
+<com:TTextBox ID="CustomerNumber" />
+<com:TButton Text="Search" />
+<com:TDataTypeValidator DataType="Integer" ControlToValidate="CustomerNumber" ErrorMessage="Customernumber must be a number." />
+
+</com:TForm>
+</body>
+</html> \ No newline at end of file
diff --git a/tests/FunctionalTests/tickets/protected/pages/Ticket205.page b/tests/FunctionalTests/tickets/protected/pages/Ticket205.page
new file mode 100644
index 00000000..1481a227
--- /dev/null
+++ b/tests/FunctionalTests/tickets/protected/pages/Ticket205.page
@@ -0,0 +1,26 @@
+<com:TContent ID="Content">
+ <h3>TCustomValidator not enabling ControlCssClass or prop:ClientSide.OnError after postback.</h3>
+ <style>
+ .required
+ {
+ border: 1px solid red;
+ background-color: pink;
+ }
+ </style>
+ <script type="text/javascript">
+ function clientSideCustomValidate(sender, param)
+ {
+ return param == "Prado";
+ }
+ </script>
+ <com:TTextBox ID="textbox1" />
+ <com:TCustomValidator
+ ID="validator1"
+ ControlToValidate="textbox1"
+ ControlCssClass="required"
+ OnServerValidate="customValidate"
+ ClientValidationFunction="clientSideCustomValidate"
+ ClientSide.OnError="alert('error')"
+ ErrorMessage="must equal to 'Prado'" />
+ <com:TButton ID="button1" Text="Submit!" />
+</com:TContent> \ No newline at end of file
diff --git a/tests/FunctionalTests/tickets/protected/pages/Ticket205.php b/tests/FunctionalTests/tickets/protected/pages/Ticket205.php
new file mode 100644
index 00000000..6145af9a
--- /dev/null
+++ b/tests/FunctionalTests/tickets/protected/pages/Ticket205.php
@@ -0,0 +1,11 @@
+<?php
+
+class Ticket205 extends TPage
+{
+ function customValidate($sender, $param)
+ {
+ $param->IsValid = $this->textbox1->Text == "Prado";
+ }
+}
+
+?> \ No newline at end of file
diff --git a/tests/FunctionalTests/tickets/protected/pages/Ticket207.page b/tests/FunctionalTests/tickets/protected/pages/Ticket207.page
new file mode 100644
index 00000000..556c5aae
--- /dev/null
+++ b/tests/FunctionalTests/tickets/protected/pages/Ticket207.page
@@ -0,0 +1,24 @@
+<com:TContent ID="Content">
+ <h2>Validators ClientSide.OnError triggered twice</h2>
+ <h3>Use ClientSide.ObseveChanges="false"</h3>
+ <com:TTextBox ID="text1" /><br />
+ <com:TRequiredFieldValidator
+ id="validator1"
+ ControlToValidate="text1" Text="Error"
+ ClientSide.ObserveChanges="false"
+ ClientSide.OnError="alert('error on text1 fired')" />
+ <br />
+ <com:TTextBox ID="text2" /><br />
+ <com:TRequiredFieldValidator id="validator2" ControlToValidate="text2" Text="Error" />
+ <br />
+ <com:TButton id="button1" Text="submit" />
+ <h3>Conditions</h3>
+<pre>
+ (TextBox? B is just there to prevent server submission)
+ To verify try exactly this:
+
+ 1. Enter nothing and click on submit : 1 error event will be triggered
+ 2. Enter something into TextBox? T and click on submit : no error event (ok)
+ 3. Delete your text from TextBox? T again and click on submit : error event will be triggered twice
+</pre>
+</com:TContent> \ No newline at end of file
diff --git a/tests/FunctionalTests/tickets/protected/pages/Ticket227.page b/tests/FunctionalTests/tickets/protected/pages/Ticket227.page
new file mode 100644
index 00000000..ab481fa2
--- /dev/null
+++ b/tests/FunctionalTests/tickets/protected/pages/Ticket227.page
@@ -0,0 +1,4 @@
+<com:TContent ID="Content">
+ <h2>Disabled HTMLArea</h2>
+ <com:THtmlArea ID="htmlArea1" Width="500px" Height="250px" Enabled="false"/>
+</com:TContent> \ No newline at end of file
diff --git a/tests/FunctionalTests/tickets/protected/pages/Ticket246.page b/tests/FunctionalTests/tickets/protected/pages/Ticket246.page
new file mode 100644
index 00000000..e25a484b
--- /dev/null
+++ b/tests/FunctionalTests/tickets/protected/pages/Ticket246.page
@@ -0,0 +1,17 @@
+<com:TContent ID="Content">
+ <h2>TDatePicker inside absolute DIV with scrollbar</h2>
+
+ <div style="position:absolute; top:100px;
+ width: 400px; background-color: #fee;
+ overflow: scroll;
+ border:1px solid red; height:350px; text-align:center">
+ <p style="height:200px; background-color: #eef;"></p>
+ <com:TDatePicker ID="datePicker1" DateFormat="dd/MM/yyyy" InputMode="DropDownList" />
+ <br /><br />
+ <com:TDropDownList ID="dropDownList1">
+ <com:TListItem Value="value 1" Text="item 1" />
+ <com:TListItem Value="value 2" Text="item 2" />
+ </com:TDropDownList>
+ <p style="height:400px; width:600px; background-color:#efe;"></p>
+ </div>
+</com:TContent> \ No newline at end of file
diff --git a/tests/FunctionalTests/tickets/tests/Ticket205TestCase.php b/tests/FunctionalTests/tickets/tests/Ticket205TestCase.php
new file mode 100644
index 00000000..85785697
--- /dev/null
+++ b/tests/FunctionalTests/tickets/tests/Ticket205TestCase.php
@@ -0,0 +1,23 @@
+<?php
+
+class Ticket205TestCase extends SeleniumTestCase
+{
+ function test()
+ {
+ $base = 'ctl0_Content_';
+ $this->open("tickets/index.php?page=Ticket205");
+ $this->assertTitle("Verifying Ticket 205");
+ $this->assertNotVisible("{$base}validator1");
+
+ $this->type("{$base}textbox1", "test");
+ $this->click("{$base}button1");
+ $this->assertVisible("{$base}validator1");
+ $this->assertAlert("error");
+
+ $this->type("{$base}textbox1", "Prado");
+ $this->clickAndWait("{$base}button1");
+ $this->assertNotVisible("{$base}validator1");
+ }
+}
+
+?> \ No newline at end of file
diff --git a/tests/FunctionalTests/tickets/tests/Ticket207TestCase.php b/tests/FunctionalTests/tickets/tests/Ticket207TestCase.php
new file mode 100644
index 00000000..53ae6528
--- /dev/null
+++ b/tests/FunctionalTests/tickets/tests/Ticket207TestCase.php
@@ -0,0 +1,37 @@
+<?php
+
+class Ticket207TestCase extends SeleniumTestCase
+{
+ function test()
+ {
+ $base = 'ctl0_Content_';
+ $this->open('tickets/index.php?page=Ticket207');
+ $this->assertTitle("Verifying Ticket 207");
+ $this->assertNotVisible("{$base}validator1");
+ $this->assertNotVisible("{$base}validator2");
+
+ $this->click("{$base}button1");
+ $this->assertAlert('error on text1 fired');
+ $this->assertVisible("{$base}validator1");
+ $this->assertVisible("{$base}validator2");
+
+ $this->type("{$base}text1", 'test');
+ $this->assertVisible("{$base}validator1");
+ $this->assertVisible("{$base}validator2");
+
+ $this->click("{$base}button1");
+ $this->assertNotVisible("{$base}validator1");
+ $this->assertVisible("{$base}validator2");
+
+ $this->type("{$base}text1", '');
+ $this->assertNotVisible("{$base}validator1");
+ $this->assertVisible("{$base}validator2");
+
+ $this->click("{$base}button1");
+ $this->assertAlert('error on text1 fired');
+ $this->assertVisible("{$base}validator1");
+ $this->assertVisible("{$base}validator2");
+ }
+}
+
+?> \ No newline at end of file
diff --git a/tests/FunctionalTests/tickets/tests/Ticket227TestCase.php b/tests/FunctionalTests/tickets/tests/Ticket227TestCase.php
new file mode 100644
index 00000000..c0dd2a98
--- /dev/null
+++ b/tests/FunctionalTests/tickets/tests/Ticket227TestCase.php
@@ -0,0 +1,12 @@
+<?php
+
+class Ticket227TestCase extends SeleniumTestCase
+{
+ function test()
+ {
+ $this->open('tickets/index.php?page=Ticket227');
+ $this->assertTitle('Verifying Ticket 227');
+ }
+}
+
+?> \ No newline at end of file
diff --git a/tests/FunctionalTests/tickets/tests/Ticket246TestCase.php b/tests/FunctionalTests/tickets/tests/Ticket246TestCase.php
new file mode 100644
index 00000000..8f07790e
--- /dev/null
+++ b/tests/FunctionalTests/tickets/tests/Ticket246TestCase.php
@@ -0,0 +1,12 @@
+<?php
+
+class Ticket246TestCase extends SeleniumTestCase
+{
+ function test()
+ {
+ $this->open('tickets/index.php?page=Ticket246');
+ $this->assertTitle('Verifying Ticket 246');
+ }
+}
+
+?> \ No newline at end of file
diff --git a/tests/FunctionalTests/validators/protected/pages/Home.page b/tests/FunctionalTests/validators/protected/pages/Home.page
new file mode 100755
index 00000000..d4ac162c
--- /dev/null
+++ b/tests/FunctionalTests/validators/protected/pages/Home.page
@@ -0,0 +1,3 @@
+<com:TContent ID="Content">
+<com:TBulletedList ID="List" DisplayMode="HyperLink"/>
+</com:TContent> \ No newline at end of file
diff --git a/tests/FunctionalTests/validators/protected/pages/Home.php b/tests/FunctionalTests/validators/protected/pages/Home.php
new file mode 100755
index 00000000..37804419
--- /dev/null
+++ b/tests/FunctionalTests/validators/protected/pages/Home.php
@@ -0,0 +1,34 @@
+<?php
+
+class Home extends TPage
+{
+ public function onLoad($param)
+ {
+ parent::onLoad($param);
+ $list=$this->getPageList(dirname(__FILE__),'');
+ $this->List->DataSource=$list;
+ $this->List->dataBind();
+ }
+
+ protected function getPageList($directory,$basePath)
+ {
+ $list=array();
+ $folder=@opendir($directory);
+ while($entry=@readdir($folder))
+ {
+ if($entry[0]==='.')
+ continue;
+ else if(is_file($directory.'/'.$entry))
+ {
+ if(($page=basename($entry,'.page'))!==$entry && strpos($page,'.')===false)
+ $list['?page='.$basePath.$page]=$basePath.$page;
+ }
+ else
+ $list=array_merge($list,$this->getPageList($directory.'/'.$entry,$basePath.$entry.'.'));
+ }
+ closedir($folder);
+ return $list;
+ }
+}
+
+?> \ No newline at end of file