diff options
13 files changed, 445 insertions, 24 deletions
diff --git a/.buildpath b/.buildpath new file mode 100644 index 00000000..b48394ff --- /dev/null +++ b/.buildpath @@ -0,0 +1,5 @@ +<?xml version="1.0" encoding="UTF-8"?> +<buildpath> + <buildpathentry excluding="framework/pradolite.php" kind="src" path=""/> + <buildpathentry kind="con" path="org.eclipse.php.core.LANGUAGE"/> +</buildpath> diff --git a/demos/quickstart/protected/pages/JuiControls/Home.page b/demos/quickstart/protected/pages/JuiControls/Home.page index 3dc81417..4bf8f7fe 100644 --- a/demos/quickstart/protected/pages/JuiControls/Home.page +++ b/demos/quickstart/protected/pages/JuiControls/Home.page @@ -88,6 +88,10 @@ For informations of the specific options of each interaction, follow jQuery-UI I <a href="?page=JuiControls.Widgets#TJuiDialog">TJuiDialog</a> displays an movable dialog control </li> + <li> + <a href="?page=JuiControls.Widgets#TJuiDatePicker">TJuiDatePicker</a> + provides a date picker control + </li> </ul> </com:TContent> diff --git a/demos/quickstart/protected/pages/JuiControls/Samples/TJuiDatePicker/Home.page b/demos/quickstart/protected/pages/JuiControls/Samples/TJuiDatePicker/Home.page new file mode 100644 index 00000000..3c2d3141 --- /dev/null +++ b/demos/quickstart/protected/pages/JuiControls/Samples/TJuiDatePicker/Home.page @@ -0,0 +1,65 @@ +<com:TContent ID="body"> +<h1>TJuiDatePicker Samples</h1> + +<table class="sampletable"> + +<tr><td class="samplenote"> +Simple TJuiDatePicker: +</td><td class="sampleaction"> +<com:TJuiDatePicker ID="dp1" /> +</td></tr> + +<tr><td class="samplenote"> +TJuiDatePicker with TRequiredFieldValidator: +</td><td class="sampleaction"> +<com:TJuiDatePicker ID="dp2" /> +<com:TRequiredFieldValidator + ValidationGroup="vg2" + ControlToValidate="dp2" + Text="Field required." /> +<com:TButton Text="Submit" ValidationGroup="vg2" /> +</td></tr> + +<tr><td class="samplenote"> +TJuiDatePicker with TDataTypeValidator: +</td><td class="sampleaction"> +<com:TJuiDatePicker ID="dp3" Options.dateFormat="yy-mm-dd" /> +<com:TDataTypeValidator + ValidationGroup="vg3" + ControlToValidate="dp3" + DataType="Date" + DateFormat="yyyy-MM-dd" + Text="You must enter a valid date (yyyy-MM-dd)." /> +<com:TButton Text="Submit" ValidationGroup="vg3" /> +</td></tr> + +<tr><td class="samplenote"> +TJuiDatePicker with animation: +</td><td class="sampleaction"> +<com:TJuiDatePicker ID="dp4" Options.dateFormat="yy-mm-dd" /> +<com:TActiveDropDownList OnSelectedIndexChanged="change4"> + <com:TListItem Value="show" Text="Show (default)" Selected="true" /> + <com:TListItem Value="slideDown" Text="Slide down" /> + <com:TListItem Value="fadeIn" Text="Fade in" /> + <com:TListItem Value="blind" Text="Blind (UI Effect)" /> + <com:TListItem Value="bounce" Text="Bounce (UI Effect)" /> + <com:TListItem Value="clip" Text="Clip (UI Effect)" /> + <com:TListItem Value="drop" Text="Drop (UI Effect)" /> + <com:TListItem Value="fold" Text="Fold (UI Effect)" /> + <com:TListItem Value="slide" Text="Slide (UI Effect)" /> +</com:TActiveDropDownList> +</td></tr> + +<tr><td class="samplenote"> +Change options of TJuiDatePicker during callback: +</td><td class="sampleaction"> +<div><com:TJuiDatePicker ID="dp5" /></div> +<div><com:TActiveCheckBox OnCheckedChanged="change5" Value="button" /> show button bar</div> +<div><com:TActiveCheckBox OnCheckedChanged="change5" Value="menu" /> display year & month menus</div> +<div><com:TActiveCheckBox OnCheckedChanged="change5" Value="week" /> show week of year</div> +<div><com:TActiveCheckBox OnCheckedChanged="change5" Value="month" /> show 3 months</div> +</td></tr> + +</table> + +</com:TContent> diff --git a/demos/quickstart/protected/pages/JuiControls/Samples/TJuiDatePicker/Home.php b/demos/quickstart/protected/pages/JuiControls/Samples/TJuiDatePicker/Home.php new file mode 100644 index 00000000..5126f68e --- /dev/null +++ b/demos/quickstart/protected/pages/JuiControls/Samples/TJuiDatePicker/Home.php @@ -0,0 +1,30 @@ +<?php + +class Home extends TPage +{ + + public function change4($sender, $param) + { + $this->dp4->getOptions()->showAnim = $sender->getSelectedValue(); + } + + public function change5($sender, $param) + { + $value = $sender->getValue(); + switch ($value) { + case 'button': + $this->dp5->getOptions()->showButtonPanel = $sender->getChecked(); + break; + case 'menu': + $this->dp5->getOptions()->changeYear = $this->dp5->getOptions()->changeMonth = $sender->getChecked(); + break; + case 'week': + $this->dp5->getOptions()->showWeek = $sender->getChecked(); + break; + case 'month': + $this->dp5->getOptions()->numberOfMonths = $sender->getChecked() ? 3 : 1; + break; + } + } + +}
\ No newline at end of file diff --git a/demos/quickstart/protected/pages/JuiControls/Widgets.page b/demos/quickstart/protected/pages/JuiControls/Widgets.page index 4c74c491..63c6aa32 100644 --- a/demos/quickstart/protected/pages/JuiControls/Widgets.page +++ b/demos/quickstart/protected/pages/JuiControls/Widgets.page @@ -70,4 +70,21 @@ The buttons may contain a callback that will be fired when they are clicked. <com:RunBar PagePath="JuiControls.Samples.TJuiDialog.Home" /> <br/> + +<a name="TJuiDatePicker" /> +<h2>TJuiDatePicker</h2> +<com:DocLink ClassPath="System.Web.UI.JuiControls.TJuiDatePicker" /> - <a href="http://api.jqueryui.com/datepicker/">jQuery UI API</a> + +<p class="block-content"> +<tt>TJuiDatePicker</tt> is an extension to <a href="?page=ActiveControls.ActiveTextBox">TActiveTextBox</a> based on jQuery-UI's <a href="http://jqueryui.com/datepicker/">datepicker</a> widget. +</p> + +<p class="block-content"> +TJuiDatePicker is an extended TActiveTextBox that shows a date picker dialog on focus for an easy way to enter a date into the textbox. +</p> + + +<com:RunBar PagePath="JuiControls.Samples.TJuiDatePicker.Home" /> +<br/> + </com:TContent> diff --git a/framework/Exceptions/messages/messages-fr.txt b/framework/Exceptions/messages/messages-fr.txt index 4e6a396b..84f53069 100644 --- a/framework/Exceptions/messages/messages-fr.txt +++ b/framework/Exceptions/messages/messages-fr.txt @@ -415,4 +415,6 @@ tactivetablecell_control_outoftable = {0} '{1}' must be enclosed within a TTabl tactivetablecell_control_notincollection = {0} '{1}' no member of the TTableCellCollection of the parent TTableRow control. tactivetablerow_control_outoftable = {0} '{1}' must be enclosed within a TTable control. -tactivetablerow_control_notincollection = {0} '{1}' no member of the TTableRowCollection of the parent TTable control.
\ No newline at end of file +tactivetablerow_control_notincollection = {0} '{1}' no member of the TTableRowCollection of the parent TTable control. + +juidatepicker_settextmode_unsupported = TextMode of TJuiDatePicker cannot be changed.
\ No newline at end of file diff --git a/framework/Exceptions/messages/messages-id.txt b/framework/Exceptions/messages/messages-id.txt index 687d4f30..dfba22bc 100644 --- a/framework/Exceptions/messages/messages-id.txt +++ b/framework/Exceptions/messages/messages-id.txt @@ -461,4 +461,6 @@ ar_data_invalid = {0}.copyFrom() hanya bisa menggunakan obyek atay array s ar_save_invalid = Turunan {0} tidak bisa disimpan karena kondisi sudah dihapus ataupun tidak dikenal.
ar_delete_invalid = Turunan {0} tidak bisa dihapus karena ada rekaman baru atau rekaman sudah dihapus.
-datasource_dbconnection_invalid = TDataSourceConfig.DbConnection '{0}' tidak benar. ia merujuk ke modul aplikasi yang benar.
\ No newline at end of file +datasource_dbconnection_invalid = TDataSourceConfig.DbConnection '{0}' tidak benar. ia merujuk ke modul aplikasi yang benar.
+
+juidatepicker_settextmode_unsupported = TextMode of TJuiDatePicker cannot be changed.
\ No newline at end of file diff --git a/framework/Exceptions/messages/messages-zh.txt b/framework/Exceptions/messages/messages-zh.txt index 9dc14a8b..7490ccde 100644 --- a/framework/Exceptions/messages/messages-zh.txt +++ b/framework/Exceptions/messages/messages-zh.txt @@ -432,3 +432,5 @@ urlmapping_configfile_inexistent = TUrlMapping.ConfigFile '{0}' is not a file. urlmapping_configfile_invalid = TUrlMapping.ConfigFile '{0}' must point to an XML file in namespace format. urlmappingpattern_serviceparameter_required = TUrlMappingPattern.ServiceParameter is required for pattern '{0}'. + +juidatepicker_settextmode_unsupported = TextMode of TJuiDatePicker cannot be changed.
\ No newline at end of file diff --git a/framework/Exceptions/messages/messages.txt b/framework/Exceptions/messages/messages.txt index 600cd1f5..46dde557 100644 --- a/framework/Exceptions/messages/messages.txt +++ b/framework/Exceptions/messages/messages.txt @@ -509,4 +509,6 @@ ratinglist_invalid_caption_id = '{0}' is not a valid caption control for TRati accordion_activeviewid_invalid = TAccordion.ActiveViewID has an invalid ID '{0}'. accordion_activeviewindex_invalid = TAccordion.ActiveViewIndex has an invalid Index '{0}'. -accordion_view_inexistent = TAccordion cannot find the specified view.
\ No newline at end of file +accordion_view_inexistent = TAccordion cannot find the specified view. + +juidatepicker_settextmode_unsupported = TextMode of TJuiDatePicker cannot be changed.
\ No newline at end of file diff --git a/framework/Web/Javascripts/source/prado/activecontrols/activecontrols3.js b/framework/Web/Javascripts/source/prado/activecontrols/activecontrols3.js index 5d4beef8..111277a1 100644 --- a/framework/Web/Javascripts/source/prado/activecontrols/activecontrols3.js +++ b/framework/Web/Javascripts/source/prado/activecontrols/activecontrols3.js @@ -146,7 +146,7 @@ Prado.WebUI.TJuiAutoComplete = jQuery.klass(Prado.WebUI.TActiveTextBox, extractLastTerm: function(string) { - var re = new RegExp("[" + this.options.Separators + "]"); + var re = new RegExp("[" + (this.options.Separators || '') + "]"); return string.split(re).pop().trim(); }, diff --git a/framework/Web/Javascripts/source/prado/validator/validation3.js b/framework/Web/Javascripts/source/prado/validator/validation3.js index 44abe295..98be95d7 100644 --- a/framework/Web/Javascripts/source/prado/validator/validation3.js +++ b/framework/Web/Javascripts/source/prado/validator/validation3.js @@ -439,9 +439,9 @@ Prado.ValidationManager.prototype = */ isValid : function(group) { - for(var i = 0; i < this.validatorPartition(group)[0]; i++) + for(var i = 0; i < this.validatorPartition(group)[0].length; i++) { - if(!this.validatorPartition(group)[0].isValid()) + if(!this.validatorPartition(group)[0][i].isValid) return false; } @@ -456,16 +456,16 @@ Prado.ValidationManager.prototype = addValidator : function(validator) { // Remove previously registered validator with same ID - // to prevent stale validators created by AJAX updates - this.removeValidator(validator); + // to prevent stale validators created by AJAX updates + this.removeValidator(validator); this.validators.push(validator); if(validator.group && jQuery.inArray(validator.group, this.groups)==-1) this.groups.push(validator.group); - if (typeof this.controls[validator.control.id] === 'undefined') - this.controls[validator.control.id] = Array(); - this.controls[validator.control.id].push(validator); + if(typeof this.controls[validator.control.id] === 'undefined') + this.controls[validator.control.id] = Array(); + this.controls[validator.control.id].push(validator); }, /** @@ -483,19 +483,25 @@ Prado.ValidationManager.prototype = * @function ? * @param {TBaseValidator} validator - Validator object */ - removeValidator : function(validator) + removeValidator : function(validator) + { + // Remove from list of validators + this.validators = jQuery.grep(this.validators, function(v) + { + return (v.options.ID!=validator.options.ID); + }); + // Remove from global list of validators per control + if (this.controls[validator.control.id]) { - this.validators = jQuery.grep(this.validators, function(v) - { - return (v.options.ID!=validator.options.ID); - }); - // WTF? - if (this.controls[validator.control.id]) - jQuery.grep(this.controls[validator.control.id], function(v) - { - return (v.options.ID!=validator.options.ID) - }); - }, + this.controls[validator.control.id] = jQuery.grep(this.controls[validator.control.id], function(v) + { + return (v.options.ID!=validator.options.ID) + }); + // Delete array if empty + if(this.controls[validator.control.id].length == 0) + delete this.controls[validator.control.id]; + } + }, /** * Gets validators with errors. diff --git a/framework/Web/UI/ActiveControls/TActiveDataGrid.php b/framework/Web/UI/ActiveControls/TActiveDataGrid.php index d5084e2d..bb5f6c0f 100644 --- a/framework/Web/UI/ActiveControls/TActiveDataGrid.php +++ b/framework/Web/UI/ActiveControls/TActiveDataGrid.php @@ -97,7 +97,7 @@ class TActiveDataGrid extends TDataGrid implements IActiveControl, ISurroundable * Returns the id of the surrounding container (div). * @return string container id */ - public function getSurroundingTagId() { + public function getSurroundingTagID() { return $this->ClientID.'_Container'; } diff --git a/framework/Web/UI/JuiControls/TJuiDatePicker.php b/framework/Web/UI/JuiControls/TJuiDatePicker.php new file mode 100644 index 00000000..d894e07d --- /dev/null +++ b/framework/Web/UI/JuiControls/TJuiDatePicker.php @@ -0,0 +1,286 @@ +<?php +/** + * TJuiDatePicker class file. + * + * @author LANDWEHR Computer und Software GmbH <programmierung@landwehr-software.de> + * @link http://www.landwehr-software.de/ + * @copyright Copyright © 2015 LANDWEHR Computer und Software GmbH + * @license http://www.pradosoft.com/license/ + * @package System.Web.UI.ActiveControls + */ + +/** + * Load active text box. + */ +Prado::using('System.Web.UI.ActiveControls.TActiveTextBox'); +Prado::using('System.Web.UI.ActiveControls.TCallbackEventParameter'); +Prado::using('System.Web.UI.JuiControls.TJuiControlAdapter'); +/** + * TJuiDatePicker class. + * + * TJuiDatePicker is a textbox that provides a date input. 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. TJuiDatePicker is an extension to {@link TActivePanel} based on + * jQuery-UI's {@link http://jqueryui.com/dialog/ Dialog} widget. + * + * <code> + * <com:TJuiDatePicker ID="datepicker1" /> + * </code> + * + * @author LANDWEHR Computer und Software GmbH <programmierung@landwehr-software.de> + * @package System.Web.UI.JuiControls + * @since 3.3 + */ +class TJuiDatePicker extends TActiveTextBox implements INamingContainer, IJuiOptions +{ + + /** + * The static variable is used to determine if this is the first instance of TJuiDatePicker. If true, + * it will register an additional clientscript to set the language specific global default settings. + * @var boolean true, if this is the first instance of TJuiDatePicker, false otherwise + */ + private static $_first = true; + + /** + * Creates a new callback control, sets the adapter to + * TActiveControlAdapter. If you override this class, be sure to set the + * adapter appropriately by, for example, by calling this constructor. + */ + public function __construct() + { + parent::__construct(); + $this->setAdapter(new TJuiControlAdapter($this)); + } + + /** + * @return string the name of the jQueryUI widget method + */ + public function getWidget() + { + return 'datepicker'; + } + + /** + * @return string the clientid of the jQueryUI widget element + */ + public function getWidgetID() + { + return $this->getClientID(); + } + + /** + * Object containing defined javascript options + * @return TJuiControlOptions + */ + public function getOptions() + { + if (($options=$this->getViewState('JuiOptions'))===null) + { + $options=new TJuiControlOptions($this); + $this->setViewState('JuiOptions', $options); + } + return $options; + } + + /** + * Array containing valid javascript options + * @return array() + */ + public function getValidOptions() + { + return array('altField', 'altFormat', 'appendText', 'autoSize', 'buttonImage', 'buttonImageOnly', 'buttonText', 'calculateWeek', + 'changeMonth', 'changeYear', 'closeText', 'constrainInput', 'currentText', 'dateFormat', 'dayNames', 'dayNamesMin', + 'dayNamesShort', 'defaultDate', 'duration', 'firstDay', 'gotoCurrent', 'hideIfNoPrevNext', 'isRTL', 'maxDate', + 'minDate', 'monthNames', 'monthNamesShort', 'navigationAsDateFormat', 'nextText', 'numberOfMonths', 'prevText', + 'selectOtherMonths', 'shortYearCutoff', 'showAnim', 'showButtonPanel', 'showCurrentAtPos', 'showMonthAfterYear', + 'showOn', 'showOptions', 'showOtherMonths', 'showWeek', 'stepMonths', 'weekHeader', 'yearRange', 'yearSuffix'); + } + + /** + * Array containing valid javascript events + * @return array() + */ + public function getValidEvents() + { + return array('beforeShow', 'beforeShowDay', 'onChangeMonthYear', 'onClose', 'onSelect'); + } + + /** + * Ensure that the ID attribute is rendered and registers the javascript code + * for initializing the active control. Also registers language specific global + * settings for the first used date picker. + */ + protected function addAttributesToRender($writer) + { + $cs=$this->getPage()->getClientScript(); + if(self::$_first) + { + $code="jQuery(document).ready(function(){jQuery.datepicker.setDefaults(jQuery.datepicker.regional['{$this->getCurrentCulture()}']);});"; + $cs->registerEndScript(sprintf('%08X', crc32($code)), $code); + self::$_first=false; + } + parent::addAttributesToRender($writer); + $options=TJavascript::encode($this->getOptions()->toArray()); + $code="jQuery('#".$this->getWidgetID()."').".$this->getWidget()."(".$options.");"; + $cs->registerEndScript(sprintf('%08X', crc32($code)), $code); + } + + /** + * @return TTextBoxMode the behavior mode of the underlying {@link TTextBox} component. + * Fixed to TTextBoxMode::SingleLine for the TJuiDatePicker. + */ + public function getTextMode() + { + return TTextBoxMode::SingleLine; + } + + /** + * Setting the behavior mode of the underlying TTextBox component is NOT supported. + * @param TTextBoxMode the text mode + * @throws TNotSupportedException not supported, fixed to TTextBoxMode::SingleLine. + */ + public function setTextMode($value) + { + throw new TNotSupportedException('juidatepicker_settextmode_unsupported'); + } + + /** + * Gets the current culture. + * @return string current culture, e.g. en_AU. + */ + public function getCulture() + { + return $this->getViewState('Culture', ''); + } + + /** + * Sets the culture/language for the date picker. + * @param string a culture string, e.g. en_AU. + */ + public function setCulture($value) + { + $this->setViewState('Culture', $value, ''); + } + + /** + * @return string the current culture, falls back to application if culture is not set. + */ + protected function getCurrentCulture() + { + $app = $this->getApplication()->getGlobalization(false); + return $this->getCulture() == '' ? + ($app ? $app->getCulture() : 'en') : $this->getCulture(); + } + + /** + * @return string the format of the date string + */ + public function getDateFormat() + { + return $this->getViewState('DateFormat','dd-MM-yyyy'); + } + + /** + * Sets the format of the date string. + * @param string the format of the date string + */ + public function setDateFormat($value) + { + $this->setViewState('DateFormat',$value,'dd-MM-yyyy'); + } + + /** + * Returns the timestamp selected by the user. + * This method is required by {@link IDataRenderer}. + * It is the same as {@link getTimeStamp()}. + * @return integer the timestamp of the TDatePicker control. + * @see getTimeStamp + * @since 3.1.2 + */ + public function getData() + { + return $this->getTimeStamp(); + } + + /** + * Sets the timestamp represented by this control. + * This method is required by {@link IDataRenderer}. + * It is the same as {@link setTimeStamp()}. + * @param integer the timestamp of the TDatePicker control. + * @see setTimeStamp + * @since 3.1.2 + */ + public function setData($value) + { + $this->setTimeStamp($value); + } + + /** + * @return string the date string. + */ + public function getDate() + { + return $this->getText(); + } + + /** + * @param string date string + */ + public function setDate($value) + { + $this->setText($value); + } + + /** + * @return integer current selected date from the date picker as timestamp, NULL if timestamp is not set previously. + */ + public function getTimeStamp() + { + if(trim($this->getText())==='') + return null; + else + return $this->getTimeStampFromText(); + } + + /** + * Sets the date for the date picker using timestamp. + * @param float time stamp for the date picker + */ + public function setTimeStamp($value) + { + if($value===null || (is_string($value) && trim($value)==='')) + $this->setText(''); + else + { + $date = TPropertyValue::ensureFloat($value); + $formatter = Prado::createComponent('System.Util.TSimpleDateFormatter',$this->getDateFormat()); + $this->setText($formatter->format($date)); + } + } + + /** + * Gets the date from the text input using TSimpleDateFormatter + * @return integer current selected date timestamp + */ + protected function getTimeStampFromText() + { + $pattern = $this->getDateFormat(); + $pattern = str_replace(array('MMMM', 'MMM'), array('MM','MM'), $pattern); + $formatter = Prado::createComponent('System.Util.TSimpleDateFormatter',$pattern); + return $formatter->parse($this->getText()); + } + + /** + * Returns the value to be validated. + * This methid is required by IValidatable interface. + * @return integer the interger timestamp if valid, otherwise the original text. + */ + public function getValidationPropertyValue() + { + if(($text = $this->getText()) === '') + return ''; + $date = $this->getTimeStamp(); + return $date == null ? $text : $date; + } + +}
\ No newline at end of file |