From 2ea02214b2fb6bedb58dbbd318ef171a9e146524 Mon Sep 17 00:00:00 2001 From: xue <> Date: Mon, 29 May 2006 03:08:07 +0000 Subject: Merge from 3.0 branch till 1099. --- .../Web/Javascripts/colorpicker/colorpicker.js | 2 +- framework/Web/Javascripts/datepicker/datepicker.js | 29 +++++--- framework/Web/Javascripts/datepicker/default.css | 25 +++++-- framework/Web/Javascripts/datepicker/spacer.gif | Bin 0 -> 43 bytes framework/Web/Javascripts/extended/event.js | 7 +- framework/Web/Javascripts/js/colorpicker.js | 2 +- framework/Web/Javascripts/js/datepicker.js | 16 +++-- framework/Web/Javascripts/js/prado.js | 3 - framework/Web/Javascripts/prado/validation3.js | 4 +- framework/Web/UI/TThemeManager.php | 17 +++++ framework/Web/UI/WebControls/TBaseValidator.php | 76 +++++++++++++-------- framework/Web/UI/WebControls/TDatePicker.php | 30 ++++++-- framework/Web/UI/WebControls/TListControl.php | 39 +++++++++++ 13 files changed, 182 insertions(+), 68 deletions(-) create mode 100755 framework/Web/Javascripts/datepicker/spacer.gif (limited to 'framework/Web') diff --git a/framework/Web/Javascripts/colorpicker/colorpicker.js b/framework/Web/Javascripts/colorpicker/colorpicker.js index dc80f0c7..06cfb037 100644 --- a/framework/Web/Javascripts/colorpicker/colorpicker.js +++ b/framework/Web/Javascripts/colorpicker/colorpicker.js @@ -74,7 +74,7 @@ Object.extend(Prado.WebUI.TColorPicker.prototype, if(Prado.Browser().ie) { this.iePopUp = document.createElement('iframe'); - this.iePopUp.src = ""; + this.iePopUp.src = Prado.WebUI.TColorPicker.UIImages['button.gif']; this.iePopUp.style.position = "absolute" this.iePopUp.scrolling="no" this.iePopUp.frameBorder="0" diff --git a/framework/Web/Javascripts/datepicker/datepicker.js b/framework/Web/Javascripts/datepicker/datepicker.js index 79763811..d5d9496c 100644 --- a/framework/Web/Javascripts/datepicker/datepicker.js +++ b/framework/Web/Javascripts/datepicker/datepicker.js @@ -81,11 +81,14 @@ Prado.WebUI.TDatePicker.prototype = Object.extend(this,options); Event.observe(this.trigger, triggerEvent, this.show.bindEvent(this)); - this.create(); + }, create : function() { + if(typeof(this._calDiv) != "undefined") + return; + var div; var table; var tbody; @@ -115,9 +118,10 @@ Prado.WebUI.TDatePicker.prototype = // Previous Month Button td = document.createElement("td"); - var previousMonth = document.createElement("button"); - previousMonth.className = "prevMonthButton"; - previousMonth.appendChild(document.createTextNode("<<")); + var previousMonth = document.createElement("input"); + previousMonth.className = "prevMonthButton button"; + previousMonth.type = "button" + previousMonth.value = "<<"; td.appendChild(previousMonth); tr.appendChild(td); @@ -162,9 +166,10 @@ Prado.WebUI.TDatePicker.prototype = td = document.createElement("td"); - td.className = "nextMonthButton"; - var nextMonth = document.createElement("button"); - nextMonth.appendChild(document.createTextNode(">>")); + var nextMonth = document.createElement("input"); + nextMonth.className = "nextMonthButton button"; + nextMonth.type = "button"; + nextMonth.value = ">>"; td.appendChild(nextMonth); tr.appendChild(td); @@ -178,6 +183,7 @@ Prado.WebUI.TDatePicker.prototype = var text; table = document.createElement("table"); + table.align="center"; table.className = "grid"; div.appendChild(table); @@ -226,11 +232,12 @@ Prado.WebUI.TDatePicker.prototype = div.className = "calendarFooter"; this._calDiv.appendChild(div); - var todayButton = document.createElement("button"); + var todayButton = document.createElement("input"); + todayButton.type="button"; todayButton.className = "todayButton"; var today = this.newDate(); var buttonText = today.SimpleFormat(this.Format,this); - todayButton.appendChild(document.createTextNode(buttonText)); + todayButton.value = buttonText; div.appendChild(todayButton); /*var clearButton = document.createElement("button"); @@ -243,7 +250,7 @@ Prado.WebUI.TDatePicker.prototype = if(Prado.Browser().ie) { this.iePopUp = document.createElement('iframe'); - this.iePopUp.src = ""; + this.iePopUp.src = Prado.WebUI.TDatePicker.spacer; this.iePopUp.style.position = "absolute" this.iePopUp.scrolling="no" this.iePopUp.frameBorder="0" @@ -521,6 +528,8 @@ Prado.WebUI.TDatePicker.prototype = show : function() { + this.create(); + if(!this.showing) { var pos = Position.cumulativeOffset(this.control); diff --git a/framework/Web/Javascripts/datepicker/default.css b/framework/Web/Javascripts/datepicker/default.css index e5d327e1..7e920f1b 100644 --- a/framework/Web/Javascripts/datepicker/default.css +++ b/framework/Web/Javascripts/datepicker/default.css @@ -21,6 +21,7 @@ margin-left: 1px; } + .TDatePickerImageButton:hover { border-color: #ddd; @@ -31,9 +32,9 @@ font-size: 11px; } -.TDatePicker .calendarHeader button +.TDatePicker input.button { - font-size: 12px; + font-size: 11px; width: 32px; } @@ -41,6 +42,7 @@ { padding: 4px 0; border: 1px solid white; + text-align: center; } .TDatePicker .hover { @@ -61,25 +63,36 @@ { border: 1px solid white; cursor: default; - height: 23px; + height: 22px; } + .TDatePicker th { width: 28px; } + +.TDatePicker .calendarBody +{ + text-align: center; + width: 210px; + margin: 3px 6px; +} + .TDatePicker .grid { border-spacing: 0px; - margin: 3px; } + .TDatePicker .calendarFooter { margin: 2px; border-top: 1px solid #919EA9; padding-top: 2px; } -.TDatePicker .calendarFooter button +.TDatePicker .todayButton { - font-size: 12px; + font-size: 11px; margin: 4px; + padding-left: 1em; + padding-right: 1em; } \ No newline at end of file diff --git a/framework/Web/Javascripts/datepicker/spacer.gif b/framework/Web/Javascripts/datepicker/spacer.gif new file mode 100755 index 00000000..fc256098 Binary files /dev/null and b/framework/Web/Javascripts/datepicker/spacer.gif differ diff --git a/framework/Web/Javascripts/extended/event.js b/framework/Web/Javascripts/extended/event.js index 29a8d5aa..4fd041d8 100644 --- a/framework/Web/Javascripts/extended/event.js +++ b/framework/Web/Javascripts/extended/event.js @@ -64,6 +64,7 @@ Object.extend(Event, * element. Only HTMLEvent and MouseEvent can be * dispatched, keyboard events or UIEvent can not be dispatch * via javascript consistently. + * For the "submit" event the submit() method is called. * @param {Object} element id string or a DOM element. * @param {String} event type to dispatch. */ @@ -86,12 +87,6 @@ Object.extend(Event, document.defaultView, 1, 0, 0, 0, 0, false, false, false, false, 0, null); } - else - { - if(typeof(Logger) != "undefined") - Logger.error("undefined event", type); - return; - } element.dispatchEvent(event); } else if(document.createEventObject) diff --git a/framework/Web/Javascripts/js/colorpicker.js b/framework/Web/Javascripts/js/colorpicker.js index 5bfab96d..47949239 100644 --- a/framework/Web/Javascripts/js/colorpicker.js +++ b/framework/Web/Javascripts/js/colorpicker.js @@ -34,7 +34,7 @@ Event.observe(this.button,"click",this._buttonOnClick);Event.observe(this.input, {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.iePopUp=document.createElement('iframe');this.iePopUp.src="";this.iePopUp.style.position="absolute" +{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" this.input.parentNode.appendChild(this.iePopUp);} diff --git a/framework/Web/Javascripts/js/datepicker.js b/framework/Web/Javascripts/js/datepicker.js index 6a28c061..a81bbeb4 100644 --- a/framework/Web/Javascripts/js/datepicker.js +++ b/framework/Web/Javascripts/js/datepicker.js @@ -8,16 +8,18 @@ Prado.WebUI.TDatePicker=Class.create();Object.extend(Prado.WebUI.TDatePicker,{ge {this.trigger=$(this.options.Trigger);var triggerEvent=this.options.TriggerEvent||"click";} else {this.trigger=this.control;var triggerEvent=this.options.TriggerEvent||"focus";} -Object.extend(this,options);Event.observe(this.trigger,triggerEvent,this.show.bindEvent(this));this.create();},create:function() -{var div;var table;var tbody;var tr;var td;this._calDiv=document.createElement("div");this._calDiv.className=this.ClassName;this._calDiv.style.display="none";this._calDiv.style.position="absolute" -div=document.createElement("div");div.className="calendarHeader";this._calDiv.appendChild(div);table=document.createElement("table");table.style.cellSpacing=0;div.appendChild(table);tbody=document.createElement("tbody");table.appendChild(tbody);tr=document.createElement("tr");tbody.appendChild(tr);td=document.createElement("td");var previousMonth=document.createElement("button");previousMonth.className="prevMonthButton";previousMonth.appendChild(document.createTextNode("<<"));td.appendChild(previousMonth);tr.appendChild(td);td=document.createElement("td");tr.appendChild(td);this._monthSelect=document.createElement("select");this._monthSelect.className="months";for(var i=0;i>"));td.appendChild(nextMonth);tr.appendChild(td);div=document.createElement("div");div.className="calendarBody";this._calDiv.appendChild(div);var calendarBody=div;var text;table=document.createElement("table");table.className="grid";div.appendChild(table);var thead=document.createElement("thead");table.appendChild(thead);tr=document.createElement("tr");thead.appendChild(tr);for(i=0;i<7;++i){td=document.createElement("th");text=document.createTextNode(this.ShortWeekDayNames[(i+this.FirstDayOfWeek)%7]);td.appendChild(text);td.className="weekDayHead";tr.appendChild(td);} +td.appendChild(this._yearSelect);td=document.createElement("td");var nextMonth=document.createElement("input");nextMonth.className="nextMonthButton button";nextMonth.type="button";nextMonth.value=">>";td.appendChild(nextMonth);tr.appendChild(td);div=document.createElement("div");div.className="calendarBody";this._calDiv.appendChild(div);var calendarBody=div;var text;table=document.createElement("table");table.align="center";table.className="grid";div.appendChild(table);var thead=document.createElement("thead");table.appendChild(thead);tr=document.createElement("tr");thead.appendChild(tr);for(i=0;i<7;++i){td=document.createElement("th");text=document.createTextNode(this.ShortWeekDayNames[(i+this.FirstDayOfWeek)%7]);td.appendChild(text);td.className="weekDayHead";tr.appendChild(td);} tbody=document.createElement("tbody");table.appendChild(tbody);for(week=0;week<6;++week){tr=document.createElement("tr");tbody.appendChild(tr);for(day=0;day<7;++day){td=document.createElement("td");td.className="calendarDate";text=document.createTextNode(String.fromCharCode(160));td.appendChild(text);tr.appendChild(td);var tmp=new Object();tmp.tag="DATE";tmp.value=-1;tmp.data=text;this.dateSlot[(week*7)+day]=tmp;Event.observe(td,"mouseover",this.hover.bindEvent(this));Event.observe(td,"mouseout",this.hover.bindEvent(this));}} -div=document.createElement("div");div.className="calendarFooter";this._calDiv.appendChild(div);var todayButton=document.createElement("button");todayButton.className="todayButton";var today=this.newDate();var buttonText=today.SimpleFormat(this.Format,this);todayButton.appendChild(document.createTextNode(buttonText));div.appendChild(todayButton);if(Prado.Browser().ie) -{this.iePopUp=document.createElement('iframe');this.iePopUp.src="";this.iePopUp.style.position="absolute" +div=document.createElement("div");div.className="calendarFooter";this._calDiv.appendChild(div);var todayButton=document.createElement("input");todayButton.type="button";todayButton.className="todayButton";var today=this.newDate();var buttonText=today.SimpleFormat(this.Format,this);todayButton.value=buttonText;div.appendChild(todayButton);if(Prado.Browser().ie) +{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);} @@ -87,7 +89,7 @@ this.onChange();},getElement:function() {var d=this.newDate(this.selectedDate);d.setMonth(month);this.setSelectedDate(d);},nextMonth:function() {this.setMonth(this.selectedDate.getMonth()+1);},prevMonth:function() {this.setMonth(this.selectedDate.getMonth()-1);},show:function() -{if(!this.showing) +{this.create();if(!this.showing) {var pos=Position.cumulativeOffset(this.control);if(this.options.InputMode=="TextBox") pos[1]+=this.control.offsetHeight;else {var dayList=Prado.WebUI.TDatePicker.getDayListControl(this.control);if(dayList) diff --git a/framework/Web/Javascripts/js/prado.js b/framework/Web/Javascripts/js/prado.js index c09cf64c..aa02e98e 100644 --- a/framework/Web/Javascripts/js/prado.js +++ b/framework/Web/Javascripts/js/prado.js @@ -129,9 +129,6 @@ return element.submit();if(document.createEvent) {var event=document.createEvent('HTMLEvents');event.initEvent(type,true,true);} else if(Event.isMouseEvent(type)) {var event=document.createEvent('MouseEvents');event.initMouseEvent(type,true,true,document.defaultView,1,0,0,0,0,false,false,false,false,0,null);} -else -{if(typeof(Logger)!="undefined") -Logger.error("undefined event",type);return;} element.dispatchEvent(event);} else if(document.createEventObject) {var evObj=document.createEventObject();element.fireEvent('on'+type,evObj);} diff --git a/framework/Web/Javascripts/prado/validation3.js b/framework/Web/Javascripts/prado/validation3.js index ad55f96b..6285dd52 100644 --- a/framework/Web/Javascripts/prado/validation3.js +++ b/framework/Web/Javascripts/prado/validation3.js @@ -763,7 +763,9 @@ Prado.WebUI.TBaseValidator.prototype = return value; }, - /** + /** + * The ControlType property comes from TBaseValidator::getClientControlClass() + * Be sure to update the TBaseValidator::$_clientClass if new cases are added. * @return mixed control value to validate */ getValidationValue : function(control) diff --git a/framework/Web/UI/TThemeManager.php b/framework/Web/UI/TThemeManager.php index 6a908759..fcb20a81 100644 --- a/framework/Web/UI/TThemeManager.php +++ b/framework/Web/UI/TThemeManager.php @@ -78,6 +78,23 @@ class TThemeManager extends TModule } + /** + * @return array list of available theme names + */ + public function getAvailableThemes() + { + $themes=array(); + $basePath=$this->getBasePath(); + $folder=@opendir($basePath); + while($file=@readdir($folder)) + { + if($file!=='.' && $file!=='..' && $file!=='.svn' && is_dir($basePath.'/'.$file)) + $themes[]=$file; + } + closedir($folder); + return $themes; + } + /** * @return string the base path for all themes. It is returned as an absolute path. * @throws TConfigurationException if base path is not set and "themes" directory does not exist. diff --git a/framework/Web/UI/WebControls/TBaseValidator.php b/framework/Web/UI/WebControls/TBaseValidator.php index ffdfd057..3c76db30 100644 --- a/framework/Web/UI/WebControls/TBaseValidator.php +++ b/framework/Web/UI/WebControls/TBaseValidator.php @@ -83,6 +83,12 @@ abstract class TBaseValidator extends TLabel implements IValidator * @var TClientSideValidatorOptions validator client-script options. */ private $_clientSide; + /** + * Controls for which the client-side validation3.js file needs to handle + * them specially. + * @var array list of control class names + */ + private static $_clientClass = array('THtmlArea', 'TDatePicker'); /** * Constructor. @@ -152,28 +158,44 @@ abstract class TBaseValidator extends TLabel implements IValidator $options['ValidationGroup'] = $this->getValidationGroup(); $options['ControlToValidate'] = $control->getClientID(); $options['ControlCssClass'] = $this->getControlCssClass(); - $options['ControlType'] = get_class($control); - + + $options['ControlType'] = $this->getClientControlClass($control); + if(!is_null($this->_clientSide)) $options = array_merge($options,$this->_clientSide->getOptions()->toArray()); - + return $options; } - + + /** + * Gets the Control type for client-side validation. If new cases exists in + * TBaseValidator::$_clientClass, be sure to update the corresponding + * "Javascript/validation3.js" file as well. + * @param TControl control to validate. + * @return string control type for client-side validation. + */ + private function getClientControlClass($control) + { + foreach(self::$_clientClass as $type) + if($control instanceof $type) + return $type; + return get_class($control); + } + /** * Gets the TClientSideValidatorOptions that allows modification of the client- - * side validator events. - * + * side validator events. + * * The client-side validator supports the following events. * # OnValidate -- raised before client-side validation is - * executed. + * executed. * # OnSuccess -- raised after client-side validation is completed * and is successfull, overrides default validator error messages updates. * # OnError -- raised after client-side validation is completed - * and failed, overrides default validator error message updates. - * + * and failed, overrides default validator error message updates. + * * You can attach custom javascript code to each of these events - * + * * @return TClientSideValidatorOptions javascript validator event options. */ public function getClientSide() @@ -182,7 +204,7 @@ abstract class TBaseValidator extends TLabel implements IValidator $this->_clientSide = $this->createClientSideOptions(); return $this->_clientSide; } - + /** * @return TClientSideValidatorOptions javascript validator event options. */ @@ -206,7 +228,7 @@ abstract class TBaseValidator extends TLabel implements IValidator if($this->getEnableClientScript() && !$scripts->isEndScriptRegistered($scriptKey)) { $manager['FormID'] = $formID; - $options = TJavaScript::encode($manager); + $options = TJavaScript::encode($manager); $scripts->registerPradoScript('validator'); $scripts->registerEndScript($scriptKey, "new Prado.ValidationManager({$options});"); } @@ -493,22 +515,22 @@ abstract class TBaseValidator extends TLabel implements IValidator /** * TClientSideValidatorOptions class. - * + * * Client-side validator events can be modified through the {@link * TBaseValidator::getClientSide ClientSide} property of a validator. The * subproperties of ClientSide are those of the TClientSideValidatorOptions * properties. The client-side validator supports the following events. - * + * * The OnValidate event is raise before the validator validation * functions are called. - * + * * The OnSuccess event is raised after the validator has successfully * validate the control. - * + * * The OnError event is raised after the validator fails validation. - * + * * See the quickstart documentation for further details. - * + * * @author Wei Zhuo * @version $Revision: $ $Date: $ * @package System.Web.UI.WebControls @@ -521,19 +543,19 @@ class TClientSideValidatorOptions extends TClientSideOptions */ public function getOnValidate() { - return $this->getOption('OnValidate'); + return $this->getOption('OnValidate'); } - + /** * Client-side OnValidate validator event is raise before the validators - * validation functions are called. + * validation functions are called. * @param string javascript code for client-side OnValidate event. */ public function setOnValidate($javascript) { $this->setFunction('OnValidate', $javascript); } - + /** * Client-side OnSuccess event is raise after validation is successfull. * This will override the default client-side validator behaviour. @@ -543,7 +565,7 @@ class TClientSideValidatorOptions extends TClientSideOptions { $this->setFunction('OnSuccess', $javascript); } - + /** * @return string javascript code for client-side OnSuccess event. */ @@ -551,7 +573,7 @@ class TClientSideValidatorOptions extends TClientSideOptions { return $this->getOption('OnSuccess'); } - + /** * Client-side OnError event is raised after validation failure. * This will override the default client-side validator behaviour. @@ -561,7 +583,7 @@ class TClientSideValidatorOptions extends TClientSideOptions { $this->setFunction('OnError', $javascript); } - + /** * @return string javascript code for client-side OnError event. */ @@ -569,7 +591,7 @@ class TClientSideValidatorOptions extends TClientSideOptions { return $this->getOption('OnError'); } - + /** * Ensure the string is a valid javascript function. If the string begins * with "javascript:" valid javascript function is assumed, otherwise the @@ -583,4 +605,4 @@ class TClientSideValidatorOptions extends TClientSideOptions } } -?> \ No newline at end of file +?> diff --git a/framework/Web/UI/WebControls/TDatePicker.php b/framework/Web/UI/WebControls/TDatePicker.php index 59a71c90..a746437b 100644 --- a/framework/Web/UI/WebControls/TDatePicker.php +++ b/framework/Web/UI/WebControls/TDatePicker.php @@ -681,6 +681,18 @@ class TDatePicker extends TTextBox else throw new TConfigurationException('datepicker_calendarstyle_invalid',$style); } + + /** + * Publish the spacer.gif for IE iframe source. + * @return string the URL for the spacer.gif. + */ + protected function publishIFrameSpacer() + { + $cs = $this->getPage()->getClientScript(); + $spacer = 'System.Web.Javascripts.datepicker.spacer'; + if(($file = Prado::getPathOfNamespace($spacer,'.gif')) != null) + return $this->publishFilePath($file); + } /** * Add the client id to the input textbox, and register the client scripts. @@ -696,18 +708,24 @@ class TDatePicker extends TTextBox /** * Registers the javascript code to initialize the date picker. - * Must use "Event.OnLoad" to initialize the date picker when the - * full page is loaded, otherwise IE will throw an error. */ protected function registerCalendarClientScript() { if($this->getShowCalendar()) { - $scripts = $this->getPage()->getClientScript(); - $scripts->registerPradoScript("datepicker"); + $cs = $this->getPage()->getClientScript(); + $cs->registerPradoScript("datepicker"); + + if(!$cs->isEndScriptRegistered('TDatePicker.spacer')) + { + $spacer = $this->publishIFrameSpacer(); + $code = "Prado.WebUI.TDatePicker.spacer = '$spacer';"; + $cs->registerEndScript('TDatePicker.spacer', $code); + } + $options = TJavaScript::encode($this->getDatePickerOptions()); - $code = "Event.OnLoad(function(){ new Prado.WebUI.TDatePicker($options); });"; - $scripts->registerEndScript("prado:".$this->getClientID(), $code); + $code = "new Prado.WebUI.TDatePicker($options);"; + $cs->registerEndScript("prado:".$this->getClientID(), $code); } } } diff --git a/framework/Web/UI/WebControls/TListControl.php b/framework/Web/UI/WebControls/TListControl.php index 57d8563a..42f09aad 100644 --- a/framework/Web/UI/WebControls/TListControl.php +++ b/framework/Web/UI/WebControls/TListControl.php @@ -502,6 +502,45 @@ abstract class TListControl extends TDataBoundControl $this->_cachedSelectedValue=$value; } + + /** + * @return array list of the selected item values (strings) + */ + public function getSelectedValues() + { + $values=array(); + if($this->_items) + { + foreach($this->_items as $item) + { + if($item->getSelected()) + $values[]=$item->getValue(); + } + } + return $values; + } + + /** + * @param array list of the selected item values + */ + public function setSelectedValues($values) + { + if($this->_items) + { + $this->clearSelection(); + $lookup=array(); + foreach($this->_items as $item) + $lookup[$item->getValue()]=$item; + foreach($values as $value) + { + if(isset($lookup["$value"])) + $lookup["$value"]->setSelected(true); + else + throw new TInvalidDataValueException('listcontrol_selectedvalue_invalid',get_class($this),$value); + } + } + } + /** * @return string selected value */ -- cgit v1.2.3