diff options
Diffstat (limited to 'framework/Web')
-rw-r--r-- | framework/Web/Javascripts/datepicker/datepicker.js | 8 | ||||
-rw-r--r-- | framework/Web/Javascripts/datepicker/default.css | 26 | ||||
-rw-r--r-- | framework/Web/Javascripts/js/compressed/datepicker.js | 6 | ||||
-rw-r--r-- | framework/Web/Javascripts/js/debug/datepicker.js | 8 | ||||
-rw-r--r-- | framework/Web/THttpRequest.php | 10 | ||||
-rw-r--r-- | framework/Web/TUrlMapping.php | 391 | ||||
-rw-r--r-- | framework/Web/UI/WebControls/TDatePicker.php | 1 |
7 files changed, 428 insertions, 22 deletions
diff --git a/framework/Web/Javascripts/datepicker/datepicker.js b/framework/Web/Javascripts/datepicker/datepicker.js index 5fff5f0f..2f1e8261 100644 --- a/framework/Web/Javascripts/datepicker/datepicker.js +++ b/framework/Web/Javascripts/datepicker/datepicker.js @@ -53,7 +53,9 @@ Prado.WebUI.TDatePicker.prototype = FirstDayOfWeek : 1, // 0 for sunday
- ClassName : "TDatePicker",
+ ClassName : "",
+
+ CalendarStyle : "default",
FromYear : 2000, UpToYear: 2015,
@@ -97,7 +99,7 @@ Prado.WebUI.TDatePicker.prototype = // Create the top-level div element
this._calDiv = document.createElement("div");
- this._calDiv.className = this.ClassName;
+ this._calDiv.className = "TDatePicker_"+this.CalendarStyle+" "+this.ClassName;
this._calDiv.style.display = "none";
this._calDiv.style.position = "absolute"
@@ -581,7 +583,7 @@ Prado.WebUI.TDatePicker.prototype = var within = false;
do
{
- within = within || el.className == this.ClassName;
+ within = within || (el.className && Element.hasClassName(el, "TDatePicker_"+this.CalendarStyle));
within = within || el == this.trigger;
within = within || el == this.control;
if(within) break;
diff --git a/framework/Web/Javascripts/datepicker/default.css b/framework/Web/Javascripts/datepicker/default.css index 7e920f1b..9532dad0 100644 --- a/framework/Web/Javascripts/datepicker/default.css +++ b/framework/Web/Javascripts/datepicker/default.css @@ -1,4 +1,4 @@ -.TDatePicker
+.TDatePicker_default
{
border: 1px solid #919EA9;
background-color: White;
@@ -27,69 +27,69 @@ border-color: #ddd;
}
-.TDatePicker select
+.TDatePicker_default select
{
font-size: 11px;
}
-.TDatePicker input.button
+.TDatePicker_default input.button
{
font-size: 11px;
width: 32px;
}
-.TDatePicker .date
+.TDatePicker_default .date
{
padding: 4px 0;
border: 1px solid white;
text-align: center;
}
-.TDatePicker .hover
+.TDatePicker_default .hover
{
border: 1px solid blue;
}
-.TDatePicker .selected
+.TDatePicker_default .selected
{
background-color: blue;
border: 1px solid blue;
color: white;
}
-.TDatePicker .today
+.TDatePicker_default .today
{
font-weight: bold;
}
-.TDatePicker td.empty
+.TDatePicker_default td.empty
{
border: 1px solid white;
cursor: default;
height: 22px;
}
-.TDatePicker th
+.TDatePicker_default th
{
width: 28px;
}
-.TDatePicker .calendarBody
+.TDatePicker_default .calendarBody
{
text-align: center;
width: 210px;
margin: 3px 6px;
}
-.TDatePicker .grid
+.TDatePicker_default .grid
{
border-spacing: 0px;
}
-.TDatePicker .calendarFooter
+.TDatePicker_default .calendarFooter
{
margin: 2px;
border-top: 1px solid #919EA9;
padding-top: 2px;
}
-.TDatePicker .todayButton
+.TDatePicker_default .todayButton
{
font-size: 11px;
margin: 4px;
diff --git a/framework/Web/Javascripts/js/compressed/datepicker.js b/framework/Web/Javascripts/js/compressed/datepicker.js index f47e557c..72b7591a 100644 --- a/framework/Web/Javascripts/js/compressed/datepicker.js +++ b/framework/Web/Javascripts/js/compressed/datepicker.js @@ -3,14 +3,14 @@ Prado.WebUI.TDatePicker=Class.create();Object.extend(Prado.WebUI.TDatePicker,{ge {var now=new Date();var year=now.getFullYear();var month=now.getMonth();var day=1;var month_list=this.getMonthListControl(control);var day_list=this.getDayListControl(control);var year_list=this.getYearListControl(control);var day=day_list?$F(day_list):1;var month=month_list?$F(month_list):now.getMonth();var year=year_list?$F(year_list):now.getFullYear();return new Date(year,month,day,0,0,0);},getYearListControl:function(control) {return $(control.id+"_year");},getMonthListControl:function(control) {return $(control.id+"_month");},getDayListControl:function(control) -{return $(control.id+"_day");}});Prado.WebUI.TDatePicker.prototype={MonthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],AbbreviatedMonthNames:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],ShortWeekDayNames:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],Format:"yyyy-MM-dd",FirstDayOfWeek:1,ClassName:"TDatePicker",FromYear:2000,UpToYear:2015,initialize:function(options) +{return $(control.id+"_day");}});Prado.WebUI.TDatePicker.prototype={MonthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],AbbreviatedMonthNames:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],ShortWeekDayNames:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],Format:"yyyy-MM-dd",FirstDayOfWeek:1,ClassName:"",CalendarStyle:"default",FromYear:2000,UpToYear:2015,initialize:function(options) {this.options=options||[];this.control=$(options.ID);this.dateSlot=new Array(42);this.weekSlot=new Array(6);this.minimalDaysInFirstWeek=4;this.selectedDate=this.newDate();if(this.options.Trigger) {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));},create:function() {if(typeof(this._calDiv)!="undefined") -return;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" +return;var div;var table;var tbody;var tr;var td;this._calDiv=document.createElement("div");this._calDiv.className="TDatePicker_"+this.CalendarStyle+" "+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("input");previousMonth.className="prevMonthButton button";previousMonth.type="button" previousMonth.value="<<";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<this.MonthNames.length;i++){var opt=document.createElement("option");opt.innerHTML=this.MonthNames[i];opt.value=i;if(i==this.selectedDate.getMonth()){opt.selected=true;} this._monthSelect.appendChild(opt);} @@ -99,7 +99,7 @@ Event.observe(document,"keydown",this.documentKeyDownEvent);this.showing=true;}} return Date.SimpleParse($F(this.control),this.Format);else return Prado.WebUI.TDatePicker.getDropDownDate(this.control);},hideOnClick:function(ev) {if(!this.showing)return;var el=Event.element(ev);var within=false;do -{within=within||el.className==this.ClassName;within=within||el==this.trigger;within=within||el==this.control;if(within)break;el=el.parentNode;} +{within=within||(el.className&&Element.hasClassName(el,"TDatePicker_"+this.CalendarStyle));within=within||el==this.trigger;within=within||el==this.control;if(within)break;el=el.parentNode;} while(el);if(!within)this.hide();},hide:function() {if(this.showing) {this._calDiv.style.display="none";if(this.iePopUp) diff --git a/framework/Web/Javascripts/js/debug/datepicker.js b/framework/Web/Javascripts/js/debug/datepicker.js index 0e21b2da..81daeddf 100644 --- a/framework/Web/Javascripts/js/debug/datepicker.js +++ b/framework/Web/Javascripts/js/debug/datepicker.js @@ -53,7 +53,9 @@ Prado.WebUI.TDatePicker.prototype = FirstDayOfWeek : 1, // 0 for sunday
- ClassName : "TDatePicker",
+ ClassName : "",
+
+ CalendarStyle : "default",
FromYear : 2000, UpToYear: 2015,
@@ -97,7 +99,7 @@ Prado.WebUI.TDatePicker.prototype = // Create the top-level div element
this._calDiv = document.createElement("div");
- this._calDiv.className = this.ClassName;
+ this._calDiv.className = "TDatePicker_"+this.CalendarStyle+" "+this.ClassName;
this._calDiv.style.display = "none";
this._calDiv.style.position = "absolute"
@@ -581,7 +583,7 @@ Prado.WebUI.TDatePicker.prototype = var within = false;
do
{
- within = within || el.className == this.ClassName;
+ within = within || (el.className && Element.hasClassName(el, "TDatePicker_"+this.CalendarStyle));
within = within || el == this.trigger;
within = within || el == this.control;
if(within) break;
diff --git a/framework/Web/THttpRequest.php b/framework/Web/THttpRequest.php index dc3143e6..33839ed0 100644 --- a/framework/Web/THttpRequest.php +++ b/framework/Web/THttpRequest.php @@ -130,6 +130,16 @@ class THttpRequest extends TApplicationComponent implements IteratorAggregate,Ar */
public function init($config)
{
+ // Fill in default request info when the script is run in command line
+ if(php_sapi_name()==='cli')
+ {
+ $_SERVER['REMOTE_ADDR']='127.0.0.1';
+ $_SERVER['REQUEST_METHOD']='GET';
+ $_SERVER['SERVER_NAME']='localhost';
+ $_SERVER['SERVER_PORT']=80;
+ $_SERVER['HTTP_USER_AGENT']='';
+ }
+
// Info about server variables:
// PHP_SELF contains real URI (w/ path info, w/o query string)
// SCRIPT_NAME is the real URI for the requested script (w/o path info and query string)
diff --git a/framework/Web/TUrlMapping.php b/framework/Web/TUrlMapping.php new file mode 100644 index 00000000..3062b898 --- /dev/null +++ b/framework/Web/TUrlMapping.php @@ -0,0 +1,391 @@ +<?php
+/**
+ * TUrlMapping and TUrlMappingPattern class file.
+ *
+ * @author Wei Zhuo <weizhuo[at]gamil[dot]com>
+ * @link http://www.pradosoft.com/
+ * @copyright Copyright © 2006 PradoSoft
+ * @license http://www.pradosoft.com/license/
+ * @version $Id$
+ * @package System.Web
+ */
+
+/**
+ * TUrlMapping Class
+ *
+ * The TUrlMapping module allows aributary URL path to be mapped to a
+ * particular service and page class. This module must be configured
+ * before a service is initialized, thus this module should be configured
+ * globally in the <tt>application.xml</tt> file and before any services.
+ *
+ * The mapping format is as follows.
+ * <code>
+ * <module id="friendly-url" class="System.Web.TUrlMapping">
+ * <url pageClass="Posts.ViewPost" pattern="post/{id}/?" parameters.id="\d+" />
+ * <url pageClass="Posts.ListPost" pattern="archive/{time}/?" parameters.time="\d{6}" />
+ * <url pageClass="Posts.ListPost" pattern="category/{cat}/?" parameters.cat="\d+" />
+ * </module>
+ * </code>
+ *
+ * See {@link TUrlMappingPattern} for details regarding the mapping patterns.
+ * Similar to other modules, the <tt><url /></tt> configuration class
+ * can be customised using the <tt>class</tt> property.
+ *
+ * The URL mapping are evaluated in order, only the first mapping that matches
+ * the URL will be used. Cascaded mapping can be achieved by placing the URL mappings
+ * in particular order. For example, placing the most specific mappings first.
+ *
+ * The mapping can be load from an external file by specifying a configuration
+ * file using the {@link setConfigFile ConfigFile} property.
+ *
+ * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
+ * @version $Id$
+ * @package System.Web
+ * @since 3.0.5
+ */
+class TUrlMapping extends THttpRequest
+{
+ /**
+ * @var string default pattern class.
+ */
+ private $_defaultPatternClass='TUrlMappingPattern';
+ /**
+ * @var TUrlMappingPattern[] list of patterns.
+ */
+ private $_patterns=array();
+ /**
+ * @var TUrlMappingPattern matched pattern.
+ */
+ private $_matched;
+ /**
+ * File extension of external configuration file
+ */
+ const CONFIG_FILE_EXT='.xml';
+ /**
+ * @var string external configuration file
+ */
+ private $_configFile=null;
+
+ /**
+ * Initializes this module.
+ * This method is required by the IModule interface.
+ * @param TXmlElement configuration for this module, can be null
+ * @throws TConfigurationException if module is configured in the global scope.
+ */
+ public function init($xml)
+ {
+ if($this->getRequest()->getRequestResolved())
+ throw new TConfigurationException('urlpath_dispatch_module_must_be_global');
+ if($this->_configFile!==null)
+ $this->loadConfigFile();
+ $this->loadUrlMappings($xml);
+ $this->resolveMappings();
+ }
+
+ /**
+ * Initialize the module from configuration file.
+ * @throws TConfigurationException if {@link getConfigFile ConfigFile} is invalid.
+ */
+ protected function loadConfigFile()
+ {
+ if(is_file($this->_configFile))
+ {
+ $dom=new TXmlDocument;
+ $dom->loadFromFile($this->_configFile);
+ $this->loadUrlMappings($dom);
+ }
+ else
+ throw new TConfigurationException(
+ 'urlpath_dispatch_configfile_invalid',$this->_configFile);
+ }
+
+ /**
+ * @return string external configuration file. Defaults to null.
+ */
+ public function getConfigFile()
+ {
+ return $this->_configFile;
+ }
+
+ /**
+ * @param string external configuration file in namespace format. The file
+ * must be suffixed with '.xml'.
+ * @throws TInvalidDataValueException if the file is invalid.
+ */
+ public function setConfigFile($value)
+ {
+ if(($this->_configFile=Prado::getPathOfNamespace($value,self::CONFIG_FILE_EXT))===null)
+ throw new TConfigurationException('logrouter_configfile_invalid',$value);
+ }
+
+ /**
+ * Load and configure each url mapping pattern.
+ * @param TXmlElement configuration node
+ * @throws TConfigurationException if specific pattern class is invalid
+ */
+ protected function loadUrlMappings($xml)
+ {
+ foreach($xml->getElementsByTagName('url') as $url)
+ {
+ $properties=$url->getAttributes();
+ $class=$properties->remove('class');
+ if($class===null)
+ $class = $this->_defaultPatternClass;
+ $pattern = Prado::createComponent($class);
+ if(!($pattern instanceof TUrlMappingPattern))
+ throw new TConfigurationException('urlpath_dispatch_invalid_pattern_class');
+ foreach($properties as $name=>$value)
+ $pattern->setSubproperty($name,$value);
+ $this->_patterns[] = $pattern;
+ $pattern->init($url);
+ }
+ }
+
+ /**
+ * Using the request URL path, find the first matching pattern. If found
+ * the matched pattern parameters are used in the Request object.
+ */
+ protected function resolveMappings()
+ {
+ $url = $this->getRequest()->getUrl();
+ foreach($this->_patterns as $pattern)
+ {
+ $matches = $pattern->getPatternMatches($url);
+ if(count($matches) > 0)
+ {
+ $this->changeServiceParameters($pattern);
+ $this->initializeRequestParameters($matches);
+ $this->_matched=$pattern;
+ break;
+ }
+ }
+ }
+
+ /**
+ * @return TUrlMappingPattern the matched pattern, null if not found.
+ */
+ public function getMatchingPattern()
+ {
+ return $this->_matched;
+ }
+
+ /**
+ * @param array initialize the Request with matched parameters.
+ */
+ protected function initializeRequestParameters($matches)
+ {
+ $request = $this->getRequest();
+ foreach($matches as $k => $v)
+ {
+ if(!is_int($k))
+ $request->add($k,$v);
+ }
+ }
+
+ /**
+ * @param TUrlMappingPattern change the Request service ID and page class.
+ */
+ protected function changeServiceParameters($pattern)
+ {
+ $request = $this->getRequest();
+ $id = $pattern->getServiceID();
+ $page = $pattern->getPageClass();
+ $request->setServiceID($id);
+ $request->setServiceParameter($page);
+ $request->add($id,$page);
+ }
+}
+
+/**
+ * URL Mapping Pattern Class
+ *
+ * Describes an URL mapping pattern, if a given URL matches the pattern, the
+ * TUrlMapping class will alter the THttpRequest parameters. The
+ * url matching is done using regular expressions.
+ *
+ * The {@link setPattern Pattern} property takes a regular expression with
+ * parameter names enclosed between a left brace '{' and a right brace '}'.
+ * The pattens for each parameter can be set using {@link getParameters Parameters}
+ * attribute collection. For example
+ * <code>
+ * <url ... pattern="articles/{year}/{month}/{day}"
+ * parameters.year="\d{4}" parameters.month="\d{2}" parameters.day="\d+" />
+ * </code>
+ *
+ * In the above example, the pattern contains 3 parameters named "year",
+ * "month" and "day". The pattern for these parameters are, respectively,
+ * "\d{4}" (4 digits), "\d{2}" (2 digits) and "\d+" (1 or more digits).
+ *
+ * In the TUrlMappingPattern class, the pattern is matched against the
+ * <b>path</b> property of the url only.
+ *
+ * Thus, only an url that matches the pattern will be valid. For example,
+ * an url "<tt>http://example.com/articles/2006/07/21</tt>" will matches and is valid.
+ * However, "<tt>http://example.com/articles/2006/07/hello</tt>" is not
+ * valid since the "day" parameter pattern is not satisfied.
+ *
+ * The parameter values are available through the standard <tt>Request</tt>
+ * object. For example, <tt>$this->Request['year']</tt>.
+ *
+ * The {@link setPageClass PageClass} and {@link setServiceID ServiceID}
+ * (the default ID is 'page') set the class and the service that will
+ * handle the matching URL.
+ *
+ * For more complicated mappings, the body of the <tt><url></tt>
+ * can be used to specify the mapping pattern.
+ *
+ * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
+ * @version $Id$
+ * @package System.Web
+ * @since 3.0.5
+ */
+class TUrlMappingPattern extends TComponent
+{
+ /**
+ * @var string page class name.
+ */
+ private $_pageClass;
+ /**
+ * @var string service ID, default is 'page'.
+ */
+ private $_serviceID='page';
+ /**
+ * @var string url pattern to match.
+ */
+ private $_pattern;
+ /**
+ * @var TMap parameter regular expressions.
+ */
+ private $_parameters;
+ /**
+ * @var string regular expression pattern.
+ */
+ private $_regexp;
+
+ public function __construct()
+ {
+ $this->_parameters = Prado::createComponent('System.Collections.TAttributeCollection');
+ }
+
+ /**
+ * Initialize the pattern, uses the body content as pattern is available.
+ * @param TXmlElement configuration for this module.
+ * @throws TConfigurationException if page class is not specified.
+ */
+ public function init($config)
+ {
+ $body = trim($config->getValue());
+ if(strlen($body)>0)
+ $this->setPattern($body);
+ if(is_null($this->_pageClass))
+ {
+ throw new TConfigurationException(
+ 'dispatcher_url_page_class_missing', $this->getPattern());
+ }
+ $this->initializePattern();
+ }
+
+ /**
+ * Subsitutue the parameter key value pairs as named groupings
+ * in the regular expression matching pattern.
+ */
+ protected function initializePattern()
+ {
+ $params= array();
+ $values = array();
+ foreach($this->parameters as $key => $value)
+ {
+ $params[] = '{'.$key.'}';
+ $values[] = '(?P<'.$key.'>'.$value.')';
+ }
+ $this->_regexp = str_replace($params,$values,$this->getPattern());
+ }
+
+ /**
+ * @return string mapping pattern
+ */
+ protected function getRegExpPattern()
+ {
+ return $this->_regexp;
+ }
+
+ /**
+ * @param string name of the page class to handle the request.
+ */
+ public function setPageClass($value)
+ {
+ $this->_pageClass=$value;
+ }
+
+ /**
+ * @return string page class name.
+ */
+ public function getPageClass()
+ {
+ return $this->_pageClass;
+ }
+
+ /**
+ * @param string service id to handle.
+ */
+ public function setServiceID($value)
+ {
+ $this->_serviceID=$value;
+ }
+
+ /**
+ * @return string service id.
+ */
+ public function getServiceID()
+ {
+ return $this->_serviceID;
+ }
+
+ /**
+ * @return string url pattern to match.
+ */
+ public function getPattern()
+ {
+ return $this->_pattern;
+ }
+
+ /**
+ * @param string url pattern to match.
+ */
+ public function setPattern($value)
+ {
+ $this->_pattern = $value;
+ }
+
+ /**
+ * @return TAttributeCollection parameter key value pairs.
+ */
+ public function getParameters()
+ {
+ return $this->_parameters;
+ }
+
+ /**
+ * @param TAttributeCollection new parameter key value pairs.
+ */
+ public function setParameters($value)
+ {
+ $this->_parameters=$value;
+ }
+
+ /**
+ * Use regular expression to match the given url path.
+ * @param TUri url to match against
+ * @return array matched parameters, empty if no matches.
+ */
+ public function getPatternMatches($url)
+ {
+ $path = $url->getPath();
+ $matches=array();
+ $pattern = str_replace('/', '\\/', $this->getRegExpPattern());
+ preg_match('/'.$pattern.'/', $path, $matches);
+ return $matches;
+ }
+}
+
+?>
\ No newline at end of file diff --git a/framework/Web/UI/WebControls/TDatePicker.php b/framework/Web/UI/WebControls/TDatePicker.php index 86d119ac..b435324d 100644 --- a/framework/Web/UI/WebControls/TDatePicker.php +++ b/framework/Web/UI/WebControls/TDatePicker.php @@ -451,6 +451,7 @@ class TDatePicker extends TTextBox $options['FirstDayOfWeek'] = $this->getFirstDayOfWeek();
if(($cssClass=$this->getCssClass())!=='')
$options['ClassName'] = $cssClass;
+ $options['CalendarStyle'] = $this->getCalendarStyle();
$options['FromYear'] = $this->getFromYear();
$options['UpToYear'] = $this->getUpToYear();
if($this->getMode()!==TDatePickerMode::Basic)
|