summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitattributes2
-rw-r--r--HISTORY1
-rw-r--r--framework/Exceptions/messages/messages.txt3
-rw-r--r--framework/Web/Javascripts/source/prado/controls/controls.js173
-rw-r--r--framework/Web/UI/WebControls/TKeyboard.php183
-rw-r--r--framework/Web/UI/WebControls/keyboard.css80
-rw-r--r--index.html2
7 files changed, 444 insertions, 0 deletions
diff --git a/.gitattributes b/.gitattributes
index b96dec72..10dbecf5 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -2436,6 +2436,7 @@ framework/Web/UI/WebControls/TImageButton.php -text
framework/Web/UI/WebControls/TImageMap.php -text
framework/Web/UI/WebControls/TInlineFrame.php -text
framework/Web/UI/WebControls/TJavascriptLogger.php -text
+framework/Web/UI/WebControls/TKeyboard.php -text
framework/Web/UI/WebControls/TLabel.php -text
framework/Web/UI/WebControls/TLinkButton.php -text
framework/Web/UI/WebControls/TListBox.php -text
@@ -2481,6 +2482,7 @@ framework/Web/UI/WebControls/TWebControlAdapter.php -text
framework/Web/UI/WebControls/TWizard.php -text
framework/Web/UI/WebControls/TWizardNavigationButtonStyle.php -text
framework/Web/UI/WebControls/TXmlTransform.php -text
+framework/Web/UI/WebControls/keyboard.css -text
framework/Xml/TXmlDocument.php -text
framework/interfaces.php -text
framework/powered.gif -text
diff --git a/HISTORY b/HISTORY
index 9a419b35..e8f8318a 100644
--- a/HISTORY
+++ b/HISTORY
@@ -21,6 +21,7 @@ CHG: Validators will not validate disabled controls (Qiang)
NEW: Ticket#676 - Added primilary Oracle support (Christophe)
NEW: Ticket#680 - Added TCacheHttpSession (Carl, Qiang)
NEW: Added TTabPanel (Qiang)
+NEW: Added TKeyboard (Qiang)
NEW: Added Indonesian translation to QuickStart, requirements and error messages (Zaenal Mutaqin)
Version 3.1.0 July 2, 2007
diff --git a/framework/Exceptions/messages/messages.txt b/framework/Exceptions/messages/messages.txt
index 4ed84093..a60b8226 100644
--- a/framework/Exceptions/messages/messages.txt
+++ b/framework/Exceptions/messages/messages.txt
@@ -430,3 +430,6 @@ 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}'.
+
+keyboard_forcontrol_required = TKeyboard.ForControl cannot be empty.
+keyboard_forcontrol_invalid = TKeyboard.ForControl '{0}' is invalid. \ No newline at end of file
diff --git a/framework/Web/Javascripts/source/prado/controls/controls.js b/framework/Web/Javascripts/source/prado/controls/controls.js
index e024234c..8975a7a2 100644
--- a/framework/Web/Javascripts/source/prado/controls/controls.js
+++ b/framework/Web/Javascripts/source/prado/controls/controls.js
@@ -339,3 +339,176 @@ Prado.WebUI.TTabPanel.prototype =
}
}
};
+
+
+Prado.WebUI.TKeyboard = Class.create();
+Prado.WebUI.TKeyboard.prototype =
+{
+ initialize : function(options)
+ {
+ this.element = $(options.ID);
+ this.onInit(options);
+ },
+
+ onInit : function(options)
+ {
+ this.cssClass = options['CssClass'];
+ this.forControl = document.getElementById(options['ForControl']);
+ this.autoHide = options['AutoHide'];
+
+ this.flagShift = false;
+ this.flagCaps = false;
+ this.flagHover = false;
+ this.flagFocus = false;
+
+ this.keys = new Array
+ (
+ new Array('` ~ D', '1 ! D', '2 @ D', '3 # D', '4 $ D', '5 % D', '6 ^ D', '7 & D', '8 * D', '9 ( D', '0 ) D', '- _ D', '= + D', 'Bksp Bksp Bksp'),
+ new Array('Del Del Del', 'q Q L', 'w W L', 'e E L', 'r R L', 't T L', 'y Y L', 'u U L', 'i I L', 'o O L', 'p P L', '[ { D', '] } D', '\\ | \\'),
+ new Array('Caps Caps Caps', 'a A L', 's S L', 'd D L', 'f F L', 'g G L', 'h H L', 'j J L', 'k K L', 'l L L', '; : D', '\' " D', 'Exit Exit Exit'),
+ new Array('Shift Shift Shift', 'z Z L', 'x X L', 'c C L', 'v V L', 'b B L', 'n N L', 'm M L', ', < D', '. > D', '/ ? D', 'Shift Shift Shift')
+ );
+
+ if (this.isObject(this.forControl))
+ {
+ this.forControl.keyboard = this;
+ this.forControl.onfocus = function() {this.keyboard.show(); };
+ this.forControl.onblur = function() {if (this.keyboard.flagHover == false) this.keyboard.hide();};
+ this.forControl.onkeydown = function(e) {if (!e) e = window.event; var key = (e.keyCode)?e.keyCode:e.which; if(key == 9) this.keyboard.hide();;};
+ this.forControl.onselect = this.saveSelection;
+ this.forControl.onclick = this.saveSelection;
+ this.forControl.onkeyup = this.saveSelection;
+ }
+
+ this.render();
+
+ this.tagKeyboard.onmouseover = function() {this.keyboard.flagHover = true;};
+ this.tagKeyboard.onmouseout = function() {this.keyboard.flagHover = false;};
+
+ if (!this.autoHide) this.show();
+ },
+
+ isObject : function(a)
+ {
+ return (typeof a == 'object' && !!a) || typeof a == 'function';
+ },
+
+ createElement : function(tagName, attributes, parent)
+ {
+ var tagElement = document.createElement(tagName);
+ if (this.isObject(attributes)) for (attribute in attributes) tagElement[attribute] = attributes[attribute];
+ if (this.isObject(parent)) parent.appendChild(tagElement);
+ return tagElement;
+ },
+
+ onmouseover : function()
+ {
+ this.className += ' Hover';
+ },
+
+ onmouseout : function()
+ {
+ this.className = this.className.replace(/( Hover| Active)/ig, '');
+ },
+
+ onmousedown : function()
+ {
+ this.className += ' Active';
+ },
+
+ onmouseup : function()
+ {
+ this.className = this.className.replace(/( Active)/ig, '');
+ this.keyboard.type(this.innerHTML);
+ },
+
+ render : function()
+ {
+ this.tagKeyboard = this.createElement('div', {className: this.cssClass, onselectstart: function() {return false;}}, this.element);
+ this.tagKeyboard.keyboard = this;
+
+ for (var line = 0; line < this.keys.length; line++)
+ {
+ var tagLine = this.createElement('div', {className: 'Line'}, this.tagKeyboard);
+ for (var key = 0; key < this.keys[line].length; key++)
+ {
+ var split = this.keys[line][key].split(' ');
+ var tagKey = this.createElement('div', {className: 'Key ' + split[2]}, tagLine);
+ var tagKey1 = this.createElement('div', {className: 'Key1', innerHTML: split[0], keyboard: this, onmouseover: this.onmouseover, onmouseout: this.onmouseout, onmousedown: this.onmousedown, onmouseup: this.onmouseup}, tagKey);
+ var tagKey2 = this.createElement('div', {className: 'Key2', innerHTML: split[1], keyboard: this, onmouseover: this.onmouseover, onmouseout: this.onmouseout, onmousedown: this.onmousedown, onmouseup: this.onmouseup}, tagKey);
+ }
+ }
+ },
+
+ isShown : function()
+ {
+ return (this.tagKeyboard.style.visibility.toLowerCase() == 'visible');
+ },
+
+ show : function()
+ {
+ if (this.isShown() == false) this.tagKeyboard.style.visibility = 'visible';
+ },
+
+ hide : function()
+ {
+ if (this.isShown() == true && this.autoHide) {this.tagKeyboard.style.visibility = 'hidden'; }
+ },
+
+ type : function(key)
+ {
+
+ var input = this.forControl;
+ var command = key.toLowerCase();
+
+ if (command == 'exit') {this.hide();}
+ else if (input != 'undefined' && input != null && command == 'bksp') {this.insert(input, 'bksp');}
+ else if (input != 'undefined' && input != null && command == 'del') {this.insert(input, 'del');}
+ else if (command == 'shift') {this.tagKeyboard.className = this.flagShift?'Keyboard Off':'Keyboard Shift';this.flagShift = this.flagShift?false:true;}
+ else if (command == 'caps') {this.tagKeyboard.className = this.caps?'Keyboard Off':'Keyboard Caps';this.caps = this.caps?false:true;}
+ else if (input != 'undefined' && input != null)
+ {
+ if (this.flagShift == true) {this.flagShift = false; this.tagKeyboard.className = 'Keyboard Off';}
+ key = key.replace(/&gt;/, '>'); key = key.replace(/&lt;/, '<'); key = key.replace(/&amp;/, '&');
+ this.insert(input, key);
+ }
+
+ if (command != 'exit') input.focus();
+
+ },
+
+ saveSelection : function()
+ {
+ if (this.keyboard.forControl.createTextRange)
+ {
+ this.keyboard.selection = document.selection.createRange().duplicate();
+ return;
+ }
+ },
+
+ insert : function(field, value)
+ {
+ if (this.forControl.createTextRange && this.selection)
+ {
+ if (value == 'bksp') {this.selection.moveStart("character", -1); this.selection.text = '';}
+ else if (value == 'del') {this.selection.moveEnd("character", 1); this.selection.text = '';}
+ else {this.selection.text = value;}
+
+ this.selection.select();
+ }
+ else
+ {
+ var selectStart = this.forControl.selectionStart;
+ var selectEnd = this.forControl.selectionEnd;
+ var start = (this.forControl.value).substring(0, selectStart);
+ var end = (this.forControl.value).substring(selectEnd, this.forControl.textLength);
+
+ if (value == 'bksp') {start = start.substring(0, start.length - 1); selectStart -= 1; value = '';}
+ if (value == 'del') {end = end.substring(1, end.length); value = '';}
+
+ this.forControl.value = start + value + end;
+ this.forControl.selectionStart = selectEnd + value.length;
+ this.forControl.selectionEnd = selectStart + value.length;
+ }
+ }
+} \ No newline at end of file
diff --git a/framework/Web/UI/WebControls/TKeyboard.php b/framework/Web/UI/WebControls/TKeyboard.php
new file mode 100644
index 00000000..4ff15613
--- /dev/null
+++ b/framework/Web/UI/WebControls/TKeyboard.php
@@ -0,0 +1,183 @@
+<?php
+/**
+ * TKeyboard class file.
+ *
+ * @author Sergey Morkovkin <sergeymorkovkin@mail.ru> and Qiang Xue <qiang.xue@gmail.com>
+ * @link http://www.pradosoft.com/
+ * @copyright Copyright &copy; 2005-2007 PradoSoft
+ * @license http://www.pradosoft.com/license/
+ * @version $Id: $
+ * @package System.Web.UI.WebControls
+ * @since 3.1.1
+ */
+
+/**
+ * Class TKeyboard.
+ *
+ * TKeyboard displays a virtual keyboard that users can click on to enter input in
+ * an associated text box. It helps to reduce the keyboard recording hacking.
+ *
+ * To use TKeyboard, write a template like following:
+ * <code>
+ * <com:TTextBox ID="PasswordInput" />
+ * <com:TKeyboard ForControl="PasswordInput" />
+ * </code>
+ *
+ * A TKeyboard control is associated with a {@link TTextBox} control by specifying {@link setForControl ForControl}
+ * to be the ID of that control. When the textbox is in focus, a virtual keyboard will pop up; and when
+ * the text box is losing focus, the keyboard will hide automatically. Set {@link setAutoHide AutoHide} to
+ * false to keep the keyboard showing all the time.
+ *
+ * The appearance of the keyboard can also be changed by specifying a customized CSS file via
+ * {@link setCssUrl CssUrl}. By default, the CSS class name for the keyboard is 'Keyboard'. This may
+ * also be changed by specifying {@link setKeyboardCssClass KeyboardCssClass}.
+ *
+ * @author Sergey Morkovkin <sergeymorkovkin@mail.ru> and Qiang Xue <qiang.xue@gmail.com>
+ * @version $Id: $
+ * @since 3.1.1
+ */
+class TKeyboard extends TWebControl
+{
+ /**
+ * @return string the ID path of the {@link TTextBox} control
+ */
+ public function getForControl()
+ {
+ return $this->getViewState('ForControl','');
+ }
+
+ /**
+ * Sets the ID path of the {@link TTextBox} control.
+ * The ID path is the dot-connected IDs of the controls reaching from
+ * the keyboard's naming container to the target control.
+ * @param string the ID path
+ */
+ public function setForControl($value)
+ {
+ $this->setViewState('ForControl', TPropertyValue::ensureString($value));
+ }
+
+ /**
+ * @return boolean whether the keyboard should be hidden when the textbox is not in focus. Defaults to true.
+ */
+ public function getAutoHide()
+ {
+ return $this->getViewState('AutoHide', true);
+ }
+
+ /**
+ * @param boolean whether the keyboard should be hidden when the textbox is not in focus.
+ */
+ public function setAutoHide($value)
+ {
+ $this->setViewState('AutoHide', TPropertyValue::ensureBoolean($value), true);
+ }
+
+ /**
+ * @return string the CSS class name for the keyboard <div> element. Defaults to 'Keyboard'.
+ */
+ public function getKeyboardCssClass()
+ {
+ return $this->getViewState('KeyboardCssClass', 'Keyboard');
+ }
+
+ /**
+ * Sets a value indicating the CSS class name for the keyboard <div> element.
+ * Note, if you change this property, make sure you also supply a customized CSS file
+ * by specifying {@link setCssUrl CssUrl} which uses the new CSS class name for styling.
+ * @param string the CSS class name for the keyboard <div> element.
+ */
+ public function setKeyboardCssClass($value)
+ {
+ $this->setViewState('KeyboardCssClass', $value, 'Keyboard');
+ }
+
+ /**
+ * @return string the URL for the CSS file to customize the appearance of the keyboard.
+ */
+ public function getCssUrl()
+ {
+ return $this->getViewState('CssUrl', '');
+ }
+
+ /**
+ * @param string the URL for the CSS file to customize the appearance of the keyboard.
+ */
+ public function setCssUrl($value)
+ {
+ $this->setViewState('CssUrl', $value, '');
+ }
+
+ /**
+ * Registers CSS and JS.
+ * This method is invoked right before the control rendering, if the control is visible.
+ * @param mixed event parameter
+ */
+ public function onPreRender($param)
+ {
+ parent::onPreRender($param);
+ if($this->getPage()->getClientSupportsJavaScript())
+ {
+ $this->registerStyleSheet();
+ $this->registerClientScript();
+ }
+ }
+
+ /**
+ * Adds attribute name-value pairs to renderer.
+ * This method overrides the parent implementation with additional TKeyboard specific attributes.
+ * @param THtmlWriter the writer used for the rendering purpose
+ */
+ protected function addAttributesToRender($writer)
+ {
+ parent::addAttributesToRender($writer);
+ if($this->getPage()->getClientSupportsJavaScript())
+ $writer->addAttribute('id',$this->getClientID());
+ }
+
+ /**
+ * Registers the CSS relevant to the TKeyboard.
+ * It will register the CSS file specified by {@link getCssUrl CssUrl}.
+ * If that is not set, it will use the default CSS.
+ */
+ protected function registerStyleSheet()
+ {
+ if(($url=$this->getCssUrl())==='')
+ $url=$this->publishAsset('keyboard.css',__CLASS__);
+ $this->getPage()->getClientScript()->registerStyleSheetFile($url,$url);
+ }
+
+ /**
+ * Registers the relevant JavaScript.
+ */
+ protected function registerClientScript()
+ {
+ $options=TJavaScript::encode($this->getClientOptions());
+ $className=$this->getClientClassName();
+ $cs=$this->getPage()->getClientScript();
+ $cs->registerPradoScript('prado');
+ $cs->registerEndScript('prado:'.$this->getClientID(), "new $className($options);");
+ }
+
+ protected function getClientClassName()
+ {
+ return 'Prado.WebUI.TKeyboard';
+ }
+
+ protected function getClientOptions()
+ {
+ if(($forControl=$this->getForControl())==='')
+ throw new TConfigurationException('keyboard_forcontrol_required');
+ if(($target=$this->findControl($forControl))===null)
+ throw new TConfigurationException('keyboard_forcontrol_invalid',$forControl);
+
+ $options['ID'] = $this->getClientID();
+ $options['ForControl'] = $target->getClientID();
+ $options['AutoHide'] = $this->getAutoHide();
+ $options['CssClass'] = $this->getKeyboardCssClass();
+
+ return $options;
+ }
+}
+
+?> \ No newline at end of file
diff --git a/framework/Web/UI/WebControls/keyboard.css b/framework/Web/UI/WebControls/keyboard.css
new file mode 100644
index 00000000..ad88d76b
--- /dev/null
+++ b/framework/Web/UI/WebControls/keyboard.css
@@ -0,0 +1,80 @@
+div.Keyboard
+{
+ -moz-background-clip: -moz-initial;
+ -moz-background-origin: -moz-initial;
+ -moz-background-inline-policy: -moz-initial;
+ -moz-user-select: none;
+
+ display: block;
+ position: absolute;
+ border: 1px solid #698977;
+ background-color: #DDDDDD;
+ z-index: 1000 !important;
+ visibility: hidden;
+ padding: 4px 4px 4px 4px;
+ text-align: center;
+}
+
+div.Keyboard div.Line
+{
+ width: 267px;
+ height: 18px;
+}
+
+div.Keyboard div.Key
+{
+ width: 17px;
+ height: 17px;
+ margin: 1px 0px 0px 1px;
+ overflow: hidden;
+ float: left;
+ display: inline;
+}
+
+div.Keyboard div.Key div.Key1,
+div.Keyboard div.Key div.Key2
+{
+ overflow: hidden;
+ border: 1px solid #A5A5A5;
+ background-color: #F7F7F7;
+ font-family: Verdana, Arial, Helvetica, sans-serif;
+ font-size: 11px;
+ color: #556C5F;
+ font-weight: normal;
+ text-align: center;
+ line-height: 15px;
+ vertical-align: middle;
+ display: block;
+ cursor: pointer;
+}
+
+div.Keyboard div.Key div.Hover
+{
+ color: #E02C03;
+ border-color: #E0431D;
+}
+
+div.Keyboard div.Key div.Active
+{
+ color: #FFFFFF;
+ background-color: #E0431D;
+}
+
+div.Keyboard.Shift div.Key div.Key1,
+div.Keyboard.Caps div.L div.Key1,
+div.Keyboard.Off div.Key div.Key2
+{
+ display: none;
+}
+
+div.Keyboard.Caps div.L div.Key2
+{
+ display: block;
+}
+
+div.Keyboard div.Bksp {width: 31px;}
+div.Keyboard div.Exit {width: 33px;}
+div.Keyboard div.Caps {width: 33px;}
+div.Keyboard div.\\ {width: 24px;}
+div.Keyboard div.Del {width: 24px;}
+div.Keyboard div.Shift {width: 42px;} \ No newline at end of file
diff --git a/index.html b/index.html
index 97fe6aa3..5cc4d0b3 100644
--- a/index.html
+++ b/index.html
@@ -122,6 +122,8 @@ PRADO component tags when you use it to edit PRADO templates.
<li>Andres Adolfo Testi - original concept and naming for Active Controls.</li>
<li><a href="http://www.jackslocum.com/">Jack Slocum</a> - inspiration for the quickstart commenting system.</li>
<li>Cesar Ramos - Active Record driver for IBM DB2.</li>
+<li>Sergey Morkovkin - TKeyboard control</li>
+<li>Tomasz Wolny - TTabPanel control</li>
<li>All PRADO users - great suggestions, feedback and support</li>
<li>ASP.NET 2.0 for its great inspiration and reference</li>
<li>All <a href="framework/3rdParty/readme.html">third-party work</a> used in PRADO</li>