diff --git a/lib/WebGUI/Form/HexSlider.pm b/lib/WebGUI/Form/HexSlider.pm
new file mode 100644
index 000000000..181662a89
--- /dev/null
+++ b/lib/WebGUI/Form/HexSlider.pm
@@ -0,0 +1,131 @@
+package WebGUI::Form::HexSlider;
+
+=head1 LEGAL
+
+ -------------------------------------------------------------------
+ WebGUI is Copyright 2001-2006 Plain Black Corporation.
+ -------------------------------------------------------------------
+ Please read the legal notices (docs/legal.txt) and the license
+ (docs/license.txt) that came with this distribution before using
+ this software.
+ -------------------------------------------------------------------
+ http://www.plainblack.com info@plainblack.com
+ -------------------------------------------------------------------
+
+=cut
+
+use strict;
+use base 'WebGUI::Form::Control';
+use WebGUI::International;
+
+=head1 NAME
+
+Package WebGUI::Form::HexSlider
+
+=head1 DESCRIPTION
+
+Creates a slider control that controls hex values, as in the red, gree, blue values for HTML colors.
+
+=head1 SEE ALSO
+
+This is a subclass of WebGUI::Form::Control.
+
+=head1 METHODS
+
+The following methods are specifically available from this class. Check the superclass for additional methods.
+
+=cut
+
+#-------------------------------------------------------------------
+
+=head2 definition ( [ additionalTerms ] )
+
+See the super class for additional details.
+
+=head3 additionalTerms
+
+The following additional parameters have been added via this sub class.
+
+=head4 maximum
+
+Defaults to "ff". The maximum that the slider can go to.
+
+=head4 minimum
+
+Defaults to "00". The minimum value that the slider can go to.
+
+=head4 profileEnabled
+
+Flag that tells the User Profile system that this is a valid form element in a User Profile
+
+=cut
+
+sub definition {
+ my $class = shift;
+ my $session = shift;
+ my $definition = shift || [];
+ my $i18n = WebGUI::International->new($session);
+ push(@{$definition}, {
+ formName=>{
+ defaultValue=> $i18n->get("475")
+ },
+ maximum=>{
+ defaultValue=> "ff",
+ },
+ minimum=>{
+ defaultValue=> "00",
+ },
+ profileEnabled=>{
+ defaultValue=>1
+ },
+ });
+ return $class->SUPER::definition($session, $definition);
+}
+
+#-------------------------------------------------------------------
+
+=head2 getValueFromPost ( )
+
+Retrieves a value from a form GET or POST and returns it. If the value comes back as undef, this method will return the defaultValue instead. Strip newlines/carriage returns from the value.
+
+=cut
+
+sub getValueFromPost {
+ my $self = shift;
+ my $formValue = $self->session->form->param($self->get("name")) if ($self->session->request);
+ if (defined $formValue && $formValue =~ m/^[a-f0-9]{2}$/) {
+ return $formValue;
+ } else {
+ return $self->{defaultValue};
+ }
+}
+
+#-------------------------------------------------------------------
+
+=head2 toHtml ( )
+
+Renders an input tag of type text.
+
+=cut
+
+sub toHtml {
+ my $self = shift;
+ $self->session->style->setScript($self->session->url->extras("slider/js/range.js"), {type=>"text/javascript"});
+ $self->session->style->setScript($self->session->url->extras("slider/js/timer.js"), {type=>"text/javascript"});
+ $self->session->style->setScript($self->session->url->extras("slider/js/slider.js"), {type=>"text/javascript"});
+ $self->session->style->setLink($self->session->url->extras("slider/css/bluecurve/bluecurve.css"), {rel=>"stylesheet", type=>"text/css"});
+ my $output = '
+
+
+
+
Timer
+ Object Oriented Encapsulation of setTimeout
+
Syntax
+
+ new Timer([nPauseTime])
Parameters
| Name | Type | Descripton |
nPauseTime | Number | Optional.
+ The time (in milliseconds) before the timer should be triggered once started.
+
+ The default value is 1000.
+ |
Static Methods
Static Fields
Methods
| Name | Description |
getPauseTimeSyntaxobject.getPauseTime()
ArgumentsNo Arguments. Return TypeNumber
| Returns the pause time (in milliseconds) used to wait once started before triggering the event |
isStartedSyntaxobject.isStarted()
ArgumentsNo Arguments. Return TypeBoolean
| Returns whether the timer is started |
setPauseTimeSyntaxobject.setPauseTime(nPauseTime)
Arguments| Name | Type | Descripton | nPauseTime | Number | The time to pause |
Return Typevoid
| Sets the time (in milliseconds) to pause before triggering the event |
startSyntaxobject.start()
ArgumentsNo Arguments. Return Typevoid
| Starts the timer |
stopSyntaxobject.stop()
ArgumentsNo Arguments. Return Typevoid
| Stops the timer if previously started |
Fields
Events
| Name | Descripton |
ontimer | Fires nPauseTime milliseconds after started |
Remarks
+ None.
+
Range
+ Used to model the data used when working with sliders, scrollbars and progress bars.
+ Based on the ideas of the javax.swing.BoundedRangeModel interface defined by Sun for Java
+ (http://java.sun.com/products/jfc/swingdoc-api-1.0.3/com/sun/java/swing/BoundedRangeModel.html).
+
Syntax
+
+ new Range()
Parameters
| Name | Type | Descripton |
| No parameters. |
Static Methods
Static Fields
Methods
| Name | Description |
getExtentSyntaxobject.getExtent()
ArgumentsReturn TypeNumber
| Returns the extent of the range |
getMaximumSyntaxobject.getMaximum()
ArgumentsReturn TypeNumber
| Returns the maximum allowed value |
getMinimumSyntaxobject.getMinimum()
ArgumentsReturn TypeNumber
| Returns the minimum value |
getValueSyntaxobject.getValue()
ArgumentsReturn TypeNumber
| Returns the current value of the range |
setExtentSyntaxobject.setExtent(nExtent)
Arguments| Name | Type | Descripton | nExtent | Number | The extent of the value |
Return Typevoid
| Sets the extent of the range |
setMaximumSyntaxobject.setMaximum(nMaximum)
Arguments| Name | Type | Descripton | nMaximum | Number | The maximum value |
Return Typevoid
| Sets the maximum allowed value |
setMinimumSyntaxobject.setMinimum(nMinimum)
Arguments| Name | Type | Descripton | nMinimum | Number | The minimum value |
Return Typevoid
| Sets the minimum allowed value |
setValueSyntaxobject.setValue(nValue)
Arguments| Name | Type | Descripton | nValue | Number | The value for the range |
Return Typevoid
| Sets the value for the range |
Fields
Events
| Name | Descripton |
ontimer | Fires on the object nPauseTime milliseconds after started |
Remarks
+ None.
+
Slider
+ A slider control that allows the user to drag a handle to change the value that
+ is limited by a maximum value and a minimum value.
+
Syntax
+
+ new Slider(oElement, oInput [, sOrientation])
Parameters
| Name | Type | Descripton |
oElement | HTMLElement | The element acting as a slider |
oInput | HTMLInputElement | The input element used for backward compatibility and posting |
sOrientation | String | Optional.
+ The orientation of the slider. Valid values are "horizontal" and "vertical"
+
+ The default value is horizontal.
+ |
Static Methods
Static Fields
| Name | Type | Descripton |
isSupported | Boolean | Read only. This value is true if the browser supports dynamic sliders |
Methods
| Name | Description |
getBlockIncrementSyntaxobject.getBlockIncrement()
ArgumentsReturn TypeNumber
| Returns the amount used for large increments |
getMaximumSyntaxobject.getMaximum()
ArgumentsReturn TypeNumber
| Returns the maximum value |
getMinimumSyntaxobject.getMinimum()
ArgumentsReturn TypeNumber
| Returns the minimum value |
getOrientationSyntaxobject.getOrientation()
ArgumentsReturn TypeString
| Returns the orientation of the slider. Valid values are "horizontal" and
+ "vertical". |
getUnitIncrementSyntaxobject.getUnitIncrement()
ArgumentsReturn TypeNumber
| Returns the amount used to do small increments |
getValueSyntaxobject.getValue()
ArgumentsReturn TypeNumber
| Returns the value of the slider |
ontimerSyntaxobject.ontimer()
ArgumentsReturn Typevoid
| Called when the timer used when holding down the mouse button is fired |
recalculateSyntaxobject.recalculate()
ArgumentsReturn Typevoid
| Recalculates the position and size of the sub elements to make ensure the
+ layout is correct. Use this message after the slider has been resized. |
setBlockIncrementSyntaxobject.setBlockIncrement(nBlockIncrement)
Arguments| Name | Type | Descripton | nBlockIncrement | Number | The block increment value |
Return Typevoid
| Sets the amounf to increment the value for large increments. This value is
+ used when using the page up and page down keys to change the value as well as when
+ holding down the mouse on the slider (but not dragging the handle). |
setMaximumSyntaxobject.setMaximum(nMaximum)
Arguments| Name | Type | Descripton | nMaximum | Number | The maximum value |
Return Typevoid
| Sets the maximum allowed value for the slider |
setMinimumSyntaxobject.setMinimum(nMinimum)
Arguments| Name | Type | Descripton | nMinimum | Number | The minimum value |
Return Typevoid
| Sets the minimum allowed value for the slider |
setOrientationSyntaxobject.setOrientation(sOrientation)
Arguments| Name | Type | Descripton | sOrientation | String | The orientation to use |
Return TypeEDIT_THIS
| Sets the orientation of the slider. Valid values are "horizontal" and
+ "vertical". |
setUnitIncrementSyntaxobject.setUnitIncrement(nUnitIncrement)
Arguments| Name | Type | Descripton | nUnitIncrement | Number | The unit increment value |
Return Typevoid
| Sets the amount to increment the value for small increments. This value is
+ used when using the arrow keys to change the value |
setValueSyntaxobject.setValue(nValue)
Arguments| Name | Type | Descripton | nValue | Number | The value to set |
Return Typevoid
| Sets the value of the slider |
Fields
| Name | Type | Descripton |
classNameTag | String | The extra string to add to the class name for a dynamic slider. This property
+ is used to allow specific CSS rules to distinguish between static sliders and dynamic.
+ This property should not be changed after any sliders have been created. |
Events
| Name | Descripton |
onchange | This event is fired when the value of the slider has changed |
Remarks
+ None.
+
+
+
+Slider
+Implementation
+API
+Demo
+Download
+
+
+
Author: Erik Arvidsson
+
+
+
+
+
+
diff --git a/www/extras/slider/css/bluecurve/bluecurve.css b/www/extras/slider/css/bluecurve/bluecurve.css
new file mode 100755
index 000000000..01e3a56da
--- /dev/null
+++ b/www/extras/slider/css/bluecurve/bluecurve.css
@@ -0,0 +1,80 @@
+/*
+ back: rgb(230,230,230)
+ dark: rgb(90,97,90)
+ medium rgb(189,190,189)
+ */
+
+.dynamic-slider-control {
+ position: relative;
+ background-color: rgb(230,230,230);
+ -moz-user-focus: normal;
+ -moz-user-select: none;
+ cursor: default;
+}
+
+.horizontal {
+ width: 200px;
+ height: 27px;
+}
+
+.vertical {
+ width: 29px;
+ height: 200px;
+}
+
+.dynamic-slider-control input {
+ display: none;
+}
+
+.dynamic-slider-control .handle {
+ position: absolute;
+ font-size: 1px;
+ overflow: hidden;
+ -moz-user-select: none;
+ cursor: default;
+}
+
+.dynamic-slider-control.horizontal .handle {
+ width: 31px;
+ height: 14px;
+ background-image: url("handle.horizontal.png");
+}
+
+.dynamic-slider-control.horizontal .handle div {}
+.dynamic-slider-control.horizontal .handle.hover {}
+
+.dynamic-slider-control.vertical .handle {
+ width: 15px;
+ height: 31px;
+ background-image: url("handle.vertical.png");
+}
+
+.dynamic-slider-control.vertical .handle.hover {}
+
+.dynamic-slider-control .line {
+ position: absolute;
+ font-size: 0.01mm;
+ overflow: hidden;
+ border: 1px solid rgb(90,97,90);
+ background: rgb(189,190,189);
+
+ behavior: url("css/boxsizing.htc"); /* ie path bug */
+ box-sizing: content-box;
+ -moz-box-sizing: content-box;
+}
+.dynamic-slider-control.vertical .line {
+ width: 3px;
+}
+
+.dynamic-slider-control.horizontal .line {
+ height: 3px;
+}
+
+.dynamic-slider-control .line div {
+ width: 1px;
+ height: 1px;
+
+ border: 1px solid;
+ border-color: rgb(230,230,230) rgb(189,190,189)
+ rgb(189,190,189) rgb(230,230,230);
+}
\ No newline at end of file
diff --git a/www/extras/slider/css/bluecurve/handle.horizontal.png b/www/extras/slider/css/bluecurve/handle.horizontal.png
new file mode 100755
index 000000000..d9dc7ff91
Binary files /dev/null and b/www/extras/slider/css/bluecurve/handle.horizontal.png differ
diff --git a/www/extras/slider/css/bluecurve/handle.vertical.png b/www/extras/slider/css/bluecurve/handle.vertical.png
new file mode 100755
index 000000000..0c00f85d0
Binary files /dev/null and b/www/extras/slider/css/bluecurve/handle.vertical.png differ
diff --git a/www/extras/slider/css/bluecurve/horizontal.gif b/www/extras/slider/css/bluecurve/horizontal.gif
new file mode 100755
index 000000000..39d816b95
Binary files /dev/null and b/www/extras/slider/css/bluecurve/horizontal.gif differ
diff --git a/www/extras/slider/css/bluecurve/vertical.gif b/www/extras/slider/css/bluecurve/vertical.gif
new file mode 100755
index 000000000..781eaace7
Binary files /dev/null and b/www/extras/slider/css/bluecurve/vertical.gif differ
diff --git a/www/extras/slider/css/boxsizing.htc b/www/extras/slider/css/boxsizing.htc
new file mode 100755
index 000000000..bbb55f6c2
--- /dev/null
+++ b/www/extras/slider/css/boxsizing.htc
@@ -0,0 +1,157 @@
+
+
+
+
Implementation
+
+
The slider implementation mostly consists of lots of event handlers that
+sets the value depending on the event arguments.
+
+
Range
+
+
The data model is handled by a class called Range (also known as BoundedRangeModel).
+This class has a few properties that fits perfectly with sliders, scrollbars and
+progress bars. A range has a minimum value, a value, an extent and a maximum value.
+The following is always true for a range object.
+
+
+minimum < value < value + extent < maximum
+
+
+
In the case of a slider the extent is always zero. Using a range for the data
+model allows the implementation of the slider to concentrate on other things than
+ensuring that the data model is valid.
+
+
Timer
+
+
For this implementation of the slider I decided to use an object oriented
+abstraction of window.setTimeout. A timer from the Timer
+class can be started and stopped and it fires a pseudo event called ontimer
+a certain amount of milliseconds after the timer is started.
+
+
+Timer.prototype.start = function () {
+ if (this.isStarted())
+ this.stop();
+ var oThis = this;
+ this._timer = window.setTimeout(function () {
+ if (typeof oThis.ontimer == "function")
+ oThis.ontimer();
+ }, this._pauseTime);
+ this._isStarted = false;
+};
+
+Timer.prototype.stop = function () {
+ if (this._timer != null)
+ window.clearTimeout(this._timer);
+ this._isStarted = false;
+};
+
+
+
Slider
+
+
The slider consists of a line element and a handle element. The line is only
+there for the visual effect. The handle on the other hand can be dragged and
+thereby changing the value. When dragging the handle the position of the mouse
+is used to calculate a new value for the data model. Once the value is changed
+the layout for the slider is recalculated.
+
+
When the user holds down the mouse on the slider, but not on the handle, a
+timer is started and every time the timer triggers the timer event
+the value is changed by the blockIncrement towards the mouse
+pointer.
+
+
The slider also allows the user to use the keyboard to change the value. This
+is done by listening to the keydown (and keypress)
+events. In the keydown handler the key is checked and the value for
+the data model is updated accordingly. The reason for the keypress
+handler is to disable the default actions in the browser.
+
+
+Slider
+Implementation
+API
+Demo
+Download
+
+
+
Author: Erik Arvidsson
+
+
+
+
+
+
diff --git a/www/extras/slider/js/range.js b/www/extras/slider/js/range.js
new file mode 100755
index 000000000..1fd0c34fa
--- /dev/null
+++ b/www/extras/slider/js/range.js
@@ -0,0 +1,147 @@
+/*----------------------------------------------------------------------------\
+| Range Class |
+|-----------------------------------------------------------------------------|
+| Created by Erik Arvidsson |
+| (http://webfx.eae.net/contact.html#erik) |
+| For WebFX (http://webfx.eae.net/) |
+|-----------------------------------------------------------------------------|
+| Used to model the data used when working with sliders, scrollbars and |
+| progress bars. Based on the ideas of the javax.swing.BoundedRangeModel |
+| interface defined by Sun for Java. http://java.sun.com/products/jfc/ |
+| swingdoc-api-1.0.3/com/sun/java/swing/BoundedRangeModel.html | |
+|-----------------------------------------------------------------------------|
+| Copyright (c) 1999 - 2002 Erik Arvidsson |
+|-----------------------------------------------------------------------------|
+| This software is provided "as is", without warranty of any kind, express or |
+| implied, including but not limited to the warranties of merchantability, |
+| fitness for a particular purpose and noninfringement. In no event shall the |
+| authors or copyright holders be liable for any claim, damages or other |
+| liability, whether in an action of contract, tort or otherwise, arising |
+| from, out of or in connection with the software or the use or other |
+| dealings in the software. |
+| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
+| This software is available under the three different licenses mentioned |
+| below. To use this software you must chose, and qualify, for one of those. |
+| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
+| The WebFX Non-Commercial License http://webfx.eae.net/license.html |
+| Permits anyone the right to use the software in a non-commercial context |
+| free of charge. |
+| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
+| The WebFX Commercial license http://webfx.eae.net/commercial.html |
+| Permits the license holder the right to use the software in a commercial |
+| context. Such license must be specifically obtained, however it's valid for |
+| any number of implementations of the licensed software. |
+| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
+| GPL - The GNU General Public License http://www.gnu.org/licenses/gpl.txt |
+| Permits anyone the right to use and modify the software without limitations |
+| as long as proper credits are given and the original and modified source |
+| code are included. Requires that the final product, software derivate from |
+| the original source or any software utilizing a GPL component, such as |
+| this, is also licensed under the GPL license. |
+|-----------------------------------------------------------------------------|
+| 2002-10-14 | Original version released |
+|-----------------------------------------------------------------------------|
+| Created 2002-10-14 | All changes are in the log above. | Updated 2002-10-14 |
+\----------------------------------------------------------------------------*/
+
+
+function Range() {
+ this._value = 0;
+ this._minimum = 0;
+ this._maximum = 100;
+ this._extent = 0;
+
+ this._isChanging = false;
+}
+
+Range.prototype.setValue = function (value) {
+ value = parseInt(value);
+ if (isNaN(value)) return;
+ if (this._value != value) {
+ if (value + this._extent > this._maximum)
+ this._value = this._maximum - this._extent;
+ else if (value < this._minimum)
+ this._value = this._minimum;
+ else
+ this._value = value;
+ if (!this._isChanging && typeof this.onchange == "function")
+ this.onchange();
+ }
+};
+
+Range.prototype.getValue = function () {
+ return this._value;
+};
+
+Range.prototype.setExtent = function (extent) {
+ if (this._extent != extent) {
+ if (extent < 0)
+ this._extent = 0;
+ else if (this._value + extent > this._maximum)
+ this._extent = this._maximum - this._value;
+ else
+ this._extent = extent;
+ if (!this._isChanging && typeof this.onchange == "function")
+ this.onchange();
+ }
+};
+
+Range.prototype.getExtent = function () {
+ return this._extent;
+};
+
+Range.prototype.setMinimum = function (minimum) {
+ if (this._minimum != minimum) {
+ var oldIsChanging = this._isChanging;
+ this._isChanging = true;
+
+ this._minimum = minimum;
+
+ if (minimum > this._value)
+ this.setValue(minimum);
+ if (minimum > this._maximum) {
+ this._extent = 0;
+ this.setMaximum(minimum);
+ this.setValue(minimum)
+ }
+ if (minimum + this._extent > this._maximum)
+ this._extent = this._maximum - this._minimum;
+
+ this._isChanging = oldIsChanging;
+ if (!this._isChanging && typeof this.onchange == "function")
+ this.onchange();
+ }
+};
+
+Range.prototype.getMinimum = function () {
+ return this._minimum;
+};
+
+Range.prototype.setMaximum = function (maximum) {
+ if (this._maximum != maximum) {
+ var oldIsChanging = this._isChanging;
+ this._isChanging = true;
+
+ this._maximum = maximum;
+
+ if (maximum < this._value)
+ this.setValue(maximum - this._extent);
+ if (maximum < this._minimum) {
+ this._extent = 0;
+ this.setMinimum(maximum);
+ this.setValue(this._maximum);
+ }
+ if (maximum < this._minimum + this._extent)
+ this._extent = this._maximum - this._minimum;
+ if (maximum < this._value + this._extent)
+ this._extent = this._maximum - this._value;
+
+ this._isChanging = oldIsChanging;
+ if (!this._isChanging && typeof this.onchange == "function")
+ this.onchange();
+ }
+};
+
+Range.prototype.getMaximum = function () {
+ return this._maximum;
+};
diff --git a/www/extras/slider/js/slider.js b/www/extras/slider/js/slider.js
new file mode 100755
index 000000000..2abb01036
--- /dev/null
+++ b/www/extras/slider/js/slider.js
@@ -0,0 +1,506 @@
+/*----------------------------------------------------------------------------\
+| Slider 1.02 |
+|-----------------------------------------------------------------------------|
+| Created by Erik Arvidsson |
+| (http://webfx.eae.net/contact.html#erik) |
+| For WebFX (http://webfx.eae.net/) |
+|-----------------------------------------------------------------------------|
+| A slider control that degrades to an input control for non supported |
+| browsers. |
+|-----------------------------------------------------------------------------|
+| Copyright (c) 1999 - 2002 Erik Arvidsson |
+|-----------------------------------------------------------------------------|
+| This software is provided "as is", without warranty of any kind, express or |
+| implied, including but not limited to the warranties of merchantability, |
+| fitness for a particular purpose and noninfringement. In no event shall the |
+| authors or copyright holders be liable for any claim, damages or other |
+| liability, whether in an action of contract, tort or otherwise, arising |
+| from, out of or in connection with the software or the use or other |
+| dealings in the software. |
+| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
+| This software is available under the three different licenses mentioned |
+| below. To use this software you must chose, and qualify, for one of those. |
+| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
+| The WebFX Non-Commercial License http://webfx.eae.net/license.html |
+| Permits anyone the right to use the software in a non-commercial context |
+| free of charge. |
+| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
+| The WebFX Commercial license http://webfx.eae.net/commercial.html |
+| Permits the license holder the right to use the software in a commercial |
+| context. Such license must be specifically obtained, however it's valid for |
+| any number of implementations of the licensed software. |
+| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
+| GPL - The GNU General Public License http://www.gnu.org/licenses/gpl.txt |
+| Permits anyone the right to use and modify the software without limitations |
+| as long as proper credits are given and the original and modified source |
+| code are included. Requires that the final product, software derivate from |
+| the original source or any software utilizing a GPL component, such as |
+| this, is also licensed under the GPL license. |
+|-----------------------------------------------------------------------------|
+| 2002-10-14 | Original version released |
+| 2003-03-27 | Added a test in the constructor for missing oElement arg |
+| 2003-11-27 | Only use mousewheel when focused |
+|-----------------------------------------------------------------------------|
+| Dependencies: timer.js - an OO abstraction of timers |
+| range.js - provides the data model for the slider |
+| winclassic.css or any other css file describing the look |
+|-----------------------------------------------------------------------------|
+| Created 2002-10-14 | All changes are in the log above. | Updated 2003-1-27 |
+\----------------------------------------------------------------------------*/
+
+
+Slider.isSupported = typeof document.createElement != "undefined" &&
+ typeof document.documentElement != "undefined" &&
+ typeof document.documentElement.offsetWidth == "number";
+
+
+function Slider(oElement, oInput, sOrientation) {
+ if (!oElement) return;
+ this._orientation = sOrientation || "horizontal";
+ this._range = new Range();
+ this._range.setExtent(0);
+ this._blockIncrement = 10;
+ this._unitIncrement = 1;
+ this._timer = new Timer(100);
+
+
+ if (Slider.isSupported && oElement) {
+
+ this.document = oElement.ownerDocument || oElement.document;
+
+ this.element = oElement;
+ this.element.slider = this;
+ this.element.unselectable = "on";
+
+ // add class name tag to class name
+ this.element.className = this._orientation + " " + this.classNameTag + " " + this.element.className;
+
+ // create line
+ this.line = this.document.createElement("DIV");
+ this.line.className = "line";
+ this.line.unselectable = "on";
+ this.line.appendChild(this.document.createElement("DIV"));
+ this.element.appendChild(this.line);
+
+ // create handle
+ this.handle = this.document.createElement("DIV");
+ this.handle.className = "handle";
+ this.handle.unselectable = "on";
+ this.handle.appendChild(this.document.createElement("DIV"));
+ this.handle.firstChild.appendChild(
+ this.document.createTextNode(String.fromCharCode(160)));
+ this.element.appendChild(this.handle);
+ }
+
+ this.input = oInput;
+
+ // events
+ var oThis = this;
+ this._range.onchange = function () {
+ oThis.recalculate();
+ if (typeof oThis.onchange == "function")
+ oThis.onchange();
+ };
+
+ if (Slider.isSupported && oElement) {
+ this.element.onfocus = Slider.eventHandlers.onfocus;
+ this.element.onblur = Slider.eventHandlers.onblur;
+ this.element.onmousedown = Slider.eventHandlers.onmousedown;
+ this.element.onmouseover = Slider.eventHandlers.onmouseover;
+ this.element.onmouseout = Slider.eventHandlers.onmouseout;
+ this.element.onkeydown = Slider.eventHandlers.onkeydown;
+ this.element.onkeypress = Slider.eventHandlers.onkeypress;
+ this.element.onmousewheel = Slider.eventHandlers.onmousewheel;
+ this.handle.onselectstart =
+ this.element.onselectstart = function () { return false; };
+
+ this._timer.ontimer = function () {
+ oThis.ontimer();
+ };
+
+ // extra recalculate for ie
+ window.setTimeout(function() {
+ oThis.recalculate();
+ }, 1);
+ }
+ else {
+ this.input.onchange = function (e) {
+ oThis.setValue(oThis.input.value);
+ };
+ }
+}
+
+Slider.eventHandlers = {
+
+ // helpers to make events a bit easier
+ getEvent: function (e, el) {
+ if (!e) {
+ if (el)
+ e = el.document.parentWindow.event;
+ else
+ e = window.event;
+ }
+ if (!e.srcElement) {
+ var el = e.target;
+ while (el != null && el.nodeType != 1)
+ el = el.parentNode;
+ e.srcElement = el;
+ }
+ if (typeof e.offsetX == "undefined") {
+ e.offsetX = e.layerX;
+ e.offsetY = e.layerY;
+ }
+
+ return e;
+ },
+
+ getDocument: function (e) {
+ if (e.target)
+ return e.target.ownerDocument;
+ return e.srcElement.document;
+ },
+
+ getSlider: function (e) {
+ var el = e.target || e.srcElement;
+ while (el != null && el.slider == null) {
+ el = el.parentNode;
+ }
+ if (el)
+ return el.slider;
+ return null;
+ },
+
+ getLine: function (e) {
+ var el = e.target || e.srcElement;
+ while (el != null && el.className != "line") {
+ el = el.parentNode;
+ }
+ return el;
+ },
+
+ getHandle: function (e) {
+ var el = e.target || e.srcElement;
+ var re = /handle/;
+ while (el != null && !re.test(el.className)) {
+ el = el.parentNode;
+ }
+ return el;
+ },
+ // end helpers
+
+ onfocus: function (e) {
+ var s = this.slider;
+ s._focused = true;
+ s.handle.className = "handle hover";
+ },
+
+ onblur: function (e) {
+ var s = this.slider
+ s._focused = false;
+ s.handle.className = "handle";
+ },
+
+ onmouseover: function (e) {
+ e = Slider.eventHandlers.getEvent(e, this);
+ var s = this.slider;
+ if (e.srcElement == s.handle)
+ s.handle.className = "handle hover";
+ },
+
+ onmouseout: function (e) {
+ e = Slider.eventHandlers.getEvent(e, this);
+ var s = this.slider;
+ if (e.srcElement == s.handle && !s._focused)
+ s.handle.className = "handle";
+ },
+
+ onmousedown: function (e) {
+ e = Slider.eventHandlers.getEvent(e, this);
+ var s = this.slider;
+ if (s.element.focus)
+ s.element.focus();
+
+ Slider._currentInstance = s;
+ var doc = s.document;
+
+ if (doc.addEventListener) {
+ doc.addEventListener("mousemove", Slider.eventHandlers.onmousemove, true);
+ doc.addEventListener("mouseup", Slider.eventHandlers.onmouseup, true);
+ }
+ else if (doc.attachEvent) {
+ doc.attachEvent("onmousemove", Slider.eventHandlers.onmousemove);
+ doc.attachEvent("onmouseup", Slider.eventHandlers.onmouseup);
+ doc.attachEvent("onlosecapture", Slider.eventHandlers.onmouseup);
+ s.element.setCapture();
+ }
+
+ if (Slider.eventHandlers.getHandle(e)) { // start drag
+ Slider._sliderDragData = {
+ screenX: e.screenX,
+ screenY: e.screenY,
+ dx: e.screenX - s.handle.offsetLeft,
+ dy: e.screenY - s.handle.offsetTop,
+ startValue: s.getValue(),
+ slider: s
+ };
+ }
+ else {
+ var lineEl = Slider.eventHandlers.getLine(e);
+ s._mouseX = e.offsetX + (lineEl ? s.line.offsetLeft : 0);
+ s._mouseY = e.offsetY + (lineEl ? s.line.offsetTop : 0);
+ s._increasing = null;
+ s.ontimer();
+ }
+ },
+
+ onmousemove: function (e) {
+ e = Slider.eventHandlers.getEvent(e, this);
+
+ if (Slider._sliderDragData) { // drag
+ var s = Slider._sliderDragData.slider;
+
+ var boundSize = s.getMaximum() - s.getMinimum();
+ var size, pos, reset;
+
+ if (s._orientation == "horizontal") {
+ size = s.element.offsetWidth - s.handle.offsetWidth;
+ pos = e.screenX - Slider._sliderDragData.dx;
+ reset = Math.abs(e.screenY - Slider._sliderDragData.screenY) > 100;
+ }
+ else {
+ size = s.element.offsetHeight - s.handle.offsetHeight;
+ pos = s.element.offsetHeight - s.handle.offsetHeight -
+ (e.screenY - Slider._sliderDragData.dy);
+ reset = Math.abs(e.screenX - Slider._sliderDragData.screenX) > 100;
+ }
+ s.setValue(reset ? Slider._sliderDragData.startValue :
+ s.getMinimum() + boundSize * pos / size);
+ return false;
+ }
+ else {
+ var s = Slider._currentInstance;
+ if (s != null) {
+ var lineEl = Slider.eventHandlers.getLine(e);
+ s._mouseX = e.offsetX + (lineEl ? s.line.offsetLeft : 0);
+ s._mouseY = e.offsetY + (lineEl ? s.line.offsetTop : 0);
+ }
+ }
+
+ },
+
+ onmouseup: function (e) {
+ e = Slider.eventHandlers.getEvent(e, this);
+ var s = Slider._currentInstance;
+ var doc = s.document;
+ if (doc.removeEventListener) {
+ doc.removeEventListener("mousemove", Slider.eventHandlers.onmousemove, true);
+ doc.removeEventListener("mouseup", Slider.eventHandlers.onmouseup, true);
+ }
+ else if (doc.detachEvent) {
+ doc.detachEvent("onmousemove", Slider.eventHandlers.onmousemove);
+ doc.detachEvent("onmouseup", Slider.eventHandlers.onmouseup);
+ doc.detachEvent("onlosecapture", Slider.eventHandlers.onmouseup);
+ s.element.releaseCapture();
+ }
+
+ if (Slider._sliderDragData) { // end drag
+ Slider._sliderDragData = null;
+ }
+ else {
+ s._timer.stop();
+ s._increasing = null;
+ }
+ Slider._currentInstance = null;
+ },
+
+ onkeydown: function (e) {
+ e = Slider.eventHandlers.getEvent(e, this);
+ //var s = Slider.eventHandlers.getSlider(e);
+ var s = this.slider;
+ var kc = e.keyCode;
+ switch (kc) {
+ case 33: // page up
+ s.setValue(s.getValue() + s.getBlockIncrement());
+ break;
+ case 34: // page down
+ s.setValue(s.getValue() - s.getBlockIncrement());
+ break;
+ case 35: // end
+ s.setValue(s.getOrientation() == "horizontal" ?
+ s.getMaximum() :
+ s.getMinimum());
+ break;
+ case 36: // home
+ s.setValue(s.getOrientation() == "horizontal" ?
+ s.getMinimum() :
+ s.getMaximum());
+ break;
+ case 38: // up
+ case 39: // right
+ s.setValue(s.getValue() + s.getUnitIncrement());
+ break;
+
+ case 37: // left
+ case 40: // down
+ s.setValue(s.getValue() - s.getUnitIncrement());
+ break;
+ }
+
+ if (kc >= 33 && kc <= 40) {
+ return false;
+ }
+ },
+
+ onkeypress: function (e) {
+ e = Slider.eventHandlers.getEvent(e, this);
+ var kc = e.keyCode;
+ if (kc >= 33 && kc <= 40) {
+ return false;
+ }
+ },
+
+ onmousewheel: function (e) {
+ e = Slider.eventHandlers.getEvent(e, this);
+ var s = this.slider;
+ if (s._focused) {
+ s.setValue(s.getValue() + e.wheelDelta / 120 * s.getUnitIncrement());
+ // windows inverts this on horizontal sliders. That does not
+ // make sense to me
+ return false;
+ }
+ }
+};
+
+
+
+Slider.prototype.classNameTag = "dynamic-slider-control",
+
+Slider.prototype.setValue = function (v) {
+ this._range.setValue(v);
+ this.input.value = this.getValue();
+};
+
+Slider.prototype.getValue = function () {
+ return this._range.getValue();
+};
+
+Slider.prototype.setMinimum = function (v) {
+ this._range.setMinimum(v);
+ this.input.value = this.getValue();
+};
+
+Slider.prototype.getMinimum = function () {
+ return this._range.getMinimum();
+};
+
+Slider.prototype.setMaximum = function (v) {
+ this._range.setMaximum(v);
+ this.input.value = this.getValue();
+};
+
+Slider.prototype.getMaximum = function () {
+ return this._range.getMaximum();
+};
+
+Slider.prototype.setUnitIncrement = function (v) {
+ this._unitIncrement = v;
+};
+
+Slider.prototype.getUnitIncrement = function () {
+ return this._unitIncrement;
+};
+
+Slider.prototype.setBlockIncrement = function (v) {
+ this._blockIncrement = v;
+};
+
+Slider.prototype.getBlockIncrement = function () {
+ return this._blockIncrement;
+};
+
+Slider.prototype.getOrientation = function () {
+ return this._orientation;
+};
+
+Slider.prototype.setOrientation = function (sOrientation) {
+ if (sOrientation != this._orientation) {
+ if (Slider.isSupported && this.element) {
+ // add class name tag to class name
+ this.element.className = this.element.className.replace(this._orientation,
+ sOrientation);
+ }
+ this._orientation = sOrientation;
+ this.recalculate();
+
+ }
+};
+
+Slider.prototype.recalculate = function() {
+ if (!Slider.isSupported || !this.element) return;
+
+ var w = this.element.offsetWidth;
+ var h = this.element.offsetHeight;
+ var hw = this.handle.offsetWidth;
+ var hh = this.handle.offsetHeight;
+ var lw = this.line.offsetWidth;
+ var lh = this.line.offsetHeight;
+
+ // this assumes a border-box layout
+
+ if (this._orientation == "horizontal") {
+ this.handle.style.left = (w - hw) * (this.getValue() - this.getMinimum()) /
+ (this.getMaximum() - this.getMinimum()) + "px";
+ this.handle.style.top = (h - hh) / 2 + "px";
+
+ this.line.style.top = (h - lh) / 2 + "px";
+ this.line.style.left = hw / 2 + "px";
+ //this.line.style.right = hw / 2 + "px";
+ this.line.style.width = Math.max(0, w - hw - 2)+ "px";
+ this.line.firstChild.style.width = Math.max(0, w - hw - 4)+ "px";
+ }
+ else {
+ this.handle.style.left = (w - hw) / 2 + "px";
+ this.handle.style.top = h - hh - (h - hh) * (this.getValue() - this.getMinimum()) /
+ (this.getMaximum() - this.getMinimum()) + "px";
+
+ this.line.style.left = (w - lw) / 2 + "px";
+ this.line.style.top = hh / 2 + "px";
+ this.line.style.height = Math.max(0, h - hh - 2) + "px"; //hard coded border width
+ //this.line.style.bottom = hh / 2 + "px";
+ this.line.firstChild.style.height = Math.max(0, h - hh - 4) + "px"; //hard coded border width
+ }
+};
+
+Slider.prototype.ontimer = function () {
+ var hw = this.handle.offsetWidth;
+ var hh = this.handle.offsetHeight;
+ var hl = this.handle.offsetLeft;
+ var ht = this.handle.offsetTop;
+
+ if (this._orientation == "horizontal") {
+ if (this._mouseX > hl + hw &&
+ (this._increasing == null || this._increasing)) {
+ this.setValue(this.getValue() + this.getBlockIncrement());
+ this._increasing = true;
+ }
+ else if (this._mouseX < hl &&
+ (this._increasing == null || !this._increasing)) {
+ this.setValue(this.getValue() - this.getBlockIncrement());
+ this._increasing = false;
+ }
+ }
+ else {
+ if (this._mouseY > ht + hh &&
+ (this._increasing == null || !this._increasing)) {
+ this.setValue(this.getValue() - this.getBlockIncrement());
+ this._increasing = false;
+ }
+ else if (this._mouseY < ht &&
+ (this._increasing == null || this._increasing)) {
+ this.setValue(this.getValue() + this.getBlockIncrement());
+ this._increasing = true;
+ }
+ }
+
+ this._timer.start();
+};
\ No newline at end of file
diff --git a/www/extras/slider/js/timer.js b/www/extras/slider/js/timer.js
new file mode 100755
index 000000000..c6688ca63
--- /dev/null
+++ b/www/extras/slider/js/timer.js
@@ -0,0 +1,78 @@
+/*----------------------------------------------------------------------------\
+| Timer Class |
+|-----------------------------------------------------------------------------|
+| Created by Erik Arvidsson |
+| (http://webfx.eae.net/contact.html#erik) |
+| For WebFX (http://webfx.eae.net/) |
+|-----------------------------------------------------------------------------|
+| Object Oriented Encapsulation of setTimeout fires ontimer when the timer |
+| is triggered. Does not work in IE5.00 |
+|-----------------------------------------------------------------------------|
+| Copyright (c) 1999 - 2002 Erik Arvidsson |
+|-----------------------------------------------------------------------------|
+| This software is provided "as is", without warranty of any kind, express or |
+| implied, including but not limited to the warranties of merchantability, |
+| fitness for a particular purpose and noninfringement. In no event shall the |
+| authors or copyright holders be liable for any claim, damages or other |
+| liability, whether in an action of contract, tort or otherwise, arising |
+| from, out of or in connection with the software or the use or other |
+| dealings in the software. |
+| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
+| This software is available under the three different licenses mentioned |
+| below. To use this software you must chose, and qualify, for one of those. |
+| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
+| The WebFX Non-Commercial License http://webfx.eae.net/license.html |
+| Permits anyone the right to use the software in a non-commercial context |
+| free of charge. |
+| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
+| The WebFX Commercial license http://webfx.eae.net/commercial.html |
+| Permits the license holder the right to use the software in a commercial |
+| context. Such license must be specifically obtained, however it's valid for |
+| any number of implementations of the licensed software. |
+| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
+| GPL - The GNU General Public License http://www.gnu.org/licenses/gpl.txt |
+| Permits anyone the right to use and modify the software without limitations |
+| as long as proper credits are given and the original and modified source |
+| code are included. Requires that the final product, software derivate from |
+| the original source or any software utilizing a GPL component, such as |
+| this, is also licensed under the GPL license. |
+|-----------------------------------------------------------------------------|
+| 2002-10-14 | Original version released |
+|-----------------------------------------------------------------------------|
+| Created 2002-10-14 | All changes are in the log above. | Updated 2002-10-14 |
+\----------------------------------------------------------------------------*/
+
+function Timer(nPauseTime) {
+ this._pauseTime = typeof nPauseTime == "undefined" ? 1000 : nPauseTime;
+ this._timer = null;
+ this._isStarted = false;
+}
+
+Timer.prototype.start = function () {
+ if (this.isStarted())
+ this.stop();
+ var oThis = this;
+ this._timer = window.setTimeout(function () {
+ if (typeof oThis.ontimer == "function")
+ oThis.ontimer();
+ }, this._pauseTime);
+ this._isStarted = false;
+};
+
+Timer.prototype.stop = function () {
+ if (this._timer != null)
+ window.clearTimeout(this._timer);
+ this._isStarted = false;
+};
+
+Timer.prototype.isStarted = function () {
+ return this._isStarted;
+};
+
+Timer.prototype.getPauseTime = function () {
+ return this._pauseTime;
+};
+
+Timer.prototype.setPauseTime = function (nPauseTime) {
+ this._pauseTime = nPauseTime;
+};
\ No newline at end of file
diff --git a/www/extras/slider/local/helptip.css b/www/extras/slider/local/helptip.css
new file mode 100755
index 000000000..7ec71d7bb
--- /dev/null
+++ b/www/extras/slider/local/helptip.css
@@ -0,0 +1,38 @@
+/*
+ Notice that IE has a display problem if the help link is on
+ the last line of a container with no padding. If this is the
+ case increase the padding bottom to at least 1px
+*/
+
+a.helpLink {
+ color: Green;
+ text-decoration: none;
+ border-bottom: 1px dashed Green;
+ cursor: help;
+}
+
+a.helpLink:hover {
+ color: Red;
+ text-decoration: none;
+ border-bottom: 1px dashed Red;
+}
+
+.help-tooltip {
+ position: absolute;
+ width: 250px;
+ border: 1px Solid WindowFrame;
+ background: Infobackground;
+ color: InfoText;
+ font: StatusBar;
+ font: Status-Bar;
+ padding: 3px;
+ filter: progid:DXImageTransform.Microsoft.Shadow(color="#777777", Direction=135, Strength=3);
+ z-index: 10000;
+}
+
+
+.help-tooltip a,
+.help-tooltip a:hover {
+ color: blue !important;
+ background: none;
+}
diff --git a/www/extras/slider/local/helptip.js b/www/extras/slider/local/helptip.js
new file mode 100755
index 000000000..a75ddf9c2
--- /dev/null
+++ b/www/extras/slider/local/helptip.js
@@ -0,0 +1,215 @@
+/*----------------------------------------------------------------------------\
+| Help Tip 1.1 |
+|-----------------------------------------------------------------------------|
+| Created by Erik Arvidsson |
+| (http://webfx.eae.net/contact.html#erik) |
+| For WebFX (http://webfx.eae.net/) |
+|-----------------------------------------------------------------------------|
+| A tool tip like script that can be used for context help |
+|-----------------------------------------------------------------------------|
+| Copyright (c) 1999 - 2002 Erik Arvidsson |
+|-----------------------------------------------------------------------------|
+| This software is provided "as is", without warranty of any kind, express or |
+| implied, including but not limited to the warranties of merchantability, |
+| fitness for a particular purpose and noninfringement. In no event shall the |
+| authors or copyright holders be liable for any claim, damages or other |
+| liability, whether in an action of contract, tort or otherwise, arising |
+| from, out of or in connection with the software or the use or other |
+| dealings in the software. |
+| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
+| This software is available under the three different licenses mentioned |
+| below. To use this software you must chose, and qualify, for one of those. |
+| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
+| The WebFX Non-Commercial License http://webfx.eae.net/license.html |
+| Permits anyone the right to use the software in a non-commercial context |
+| free of charge. |
+| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
+| The WebFX Commercial license http://webfx.eae.net/commercial.html |
+| Permits the license holder the right to use the software in a commercial |
+| context. Such license must be specifically obtained, however it's valid for |
+| any number of implementations of the licensed software. |
+| - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - |
+| GPL - The GNU General Public License http://www.gnu.org/licenses/gpl.txt |
+| Permits anyone the right to use and modify the software without limitations |
+| as long as proper credits are given and the original and modified source |
+| code are included. Requires that the final product, software derivate from |
+| the original source or any software utilizing a GPL component, such as |
+| this, is also licensed under the GPL license. |
+|-----------------------------------------------------------------------------|
+| 2002-09-27 | |
+| 2001-11-25 | Added a resize to the tooltip if the document width is too |
+| | small. |
+| 2002-05-19 | IE50 did not recognise the JS keyword undefined so the test |
+| | for scroll support was updated to be IE50 friendly. |
+| 2002-07-06 | Added flag to hide selects for IE |
+| 2002-10-04 | (1.1) Restructured and made code more IE garbage collector |
+| | friendly. This solved the most nasty memory leaks. Also added |
+| | support for hiding the tooltip if ESC is pressed. |
+|-----------------------------------------------------------------------------|
+| Dependencies: helptip.css (To set up the CSS of the help-tooltip class) |
+|-----------------------------------------------------------------------------|
+| Usage: |
+| |
+| |
+|