summaryrefslogtreecommitdiff
path: root/framework/Web/Javascripts/source
diff options
context:
space:
mode:
authorctrlaltca <>2012-07-12 11:21:01 +0000
committerctrlaltca <>2012-07-12 11:21:01 +0000
commit903ae8a581fac1e6917fc3e31d2ad8fb91df80c3 (patch)
treee08bf04f0823650a231227ac3499121270172a23 /framework/Web/Javascripts/source
parent3e4e6e66aeb3f8fea4e1eb4237498ef9d2358f63 (diff)
standardize the use of unix eol; use svn properties to enforce native eol
Diffstat (limited to 'framework/Web/Javascripts/source')
-rw-r--r--framework/Web/Javascripts/source/prado/activecontrols/activecontrols3.js820
-rwxr-xr-xframework/Web/Javascripts/source/prado/activecontrols/activedatepicker.js174
-rw-r--r--framework/Web/Javascripts/source/prado/activecontrols/ajax3.js2288
-rwxr-xr-xframework/Web/Javascripts/source/prado/activecontrols/dragdrop.js122
-rw-r--r--framework/Web/Javascripts/source/prado/activecontrols/inlineeditor.js602
-rw-r--r--framework/Web/Javascripts/source/prado/colorpicker/colorpicker.js1560
-rw-r--r--framework/Web/Javascripts/source/prado/controls/controls.js1034
-rw-r--r--framework/Web/Javascripts/source/prado/controls/htmlarea.js298
-rw-r--r--framework/Web/Javascripts/source/prado/controls/keyboard.js322
-rw-r--r--framework/Web/Javascripts/source/prado/controls/tabpanel.js120
-rw-r--r--framework/Web/Javascripts/source/prado/datepicker/datepicker.js1578
-rw-r--r--framework/Web/Javascripts/source/prado/logger/logger.js1506
-rw-r--r--framework/Web/Javascripts/source/prado/prado.js188
-rw-r--r--framework/Web/Javascripts/source/prado/ratings/ratings.js412
-rw-r--r--framework/Web/Javascripts/source/prado/scriptaculous-adapter.js2792
-rw-r--r--framework/Web/Javascripts/source/prado/validator/validation3.js3886
16 files changed, 8851 insertions, 8851 deletions
diff --git a/framework/Web/Javascripts/source/prado/activecontrols/activecontrols3.js b/framework/Web/Javascripts/source/prado/activecontrols/activecontrols3.js
index 7dbdbe2a..3e6fe5b7 100644
--- a/framework/Web/Javascripts/source/prado/activecontrols/activecontrols3.js
+++ b/framework/Web/Javascripts/source/prado/activecontrols/activecontrols3.js
@@ -1,410 +1,410 @@
-/**
- * Generic postback control.
- */
-Prado.WebUI.CallbackControl = Class.extend(Prado.WebUI.PostBackControl,
-{
- onPostBack : function(event, options)
- {
- var request = new Prado.CallbackRequest(options.EventTarget, options);
- request.dispatch();
- Event.stop(event);
- }
-});
-
-/**
- * TActiveButton control.
- */
-Prado.WebUI.TActiveButton = Class.extend(Prado.WebUI.CallbackControl);
-/**
- * TActiveLinkButton control.
- */
-Prado.WebUI.TActiveLinkButton = Class.extend(Prado.WebUI.CallbackControl);
-
-Prado.WebUI.TActiveImageButton = Class.extend(Prado.WebUI.TImageButton,
-{
- onPostBack : function(event, options)
- {
- this.addXYInput(event,options);
- var request = new Prado.CallbackRequest(options.EventTarget, options);
- request.dispatch();
- Event.stop(event);
- this.removeXYInput(event,options);
- }
-});
-/**
- * Active check box.
- */
-Prado.WebUI.TActiveCheckBox = Class.extend(Prado.WebUI.CallbackControl,
-{
- onPostBack : function(event, options)
- {
- var request = new Prado.CallbackRequest(options.EventTarget, options);
- if(request.dispatch()==false)
- Event.stop(event);
- }
-});
-
-/**
- * TActiveRadioButton control.
- */
-Prado.WebUI.TActiveRadioButton = Class.extend(Prado.WebUI.TActiveCheckBox);
-
-
-Prado.WebUI.TActiveCheckBoxList = Base.extend(
-{
- constructor : function(options)
- {
- Prado.Registry.set(options.ListID, this);
- for(var i = 0; i<options.ItemCount; i++)
- {
- var checkBoxOptions = Object.extend(
- {
- ID : options.ListID+"_c"+i,
- EventTarget : options.ListName+"$c"+i
- }, options);
- new Prado.WebUI.TActiveCheckBox(checkBoxOptions);
- }
- }
-});
-
-Prado.WebUI.TActiveRadioButtonList = Prado.WebUI.TActiveCheckBoxList;
-
-/**
- * TActiveTextBox control, handles onchange event.
- */
-Prado.WebUI.TActiveTextBox = Class.extend(Prado.WebUI.TTextBox,
-{
- onInit : function(options)
- {
- this.options=options;
- if(options['TextMode'] != 'MultiLine')
- this.observe(this.element, "keydown", this.handleReturnKey.bind(this));
- if(this.options['AutoPostBack']==true)
- this.observe(this.element, "change", this.doCallback.bindEvent(this,options));
- },
-
- doCallback : function(event, options)
- {
- var request = new Prado.CallbackRequest(options.EventTarget, options);
- request.dispatch();
- if (!Prototype.Browser.IE)
- Event.stop(event);
- }
-});
-
-/**
- * TAutoComplete control.
- */
-Prado.WebUI.TAutoComplete = Class.extend(Autocompleter.Base, Prado.WebUI.TActiveTextBox.prototype);
-Prado.WebUI.TAutoComplete = Class.extend(Prado.WebUI.TAutoComplete,
-{
- initialize : function(options)
- {
- this.options = options;
- this.observers = new Array();
- this.hasResults = false;
- this.baseInitialize(options.ID, options.ResultPanel, options);
- Object.extend(this.options,
- {
- onSuccess : this.onComplete.bind(this)
- });
-
- if(options.AutoPostBack)
- this.onInit(options);
-
- Prado.Registry.set(options.ID, this);
- },
-
- doCallback : function(event, options)
- {
- if(!this.active)
- {
- var request = new Prado.CallbackRequest(this.options.EventTarget, options);
- request.dispatch();
- Event.stop(event);
- }
- },
-
- //Overrides parent implementation, fires onchange event.
- onClick: function(event)
- {
- var element = Event.findElement(event, 'LI');
- this.index = element.autocompleteIndex;
- this.selectEntry();
- this.hide();
- Event.fireEvent(this.element, "change");
- },
-
- getUpdatedChoices : function()
- {
- var options = new Array(this.getToken(),"__TAutoComplete_onSuggest__");
- Prado.Callback(this.options.EventTarget, options, null, this.options);
- },
-
- /**
- * Overrides parent implements, don't update if no results.
- */
- selectEntry: function()
- {
- if(this.hasResults)
- {
- this.active = false;
- this.updateElement(this.getCurrentEntry());
- var options = [this.index, "__TAutoComplete_onSuggestionSelected__"];
- Prado.Callback(this.options.EventTarget, options, null, this.options);
- }
- },
-
- onComplete : function(request, boundary)
- {
- var result = Prado.Element.extractContent(request.transport.responseText, boundary);
- if(typeof(result) == "string")
- {
- if(result.length > 0)
- {
- this.hasResults = true;
- this.updateChoices(result);
- }
- else
- {
- this.active = false;
- this.hasResults = false;
- this.hide();
- }
- }
- }
-});
-
-/**
- * Time Triggered Callback class.
- */
-Prado.WebUI.TTimeTriggeredCallback = Class.create(Prado.WebUI.Control,
-{
- onInit : function(options)
- {
- this.options = Object.extend({ Interval : 1 }, options || {});
- Prado.WebUI.TTimeTriggeredCallback.registerTimer(this);
- },
-
- startTimer : function()
- {
- if(typeof(this.timer) == 'undefined' || this.timer == null)
- this.timer = this.setInterval(this.onTimerEvent.bind(this),this.options.Interval*1000);
- },
-
- stopTimer : function()
- {
- if(typeof(this.timer) != 'undefined')
- {
- this.clearInterval(this.timer);
- this.timer = null;
- }
- },
-
- resetTimer : function()
- {
- if(typeof(this.timer) != 'undefined')
- {
- this.clearInterval(this.timer);
- this.timer = null;
- this.timer = this.setInterval(this.onTimerEvent.bind(this),this.options.Interval*1000);
- }
- },
-
- onTimerEvent : function()
- {
- var request = new Prado.CallbackRequest(this.options.EventTarget, this.options);
- request.dispatch();
- },
-
- setTimerInterval : function(value)
- {
- if (this.options.Interval != value){
- this.options.Interval = value;
- this.resetTimer();
- }
- },
-
- onDone: function()
- {
- this.stopTimer();
- }
-});
-
-Object.extend(Prado.WebUI.TTimeTriggeredCallback,
-{
-
- //class methods
-
- timers : {},
-
- registerTimer : function(timer)
- {
- Prado.WebUI.TTimeTriggeredCallback.timers[timer.options.ID] = timer;
- },
-
- start : function(id)
- {
- if(Prado.WebUI.TTimeTriggeredCallback.timers[id])
- Prado.WebUI.TTimeTriggeredCallback.timers[id].startTimer();
- },
-
- stop : function(id)
- {
- if(Prado.WebUI.TTimeTriggeredCallback.timers[id])
- Prado.WebUI.TTimeTriggeredCallback.timers[id].stopTimer();
- },
-
- setTimerInterval : function (id,value)
- {
- if(Prado.WebUI.TTimeTriggeredCallback.timers[id])
- Prado.WebUI.TTimeTriggeredCallback.timers[id].setTimerInterval(value);
- }
-});
-
-Prado.WebUI.ActiveListControl = Class.create(Prado.WebUI.Control,
-{
- onInit : function(options)
- {
- if(this.element)
- {
- this.options = options;
- this.observe(this.element, "change", this.doCallback.bind(this));
- }
- },
-
- doCallback : function(event)
- {
- var request = new Prado.CallbackRequest(this.options.EventTarget, this.options);
- request.dispatch();
- Event.stop(event);
- }
-});
-
-Prado.WebUI.TActiveDropDownList = Class.create(Prado.WebUI.ActiveListControl);
-Prado.WebUI.TActiveListBox = Class.create(Prado.WebUI.ActiveListControl);
-
-/**
- * Observe event of a particular control to trigger a callback request.
- */
-Prado.WebUI.TEventTriggeredCallback = Class.create(Prado.WebUI.Control,
-{
- onInit : function(options)
- {
- this.options = options || {} ;
- var element = $(options['ControlID']);
- if(element)
- this.observe(element, this.getEventName(element), this.doCallback.bind(this));
- },
-
- getEventName : function(element)
- {
- var name = this.options.EventName;
- if(typeof(name) == "undefined" && element.type)
- {
- switch (element.type.toLowerCase())
- {
- case 'password':
- case 'text':
- case 'textarea':
- case 'select-one':
- case 'select-multiple':
- return 'change';
- }
- }
- return typeof(name) == "undefined" || name == "undefined" ? 'click' : name;
- },
-
- doCallback : function(event)
- {
- var request = new Prado.CallbackRequest(this.options.EventTarget, this.options);
- request.dispatch();
- if(this.options.StopEvent == true)
- Event.stop(event);
- }
-});
-
-/**
- * Observe changes to a property of a particular control to trigger a callback.
- */
-Prado.WebUI.TValueTriggeredCallback = Class.create(Prado.WebUI.Control,
-{
- count : 1,
-
- observing : true,
-
- onInit : function(options)
- {
- this.options = options || {} ;
- this.options.PropertyName = this.options.PropertyName || 'value';
- var element = $(options['ControlID']);
- this.value = element ? element[this.options.PropertyName] : undefined;
- Prado.WebUI.TValueTriggeredCallback.register(this);
- this.startObserving();
- },
-
- stopObserving : function()
- {
- this.clearTimeout(this.timer);
- this.observing = false;
- },
-
- startObserving : function()
- {
- this.timer = this.setTimeout(this.checkChanges.bind(this), this.options.Interval*1000);
- },
-
- checkChanges : function()
- {
- var element = $(this.options.ControlID);
- if(element)
- {
- var value = element[this.options.PropertyName];
- if(this.value != value)
- {
- this.doCallback(this.value, value);
- this.value = value;
- this.count=1;
- }
- else
- this.count = this.count + this.options.Decay;
- if(this.observing)
- this.time = this.setTimeout(this.checkChanges.bind(this),
- parseInt(this.options.Interval*1000*this.count));
- }
- },
-
- doCallback : function(oldValue, newValue)
- {
- var request = new Prado.CallbackRequest(this.options.EventTarget, this.options);
- var param = {'OldValue' : oldValue, 'NewValue' : newValue};
- request.setCallbackParameter(param);
- request.dispatch();
- },
-
- onDone : function()
- {
- if (this.observing)
- this.stopObserving();
- }
-});
-
-Object.extend(Prado.WebUI.TValueTriggeredCallback,
-{
- //class methods
-
- timers : {},
-
- register : function(timer)
- {
- Prado.WebUI.TValueTriggeredCallback.timers[timer.options.ID] = timer;
- },
-
- stop : function(id)
- {
- Prado.WebUI.TValueTriggeredCallback.timers[id].stopObserving();
- }
-});
-
-Prado.WebUI.TActiveTableCell = Class.create(Prado.WebUI.CallbackControl);
-Prado.WebUI.TActiveTableRow = Class.create(Prado.WebUI.CallbackControl);
+/**
+ * Generic postback control.
+ */
+Prado.WebUI.CallbackControl = Class.extend(Prado.WebUI.PostBackControl,
+{
+ onPostBack : function(event, options)
+ {
+ var request = new Prado.CallbackRequest(options.EventTarget, options);
+ request.dispatch();
+ Event.stop(event);
+ }
+});
+
+/**
+ * TActiveButton control.
+ */
+Prado.WebUI.TActiveButton = Class.extend(Prado.WebUI.CallbackControl);
+/**
+ * TActiveLinkButton control.
+ */
+Prado.WebUI.TActiveLinkButton = Class.extend(Prado.WebUI.CallbackControl);
+
+Prado.WebUI.TActiveImageButton = Class.extend(Prado.WebUI.TImageButton,
+{
+ onPostBack : function(event, options)
+ {
+ this.addXYInput(event,options);
+ var request = new Prado.CallbackRequest(options.EventTarget, options);
+ request.dispatch();
+ Event.stop(event);
+ this.removeXYInput(event,options);
+ }
+});
+/**
+ * Active check box.
+ */
+Prado.WebUI.TActiveCheckBox = Class.extend(Prado.WebUI.CallbackControl,
+{
+ onPostBack : function(event, options)
+ {
+ var request = new Prado.CallbackRequest(options.EventTarget, options);
+ if(request.dispatch()==false)
+ Event.stop(event);
+ }
+});
+
+/**
+ * TActiveRadioButton control.
+ */
+Prado.WebUI.TActiveRadioButton = Class.extend(Prado.WebUI.TActiveCheckBox);
+
+
+Prado.WebUI.TActiveCheckBoxList = Base.extend(
+{
+ constructor : function(options)
+ {
+ Prado.Registry.set(options.ListID, this);
+ for(var i = 0; i<options.ItemCount; i++)
+ {
+ var checkBoxOptions = Object.extend(
+ {
+ ID : options.ListID+"_c"+i,
+ EventTarget : options.ListName+"$c"+i
+ }, options);
+ new Prado.WebUI.TActiveCheckBox(checkBoxOptions);
+ }
+ }
+});
+
+Prado.WebUI.TActiveRadioButtonList = Prado.WebUI.TActiveCheckBoxList;
+
+/**
+ * TActiveTextBox control, handles onchange event.
+ */
+Prado.WebUI.TActiveTextBox = Class.extend(Prado.WebUI.TTextBox,
+{
+ onInit : function(options)
+ {
+ this.options=options;
+ if(options['TextMode'] != 'MultiLine')
+ this.observe(this.element, "keydown", this.handleReturnKey.bind(this));
+ if(this.options['AutoPostBack']==true)
+ this.observe(this.element, "change", this.doCallback.bindEvent(this,options));
+ },
+
+ doCallback : function(event, options)
+ {
+ var request = new Prado.CallbackRequest(options.EventTarget, options);
+ request.dispatch();
+ if (!Prototype.Browser.IE)
+ Event.stop(event);
+ }
+});
+
+/**
+ * TAutoComplete control.
+ */
+Prado.WebUI.TAutoComplete = Class.extend(Autocompleter.Base, Prado.WebUI.TActiveTextBox.prototype);
+Prado.WebUI.TAutoComplete = Class.extend(Prado.WebUI.TAutoComplete,
+{
+ initialize : function(options)
+ {
+ this.options = options;
+ this.observers = new Array();
+ this.hasResults = false;
+ this.baseInitialize(options.ID, options.ResultPanel, options);
+ Object.extend(this.options,
+ {
+ onSuccess : this.onComplete.bind(this)
+ });
+
+ if(options.AutoPostBack)
+ this.onInit(options);
+
+ Prado.Registry.set(options.ID, this);
+ },
+
+ doCallback : function(event, options)
+ {
+ if(!this.active)
+ {
+ var request = new Prado.CallbackRequest(this.options.EventTarget, options);
+ request.dispatch();
+ Event.stop(event);
+ }
+ },
+
+ //Overrides parent implementation, fires onchange event.
+ onClick: function(event)
+ {
+ var element = Event.findElement(event, 'LI');
+ this.index = element.autocompleteIndex;
+ this.selectEntry();
+ this.hide();
+ Event.fireEvent(this.element, "change");
+ },
+
+ getUpdatedChoices : function()
+ {
+ var options = new Array(this.getToken(),"__TAutoComplete_onSuggest__");
+ Prado.Callback(this.options.EventTarget, options, null, this.options);
+ },
+
+ /**
+ * Overrides parent implements, don't update if no results.
+ */
+ selectEntry: function()
+ {
+ if(this.hasResults)
+ {
+ this.active = false;
+ this.updateElement(this.getCurrentEntry());
+ var options = [this.index, "__TAutoComplete_onSuggestionSelected__"];
+ Prado.Callback(this.options.EventTarget, options, null, this.options);
+ }
+ },
+
+ onComplete : function(request, boundary)
+ {
+ var result = Prado.Element.extractContent(request.transport.responseText, boundary);
+ if(typeof(result) == "string")
+ {
+ if(result.length > 0)
+ {
+ this.hasResults = true;
+ this.updateChoices(result);
+ }
+ else
+ {
+ this.active = false;
+ this.hasResults = false;
+ this.hide();
+ }
+ }
+ }
+});
+
+/**
+ * Time Triggered Callback class.
+ */
+Prado.WebUI.TTimeTriggeredCallback = Class.create(Prado.WebUI.Control,
+{
+ onInit : function(options)
+ {
+ this.options = Object.extend({ Interval : 1 }, options || {});
+ Prado.WebUI.TTimeTriggeredCallback.registerTimer(this);
+ },
+
+ startTimer : function()
+ {
+ if(typeof(this.timer) == 'undefined' || this.timer == null)
+ this.timer = this.setInterval(this.onTimerEvent.bind(this),this.options.Interval*1000);
+ },
+
+ stopTimer : function()
+ {
+ if(typeof(this.timer) != 'undefined')
+ {
+ this.clearInterval(this.timer);
+ this.timer = null;
+ }
+ },
+
+ resetTimer : function()
+ {
+ if(typeof(this.timer) != 'undefined')
+ {
+ this.clearInterval(this.timer);
+ this.timer = null;
+ this.timer = this.setInterval(this.onTimerEvent.bind(this),this.options.Interval*1000);
+ }
+ },
+
+ onTimerEvent : function()
+ {
+ var request = new Prado.CallbackRequest(this.options.EventTarget, this.options);
+ request.dispatch();
+ },
+
+ setTimerInterval : function(value)
+ {
+ if (this.options.Interval != value){
+ this.options.Interval = value;
+ this.resetTimer();
+ }
+ },
+
+ onDone: function()
+ {
+ this.stopTimer();
+ }
+});
+
+Object.extend(Prado.WebUI.TTimeTriggeredCallback,
+{
+
+ //class methods
+
+ timers : {},
+
+ registerTimer : function(timer)
+ {
+ Prado.WebUI.TTimeTriggeredCallback.timers[timer.options.ID] = timer;
+ },
+
+ start : function(id)
+ {
+ if(Prado.WebUI.TTimeTriggeredCallback.timers[id])
+ Prado.WebUI.TTimeTriggeredCallback.timers[id].startTimer();
+ },
+
+ stop : function(id)
+ {
+ if(Prado.WebUI.TTimeTriggeredCallback.timers[id])
+ Prado.WebUI.TTimeTriggeredCallback.timers[id].stopTimer();
+ },
+
+ setTimerInterval : function (id,value)
+ {
+ if(Prado.WebUI.TTimeTriggeredCallback.timers[id])
+ Prado.WebUI.TTimeTriggeredCallback.timers[id].setTimerInterval(value);
+ }
+});
+
+Prado.WebUI.ActiveListControl = Class.create(Prado.WebUI.Control,
+{
+ onInit : function(options)
+ {
+ if(this.element)
+ {
+ this.options = options;
+ this.observe(this.element, "change", this.doCallback.bind(this));
+ }
+ },
+
+ doCallback : function(event)
+ {
+ var request = new Prado.CallbackRequest(this.options.EventTarget, this.options);
+ request.dispatch();
+ Event.stop(event);
+ }
+});
+
+Prado.WebUI.TActiveDropDownList = Class.create(Prado.WebUI.ActiveListControl);
+Prado.WebUI.TActiveListBox = Class.create(Prado.WebUI.ActiveListControl);
+
+/**
+ * Observe event of a particular control to trigger a callback request.
+ */
+Prado.WebUI.TEventTriggeredCallback = Class.create(Prado.WebUI.Control,
+{
+ onInit : function(options)
+ {
+ this.options = options || {} ;
+ var element = $(options['ControlID']);
+ if(element)
+ this.observe(element, this.getEventName(element), this.doCallback.bind(this));
+ },
+
+ getEventName : function(element)
+ {
+ var name = this.options.EventName;
+ if(typeof(name) == "undefined" && element.type)
+ {
+ switch (element.type.toLowerCase())
+ {
+ case 'password':
+ case 'text':
+ case 'textarea':
+ case 'select-one':
+ case 'select-multiple':
+ return 'change';
+ }
+ }
+ return typeof(name) == "undefined" || name == "undefined" ? 'click' : name;
+ },
+
+ doCallback : function(event)
+ {
+ var request = new Prado.CallbackRequest(this.options.EventTarget, this.options);
+ request.dispatch();
+ if(this.options.StopEvent == true)
+ Event.stop(event);
+ }
+});
+
+/**
+ * Observe changes to a property of a particular control to trigger a callback.
+ */
+Prado.WebUI.TValueTriggeredCallback = Class.create(Prado.WebUI.Control,
+{
+ count : 1,
+
+ observing : true,
+
+ onInit : function(options)
+ {
+ this.options = options || {} ;
+ this.options.PropertyName = this.options.PropertyName || 'value';
+ var element = $(options['ControlID']);
+ this.value = element ? element[this.options.PropertyName] : undefined;
+ Prado.WebUI.TValueTriggeredCallback.register(this);
+ this.startObserving();
+ },
+
+ stopObserving : function()
+ {
+ this.clearTimeout(this.timer);
+ this.observing = false;
+ },
+
+ startObserving : function()
+ {
+ this.timer = this.setTimeout(this.checkChanges.bind(this), this.options.Interval*1000);
+ },
+
+ checkChanges : function()
+ {
+ var element = $(this.options.ControlID);
+ if(element)
+ {
+ var value = element[this.options.PropertyName];
+ if(this.value != value)
+ {
+ this.doCallback(this.value, value);
+ this.value = value;
+ this.count=1;
+ }
+ else
+ this.count = this.count + this.options.Decay;
+ if(this.observing)
+ this.time = this.setTimeout(this.checkChanges.bind(this),
+ parseInt(this.options.Interval*1000*this.count));
+ }
+ },
+
+ doCallback : function(oldValue, newValue)
+ {
+ var request = new Prado.CallbackRequest(this.options.EventTarget, this.options);
+ var param = {'OldValue' : oldValue, 'NewValue' : newValue};
+ request.setCallbackParameter(param);
+ request.dispatch();
+ },
+
+ onDone : function()
+ {
+ if (this.observing)
+ this.stopObserving();
+ }
+});
+
+Object.extend(Prado.WebUI.TValueTriggeredCallback,
+{
+ //class methods
+
+ timers : {},
+
+ register : function(timer)
+ {
+ Prado.WebUI.TValueTriggeredCallback.timers[timer.options.ID] = timer;
+ },
+
+ stop : function(id)
+ {
+ Prado.WebUI.TValueTriggeredCallback.timers[id].stopObserving();
+ }
+});
+
+Prado.WebUI.TActiveTableCell = Class.create(Prado.WebUI.CallbackControl);
+Prado.WebUI.TActiveTableRow = Class.create(Prado.WebUI.CallbackControl);
diff --git a/framework/Web/Javascripts/source/prado/activecontrols/activedatepicker.js b/framework/Web/Javascripts/source/prado/activecontrols/activedatepicker.js
index 1b0b1492..f7f63026 100755
--- a/framework/Web/Javascripts/source/prado/activecontrols/activedatepicker.js
+++ b/framework/Web/Javascripts/source/prado/activecontrols/activedatepicker.js
@@ -1,87 +1,87 @@
-/**
- * TActiveDatePicker control
- */
-Prado.WebUI.TActiveDatePicker = Class.create(Prado.WebUI.TDatePicker,
-{
- onInit : 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();
- this.positionMode = 'Bottom';
-
-
- //which element to trigger to show the calendar
- 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";
- }
-
- // Popup position
- if(this.options.PositionMode == 'Top')
- {
- this.positionMode = this.options.PositionMode;
- }
-
- Object.extend(this,options);
-
- if (this.options.ShowCalendar)
- this.observe(this.trigger, triggerEvent, this.show.bindEvent(this));
-
- // Listen to change event
- if(this.options.InputMode == "TextBox")
- {
- this.observe(this.control, "change", this.onDateChanged.bindEvent(this));
- }
- else
- {
- var day = Prado.WebUI.TDatePicker.getDayListControl(this.control);
- var month = Prado.WebUI.TDatePicker.getMonthListControl(this.control);
- var year = Prado.WebUI.TDatePicker.getYearListControl(this.control);
- if (day) this.observe (day, "change", this.onDateChanged.bindEvent(this));
- if (month) this.observe (month, "change", this.onDateChanged.bindEvent(this));
- if (year) this.observe (year, "change", this.onDateChanged.bindEvent(this));
-
- }
-
- },
-
- // Respond to change event on the textbox or dropdown list
- // This method raises OnDateChanged event on client side if it has been defined,
- // and raise the callback request
- onDateChanged : function ()
- {
- var date;
- if (this.options.InputMode == "TextBox")
- {
- date=this.control.value;
- }
- else
- {
- var day = Prado.WebUI.TDatePicker.getDayListControl(this.control);
- if (day) day=day.selectedIndex+1;
- var month = Prado.WebUI.TDatePicker.getMonthListControl(this.control);
- if (month) month=month.selectedIndex;
- var year = Prado.WebUI.TDatePicker.getYearListControl(this.control);
- if (year) year=year.value;
- date=new Date(year, month, day, 0,0,0).SimpleFormat(this.Format, this);
- }
- if (typeof(this.options.OnDateChanged) == "function") this.options.OnDateChanged(this, date);
-
- if(this.options['AutoPostBack']==true)
- {
- // Make callback request
- var request = new Prado.CallbackRequest(this.options.EventTarget,this.options);
- request.dispatch();
- }
- }
-});
+/**
+ * TActiveDatePicker control
+ */
+Prado.WebUI.TActiveDatePicker = Class.create(Prado.WebUI.TDatePicker,
+{
+ onInit : 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();
+ this.positionMode = 'Bottom';
+
+
+ //which element to trigger to show the calendar
+ 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";
+ }
+
+ // Popup position
+ if(this.options.PositionMode == 'Top')
+ {
+ this.positionMode = this.options.PositionMode;
+ }
+
+ Object.extend(this,options);
+
+ if (this.options.ShowCalendar)
+ this.observe(this.trigger, triggerEvent, this.show.bindEvent(this));
+
+ // Listen to change event
+ if(this.options.InputMode == "TextBox")
+ {
+ this.observe(this.control, "change", this.onDateChanged.bindEvent(this));
+ }
+ else
+ {
+ var day = Prado.WebUI.TDatePicker.getDayListControl(this.control);
+ var month = Prado.WebUI.TDatePicker.getMonthListControl(this.control);
+ var year = Prado.WebUI.TDatePicker.getYearListControl(this.control);
+ if (day) this.observe (day, "change", this.onDateChanged.bindEvent(this));
+ if (month) this.observe (month, "change", this.onDateChanged.bindEvent(this));
+ if (year) this.observe (year, "change", this.onDateChanged.bindEvent(this));
+
+ }
+
+ },
+
+ // Respond to change event on the textbox or dropdown list
+ // This method raises OnDateChanged event on client side if it has been defined,
+ // and raise the callback request
+ onDateChanged : function ()
+ {
+ var date;
+ if (this.options.InputMode == "TextBox")
+ {
+ date=this.control.value;
+ }
+ else
+ {
+ var day = Prado.WebUI.TDatePicker.getDayListControl(this.control);
+ if (day) day=day.selectedIndex+1;
+ var month = Prado.WebUI.TDatePicker.getMonthListControl(this.control);
+ if (month) month=month.selectedIndex;
+ var year = Prado.WebUI.TDatePicker.getYearListControl(this.control);
+ if (year) year=year.value;
+ date=new Date(year, month, day, 0,0,0).SimpleFormat(this.Format, this);
+ }
+ if (typeof(this.options.OnDateChanged) == "function") this.options.OnDateChanged(this, date);
+
+ if(this.options['AutoPostBack']==true)
+ {
+ // Make callback request
+ var request = new Prado.CallbackRequest(this.options.EventTarget,this.options);
+ request.dispatch();
+ }
+ }
+});
diff --git a/framework/Web/Javascripts/source/prado/activecontrols/ajax3.js b/framework/Web/Javascripts/source/prado/activecontrols/ajax3.js
index 995e8e97..55ef64cb 100644
--- a/framework/Web/Javascripts/source/prado/activecontrols/ajax3.js
+++ b/framework/Web/Javascripts/source/prado/activecontrols/ajax3.js
@@ -1,1144 +1,1144 @@
-
-Prado.AjaxRequest = Class.create();
-Prado.AjaxRequest.prototype = Object.clone(Ajax.Request.prototype);
-
-/**
- * Override Prototype's response implementation.
- */
-Object.extend(Prado.AjaxRequest.prototype,
-{
- /*initialize: function(request)
- {
- this.CallbackRequest = request;
- this.transport = Ajax.getTransport();
- this.setOptions(request.options);
- this.request(request.url);
- },*/
-
- /**
- * Customize the response, dispatch onXXX response code events, and
- * tries to execute response actions (javascript statements).
- */
- respondToReadyState : function(readyState)
- {
- var event = Ajax.Request.Events[readyState];
- var transport = this.transport, json = this.getBodyDataPart(Prado.CallbackRequest.DATA_HEADER);
-
- if (event == 'Complete')
- {
- var redirectUrl = this.getBodyContentPart(Prado.CallbackRequest.REDIRECT_HEADER);
- if (redirectUrl)
- document.location.href = redirectUrl;
-
- if ((this.getHeader('Content-type') || '').match(/^text\/javascript/i))
- {
- try
- {
- json = eval('(' + transport.responseText + ')');
- }
- catch (e)
- {
- if(typeof(json) == "string")
- json = Prado.CallbackRequest.decode(result);
- }
- }
-
- try
- {
- Prado.CallbackRequest.updatePageState(this,transport);
- Prado.CallbackRequest.checkHiddenFields(this,transport);
- var obj = this;
- Prado.CallbackRequest.loadAssets(this,transport, function()
-
- {
- try
- {
- Ajax.Responders.dispatch('on' + transport.status, obj, transport, json);
- Prado.CallbackRequest.dispatchActions(transport,obj.getBodyDataPart(Prado.CallbackRequest.ACTION_HEADER));
-
- (
- obj.options['on' + obj.transport.status]
- ||
- obj.options['on' + (obj.success() ? 'Success' : 'Failure')]
- ||
- Prototype.emptyFunction
- ) (obj, json);
- }
- catch (e)
- {
- obj.dispatchException(e);
- }
- }
- );
- }
- catch (e)
- {
- this.dispatchException(e);
- }
- }
-
- try {
- (this.options['on' + event] || Prototype.emptyFunction)(this, json);
- Ajax.Responders.dispatch('on' + event, this, transport, json);
- } catch (e) {
- this.dispatchException(e);
- }
-
- /* Avoid memory leak in MSIE: clean up the oncomplete event handler */
- if (event == 'Complete')
- this.transport.onreadystatechange = Prototype.emptyFunction;
- },
-
- /**
- * Gets header data assuming JSON encoding.
- * @param string header name
- * @return object header data as javascript structures.
- */
- getHeaderData : function(name)
- {
- return this.getJsonData(this.getHeader(name));
- },
-
- getBodyContentPart : function(name)
- {
- if(typeof(this.transport.responseText)=="string")
- return Prado.Element.extractContent(this.transport.responseText, name);
- },
-
- getJsonData : function(json)
- {
- try
- {
- return eval('(' + json + ')');
- }
- catch (e)
- {
- if(typeof(json) == "string")
- return Prado.CallbackRequest.decode(json);
- }
- },
-
- getBodyDataPart : function(name)
- {
- return this.getJsonData(this.getBodyContentPart(name));
- }
-});
-
-/**
- * Prado Callback client-side request handler.
- */
-Prado.CallbackRequest = Class.create();
-
-/**
- * Static definitions.
- */
-Object.extend(Prado.CallbackRequest,
-{
- /**
- * Callback request target POST field name.
- */
- FIELD_CALLBACK_TARGET : 'PRADO_CALLBACK_TARGET',
- /**
- * Callback request parameter POST field name.
- */
- FIELD_CALLBACK_PARAMETER : 'PRADO_CALLBACK_PARAMETER',
- /**
- * Callback request page state field name,
- */
- FIELD_CALLBACK_PAGESTATE : 'PRADO_PAGESTATE',
-
- FIELD_POSTBACK_TARGET : 'PRADO_POSTBACK_TARGET',
-
- FIELD_POSTBACK_PARAMETER : 'PRADO_POSTBACK_PARAMETER',
-
- /**
- * List of form fields that will be collected during callback.
- */
- PostDataLoaders : [],
- /**
- * Response data header name.
- */
- DATA_HEADER : 'X-PRADO-DATA',
- /**
- * Response javascript execution statement header name.
- */
- ACTION_HEADER : 'X-PRADO-ACTIONS',
- /**
- * Response errors/exceptions header name.
- */
- ERROR_HEADER : 'X-PRADO-ERROR',
- /**
- * Page state header name.
- */
- PAGESTATE_HEADER : 'X-PRADO-PAGESTATE',
- /**
- * Script list header name.
- */
- SCRIPTLIST_HEADER : 'X-PRADO-SCRIPTLIST',
- /**
- * Stylesheet list header name.
- */
- STYLESHEETLIST_HEADER : 'X-PRADO-STYLESHEETLIST',
- /**
- * Hidden field list header name.
- */
- HIDDENFIELDLIST_HEADER : 'X-PRADO-HIDDENFIELDLIST',
-
- REDIRECT_HEADER : 'X-PRADO-REDIRECT',
-
- requestQueue : [],
-
- //all request objects
- requests : {},
-
- getRequestById : function(id)
- {
- var requests = Prado.CallbackRequest.requests;
- if(typeof(requests[id]) != "undefined")
- return requests[id];
- },
-
- dispatch : function(id)
- {
- var requests = Prado.CallbackRequest.requests;
- if(typeof(requests[id]) != "undefined")
- requests[id].dispatch();
- },
-
- /**
- * Add ids of inputs element to post in the request.
- */
- addPostLoaders : function(ids)
- {
- var self = Prado.CallbackRequest;
- self.PostDataLoaders = self.PostDataLoaders.concat(ids);
- var list = [];
- self.PostDataLoaders.each(function(id)
- {
- if(list.indexOf(id) < 0)
- list.push(id);
- });
- self.PostDataLoaders = list;
- },
-
- /**
- * Dispatch callback response actions.
- */
- dispatchActions : function(transport,actions)
- {
- var self = Prado.CallbackRequest;
- if(actions && actions.length > 0)
- actions.each(self.__run.bind(self,transport));
- },
-
- /**
- * Prase and evaluate a Callback clien-side action
- */
- __run : function(transport, command)
- {
- var self = Prado.CallbackRequest;
- self.transport = transport;
- for(var method in command)
- {
- try
- {
- method.toFunction().apply(self,command[method]);
- }
- catch(e)
- {
- if(typeof(Logger) != "undefined")
- self.Exception.onException(null,e);
- else
- debugger;
- }
- }
- },
-
- /**
- * Respond to Prado Callback request exceptions.
- */
- Exception :
- {
- /**
- * Server returns 500 exception. Just log it.
- */
- "on500" : function(request, transport, data)
- {
- var e = request.getHeaderData(Prado.CallbackRequest.ERROR_HEADER);
- if (e)
- Logger.error("Callback Server Error "+e.code, this.formatException(e));
- else
- Logger.error("Callback Server Error Unknown",'');
- },
-
- /**
- * Callback OnComplete event,logs reponse and data to console.
- */
- 'on200' : function(request, transport, data)
- {
- if(transport.status < 500)
- {
- var msg = 'HTTP '+transport.status+" with response : \n";
- if(transport.responseText.trim().length >0)
- {
- var f = RegExp('(<!--X-PRADO[^>]+-->)([\\s\\S\\w\\W]*)(<!--//X-PRADO[^>]+-->)',"m");
- msg += transport.responseText.replace(f,'') + "\n";
- }
- if(typeof(data)!="undefined" && data != null)
- msg += "Data : \n"+inspect(data)+"\n";
- data = request.getBodyDataPart(Prado.CallbackRequest.ACTION_HEADER);
- if(data && data.length > 0)
- {
- msg += "Actions : \n";
- data.each(function(action)
- {
- msg += inspect(action)+"\n";
- });
- }
- Logger.info(msg);
- }
- },
-
- /**
- * Uncaught exceptions during callback response.
- */
- onException : function(request,e)
- {
- var msg = "";
- $H(e).each(function(item)
- {
- msg += item.key+": "+item.value+"\n";
- })
- Logger.error('Uncaught Callback Client Exception:', msg);
- },
-
- /**
- * Formats the exception message for display in console.
- */
- formatException : function(e)
- {
- var msg = e.type + " with message \""+e.message+"\"";
- msg += " in "+e.file+"("+e.line+")\n";
- msg += "Stack trace:\n";
- var trace = e.trace;
- for(var i = 0; i<trace.length; i++)
- {
- msg += " #"+i+" "+trace[i].file;
- msg += "("+trace[i].line+"): ";
- msg += trace[i]["class"]+"->"+trace[i]["function"]+"()"+"\n";
- }
- msg += e.version+" "+e.time+"\n";
- return msg;
- }
- },
-
- /**
- * @return string JSON encoded data.
- */
- encode : function(data)
- {
- return Prado.JSON.stringify(data);
- },
-
- /**
- * @return mixed javascript data decoded from string using JSON decoding.
- */
- decode : function(data)
- {
- if(typeof(data) == "string" && data.trim().length > 0)
- return Prado.JSON.parse(data);
- else
- return null;
- },
-
- /**
- * Dispatch a normal request, no timeouts or aborting of requests.
- */
- dispatchNormalRequest : function(callback)
- {
- callback.options.postBody = callback._getPostData(),
- callback.request(callback.url);
- return true;
- },
-
- /**
- * Abort the current priority request in progress.
- */
- tryNextRequest : function()
- {
- var self = Prado.CallbackRequest;
- //Logger.debug('trying next request');
- if(typeof(self.currentRequest) == 'undefined' || self.currentRequest==null)
- {
- if(self.requestQueue.length > 0)
- return self.dispatchQueue();
- //else
- //Logger.warn('empty queque');
- }
- //else
- //Logger.warn('current request ' + self.currentRequest.id);
- },
-
- /*
- * Checks which scripts are used by the response and ensures they're loaded
- */
- loadScripts : function(request, transport, callback)
- {
- var self = Prado.CallbackRequest;
- var data = request.getBodyContentPart(self.SCRIPTLIST_HEADER);
- if (!this.ScriptsToLoad) this.ScriptsToLoad = new Array();
- this.ScriptLoadFinishedCallback = callback;
- if (typeof(data) == "string" && data.length > 0)
- {
- json = Prado.CallbackRequest.decode(data);
- if(typeof(json) != "object")
- Logger.warn("Invalid script list:"+data);
- else
- for(var key in json)
- if (/^\d+$/.test(key))
- {
- var url = json[key];
- if (!Prado.ScriptManager.isAssetLoaded(url))
- this.ScriptsToLoad.push(url);
- }
- }
- this.loadNextScript();
- },
-
- loadNextScript: function()
- {
- var done = (!this.ScriptsToLoad || (this.ScriptsToLoad.length==0));
- if (!done)
- {
- var url = this.ScriptsToLoad.shift(); var obj = this;
- if (
- Prado.ScriptManager.ensureAssetIsLoaded(url,
- function() {
- obj.loadNextScript();
- }
- )
- )
- this.loadNextScript();
- }
- else
- {
- if (this.ScriptLoadFinishedCallback)
- {
- var cb = this.ScriptLoadFinishedCallback;
- this.ScriptLoadFinishedCallback = null;
- cb();
- }
- }
- },
-
- loadStyleSheetsAsync : function(request, transport)
- {
- var self = Prado.CallbackRequest;
- var data = request.getBodyContentPart(self.STYLESHEETLIST_HEADER);
- if (typeof(data) == "string" && data.length > 0)
- {
- json = Prado.CallbackRequest.decode(data);
- if(typeof(json) != "object")
- Logger.warn("Invalid stylesheet list:"+data);
- else
- for(var key in json)
- if (/^\d+$/.test(key))
- Prado.StyleSheetManager.ensureAssetIsLoaded(json[key],null);
- }
- },
-
- loadStyleSheets : function(request, transport, callback)
- {
- var self = Prado.CallbackRequest;
- var data = request.getBodyContentPart(self.STYLESHEETLIST_HEADER);
- if (!this.StyleSheetsToLoad) this.StyleSheetsToLoad = new Array();
- this.StyleSheetLoadFinishedCallback = callback;
- if (typeof(data) == "string" && data.length > 0)
- {
- json = Prado.CallbackRequest.decode(data);
- if(typeof(json) != "object")
- Logger.warn("Invalid stylesheet list:"+data);
- else
- for(var key in json)
- if (/^\d+$/.test(key))
- {
- var url = json[key];
- if (!Prado.StyleSheetManager.isAssetLoaded(url))
- this.StyleSheetsToLoad.push(url);
- }
- }
- this.loadNextStyleSheet();
- },
-
- loadNextStyleSheet: function()
- {
- var done = (!this.StyleSheetsToLoad || (this.StyleSheetsToLoad.length==0));
- if (!done)
- {
- var url = this.StyleSheetsToLoad.shift(); var obj = this;
- if (
- Prado.StyleSheetManager.ensureAssetIsLoaded(url,
- function() {
- obj.loadNextStyleSheet();
- }
- )
- )
- this.loadNextStyleSheet();
- }
- else
- {
- if (this.StyleSheetLoadFinishedCallback)
- {
- var cb = this.StyleSheetLoadFinishedCallback;
- this.StyleSheetLoadFinishedCallback = null;
- cb();
- }
- }
- },
-
- /*
- * Checks which assets are used by the response and ensures they're loaded
- */
- loadAssets : function(request, transport, callback)
- {
- /*
-
- ! This is the callback-based loader for stylesheets, which loads them one-by-one, and
- ! waits for all of them to be loaded before loading scripts and processing the rest of
- ! the callback.
- !
- ! That however is not neccessary, as stylesheets can be loaded asynchronously too.
- !
- ! I leave this code here for the case that this turns out to be a compatibility issue
- ! (for ex. I can imagine some scripts trying to access stylesheet properties and such)
- ! so if need can be reactivated. If you do so, comment out the async stylesheet loader below!
-
- var obj = this;
- this.loadStyleSheets(request,transport, function() {
- obj.loadScripts(request,transport,callback);
- });
-
- */
-
- this.loadStyleSheetsAsync(request,transport);
-
- this.loadScripts(request,transport,callback);
- },
-
- checkHiddenField: function(name, value)
- {
- var id = name.replace(':','_');
- if (!document.getElementById(id))
- {
- var field = document.createElement('input');
- field.setAttribute('type','hidden');
- field.id = id;
- field.name = name;
- field.value = value;
- document.body.appendChild(field);
- }
- },
-
- checkHiddenFields : function(request, transport)
- {
- var self = Prado.CallbackRequest;
- var data = request.getBodyContentPart(self.HIDDENFIELDLIST_HEADER);
- if (typeof(data) == "string" && data.length > 0)
- {
- json = Prado.CallbackRequest.decode(data);
- if(typeof(json) != "object")
- Logger.warn("Invalid hidden field list:"+data);
- else
- for(var key in json)
- this.checkHiddenField(key,json[key]);
- }
- },
-
- /**
- * Updates the page state. It will update only if EnablePageStateUpdate and
- * HasPriority options are both true.
- */
- updatePageState : function(request, transport)
- {
- var self = Prado.CallbackRequest;
- var pagestate = $(self.FIELD_CALLBACK_PAGESTATE);
- var enabled = request.ActiveControl.EnablePageStateUpdate && request.ActiveControl.HasPriority;
- var aborted = typeof(self.currentRequest) == 'undefined' || self.currentRequest == null;
- if(enabled && !aborted && pagestate)
- {
- var data = request.getBodyContentPart(self.PAGESTATE_HEADER);
- if(typeof(data) == "string" && data.length > 0)
- pagestate.value = data;
- else
- {
- if(typeof(Logger) != "undefined")
- Logger.warn("Missing page state:"+data);
- //Logger.warn('## bad state: setting current request to null');
- self.endCurrentRequest();
- //self.tryNextRequest();
- return false;
- }
- }
- self.endCurrentRequest();
- //Logger.warn('## state updated: setting current request to null');
- //self.tryNextRequest();
- return true;
- },
-
- enqueue : function(callback)
- {
- var self = Prado.CallbackRequest;
- self.requestQueue.push(callback);
- //Logger.warn("equeued "+callback.id+", current queque length="+self.requestQueue.length);
- self.tryNextRequest();
- },
-
- dispatchQueue : function()
- {
- var self = Prado.CallbackRequest;
- //Logger.warn("dispatching queque, length="+self.requestQueue.length+" request="+self.currentRequest);
- var callback = self.requestQueue.shift();
- self.currentRequest = callback;
-
- //get data
- callback.options.postBody = callback._getPostData(),
-
- //callback.request = new Prado.AjaxRequest(callback);
- callback.timeout = setTimeout(function()
- {
- //Logger.warn("priority timeout");
- self.abortRequest(callback.id);
- },callback.ActiveControl.RequestTimeOut);
- callback.request(callback.url);
- //Logger.debug("dispatched "+self.currentRequest.id + " ...")
- },
-
- endCurrentRequest : function()
- {
- var self = Prado.CallbackRequest;
- if(typeof(self.currentRequest) != 'undefined' && self.currentRequest != null)
- clearTimeout(self.currentRequest.timeout);
- self.currentRequest=null;
- },
-
- abortRequest : function(id)
- {
- //Logger.warn("abort id="+id);
- var self = Prado.CallbackRequest;
- if(typeof(self.currentRequest) != 'undefined'
- && self.currentRequest != null && self.currentRequest.id == id)
- {
- var request = self.currentRequest;
- if(request.transport.readyState < 4)
- request.transport.abort();
- //Logger.warn('## aborted: setting current request to null');
- self.endCurrentRequest();
- }
- self.tryNextRequest();
- }
-});
-
-/**
- * Automatically aborts the current request when a priority request has returned.
- */
-Ajax.Responders.register({onComplete : function(request)
-{
- if(request && request instanceof Prado.AjaxRequest)
- {
- if(request.ActiveControl.HasPriority)
- Prado.CallbackRequest.tryNextRequest();
- }
-}});
-
-//Add HTTP exception respones when logger is enabled.
-Event.OnLoad(function()
-{
- if(typeof Logger != "undefined")
- Ajax.Responders.register(Prado.CallbackRequest.Exception);
-});
-
-/**
- * Create and prepare a new callback request.
- * Call the dispatch() method to start the callback request.
- * <code>
- * request = new Prado.CallbackRequest(UniqueID, callback);
- * request.dispatch();
- * </code>
- */
-Prado.CallbackRequest.prototype = Object.extend(Prado.AjaxRequest.prototype,
-{
-
- /**
- * Prepare and inititate a callback request.
- */
- initialize : function(id, options)
- {
- /**
- * Callback URL, same url as the current page.
- */
- this.url = this.getCallbackUrl();
-
- this.transport = Ajax.getTransport();
- this.Enabled = true;
- this.id = id;
- this.randomId = this.randomString();
-
- if(typeof(id)=="string"){
- Prado.CallbackRequest.requests[id+"__"+this.randomId] = this;
- }
-
- this.setOptions(Object.extend(
- {
- RequestTimeOut : 30000, // 30 second timeout.
- EnablePageStateUpdate : true,
- HasPriority : true,
- CausesValidation : true,
- ValidationGroup : null,
- PostInputs : true
- }, options || {}));
-
- this.ActiveControl = this.options;
- Prado.CallbackRequest.requests[id+"__"+this.randomId].ActiveControl = this.options;
- },
-
- /**
- * Sets the request options
- * @return {Array} request options.
- */
- setOptions: function(options){
-
- this.options = {
- method: 'post',
- asynchronous: true,
- contentType: 'application/x-www-form-urlencoded',
- encoding: 'UTF-8',
- parameters: '',
- evalJSON: true,
- evalJS: true
- };
-
- Object.extend(this.options, options || { });
-
- this.options.method = this.options.method.toLowerCase();
- if(Object.isString(this.options.parameters)){
- this.options.parameters = this.options.parameters.toQueryParams();
- }
- },
-
- /**
- * Gets the url from the forms that contains the PRADO_PAGESTATE
- * @return {String} callback url.
- */
- getCallbackUrl : function()
- {
- return $('PRADO_PAGESTATE').form.action;
- },
-
- /**
- * Sets the request parameter
- * @param {Object} parameter value
- */
- setCallbackParameter : function(value)
- {
- var requestId = this.id+"__"+this.randomId;
- this.ActiveControl['CallbackParameter'] = value;
- Prado.CallbackRequest.requests[requestId].ActiveControl['CallbackParameter'] = value;
- },
-
- /**
- * @return {Object} request paramater value.
- */
- getCallbackParameter : function()
- {
- return Prado.CallbackRequest.requests[this.id+"__"+this.randomId].ActiveControl['CallbackParameter'];
- },
-
- /**
- * Sets the callback request timeout.
- * @param {integer} timeout in milliseconds
- */
- setRequestTimeOut : function(timeout)
- {
- this.ActiveControl['RequestTimeOut'] = timeout;
- },
-
- /**
- * @return {integer} request timeout in milliseconds
- */
- getRequestTimeOut : function()
- {
- return this.ActiveControl['RequestTimeOut'];
- },
-
- /**
- * Set true to enable validation on callback dispatch.
- * @param {boolean} true to validate
- */
- setCausesValidation : function(validate)
- {
- this.ActiveControl['CausesValidation'] = validate;
- },
-
- /**
- * @return {boolean} validate on request dispatch
- */
- getCausesValidation : function()
- {
- return this.ActiveControl['CausesValidation'];
- },
-
- /**
- * Sets the validation group to validate during request dispatch.
- * @param {string} validation group name
- */
- setValidationGroup : function(group)
- {
- this.ActiveControl['ValidationGroup'] = group;
- },
-
- /**
- * @return {string} validation group name.
- */
- getValidationGroup : function()
- {
- return this.ActiveControl['ValidationGroup'];
- },
-
- /**
- * Dispatch the callback request.
- */
- dispatch : function()
- {
- //Logger.info("dispatching request");
- //trigger tinyMCE to save data.
- if(typeof tinyMCE != "undefined")
- tinyMCE.triggerSave();
-
- if(this.ActiveControl.CausesValidation && typeof(Prado.Validation) != "undefined")
- {
- var form = this.ActiveControl.Form || Prado.Validation.getForm();
- if(Prado.Validation.validate(form,this.ActiveControl.ValidationGroup,this) == false)
- return false;
- }
-
- if(this.ActiveControl.onPreDispatch)
- this.ActiveControl.onPreDispatch(this,null);
-
- if(!this.Enabled)
- return;
-
- // Opera don't have onLoading/onLoaded state, so, simulate them just
- // before sending the request.
- if (Prototype.Browser.Opera)
- {
- if (this.ActiveControl.onLoading)
- {
- this.ActiveControl.onLoading(this,null);
- Ajax.Responders.dispatch('onLoading',this, this.transport,null);
- }
- if (this.ActiveControl.onLoaded)
- {
- this.ActiveControl.onLoaded(this,null);
- Ajax.Responders.dispatch('onLoaded',this, this.transport,null);
- }
- }
-
- var result;
- if(this.ActiveControl.HasPriority)
- {
- return Prado.CallbackRequest.enqueue(this);
- //return Prado.CallbackRequest.dispatchPriorityRequest(this);
- }
- else
- return Prado.CallbackRequest.dispatchNormalRequest(this);
- },
-
- abort : function()
- {
- return Prado.CallbackRequest.abortRequest(this.id);
- },
-
- /**
- * Collects the form inputs, encode the parameters, and sets the callback
- * target id. The resulting string is the request content body.
- * @return string request body content containing post data.
- */
- _getPostData : function()
- {
- var data = {};
- var callback = Prado.CallbackRequest;
- if(this.ActiveControl.PostInputs != false)
- {
- callback.PostDataLoaders.each(function(name)
- {
- var elements=$A(document.getElementsByName(name));
- if(elements.size() == 0)
- {
- name += '[]';
- elements=$A(document.getElementsByName(name));
- }
- elements.each(function(element)
- {
- //IE will try to get elements with ID == name as well.
- if(element.type && element.name == name)
- {
- var value = $F(element);
- if(typeof(value) != "undefined" && value != null)
- data[name] = value;
- }
- })
- })
- }
- if(typeof(this.ActiveControl.CallbackParameter) != "undefined")
- data[callback.FIELD_CALLBACK_PARAMETER] = callback.encode(this.getCallbackParameter());
- var pageState = $F(callback.FIELD_CALLBACK_PAGESTATE);
- if(typeof(pageState) != "undefined")
- data[callback.FIELD_CALLBACK_PAGESTATE] = pageState;
- data[callback.FIELD_CALLBACK_TARGET] = this.id;
- if(this.ActiveControl.EventTarget)
- data[callback.FIELD_POSTBACK_TARGET] = this.ActiveControl.EventTarget;
- if(this.ActiveControl.EventParameter)
- data[callback.FIELD_POSTBACK_PARAMETER] = this.ActiveControl.EventParameter;
- return $H(data).toQueryString();
- },
-
- /**
- * Creates a random string with a length of 8 chars.
- * @return string
- */
- randomString : function()
- {
- chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
- randomString = "";
- for(x=0;x<8;x++)
- randomString += chars.charAt(Math.floor(Math.random() * 62));
- return randomString
- }
-});
-
-/**
- * Create a new callback request using default settings.
- * @param string callback handler unique ID.
- * @param mixed parameter to pass to callback handler on the server side.
- * @param function client side onSuccess event handler.
- * @param object additional request options.
- * @return boolean always false.
- */
-Prado.Callback = function(UniqueID, parameter, onSuccess, options)
-{
- var callback =
- {
- 'CallbackParameter' : parameter || '',
- 'onSuccess' : onSuccess || Prototype.emptyFunction
- };
-
- Object.extend(callback, options || {});
-
- var request = new Prado.CallbackRequest(UniqueID, callback);
- request.dispatch();
- return false;
-};
-
-
-
-/**
- * Asset manager classes for lazy loading of scripts and stylesheets
- * @author Gabor Berczi (gabor.berczi@devworx.hu)
- */
-
-if (typeof(Prado.AssetManagerClass)=="undefined") {
-
- Prado.AssetManagerClass = Class.create();
- Prado.AssetManagerClass.prototype = {
-
- initialize: function() {
- this.loadedAssets = new Array();
- this.discoverLoadedAssets();
- },
-
-
- /**
- * Detect which assets are already loaded by page markup.
- * This is done by looking up all <asset> elements and registering the values of their src attributes.
- */
- discoverLoadedAssets: function() {
-
- // wait until document has finished loading to avoid javascript errors
- if (!document.body) return;
-
- var assets = this.findAssetUrlsInMarkup();
- for(var i=0;i<assets.length;i++)
- this.markAssetAsLoaded(assets[i]);
- },
-
- /**
- * Extend url to a fully qualified url.
- * @param string url
- */
- makeFullUrl: function(url) {
-
- // this is not intended to be a fully blown url "canonicalizator",
- // just to handle the most common and basic asset paths used by Prado
-
- if (!this.baseUri) this.baseUri = window.location;
-
- if (url.indexOf('://')==-1)
- {
- var a = document.createElement('a');
- a.href = url;
-
- if (a.href.indexOf('://')!=-1)
- url = a.href;
- else
- {
- var path = a.pathname;
- if (path.substr(0,1)!='/') path = '/'+path;
- url = this.baseUri.protocol+'//'+this.baseUri.host+path;
- }
- }
- return url;
- },
-
- isAssetLoaded: function(url) {
- url = this.makeFullUrl(url);
- return (this.loadedAssets.indexOf(url)!=-1);
- },
-
- /**
- * Mark asset as being already loaded
- * @param string url of the asset
- */
- markAssetAsLoaded: function(url) {
- url = this.makeFullUrl(url);
- if (this.loadedAssets.indexOf(url)==-1)
- this.loadedAssets.push(url);
- },
-
- assetReadyStateChanged: function(url, element, callback, finalevent) {
- if (finalevent || (element.readyState == 'loaded') || (element.readyState == 'complete'))
- if (!element.assetCallbackFired)
- {
- element.assetCallbackFired = true;
- callback(url,element);
- }
- },
-
- assetLoadFailed: function(url, element, callback) {
- debugger;
- element.assetCallbackFired = true;
- if(typeof Logger != "undefined")
- Logger.error("Failed to load asset: "+url, this);
- if (!element.assetCallbackFired)
- callback(url,element,false);
- },
-
- /**
- * Load a new asset dynamically into the page.
- * Please not thet loading is asynchronous and therefore you can't assume that
- * the asset is loaded and ready when returning from this function.
- * @param string url of the asset to load
- * @param callback will be called when the asset has loaded (or failed to load)
- */
- startAssetLoad: function(url, callback) {
-
- // create new <asset> element in page header
- var asset = this.createAssetElement(url);
-
- if (callback)
- {
- asset.onreadystatechange = this.assetReadyStateChanged.bind(this, url, asset, callback, false);
- asset.onload = this.assetReadyStateChanged.bind(this, url, asset, callback, true);
- asset.onerror = this.assetLoadFailed.bind(this, url, asset, callback);
- asset.assetCallbackFired = false;
- }
-
- var head = document.getElementsByTagName('head')[0];
- head.appendChild(asset);
-
- // mark this asset as loaded
- this.markAssetAsLoaded(url);
-
- return (callback!=false);
- },
-
- /**
- * Check whether a asset is loaded into the page, and if itsn't, load it now
- * @param string url of the asset to check/load
- * @return boolean returns true if asset is already loaded, or false, if loading has just started. callback will be called when loading has finished.
- */
- ensureAssetIsLoaded: function(url, callback) {
- url = this.makeFullUrl(url);
- if (this.loadedAssets.indexOf(url)==-1)
- {
- this.startAssetLoad(url,callback);
- return false;
- }
- else
- return true;
- }
-
- }
-
-};
-
- Prado.ScriptManagerClass = Class.extend(Prado.AssetManagerClass, {
-
- findAssetUrlsInMarkup: function() {
- var urls = new Array();
- var scripts = document.getElementsByTagName('script');
- for(var i=0;i<scripts.length;i++)
- {
- var e = scripts[i]; var src = e.src;
- if (src!="")
- urls.push(src);
- }
- return urls;
- },
-
- createAssetElement: function(url) {
- var asset = document.createElement('script');
- asset.type = 'text/javascript';
- asset.src = url;
-// asset.async = false; // HTML5 only
- return asset;
- }
-
- });
-
- Prado.StyleSheetManagerClass = Class.extend(Prado.AssetManagerClass, {
-
- findAssetUrlsInMarkup: function() {
- var urls = new Array();
- var scripts = document.getElementsByTagName('link');
- for(var i=0;i<scripts.length;i++)
- {
- var e = scripts[i]; var href = e.href;
- if ((e.rel=="stylesheet") && (href.length>0))
- urls.push(href);
- }
- return urls;
- },
-
- createAssetElement: function(url) {
- var asset = document.createElement('link');
- asset.rel = 'stylesheet';
- asset.media = 'screen';
- asset.setAttribute('type', 'text/css');
- asset.href = url;
-// asset.async = false; // HTML5 only
- return asset;
- }
-
- });
-
- if (typeof(Prado.ScriptManager)=="undefined") Prado.ScriptManager = new Prado.ScriptManagerClass();
- if (typeof(Prado.StyleSheetManager)=="undefined") Prado.StyleSheetManager = new Prado.StyleSheetManagerClass();
-
- // make sure we scan for loaded scripts again when the page has been loaded
- var discover = function() {
- Prado.ScriptManager.discoverLoadedAssets();
- Prado.StyleSheetManager.discoverLoadedAssets();
- }
- if (window.attachEvent) window.attachEvent('onload', discover);
- else if (window.addEventListener) window.addEventListener('load', discover, false);
-
+
+Prado.AjaxRequest = Class.create();
+Prado.AjaxRequest.prototype = Object.clone(Ajax.Request.prototype);
+
+/**
+ * Override Prototype's response implementation.
+ */
+Object.extend(Prado.AjaxRequest.prototype,
+{
+ /*initialize: function(request)
+ {
+ this.CallbackRequest = request;
+ this.transport = Ajax.getTransport();
+ this.setOptions(request.options);
+ this.request(request.url);
+ },*/
+
+ /**
+ * Customize the response, dispatch onXXX response code events, and
+ * tries to execute response actions (javascript statements).
+ */
+ respondToReadyState : function(readyState)
+ {
+ var event = Ajax.Request.Events[readyState];
+ var transport = this.transport, json = this.getBodyDataPart(Prado.CallbackRequest.DATA_HEADER);
+
+ if (event == 'Complete')
+ {
+ var redirectUrl = this.getBodyContentPart(Prado.CallbackRequest.REDIRECT_HEADER);
+ if (redirectUrl)
+ document.location.href = redirectUrl;
+
+ if ((this.getHeader('Content-type') || '').match(/^text\/javascript/i))
+ {
+ try
+ {
+ json = eval('(' + transport.responseText + ')');
+ }
+ catch (e)
+ {
+ if(typeof(json) == "string")
+ json = Prado.CallbackRequest.decode(result);
+ }
+ }
+
+ try
+ {
+ Prado.CallbackRequest.updatePageState(this,transport);
+ Prado.CallbackRequest.checkHiddenFields(this,transport);
+ var obj = this;
+ Prado.CallbackRequest.loadAssets(this,transport, function()
+
+ {
+ try
+ {
+ Ajax.Responders.dispatch('on' + transport.status, obj, transport, json);
+ Prado.CallbackRequest.dispatchActions(transport,obj.getBodyDataPart(Prado.CallbackRequest.ACTION_HEADER));
+
+ (
+ obj.options['on' + obj.transport.status]
+ ||
+ obj.options['on' + (obj.success() ? 'Success' : 'Failure')]
+ ||
+ Prototype.emptyFunction
+ ) (obj, json);
+ }
+ catch (e)
+ {
+ obj.dispatchException(e);
+ }
+ }
+ );
+ }
+ catch (e)
+ {
+ this.dispatchException(e);
+ }
+ }
+
+ try {
+ (this.options['on' + event] || Prototype.emptyFunction)(this, json);
+ Ajax.Responders.dispatch('on' + event, this, transport, json);
+ } catch (e) {
+ this.dispatchException(e);
+ }
+
+ /* Avoid memory leak in MSIE: clean up the oncomplete event handler */
+ if (event == 'Complete')
+ this.transport.onreadystatechange = Prototype.emptyFunction;
+ },
+
+ /**
+ * Gets header data assuming JSON encoding.
+ * @param string header name
+ * @return object header data as javascript structures.
+ */
+ getHeaderData : function(name)
+ {
+ return this.getJsonData(this.getHeader(name));
+ },
+
+ getBodyContentPart : function(name)
+ {
+ if(typeof(this.transport.responseText)=="string")
+ return Prado.Element.extractContent(this.transport.responseText, name);
+ },
+
+ getJsonData : function(json)
+ {
+ try
+ {
+ return eval('(' + json + ')');
+ }
+ catch (e)
+ {
+ if(typeof(json) == "string")
+ return Prado.CallbackRequest.decode(json);
+ }
+ },
+
+ getBodyDataPart : function(name)
+ {
+ return this.getJsonData(this.getBodyContentPart(name));
+ }
+});
+
+/**
+ * Prado Callback client-side request handler.
+ */
+Prado.CallbackRequest = Class.create();
+
+/**
+ * Static definitions.
+ */
+Object.extend(Prado.CallbackRequest,
+{
+ /**
+ * Callback request target POST field name.
+ */
+ FIELD_CALLBACK_TARGET : 'PRADO_CALLBACK_TARGET',
+ /**
+ * Callback request parameter POST field name.
+ */
+ FIELD_CALLBACK_PARAMETER : 'PRADO_CALLBACK_PARAMETER',
+ /**
+ * Callback request page state field name,
+ */
+ FIELD_CALLBACK_PAGESTATE : 'PRADO_PAGESTATE',
+
+ FIELD_POSTBACK_TARGET : 'PRADO_POSTBACK_TARGET',
+
+ FIELD_POSTBACK_PARAMETER : 'PRADO_POSTBACK_PARAMETER',
+
+ /**
+ * List of form fields that will be collected during callback.
+ */
+ PostDataLoaders : [],
+ /**
+ * Response data header name.
+ */
+ DATA_HEADER : 'X-PRADO-DATA',
+ /**
+ * Response javascript execution statement header name.
+ */
+ ACTION_HEADER : 'X-PRADO-ACTIONS',
+ /**
+ * Response errors/exceptions header name.
+ */
+ ERROR_HEADER : 'X-PRADO-ERROR',
+ /**
+ * Page state header name.
+ */
+ PAGESTATE_HEADER : 'X-PRADO-PAGESTATE',
+ /**
+ * Script list header name.
+ */
+ SCRIPTLIST_HEADER : 'X-PRADO-SCRIPTLIST',
+ /**
+ * Stylesheet list header name.
+ */
+ STYLESHEETLIST_HEADER : 'X-PRADO-STYLESHEETLIST',
+ /**
+ * Hidden field list header name.
+ */
+ HIDDENFIELDLIST_HEADER : 'X-PRADO-HIDDENFIELDLIST',
+
+ REDIRECT_HEADER : 'X-PRADO-REDIRECT',
+
+ requestQueue : [],
+
+ //all request objects
+ requests : {},
+
+ getRequestById : function(id)
+ {
+ var requests = Prado.CallbackRequest.requests;
+ if(typeof(requests[id]) != "undefined")
+ return requests[id];
+ },
+
+ dispatch : function(id)
+ {
+ var requests = Prado.CallbackRequest.requests;
+ if(typeof(requests[id]) != "undefined")
+ requests[id].dispatch();
+ },
+
+ /**
+ * Add ids of inputs element to post in the request.
+ */
+ addPostLoaders : function(ids)
+ {
+ var self = Prado.CallbackRequest;
+ self.PostDataLoaders = self.PostDataLoaders.concat(ids);
+ var list = [];
+ self.PostDataLoaders.each(function(id)
+ {
+ if(list.indexOf(id) < 0)
+ list.push(id);
+ });
+ self.PostDataLoaders = list;
+ },
+
+ /**
+ * Dispatch callback response actions.
+ */
+ dispatchActions : function(transport,actions)
+ {
+ var self = Prado.CallbackRequest;
+ if(actions && actions.length > 0)
+ actions.each(self.__run.bind(self,transport));
+ },
+
+ /**
+ * Prase and evaluate a Callback clien-side action
+ */
+ __run : function(transport, command)
+ {
+ var self = Prado.CallbackRequest;
+ self.transport = transport;
+ for(var method in command)
+ {
+ try
+ {
+ method.toFunction().apply(self,command[method]);
+ }
+ catch(e)
+ {
+ if(typeof(Logger) != "undefined")
+ self.Exception.onException(null,e);
+ else
+ debugger;
+ }
+ }
+ },
+
+ /**
+ * Respond to Prado Callback request exceptions.
+ */
+ Exception :
+ {
+ /**
+ * Server returns 500 exception. Just log it.
+ */
+ "on500" : function(request, transport, data)
+ {
+ var e = request.getHeaderData(Prado.CallbackRequest.ERROR_HEADER);
+ if (e)
+ Logger.error("Callback Server Error "+e.code, this.formatException(e));
+ else
+ Logger.error("Callback Server Error Unknown",'');
+ },
+
+ /**
+ * Callback OnComplete event,logs reponse and data to console.
+ */
+ 'on200' : function(request, transport, data)
+ {
+ if(transport.status < 500)
+ {
+ var msg = 'HTTP '+transport.status+" with response : \n";
+ if(transport.responseText.trim().length >0)
+ {
+ var f = RegExp('(<!--X-PRADO[^>]+-->)([\\s\\S\\w\\W]*)(<!--//X-PRADO[^>]+-->)',"m");
+ msg += transport.responseText.replace(f,'') + "\n";
+ }
+ if(typeof(data)!="undefined" && data != null)
+ msg += "Data : \n"+inspect(data)+"\n";
+ data = request.getBodyDataPart(Prado.CallbackRequest.ACTION_HEADER);
+ if(data && data.length > 0)
+ {
+ msg += "Actions : \n";
+ data.each(function(action)
+ {
+ msg += inspect(action)+"\n";
+ });
+ }
+ Logger.info(msg);
+ }
+ },
+
+ /**
+ * Uncaught exceptions during callback response.
+ */
+ onException : function(request,e)
+ {
+ var msg = "";
+ $H(e).each(function(item)
+ {
+ msg += item.key+": "+item.value+"\n";
+ })
+ Logger.error('Uncaught Callback Client Exception:', msg);
+ },
+
+ /**
+ * Formats the exception message for display in console.
+ */
+ formatException : function(e)
+ {
+ var msg = e.type + " with message \""+e.message+"\"";
+ msg += " in "+e.file+"("+e.line+")\n";
+ msg += "Stack trace:\n";
+ var trace = e.trace;
+ for(var i = 0; i<trace.length; i++)
+ {
+ msg += " #"+i+" "+trace[i].file;
+ msg += "("+trace[i].line+"): ";
+ msg += trace[i]["class"]+"->"+trace[i]["function"]+"()"+"\n";
+ }
+ msg += e.version+" "+e.time+"\n";
+ return msg;
+ }
+ },
+
+ /**
+ * @return string JSON encoded data.
+ */
+ encode : function(data)
+ {
+ return Prado.JSON.stringify(data);
+ },
+
+ /**
+ * @return mixed javascript data decoded from string using JSON decoding.
+ */
+ decode : function(data)
+ {
+ if(typeof(data) == "string" && data.trim().length > 0)
+ return Prado.JSON.parse(data);
+ else
+ return null;
+ },
+
+ /**
+ * Dispatch a normal request, no timeouts or aborting of requests.
+ */
+ dispatchNormalRequest : function(callback)
+ {
+ callback.options.postBody = callback._getPostData(),
+ callback.request(callback.url);
+ return true;
+ },
+
+ /**
+ * Abort the current priority request in progress.
+ */
+ tryNextRequest : function()
+ {
+ var self = Prado.CallbackRequest;
+ //Logger.debug('trying next request');
+ if(typeof(self.currentRequest) == 'undefined' || self.currentRequest==null)
+ {
+ if(self.requestQueue.length > 0)
+ return self.dispatchQueue();
+ //else
+ //Logger.warn('empty queque');
+ }
+ //else
+ //Logger.warn('current request ' + self.currentRequest.id);
+ },
+
+ /*
+ * Checks which scripts are used by the response and ensures they're loaded
+ */
+ loadScripts : function(request, transport, callback)
+ {
+ var self = Prado.CallbackRequest;
+ var data = request.getBodyContentPart(self.SCRIPTLIST_HEADER);
+ if (!this.ScriptsToLoad) this.ScriptsToLoad = new Array();
+ this.ScriptLoadFinishedCallback = callback;
+ if (typeof(data) == "string" && data.length > 0)
+ {
+ json = Prado.CallbackRequest.decode(data);
+ if(typeof(json) != "object")
+ Logger.warn("Invalid script list:"+data);
+ else
+ for(var key in json)
+ if (/^\d+$/.test(key))
+ {
+ var url = json[key];
+ if (!Prado.ScriptManager.isAssetLoaded(url))
+ this.ScriptsToLoad.push(url);
+ }
+ }
+ this.loadNextScript();
+ },
+
+ loadNextScript: function()
+ {
+ var done = (!this.ScriptsToLoad || (this.ScriptsToLoad.length==0));
+ if (!done)
+ {
+ var url = this.ScriptsToLoad.shift(); var obj = this;
+ if (
+ Prado.ScriptManager.ensureAssetIsLoaded(url,
+ function() {
+ obj.loadNextScript();
+ }
+ )
+ )
+ this.loadNextScript();
+ }
+ else
+ {
+ if (this.ScriptLoadFinishedCallback)
+ {
+ var cb = this.ScriptLoadFinishedCallback;
+ this.ScriptLoadFinishedCallback = null;
+ cb();
+ }
+ }
+ },
+
+ loadStyleSheetsAsync : function(request, transport)
+ {
+ var self = Prado.CallbackRequest;
+ var data = request.getBodyContentPart(self.STYLESHEETLIST_HEADER);
+ if (typeof(data) == "string" && data.length > 0)
+ {
+ json = Prado.CallbackRequest.decode(data);
+ if(typeof(json) != "object")
+ Logger.warn("Invalid stylesheet list:"+data);
+ else
+ for(var key in json)
+ if (/^\d+$/.test(key))
+ Prado.StyleSheetManager.ensureAssetIsLoaded(json[key],null);
+ }
+ },
+
+ loadStyleSheets : function(request, transport, callback)
+ {
+ var self = Prado.CallbackRequest;
+ var data = request.getBodyContentPart(self.STYLESHEETLIST_HEADER);
+ if (!this.StyleSheetsToLoad) this.StyleSheetsToLoad = new Array();
+ this.StyleSheetLoadFinishedCallback = callback;
+ if (typeof(data) == "string" && data.length > 0)
+ {
+ json = Prado.CallbackRequest.decode(data);
+ if(typeof(json) != "object")
+ Logger.warn("Invalid stylesheet list:"+data);
+ else
+ for(var key in json)
+ if (/^\d+$/.test(key))
+ {
+ var url = json[key];
+ if (!Prado.StyleSheetManager.isAssetLoaded(url))
+ this.StyleSheetsToLoad.push(url);
+ }
+ }
+ this.loadNextStyleSheet();
+ },
+
+ loadNextStyleSheet: function()
+ {
+ var done = (!this.StyleSheetsToLoad || (this.StyleSheetsToLoad.length==0));
+ if (!done)
+ {
+ var url = this.StyleSheetsToLoad.shift(); var obj = this;
+ if (
+ Prado.StyleSheetManager.ensureAssetIsLoaded(url,
+ function() {
+ obj.loadNextStyleSheet();
+ }
+ )
+ )
+ this.loadNextStyleSheet();
+ }
+ else
+ {
+ if (this.StyleSheetLoadFinishedCallback)
+ {
+ var cb = this.StyleSheetLoadFinishedCallback;
+ this.StyleSheetLoadFinishedCallback = null;
+ cb();
+ }
+ }
+ },
+
+ /*
+ * Checks which assets are used by the response and ensures they're loaded
+ */
+ loadAssets : function(request, transport, callback)
+ {
+ /*
+
+ ! This is the callback-based loader for stylesheets, which loads them one-by-one, and
+ ! waits for all of them to be loaded before loading scripts and processing the rest of
+ ! the callback.
+ !
+ ! That however is not neccessary, as stylesheets can be loaded asynchronously too.
+ !
+ ! I leave this code here for the case that this turns out to be a compatibility issue
+ ! (for ex. I can imagine some scripts trying to access stylesheet properties and such)
+ ! so if need can be reactivated. If you do so, comment out the async stylesheet loader below!
+
+ var obj = this;
+ this.loadStyleSheets(request,transport, function() {
+ obj.loadScripts(request,transport,callback);
+ });
+
+ */
+
+ this.loadStyleSheetsAsync(request,transport);
+
+ this.loadScripts(request,transport,callback);
+ },
+
+ checkHiddenField: function(name, value)
+ {
+ var id = name.replace(':','_');
+ if (!document.getElementById(id))
+ {
+ var field = document.createElement('input');
+ field.setAttribute('type','hidden');
+ field.id = id;
+ field.name = name;
+ field.value = value;
+ document.body.appendChild(field);
+ }
+ },
+
+ checkHiddenFields : function(request, transport)
+ {
+ var self = Prado.CallbackRequest;
+ var data = request.getBodyContentPart(self.HIDDENFIELDLIST_HEADER);
+ if (typeof(data) == "string" && data.length > 0)
+ {
+ json = Prado.CallbackRequest.decode(data);
+ if(typeof(json) != "object")
+ Logger.warn("Invalid hidden field list:"+data);
+ else
+ for(var key in json)
+ this.checkHiddenField(key,json[key]);
+ }
+ },
+
+ /**
+ * Updates the page state. It will update only if EnablePageStateUpdate and
+ * HasPriority options are both true.
+ */
+ updatePageState : function(request, transport)
+ {
+ var self = Prado.CallbackRequest;
+ var pagestate = $(self.FIELD_CALLBACK_PAGESTATE);
+ var enabled = request.ActiveControl.EnablePageStateUpdate && request.ActiveControl.HasPriority;
+ var aborted = typeof(self.currentRequest) == 'undefined' || self.currentRequest == null;
+ if(enabled && !aborted && pagestate)
+ {
+ var data = request.getBodyContentPart(self.PAGESTATE_HEADER);
+ if(typeof(data) == "string" && data.length > 0)
+ pagestate.value = data;
+ else
+ {
+ if(typeof(Logger) != "undefined")
+ Logger.warn("Missing page state:"+data);
+ //Logger.warn('## bad state: setting current request to null');
+ self.endCurrentRequest();
+ //self.tryNextRequest();
+ return false;
+ }
+ }
+ self.endCurrentRequest();
+ //Logger.warn('## state updated: setting current request to null');
+ //self.tryNextRequest();
+ return true;
+ },
+
+ enqueue : function(callback)
+ {
+ var self = Prado.CallbackRequest;
+ self.requestQueue.push(callback);
+ //Logger.warn("equeued "+callback.id+", current queque length="+self.requestQueue.length);
+ self.tryNextRequest();
+ },
+
+ dispatchQueue : function()
+ {
+ var self = Prado.CallbackRequest;
+ //Logger.warn("dispatching queque, length="+self.requestQueue.length+" request="+self.currentRequest);
+ var callback = self.requestQueue.shift();
+ self.currentRequest = callback;
+
+ //get data
+ callback.options.postBody = callback._getPostData(),
+
+ //callback.request = new Prado.AjaxRequest(callback);
+ callback.timeout = setTimeout(function()
+ {
+ //Logger.warn("priority timeout");
+ self.abortRequest(callback.id);
+ },callback.ActiveControl.RequestTimeOut);
+ callback.request(callback.url);
+ //Logger.debug("dispatched "+self.currentRequest.id + " ...")
+ },
+
+ endCurrentRequest : function()
+ {
+ var self = Prado.CallbackRequest;
+ if(typeof(self.currentRequest) != 'undefined' && self.currentRequest != null)
+ clearTimeout(self.currentRequest.timeout);
+ self.currentRequest=null;
+ },
+
+ abortRequest : function(id)
+ {
+ //Logger.warn("abort id="+id);
+ var self = Prado.CallbackRequest;
+ if(typeof(self.currentRequest) != 'undefined'
+ && self.currentRequest != null && self.currentRequest.id == id)
+ {
+ var request = self.currentRequest;
+ if(request.transport.readyState < 4)
+ request.transport.abort();
+ //Logger.warn('## aborted: setting current request to null');
+ self.endCurrentRequest();
+ }
+ self.tryNextRequest();
+ }
+});
+
+/**
+ * Automatically aborts the current request when a priority request has returned.
+ */
+Ajax.Responders.register({onComplete : function(request)
+{
+ if(request && request instanceof Prado.AjaxRequest)
+ {
+ if(request.ActiveControl.HasPriority)
+ Prado.CallbackRequest.tryNextRequest();
+ }
+}});
+
+//Add HTTP exception respones when logger is enabled.
+Event.OnLoad(function()
+{
+ if(typeof Logger != "undefined")
+ Ajax.Responders.register(Prado.CallbackRequest.Exception);
+});
+
+/**
+ * Create and prepare a new callback request.
+ * Call the dispatch() method to start the callback request.
+ * <code>
+ * request = new Prado.CallbackRequest(UniqueID, callback);
+ * request.dispatch();
+ * </code>
+ */
+Prado.CallbackRequest.prototype = Object.extend(Prado.AjaxRequest.prototype,
+{
+
+ /**
+ * Prepare and inititate a callback request.
+ */
+ initialize : function(id, options)
+ {
+ /**
+ * Callback URL, same url as the current page.
+ */
+ this.url = this.getCallbackUrl();
+
+ this.transport = Ajax.getTransport();
+ this.Enabled = true;
+ this.id = id;
+ this.randomId = this.randomString();
+
+ if(typeof(id)=="string"){
+ Prado.CallbackRequest.requests[id+"__"+this.randomId] = this;
+ }
+
+ this.setOptions(Object.extend(
+ {
+ RequestTimeOut : 30000, // 30 second timeout.
+ EnablePageStateUpdate : true,
+ HasPriority : true,
+ CausesValidation : true,
+ ValidationGroup : null,
+ PostInputs : true
+ }, options || {}));
+
+ this.ActiveControl = this.options;
+ Prado.CallbackRequest.requests[id+"__"+this.randomId].ActiveControl = this.options;
+ },
+
+ /**
+ * Sets the request options
+ * @return {Array} request options.
+ */
+ setOptions: function(options){
+
+ this.options = {
+ method: 'post',
+ asynchronous: true,
+ contentType: 'application/x-www-form-urlencoded',
+ encoding: 'UTF-8',
+ parameters: '',
+ evalJSON: true,
+ evalJS: true
+ };
+
+ Object.extend(this.options, options || { });
+
+ this.options.method = this.options.method.toLowerCase();
+ if(Object.isString(this.options.parameters)){
+ this.options.parameters = this.options.parameters.toQueryParams();
+ }
+ },
+
+ /**
+ * Gets the url from the forms that contains the PRADO_PAGESTATE
+ * @return {String} callback url.
+ */
+ getCallbackUrl : function()
+ {
+ return $('PRADO_PAGESTATE').form.action;
+ },
+
+ /**
+ * Sets the request parameter
+ * @param {Object} parameter value
+ */
+ setCallbackParameter : function(value)
+ {
+ var requestId = this.id+"__"+this.randomId;
+ this.ActiveControl['CallbackParameter'] = value;
+ Prado.CallbackRequest.requests[requestId].ActiveControl['CallbackParameter'] = value;
+ },
+
+ /**
+ * @return {Object} request paramater value.
+ */
+ getCallbackParameter : function()
+ {
+ return Prado.CallbackRequest.requests[this.id+"__"+this.randomId].ActiveControl['CallbackParameter'];
+ },
+
+ /**
+ * Sets the callback request timeout.
+ * @param {integer} timeout in milliseconds
+ */
+ setRequestTimeOut : function(timeout)
+ {
+ this.ActiveControl['RequestTimeOut'] = timeout;
+ },
+
+ /**
+ * @return {integer} request timeout in milliseconds
+ */
+ getRequestTimeOut : function()
+ {
+ return this.ActiveControl['RequestTimeOut'];
+ },
+
+ /**
+ * Set true to enable validation on callback dispatch.
+ * @param {boolean} true to validate
+ */
+ setCausesValidation : function(validate)
+ {
+ this.ActiveControl['CausesValidation'] = validate;
+ },
+
+ /**
+ * @return {boolean} validate on request dispatch
+ */
+ getCausesValidation : function()
+ {
+ return this.ActiveControl['CausesValidation'];
+ },
+
+ /**
+ * Sets the validation group to validate during request dispatch.
+ * @param {string} validation group name
+ */
+ setValidationGroup : function(group)
+ {
+ this.ActiveControl['ValidationGroup'] = group;
+ },
+
+ /**
+ * @return {string} validation group name.
+ */
+ getValidationGroup : function()
+ {
+ return this.ActiveControl['ValidationGroup'];
+ },
+
+ /**
+ * Dispatch the callback request.
+ */
+ dispatch : function()
+ {
+ //Logger.info("dispatching request");
+ //trigger tinyMCE to save data.
+ if(typeof tinyMCE != "undefined")
+ tinyMCE.triggerSave();
+
+ if(this.ActiveControl.CausesValidation && typeof(Prado.Validation) != "undefined")
+ {
+ var form = this.ActiveControl.Form || Prado.Validation.getForm();
+ if(Prado.Validation.validate(form,this.ActiveControl.ValidationGroup,this) == false)
+ return false;
+ }
+
+ if(this.ActiveControl.onPreDispatch)
+ this.ActiveControl.onPreDispatch(this,null);
+
+ if(!this.Enabled)
+ return;
+
+ // Opera don't have onLoading/onLoaded state, so, simulate them just
+ // before sending the request.
+ if (Prototype.Browser.Opera)
+ {
+ if (this.ActiveControl.onLoading)
+ {
+ this.ActiveControl.onLoading(this,null);
+ Ajax.Responders.dispatch('onLoading',this, this.transport,null);
+ }
+ if (this.ActiveControl.onLoaded)
+ {
+ this.ActiveControl.onLoaded(this,null);
+ Ajax.Responders.dispatch('onLoaded',this, this.transport,null);
+ }
+ }
+
+ var result;
+ if(this.ActiveControl.HasPriority)
+ {
+ return Prado.CallbackRequest.enqueue(this);
+ //return Prado.CallbackRequest.dispatchPriorityRequest(this);
+ }
+ else
+ return Prado.CallbackRequest.dispatchNormalRequest(this);
+ },
+
+ abort : function()
+ {
+ return Prado.CallbackRequest.abortRequest(this.id);
+ },
+
+ /**
+ * Collects the form inputs, encode the parameters, and sets the callback
+ * target id. The resulting string is the request content body.
+ * @return string request body content containing post data.
+ */
+ _getPostData : function()
+ {
+ var data = {};
+ var callback = Prado.CallbackRequest;
+ if(this.ActiveControl.PostInputs != false)
+ {
+ callback.PostDataLoaders.each(function(name)
+ {
+ var elements=$A(document.getElementsByName(name));
+ if(elements.size() == 0)
+ {
+ name += '[]';
+ elements=$A(document.getElementsByName(name));
+ }
+ elements.each(function(element)
+ {
+ //IE will try to get elements with ID == name as well.
+ if(element.type && element.name == name)
+ {
+ var value = $F(element);
+ if(typeof(value) != "undefined" && value != null)
+ data[name] = value;
+ }
+ })
+ })
+ }
+ if(typeof(this.ActiveControl.CallbackParameter) != "undefined")
+ data[callback.FIELD_CALLBACK_PARAMETER] = callback.encode(this.getCallbackParameter());
+ var pageState = $F(callback.FIELD_CALLBACK_PAGESTATE);
+ if(typeof(pageState) != "undefined")
+ data[callback.FIELD_CALLBACK_PAGESTATE] = pageState;
+ data[callback.FIELD_CALLBACK_TARGET] = this.id;
+ if(this.ActiveControl.EventTarget)
+ data[callback.FIELD_POSTBACK_TARGET] = this.ActiveControl.EventTarget;
+ if(this.ActiveControl.EventParameter)
+ data[callback.FIELD_POSTBACK_PARAMETER] = this.ActiveControl.EventParameter;
+ return $H(data).toQueryString();
+ },
+
+ /**
+ * Creates a random string with a length of 8 chars.
+ * @return string
+ */
+ randomString : function()
+ {
+ chars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";
+ randomString = "";
+ for(x=0;x<8;x++)
+ randomString += chars.charAt(Math.floor(Math.random() * 62));
+ return randomString
+ }
+});
+
+/**
+ * Create a new callback request using default settings.
+ * @param string callback handler unique ID.
+ * @param mixed parameter to pass to callback handler on the server side.
+ * @param function client side onSuccess event handler.
+ * @param object additional request options.
+ * @return boolean always false.
+ */
+Prado.Callback = function(UniqueID, parameter, onSuccess, options)
+{
+ var callback =
+ {
+ 'CallbackParameter' : parameter || '',
+ 'onSuccess' : onSuccess || Prototype.emptyFunction
+ };
+
+ Object.extend(callback, options || {});
+
+ var request = new Prado.CallbackRequest(UniqueID, callback);
+ request.dispatch();
+ return false;
+};
+
+
+
+/**
+ * Asset manager classes for lazy loading of scripts and stylesheets
+ * @author Gabor Berczi (gabor.berczi@devworx.hu)
+ */
+
+if (typeof(Prado.AssetManagerClass)=="undefined") {
+
+ Prado.AssetManagerClass = Class.create();
+ Prado.AssetManagerClass.prototype = {
+
+ initialize: function() {
+ this.loadedAssets = new Array();
+ this.discoverLoadedAssets();
+ },
+
+
+ /**
+ * Detect which assets are already loaded by page markup.
+ * This is done by looking up all <asset> elements and registering the values of their src attributes.
+ */
+ discoverLoadedAssets: function() {
+
+ // wait until document has finished loading to avoid javascript errors
+ if (!document.body) return;
+
+ var assets = this.findAssetUrlsInMarkup();
+ for(var i=0;i<assets.length;i++)
+ this.markAssetAsLoaded(assets[i]);
+ },
+
+ /**
+ * Extend url to a fully qualified url.
+ * @param string url
+ */
+ makeFullUrl: function(url) {
+
+ // this is not intended to be a fully blown url "canonicalizator",
+ // just to handle the most common and basic asset paths used by Prado
+
+ if (!this.baseUri) this.baseUri = window.location;
+
+ if (url.indexOf('://')==-1)
+ {
+ var a = document.createElement('a');
+ a.href = url;
+
+ if (a.href.indexOf('://')!=-1)
+ url = a.href;
+ else
+ {
+ var path = a.pathname;
+ if (path.substr(0,1)!='/') path = '/'+path;
+ url = this.baseUri.protocol+'//'+this.baseUri.host+path;
+ }
+ }
+ return url;
+ },
+
+ isAssetLoaded: function(url) {
+ url = this.makeFullUrl(url);
+ return (this.loadedAssets.indexOf(url)!=-1);
+ },
+
+ /**
+ * Mark asset as being already loaded
+ * @param string url of the asset
+ */
+ markAssetAsLoaded: function(url) {
+ url = this.makeFullUrl(url);
+ if (this.loadedAssets.indexOf(url)==-1)
+ this.loadedAssets.push(url);
+ },
+
+ assetReadyStateChanged: function(url, element, callback, finalevent) {
+ if (finalevent || (element.readyState == 'loaded') || (element.readyState == 'complete'))
+ if (!element.assetCallbackFired)
+ {
+ element.assetCallbackFired = true;
+ callback(url,element);
+ }
+ },
+
+ assetLoadFailed: function(url, element, callback) {
+ debugger;
+ element.assetCallbackFired = true;
+ if(typeof Logger != "undefined")
+ Logger.error("Failed to load asset: "+url, this);
+ if (!element.assetCallbackFired)
+ callback(url,element,false);
+ },
+
+ /**
+ * Load a new asset dynamically into the page.
+ * Please not thet loading is asynchronous and therefore you can't assume that
+ * the asset is loaded and ready when returning from this function.
+ * @param string url of the asset to load
+ * @param callback will be called when the asset has loaded (or failed to load)
+ */
+ startAssetLoad: function(url, callback) {
+
+ // create new <asset> element in page header
+ var asset = this.createAssetElement(url);
+
+ if (callback)
+ {
+ asset.onreadystatechange = this.assetReadyStateChanged.bind(this, url, asset, callback, false);
+ asset.onload = this.assetReadyStateChanged.bind(this, url, asset, callback, true);
+ asset.onerror = this.assetLoadFailed.bind(this, url, asset, callback);
+ asset.assetCallbackFired = false;
+ }
+
+ var head = document.getElementsByTagName('head')[0];
+ head.appendChild(asset);
+
+ // mark this asset as loaded
+ this.markAssetAsLoaded(url);
+
+ return (callback!=false);
+ },
+
+ /**
+ * Check whether a asset is loaded into the page, and if itsn't, load it now
+ * @param string url of the asset to check/load
+ * @return boolean returns true if asset is already loaded, or false, if loading has just started. callback will be called when loading has finished.
+ */
+ ensureAssetIsLoaded: function(url, callback) {
+ url = this.makeFullUrl(url);
+ if (this.loadedAssets.indexOf(url)==-1)
+ {
+ this.startAssetLoad(url,callback);
+ return false;
+ }
+ else
+ return true;
+ }
+
+ }
+
+};
+
+ Prado.ScriptManagerClass = Class.extend(Prado.AssetManagerClass, {
+
+ findAssetUrlsInMarkup: function() {
+ var urls = new Array();
+ var scripts = document.getElementsByTagName('script');
+ for(var i=0;i<scripts.length;i++)
+ {
+ var e = scripts[i]; var src = e.src;
+ if (src!="")
+ urls.push(src);
+ }
+ return urls;
+ },
+
+ createAssetElement: function(url) {
+ var asset = document.createElement('script');
+ asset.type = 'text/javascript';
+ asset.src = url;
+// asset.async = false; // HTML5 only
+ return asset;
+ }
+
+ });
+
+ Prado.StyleSheetManagerClass = Class.extend(Prado.AssetManagerClass, {
+
+ findAssetUrlsInMarkup: function() {
+ var urls = new Array();
+ var scripts = document.getElementsByTagName('link');
+ for(var i=0;i<scripts.length;i++)
+ {
+ var e = scripts[i]; var href = e.href;
+ if ((e.rel=="stylesheet") && (href.length>0))
+ urls.push(href);
+ }
+ return urls;
+ },
+
+ createAssetElement: function(url) {
+ var asset = document.createElement('link');
+ asset.rel = 'stylesheet';
+ asset.media = 'screen';
+ asset.setAttribute('type', 'text/css');
+ asset.href = url;
+// asset.async = false; // HTML5 only
+ return asset;
+ }
+
+ });
+
+ if (typeof(Prado.ScriptManager)=="undefined") Prado.ScriptManager = new Prado.ScriptManagerClass();
+ if (typeof(Prado.StyleSheetManager)=="undefined") Prado.StyleSheetManager = new Prado.StyleSheetManagerClass();
+
+ // make sure we scan for loaded scripts again when the page has been loaded
+ var discover = function() {
+ Prado.ScriptManager.discoverLoadedAssets();
+ Prado.StyleSheetManager.discoverLoadedAssets();
+ }
+ if (window.attachEvent) window.attachEvent('onload', discover);
+ else if (window.addEventListener) window.addEventListener('load', discover, false);
+
diff --git a/framework/Web/Javascripts/source/prado/activecontrols/dragdrop.js b/framework/Web/Javascripts/source/prado/activecontrols/dragdrop.js
index 59c62cc2..511c2ab9 100755
--- a/framework/Web/Javascripts/source/prado/activecontrols/dragdrop.js
+++ b/framework/Web/Javascripts/source/prado/activecontrols/dragdrop.js
@@ -1,61 +1,61 @@
-/**
- * DropContainer control
- */
-
-Prado.WebUI.DropContainer = Class.create(Prado.WebUI.CallbackControl,
-{
- onInit: function(options)
- {
- this.options = options;
- Object.extend (this.options,
- {
- onDrop: this.onDrop.bind(this)
- });
-
- Droppables.add (options.ID, this.options);
- },
-
- onDrop: function(dragElement, dropElement, event)
- {
- var elementId=dragElement.id.replace(/clone_/,"");
- var req = new Prado.CallbackRequest(this.options.EventTarget, this.options);
- var curleft = curtop = 0;
- var obj = dropElement;
- if (obj.offsetParent) {
- curleft = obj.offsetLeft
- curtop = obj.offsetTop
- while (obj = obj.offsetParent) {
- curleft += obj.offsetLeft
- curtop += obj.offsetTop
- }
- }
- var scrOfX = 0, scrOfY = 0;
- if( typeof( window.pageYOffset ) == 'number' ) {
- //Netscape compliant
- scrOfY = window.pageYOffset;
- scrOfX = window.pageXOffset;
- } else if( document.body && ( document.body.scrollLeft || document.body.scrollTop ) ) {
- //DOM compliant
- scrOfY = document.body.scrollTop;
- scrOfX = document.body.scrollLeft;
- } else if( document.documentElement && ( document.documentElement.scrollLeft || document.documentElement.scrollTop ) ) {
- //IE6 standards compliant mode
- scrOfY = document.documentElement.scrollTop;
- scrOfX = document.documentElement.scrollLeft;
- }
- req.setCallbackParameter({
- DragElementID : elementId,
- ScreenX : event.screenX,
- ScreenY : event.screenY,
- OffsetX : event.offsetX || event.clientX - curleft + scrOfX,
- OffsetY : event.offsetY || event.clientY - curtop + scrOfY,
- ClientX : event.clientX,
- ClientY : event.clientY,
- AltKey : event.altKey,
- CtrlKey : event.ctrlKey,
- ShiftKey : event.shiftKey
- });
- req.dispatch();
-
- }
-});
+/**
+ * DropContainer control
+ */
+
+Prado.WebUI.DropContainer = Class.create(Prado.WebUI.CallbackControl,
+{
+ onInit: function(options)
+ {
+ this.options = options;
+ Object.extend (this.options,
+ {
+ onDrop: this.onDrop.bind(this)
+ });
+
+ Droppables.add (options.ID, this.options);
+ },
+
+ onDrop: function(dragElement, dropElement, event)
+ {
+ var elementId=dragElement.id.replace(/clone_/,"");
+ var req = new Prado.CallbackRequest(this.options.EventTarget, this.options);
+ var curleft = curtop = 0;
+ var obj = dropElement;
+ if (obj.offsetParent) {
+ curleft = obj.offsetLeft
+ curtop = obj.offsetTop
+ while (obj = obj.offsetParent) {
+ curleft += obj.offsetLeft
+ curtop += obj.offsetTop
+ }
+ }
+ var scrOfX = 0, scrOfY = 0;
+ if( typeof( window.pageYOffset ) == 'number' ) {
+ //Netscape compliant
+ scrOfY = window.pageYOffset;
+ scrOfX = window.pageXOffset;
+ } else if( document.body && ( document.body.scrollLeft || document.body.scrollTop ) ) {
+ //DOM compliant
+ scrOfY = document.body.scrollTop;
+ scrOfX = document.body.scrollLeft;
+ } else if( document.documentElement && ( document.documentElement.scrollLeft || document.documentElement.scrollTop ) ) {
+ //IE6 standards compliant mode
+ scrOfY = document.documentElement.scrollTop;
+ scrOfX = document.documentElement.scrollLeft;
+ }
+ req.setCallbackParameter({
+ DragElementID : elementId,
+ ScreenX : event.screenX,
+ ScreenY : event.screenY,
+ OffsetX : event.offsetX || event.clientX - curleft + scrOfX,
+ OffsetY : event.offsetY || event.clientY - curtop + scrOfY,
+ ClientX : event.clientX,
+ ClientY : event.clientY,
+ AltKey : event.altKey,
+ CtrlKey : event.ctrlKey,
+ ShiftKey : event.shiftKey
+ });
+ req.dispatch();
+
+ }
+});
diff --git a/framework/Web/Javascripts/source/prado/activecontrols/inlineeditor.js b/framework/Web/Javascripts/source/prado/activecontrols/inlineeditor.js
index a53ac8fd..0260c219 100644
--- a/framework/Web/Javascripts/source/prado/activecontrols/inlineeditor.js
+++ b/framework/Web/Javascripts/source/prado/activecontrols/inlineeditor.js
@@ -1,302 +1,302 @@
-Prado.WebUI.TInPlaceTextBox = Class.create(Prado.WebUI.Control,
-{
- onInit : function(options)
- {
-
- this.isSaving = false;
- this.isEditing = false;
- this.editField = null;
- this.readOnly = options.ReadOnly;
-
- this.options = Object.extend(
- {
- LoadTextFromSource : false,
- TextMode : 'SingleLine'
-
- }, options || {});
- this.element = $(this.options.ID);
- Prado.WebUI.TInPlaceTextBox.register(this);
- this.createEditorInput();
- this.initializeListeners();
- },
-
- /**
- * Initialize the listeners.
- */
- initializeListeners : function()
- {
- this.onclickListener = this.enterEditMode.bindAsEventListener(this);
- this.observe(this.element, 'click', this.onclickListener);
- if (this.options.ExternalControl)
- this.observe($(this.options.ExternalControl), 'click', this.onclickListener);
- },
-
- /**
- * Changes the panel to an editable input.
- * @param {Event} evt event source
- */
- enterEditMode : function(evt)
- {
- if (this.isSaving || this.isEditing || this.readOnly) return;
- this.isEditing = true;
- this.onEnterEditMode();
- this.createEditorInput();
- this.showTextBox();
- this.editField.disabled = false;
- if(this.options.LoadTextOnEdit)
- this.loadExternalText();
- Prado.Element.focus(this.editField);
- if (evt)
- Event.stop(evt);
- return false;
- },
-
- exitEditMode : function(evt)
- {
- this.isEditing = false;
- this.isSaving = false;
- this.editField.disabled = false;
- this.element.innerHTML = this.editField.value;
- this.showLabel();
- },
-
- showTextBox : function()
- {
- Element.hide(this.element);
- Element.show(this.editField);
- },
-
- showLabel : function()
- {
- Element.show(this.element);
- Element.hide(this.editField);
- },
-
- /**
- * Create the edit input field.
- */
- createEditorInput : function()
- {
- if(this.editField == null)
- this.createTextBox();
-
- this.editField.value = this.getText();
- },
-
- loadExternalText : function()
- {
- this.editField.disabled = true;
- this.onLoadingText();
- var options = new Array('__InlineEditor_loadExternalText__', this.getText());
- var request = new Prado.CallbackRequest(this.options.EventTarget, this.options);
- request.setCausesValidation(false);
- request.setCallbackParameter(options);
- request.ActiveControl.onSuccess = this.onloadExternalTextSuccess.bind(this);
- request.ActiveControl.onFailure = this.onloadExternalTextFailure.bind(this);
- request.dispatch();
- },
-
- /**
- * Create a new input textbox or textarea
- */
- createTextBox : function()
- {
- var cssClass= this.element.className || '';
- var inputName = this.options.EventTarget;
- var options = {'className' : cssClass, name : inputName, id : this.options.TextBoxID};
- if(this.options.TextMode == 'SingleLine')
- {
- if(this.options.MaxLength > 0)
- options['maxlength'] = this.options.MaxLength;
- if(this.options.Columns > 0)
- options['size'] = this.options.Columns;
- this.editField = INPUT(options);
- }
- else
- {
- if(this.options.Rows > 0)
- options['rows'] = this.options.Rows;
- if(this.options.Columns > 0)
- options['cols'] = this.options.Columns;
- if(this.options.Wrap)
- options['wrap'] = 'off';
- this.editField = TEXTAREA(options);
- }
-
- this.editField.style.display="none";
- this.element.parentNode.insertBefore(this.editField,this.element)
-
- //handle return key within single line textbox
- if(this.options.TextMode == 'SingleLine')
- {
- this.observe(this.editField, "keydown", function(e)
- {
- if(Event.keyCode(e) == Event.KEY_RETURN)
- {
- var target = Event.element(e);
- if(target)
- {
- Event.fireEvent(target, "blur");
- Event.stop(e);
- }
- }
- });
- }
-
- this.observe(this.editField, "blur", this.onTextBoxBlur.bind(this));
- this.observe(this.editField, "keypress", this.onKeyPressed.bind(this));
- },
-
- /**
- * @return {String} panel inner html text.
- */
- getText: function()
- {
- return this.element.innerHTML;
- },
-
- /**
- * Edit mode entered, calls optional event handlers.
- */
- onEnterEditMode : function()
- {
- if(typeof(this.options.onEnterEditMode) == "function")
- this.options.onEnterEditMode(this,null);
- },
-
- onTextBoxBlur : function(e)
- {
- var text = this.element.innerHTML;
- if(this.options.AutoPostBack && text != this.editField.value)
- {
- if(this.isEditing)
- this.onTextChanged(text);
- }
- else
- {
- this.element.innerHTML = this.editField.value;
- this.isEditing = false;
- if(this.options.AutoHide)
- this.showLabel();
- }
- },
-
- onKeyPressed : function(e)
- {
- if (Event.keyCode(e) == Event.KEY_ESC)
- {
- this.editField.value = this.getText();
- this.isEditing = false;
- if(this.options.AutoHide)
- this.showLabel();
- }
- else if (Event.keyCode(e) == Event.KEY_RETURN && this.options.TextMode != 'MultiLine')
- Event.stop(e);
- },
-
- /**
- * When the text input value has changed.
- * @param {String} original text
- */
- onTextChanged : function(text)
- {
- var request = new Prado.CallbackRequest(this.options.EventTarget, this.options);
- request.setCallbackParameter(text);
- request.ActiveControl.onSuccess = this.onTextChangedSuccess.bind(this);
- request.ActiveControl.onFailure = this.onTextChangedFailure.bind(this);
- if(request.dispatch())
- {
- this.isSaving = true;
- this.editField.disabled = true;
- }
- },
-
- /**
- * When loading external text.
- */
- onLoadingText : function()
- {
- //Logger.info("on loading text");
- },
-
- onloadExternalTextSuccess : function(request, parameter)
- {
- this.isEditing = true;
- this.editField.disabled = false;
- this.editField.value = this.getText();
- Prado.Element.focus(this.editField);
- if(typeof(this.options.onSuccess)=="function")
- this.options.onSuccess(sender,parameter);
- },
-
- onloadExternalTextFailure : function(request, parameter)
- {
- this.isSaving = false;
- this.isEditing = false;
- this.showLabel();
- if(typeof(this.options.onFailure)=="function")
- this.options.onFailure(sender,parameter);
- },
-
- /**
- * Text change successfully.
- * @param {Object} sender
- * @param {Object} parameter
- */
- onTextChangedSuccess : function(sender, parameter)
- {
- this.isSaving = false;
- this.isEditing = false;
- if(this.options.AutoHide)
- this.showLabel();
- this.element.innerHTML = parameter == null ? this.editField.value : parameter;
- this.editField.disabled = false;
- if(typeof(this.options.onSuccess)=="function")
- this.options.onSuccess(sender,parameter);
- },
-
- onTextChangedFailure : function(sender, parameter)
- {
- this.editField.disabled = false;
- this.isSaving = false;
- this.isEditing = false;
- if(typeof(this.options.onFailure)=="function")
- this.options.onFailure(sender,parameter);
- }
-});
-
-
-Object.extend(Prado.WebUI.TInPlaceTextBox,
-{
- //class methods
-
- textboxes : {},
-
- register : function(obj)
- {
- Prado.WebUI.TInPlaceTextBox.textboxes[obj.options.TextBoxID] = obj;
- },
-
- setDisplayTextBox : function(id,value)
- {
- var textbox = Prado.WebUI.TInPlaceTextBox.textboxes[id];
- if(textbox)
- {
- if(value)
- textbox.enterEditMode(null);
- else
- {
- textbox.exitEditMode(null);
- }
- }
- },
-
- setReadOnly : function(id, value)
- {
- var textbox = Prado.WebUI.TInPlaceTextBox.textboxes[id];
- if (textbox)
- {
- textbox.readOnly=value;
- }
- }
+Prado.WebUI.TInPlaceTextBox = Class.create(Prado.WebUI.Control,
+{
+ onInit : function(options)
+ {
+
+ this.isSaving = false;
+ this.isEditing = false;
+ this.editField = null;
+ this.readOnly = options.ReadOnly;
+
+ this.options = Object.extend(
+ {
+ LoadTextFromSource : false,
+ TextMode : 'SingleLine'
+
+ }, options || {});
+ this.element = $(this.options.ID);
+ Prado.WebUI.TInPlaceTextBox.register(this);
+ this.createEditorInput();
+ this.initializeListeners();
+ },
+
+ /**
+ * Initialize the listeners.
+ */
+ initializeListeners : function()
+ {
+ this.onclickListener = this.enterEditMode.bindAsEventListener(this);
+ this.observe(this.element, 'click', this.onclickListener);
+ if (this.options.ExternalControl)
+ this.observe($(this.options.ExternalControl), 'click', this.onclickListener);
+ },
+
+ /**
+ * Changes the panel to an editable input.
+ * @param {Event} evt event source
+ */
+ enterEditMode : function(evt)
+ {
+ if (this.isSaving || this.isEditing || this.readOnly) return;
+ this.isEditing = true;
+ this.onEnterEditMode();
+ this.createEditorInput();
+ this.showTextBox();
+ this.editField.disabled = false;
+ if(this.options.LoadTextOnEdit)
+ this.loadExternalText();
+ Prado.Element.focus(this.editField);
+ if (evt)
+ Event.stop(evt);
+ return false;
+ },
+
+ exitEditMode : function(evt)
+ {
+ this.isEditing = false;
+ this.isSaving = false;
+ this.editField.disabled = false;
+ this.element.innerHTML = this.editField.value;
+ this.showLabel();
+ },
+
+ showTextBox : function()
+ {
+ Element.hide(this.element);
+ Element.show(this.editField);
+ },
+
+ showLabel : function()
+ {
+ Element.show(this.element);
+ Element.hide(this.editField);
+ },
+
+ /**
+ * Create the edit input field.
+ */
+ createEditorInput : function()
+ {
+ if(this.editField == null)
+ this.createTextBox();
+
+ this.editField.value = this.getText();
+ },
+
+ loadExternalText : function()
+ {
+ this.editField.disabled = true;
+ this.onLoadingText();
+ var options = new Array('__InlineEditor_loadExternalText__', this.getText());
+ var request = new Prado.CallbackRequest(this.options.EventTarget, this.options);
+ request.setCausesValidation(false);
+ request.setCallbackParameter(options);
+ request.ActiveControl.onSuccess = this.onloadExternalTextSuccess.bind(this);
+ request.ActiveControl.onFailure = this.onloadExternalTextFailure.bind(this);
+ request.dispatch();
+ },
+
+ /**
+ * Create a new input textbox or textarea
+ */
+ createTextBox : function()
+ {
+ var cssClass= this.element.className || '';
+ var inputName = this.options.EventTarget;
+ var options = {'className' : cssClass, name : inputName, id : this.options.TextBoxID};
+ if(this.options.TextMode == 'SingleLine')
+ {
+ if(this.options.MaxLength > 0)
+ options['maxlength'] = this.options.MaxLength;
+ if(this.options.Columns > 0)
+ options['size'] = this.options.Columns;
+ this.editField = INPUT(options);
+ }
+ else
+ {
+ if(this.options.Rows > 0)
+ options['rows'] = this.options.Rows;
+ if(this.options.Columns > 0)
+ options['cols'] = this.options.Columns;
+ if(this.options.Wrap)
+ options['wrap'] = 'off';
+ this.editField = TEXTAREA(options);
+ }
+
+ this.editField.style.display="none";
+ this.element.parentNode.insertBefore(this.editField,this.element)
+
+ //handle return key within single line textbox
+ if(this.options.TextMode == 'SingleLine')
+ {
+ this.observe(this.editField, "keydown", function(e)
+ {
+ if(Event.keyCode(e) == Event.KEY_RETURN)
+ {
+ var target = Event.element(e);
+ if(target)
+ {
+ Event.fireEvent(target, "blur");
+ Event.stop(e);
+ }
+ }
+ });
+ }
+
+ this.observe(this.editField, "blur", this.onTextBoxBlur.bind(this));
+ this.observe(this.editField, "keypress", this.onKeyPressed.bind(this));
+ },
+
+ /**
+ * @return {String} panel inner html text.
+ */
+ getText: function()
+ {
+ return this.element.innerHTML;
+ },
+
+ /**
+ * Edit mode entered, calls optional event handlers.
+ */
+ onEnterEditMode : function()
+ {
+ if(typeof(this.options.onEnterEditMode) == "function")
+ this.options.onEnterEditMode(this,null);
+ },
+
+ onTextBoxBlur : function(e)
+ {
+ var text = this.element.innerHTML;
+ if(this.options.AutoPostBack && text != this.editField.value)
+ {
+ if(this.isEditing)
+ this.onTextChanged(text);
+ }
+ else
+ {
+ this.element.innerHTML = this.editField.value;
+ this.isEditing = false;
+ if(this.options.AutoHide)
+ this.showLabel();
+ }
+ },
+
+ onKeyPressed : function(e)
+ {
+ if (Event.keyCode(e) == Event.KEY_ESC)
+ {
+ this.editField.value = this.getText();
+ this.isEditing = false;
+ if(this.options.AutoHide)
+ this.showLabel();
+ }
+ else if (Event.keyCode(e) == Event.KEY_RETURN && this.options.TextMode != 'MultiLine')
+ Event.stop(e);
+ },
+
+ /**
+ * When the text input value has changed.
+ * @param {String} original text
+ */
+ onTextChanged : function(text)
+ {
+ var request = new Prado.CallbackRequest(this.options.EventTarget, this.options);
+ request.setCallbackParameter(text);
+ request.ActiveControl.onSuccess = this.onTextChangedSuccess.bind(this);
+ request.ActiveControl.onFailure = this.onTextChangedFailure.bind(this);
+ if(request.dispatch())
+ {
+ this.isSaving = true;
+ this.editField.disabled = true;
+ }
+ },
+
+ /**
+ * When loading external text.
+ */
+ onLoadingText : function()
+ {
+ //Logger.info("on loading text");
+ },
+
+ onloadExternalTextSuccess : function(request, parameter)
+ {
+ this.isEditing = true;
+ this.editField.disabled = false;
+ this.editField.value = this.getText();
+ Prado.Element.focus(this.editField);
+ if(typeof(this.options.onSuccess)=="function")
+ this.options.onSuccess(sender,parameter);
+ },
+
+ onloadExternalTextFailure : function(request, parameter)
+ {
+ this.isSaving = false;
+ this.isEditing = false;
+ this.showLabel();
+ if(typeof(this.options.onFailure)=="function")
+ this.options.onFailure(sender,parameter);
+ },
+
+ /**
+ * Text change successfully.
+ * @param {Object} sender
+ * @param {Object} parameter
+ */
+ onTextChangedSuccess : function(sender, parameter)
+ {
+ this.isSaving = false;
+ this.isEditing = false;
+ if(this.options.AutoHide)
+ this.showLabel();
+ this.element.innerHTML = parameter == null ? this.editField.value : parameter;
+ this.editField.disabled = false;
+ if(typeof(this.options.onSuccess)=="function")
+ this.options.onSuccess(sender,parameter);
+ },
+
+ onTextChangedFailure : function(sender, parameter)
+ {
+ this.editField.disabled = false;
+ this.isSaving = false;
+ this.isEditing = false;
+ if(typeof(this.options.onFailure)=="function")
+ this.options.onFailure(sender,parameter);
+ }
+});
+
+
+Object.extend(Prado.WebUI.TInPlaceTextBox,
+{
+ //class methods
+
+ textboxes : {},
+
+ register : function(obj)
+ {
+ Prado.WebUI.TInPlaceTextBox.textboxes[obj.options.TextBoxID] = obj;
+ },
+
+ setDisplayTextBox : function(id,value)
+ {
+ var textbox = Prado.WebUI.TInPlaceTextBox.textboxes[id];
+ if(textbox)
+ {
+ if(value)
+ textbox.enterEditMode(null);
+ else
+ {
+ textbox.exitEditMode(null);
+ }
+ }
+ },
+
+ setReadOnly : function(id, value)
+ {
+ var textbox = Prado.WebUI.TInPlaceTextBox.textboxes[id];
+ if (textbox)
+ {
+ textbox.readOnly=value;
+ }
+ }
}); \ No newline at end of file
diff --git a/framework/Web/Javascripts/source/prado/colorpicker/colorpicker.js b/framework/Web/Javascripts/source/prado/colorpicker/colorpicker.js
index 164295cd..142745cf 100644
--- a/framework/Web/Javascripts/source/prado/colorpicker/colorpicker.js
+++ b/framework/Web/Javascripts/source/prado/colorpicker/colorpicker.js
@@ -1,780 +1,780 @@
-//-------------------- ricoColor.js
-if(typeof(Rico) == "undefined") Rico = {};
-
-Rico.Color = Class.create();
-
-Rico.Color.prototype = {
-
- initialize: function(red, green, blue) {
- this.rgb = { r: red, g : green, b : blue };
- },
-
- setRed: function(r) {
- this.rgb.r = r;
- },
-
- setGreen: function(g) {
- this.rgb.g = g;
- },
-
- setBlue: function(b) {
- this.rgb.b = b;
- },
-
- setHue: function(h) {
-
- // get an HSB model, and set the new hue...
- var hsb = this.asHSB();
- hsb.h = h;
-
- // convert back to RGB...
- this.rgb = Rico.Color.HSBtoRGB(hsb.h, hsb.s, hsb.b);
- },
-
- setSaturation: function(s) {
- // get an HSB model, and set the new hue...
- var hsb = this.asHSB();
- hsb.s = s;
-
- // convert back to RGB and set values...
- this.rgb = Rico.Color.HSBtoRGB(hsb.h, hsb.s, hsb.b);
- },
-
- setBrightness: function(b) {
- // get an HSB model, and set the new hue...
- var hsb = this.asHSB();
- hsb.b = b;
-
- // convert back to RGB and set values...
- this.rgb = Rico.Color.HSBtoRGB( hsb.h, hsb.s, hsb.b );
- },
-
- darken: function(percent) {
- var hsb = this.asHSB();
- this.rgb = Rico.Color.HSBtoRGB(hsb.h, hsb.s, Math.max(hsb.b - percent,0));
- },
-
- brighten: function(percent) {
- var hsb = this.asHSB();
- this.rgb = Rico.Color.HSBtoRGB(hsb.h, hsb.s, Math.min(hsb.b + percent,1));
- },
-
- blend: function(other) {
- this.rgb.r = Math.floor((this.rgb.r + other.rgb.r)/2);
- this.rgb.g = Math.floor((this.rgb.g + other.rgb.g)/2);
- this.rgb.b = Math.floor((this.rgb.b + other.rgb.b)/2);
- },
-
- isBright: function() {
- var hsb = this.asHSB();
- return this.asHSB().b > 0.5;
- },
-
- isDark: function() {
- return ! this.isBright();
- },
-
- asRGB: function() {
- return "rgb(" + this.rgb.r + "," + this.rgb.g + "," + this.rgb.b + ")";
- },
-
- asHex: function() {
- return "#" + this.rgb.r.toColorPart() + this.rgb.g.toColorPart() + this.rgb.b.toColorPart();
- },
-
- asHSB: function() {
- return Rico.Color.RGBtoHSB(this.rgb.r, this.rgb.g, this.rgb.b);
- },
-
- toString: function() {
- return this.asHex();
- }
-
-};
-
-Rico.Color.createFromHex = function(hexCode) {
-
- if ( hexCode.indexOf('#') == 0 )
- hexCode = hexCode.substring(1);
-
- var red = "ff", green = "ff", blue="ff";
- if(hexCode.length > 4)
- {
- red = hexCode.substring(0,2);
- green = hexCode.substring(2,4);
- blue = hexCode.substring(4,6);
- }
- else if(hexCode.length > 0 & hexCode.length < 4)
- {
- var r = hexCode.substring(0,1);
- var g = hexCode.substring(1,2);
- var b = hexCode.substring(2);
- red = r+r;
- green = g+g;
- blue = b+b;
- }
- return new Rico.Color( parseInt(red,16), parseInt(green,16), parseInt(blue,16) );
-};
-
-/**
- * Factory method for creating a color from the background of
- * an HTML element.
- */
-Rico.Color.createColorFromBackground = function(elem) {
-
- var actualColor = Element.getStyle($(elem), "background-color");
- if ( actualColor == "transparent" && elem.parent )
- return Rico.Color.createColorFromBackground(elem.parent);
-
- if ( actualColor == null )
- return new Rico.Color(255,255,255);
-
- if ( actualColor.indexOf("rgb(") == 0 ) {
- var colors = actualColor.substring(4, actualColor.length - 1 );
- var colorArray = colors.split(",");
- return new Rico.Color( parseInt( colorArray[0] ),
- parseInt( colorArray[1] ),
- parseInt( colorArray[2] ) );
-
- }
- else if ( actualColor.indexOf("#") == 0 ) {
- return Rico.Color.createFromHex(actualColor);
- }
- else
- return new Rico.Color(255,255,255);
-};
-
-Rico.Color.HSBtoRGB = function(hue, saturation, brightness) {
-
- var red = 0;
- var green = 0;
- var blue = 0;
-
- if (saturation == 0) {
- red = parseInt(brightness * 255.0 + 0.5);
- green = red;
- blue = red;
- }
- else {
- var h = (hue - Math.floor(hue)) * 6.0;
- var f = h - Math.floor(h);
- var p = brightness * (1.0 - saturation);
- var q = brightness * (1.0 - saturation * f);
- var t = brightness * (1.0 - (saturation * (1.0 - f)));
-
- switch (parseInt(h)) {
- case 0:
- red = (brightness * 255.0 + 0.5);
- green = (t * 255.0 + 0.5);
- blue = (p * 255.0 + 0.5);
- break;
- case 1:
- red = (q * 255.0 + 0.5);
- green = (brightness * 255.0 + 0.5);
- blue = (p * 255.0 + 0.5);
- break;
- case 2:
- red = (p * 255.0 + 0.5);
- green = (brightness * 255.0 + 0.5);
- blue = (t * 255.0 + 0.5);
- break;
- case 3:
- red = (p * 255.0 + 0.5);
- green = (q * 255.0 + 0.5);
- blue = (brightness * 255.0 + 0.5);
- break;
- case 4:
- red = (t * 255.0 + 0.5);
- green = (p * 255.0 + 0.5);
- blue = (brightness * 255.0 + 0.5);
- break;
- case 5:
- red = (brightness * 255.0 + 0.5);
- green = (p * 255.0 + 0.5);
- blue = (q * 255.0 + 0.5);
- break;
- }
- }
-
- return { r : parseInt(red), g : parseInt(green) , b : parseInt(blue) };
-};
-
-Rico.Color.RGBtoHSB = function(r, g, b) {
-
- var hue;
- var saturation;
- var brightness;
-
- var cmax = (r > g) ? r : g;
- if (b > cmax)
- cmax = b;
-
- var cmin = (r < g) ? r : g;
- if (b < cmin)
- cmin = b;
-
- brightness = cmax / 255.0;
- if (cmax != 0)
- saturation = (cmax - cmin)/cmax;
- else
- saturation = 0;
-
- if (saturation == 0)
- hue = 0;
- else {
- var redc = (cmax - r)/(cmax - cmin);
- var greenc = (cmax - g)/(cmax - cmin);
- var bluec = (cmax - b)/(cmax - cmin);
-
- if (r == cmax)
- hue = bluec - greenc;
- else if (g == cmax)
- hue = 2.0 + redc - bluec;
- else
- hue = 4.0 + greenc - redc;
-
- hue = hue / 6.0;
- if (hue < 0)
- hue = hue + 1.0;
- }
-
- return { h : hue, s : saturation, b : brightness };
-};
-
-
-Prado.WebUI.TColorPicker = Class.create();
-
-Object.extend(Prado.WebUI.TColorPicker,
-{
- palettes:
- {
- Small : [["fff", "fcc", "fc9", "ff9", "ffc", "9f9", "9ff", "cff", "ccf", "fcf"],
- ["ccc", "f66", "f96", "ff6", "ff3", "6f9", "3ff", "6ff", "99f", "f9f"],
- ["c0c0c0", "f00", "f90", "fc6", "ff0", "3f3", "6cc", "3cf", "66c", "c6c"],
- ["999", "c00", "f60", "fc3", "fc0", "3c0", "0cc", "36f", "63f", "c3c"],
- ["666", "900", "c60", "c93", "990", "090", "399", "33f", "60c", "939"],
- ["333", "600", "930", "963", "660", "060", "366", "009", "339", "636"],
- ["000", "300", "630", "633", "330", "030", "033", "006", "309", "303"]],
-
- Tiny : [["ffffff"/*white*/, "00ff00"/*lime*/, "008000"/*green*/, "0000ff"/*blue*/],
- ["c0c0c0"/*silver*/, "ffff00"/*yellow*/, "ff00ff"/*fuchsia*/, "000080"/*navy*/],
- ["808080"/*gray*/, "ff0000"/*red*/, "800080"/*purple*/, "000000"/*black*/]]
- },
-
- UIImages :
- {
- 'button.gif' : 'button.gif',
-// 'target_black.gif' : 'target_black.gif',
-// 'target_white.gif' : 'target_white.gif',
- 'background.png' : 'background.png'
-// 'slider.gif' : 'slider.gif',
-// 'hue.gif' : 'hue.gif'
- }
-});
-
-Object.extend(Prado.WebUI.TColorPicker.prototype,
-{
- initialize : function(options)
- {
- var basics =
- {
- Palette : 'Small',
- ClassName : 'TColorPicker',
- Mode : 'Basic',
- OKButtonText : 'OK',
- CancelButtonText : 'Cancel',
- ShowColorPicker : true
- }
-
- this.element = null;
- this.showing = false;
-
- options = Object.extend(basics, options);
- this.options = options;
- this.input = $(options['ID']);
- this.button = $(options['ID']+'_button');
- this._buttonOnClick = this.buttonOnClick.bind(this);
- if(options['ShowColorPicker'])
- Event.observe(this.button, "click", this._buttonOnClick);
- Event.observe(this.input, "change", this.updatePicker.bind(this));
-
- Prado.Registry.set(options.ID, this);
- },
-
- updatePicker : function(e)
- {
- var color = Rico.Color.createFromHex(this.input.value);
- this.button.style.backgroundColor = color.toString();
- },
-
- buttonOnClick : function(event)
- {
- var mode = this.options['Mode'];
- if(this.element == null)
- {
- var constructor = mode == "Basic" ? "getBasicPickerContainer": "getFullPickerContainer"
- this.element = this[constructor](this.options['ID'], this.options['Palette'])
- this.input.parentNode.appendChild(this.element);
- this.element.style.display = "none";
-
- if(Prado.Browser().ie)
- {
- 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);
- }
- if(mode == "Full")
- this.initializeFullPicker();
- }
- this.show(mode);
- },
-
- show : function(type)
- {
- if(!this.showing)
- {
- var pos = this.input.positionedOffset();
- pos[1] += this.input.offsetHeight;
-
- this.element.style.top = (pos[1]-1) + "px";
- this.element.style.left = pos[0] + "px";
- this.element.style.display = "block";
-
- this.ieHack(type);
-
- //observe for clicks on the document body
- this._documentClickEvent = this.hideOnClick.bindEvent(this, type);
- this._documentKeyDownEvent = this.keyPressed.bindEvent(this, type);
- Event.observe(document.body, "click", this._documentClickEvent);
- Event.observe(document,"keydown", this._documentKeyDownEvent);
- this.showing = true;
-
- if(type == "Full")
- {
- this.observeMouseMovement();
- var color = Rico.Color.createFromHex(this.input.value);
- this.inputs.oldColor.style.backgroundColor = color.asHex();
- this.setColor(color,true);
- }
- }
- },
-
- hide : function(event)
- {
- if(this.showing)
- {
- if(this.iePopUp)
- this.iePopUp.style.display = "none";
-
- this.element.style.display = "none";
- this.showing = false;
- Event.stopObserving(document.body, "click", this._documentClickEvent);
- Event.stopObserving(document,"keydown", this._documentKeyDownEvent);
-
- if(this._observingMouseMove)
- {
- Event.stopObserving(document.body, "mousemove", this._onMouseMove);
- this._observingMouseMove = false;
- }
- }
- },
-
- keyPressed : function(event,type)
- {
- if(Event.keyCode(event) == Event.KEY_ESC)
- this.hide(event,type);
- },
-
- hideOnClick : function(ev)
- {
- if(!this.showing) return;
- var el = Event.element(ev);
- var within = false;
- do
- { within = within || String(el.className).indexOf('FullColorPicker') > -1
- within = within || el == this.button;
- within = within || el == this.input;
- if(within) break;
- el = el.parentNode;
- }
- while(el);
- if(!within) this.hide(ev);
- },
-
- ieHack : function()
- {
- // IE hack
- if(this.iePopUp)
- {
- this.iePopUp.style.display = "block";
- this.iePopUp.style.top = (this.element.offsetTop) + "px";
- this.iePopUp.style.left = (this.element.offsetLeft)+ "px";
- this.iePopUp.style.width = Math.abs(this.element.offsetWidth)+ "px";
- this.iePopUp.style.height = (this.element.offsetHeight + 1)+ "px";
- }
- },
-
- getBasicPickerContainer : function(pickerID, palette)
- {
- var table = TABLE({className:'basic_colors palette_'+palette},TBODY());
- var colors = Prado.WebUI.TColorPicker.palettes[palette];
- var pickerOnClick = this.cellOnClick.bind(this);
- colors.each(function(color)
- {
- var row = document.createElement("tr");
- color.each(function(c)
- {
- var td = document.createElement("td");
- var img = IMG({src:Prado.WebUI.TColorPicker.UIImages['button.gif'],width:16,height:16});
- img.style.backgroundColor = "#"+c;
- Event.observe(img,"click", pickerOnClick);
- Event.observe(img,"mouseover", function(e)
- {
- Element.addClassName(Event.element(e), "pickerhover");
- });
- Event.observe(img,"mouseout", function(e)
- {
- Element.removeClassName(Event.element(e), "pickerhover");
- });
- td.appendChild(img);
- row.appendChild(td);
- });
- table.childNodes[0].appendChild(row);
- });
- return DIV({className:this.options['ClassName']+" BasicColorPicker",
- id:pickerID+"_picker"}, table);
- },
-
- cellOnClick : function(e)
- {
- var el = Event.element(e);
- if(el.tagName.toLowerCase() != "img")
- return;
- var color = Rico.Color.createColorFromBackground(el);
- this.updateColor(color);
- },
-
- updateColor : function(color)
- {
- this.input.value = color.toString().toUpperCase();
- this.button.style.backgroundColor = color.toString();
- if(typeof(this.onChange) == "function")
- this.onChange(color);
- if(this.options.OnColorSelected)
- this.options.OnColorSelected(this,color);
- },
-
- getFullPickerContainer : function(pickerID)
- {
- //create the 3 buttons
- this.buttons =
- {
- //Less : INPUT({value:'Less Colors', className:'button', type:'button'}),
- OK : INPUT({value:this.options.OKButtonText, className:'button', type:'button'}),
- Cancel : INPUT({value:this.options.CancelButtonText, className:'button', type:'button'})
- };
-
- //create the 6 inputs
- var inputs = {};
- ['H','S','V','R','G','B'].each(function(type)
- {
- inputs[type] = INPUT({type:'text',size:'3',maxlength:'3'});
- });
-
- //create the HEX input
- inputs['HEX'] = INPUT({className:'hex',type:'text',size:'6',maxlength:'6'});
- this.inputs = inputs;
-
- var images = Prado.WebUI.TColorPicker.UIImages;
-
- this.inputs['currentColor'] = SPAN({className:'currentColor'});
- this.inputs['oldColor'] = SPAN({className:'oldColor'});
-
- var inputsTable =
- TABLE({className:'inputs'}, TBODY(null,
- TR(null,
- TD({className:'currentcolor',colSpan:2},
- this.inputs['currentColor'], this.inputs['oldColor'])),
-
- TR(null,
- TD(null,'H:'),
- TD(null,this.inputs['H'], '??')),
-
- TR(null,
- TD(null,'S:'),
- TD(null,this.inputs['S'], '%')),
-
- TR(null,
- TD(null,'V:'),
- TD(null,this.inputs['V'], '%')),
-
- TR(null,
- TD({className:'gap'},'R:'),
- TD({className:'gap'},this.inputs['R'])),
-
- TR(null,
- TD(null,'G:'),
- TD(null, this.inputs['G'])),
-
- TR(null,
- TD(null,'B:'),
- TD(null, this.inputs['B'])),
-
- TR(null,
- TD({className:'gap'},'#'),
- TD({className:'gap'},this.inputs['HEX']))
- ));
-
- var UIimages =
- {
- selector : SPAN({className:'selector'}),
- background : SPAN({className:'colorpanel'}),
- slider : SPAN({className:'slider'}),
- hue : SPAN({className:'strip'})
- }
-
- //png alpha channels for IE
- if(Prado.Browser().ie)
- {
- var filter = "filter:progid:DXImageTransform.Microsoft.AlphaImageLoader";
- UIimages['background'] = SPAN({className:'colorpanel',style:filter+"(src='"+images['background.png']+"' sizingMethod=scale);"})
- }
-
- this.inputs = Object.extend(this.inputs, UIimages);
-
- var pickerTable =
- TABLE(null,TBODY(null,
- TR({className:'selection'},
- TD({className:'colors'},UIimages['selector'],UIimages['background']),
- TD({className:'hue'},UIimages['slider'],UIimages['hue']),
- TD({className:'inputs'}, inputsTable)
- ),
- TR({className:'options'},
- TD({colSpan:3},
- this.buttons['OK'],
- this.buttons['Cancel'])
- )
- ));
-
- return DIV({className:this.options['ClassName']+" FullColorPicker",
- id:pickerID+"_picker"},pickerTable);
- },
-
- initializeFullPicker : function()
- {
- var color = Rico.Color.createFromHex(this.input.value);
- this.inputs.oldColor.style.backgroundColor = color.asHex();
- this.setColor(color,true);
-
- var i = 0;
- for(var type in this.inputs)
- {
- Event.observe(this.inputs[type], "change",
- this.onInputChanged.bindEvent(this,type));
- i++;
-
- if(i > 6) break;
- }
-
- this.isMouseDownOnColor = false;
- this.isMouseDownOnHue = false;
-
- this._onColorMouseDown = this.onColorMouseDown.bind(this);
- this._onHueMouseDown = this.onHueMouseDown.bind(this);
- this._onMouseUp = this.onMouseUp.bind(this);
- this._onMouseMove = this.onMouseMove.bind(this);
-
- Event.observe(this.inputs.background, "mousedown", this._onColorMouseDown);
- Event.observe(this.inputs.selector, "mousedown", this._onColorMouseDown);
- Event.observe(this.inputs.hue, "mousedown", this._onHueMouseDown);
- Event.observe(this.inputs.slider, "mousedown", this._onHueMouseDown);
-
- Event.observe(document.body, "mouseup", this._onMouseUp);
-
- this.observeMouseMovement();
-
- Event.observe(this.buttons.Cancel, "click", this.hide.bindEvent(this,this.options['Mode']));
- Event.observe(this.buttons.OK, "click", this.onOKClicked.bind(this));
- },
-
- observeMouseMovement : function()
- {
- if(!this._observingMouseMove)
- {
- Event.observe(document.body, "mousemove", this._onMouseMove);
- this._observingMouseMove = true;
- }
- },
-
- onColorMouseDown : function(ev)
- {
- this.isMouseDownOnColor = true;
- this.onMouseMove(ev);
- Event.stop(ev);
- },
-
- onHueMouseDown : function(ev)
- {
- this.isMouseDownOnHue = true;
- this.onMouseMove(ev);
- Event.stop(ev);
- },
-
- onMouseUp : function(ev)
- {
- this.isMouseDownOnColor = false;
- this.isMouseDownOnHue = false;
- Event.stop(ev);
- },
-
- onMouseMove : function(ev)
- {
- if(this.isMouseDownOnColor)
- this.changeSV(ev);
- if(this.isMouseDownOnHue)
- this.changeH(ev);
- Event.stop(ev);
- },
-
- changeSV : function(ev)
- {
- var px = Event.pointerX(ev);
- var py = Event.pointerY(ev);
- var pos = this.inputs.background.cumulativeOffset();
-
- var x = this.truncate(px - pos[0],0,255);
- var y = this.truncate(py - pos[1],0,255);
-
-
- var s = x/255;
- var b = (255-y)/255;
-
- var current_s = parseInt(this.inputs.S.value);
- var current_b = parseInt(this.inputs.V.value);
-
- if(current_s == parseInt(s*100) && current_b == parseInt(b*100)) return;
-
- var h = this.truncate(this.inputs.H.value,0,360)/360;
-
- var color = new Rico.Color();
- color.rgb = Rico.Color.HSBtoRGB(h,s,b);
-
-
- this.inputs.selector.style.left = x+"px";
- this.inputs.selector.style.top = y+"px";
-
- this.inputs.currentColor.style.backgroundColor = color.asHex();
-
- return this.setColor(color);
- },
-
- changeH : function(ev)
- {
- var py = Event.pointerY(ev);
- var pos = this.inputs.background.cumulativeOffset();
- var y = this.truncate(py - pos[1],0,255);
-
- var h = (255-y)/255;
- var current_h = this.truncate(this.inputs.H.value,0,360);
- current_h = current_h == 0 ? 360 : current_h;
- if(current_h == parseInt(h*360)) return;
-
- var s = parseInt(this.inputs.S.value)/100;
- var b = parseInt(this.inputs.V.value)/100;
- var color = new Rico.Color();
- color.rgb = Rico.Color.HSBtoRGB(h,s,b);
-
- var hue = new Rico.Color(color.rgb.r,color.rgb.g,color.rgb.b);
- hue.setSaturation(1); hue.setBrightness(1);
-
- this.inputs.background.style.backgroundColor = hue.asHex();
- this.inputs.currentColor.style.backgroundColor = color.asHex();
-
- this.inputs.slider.style.top = this.truncate(y,0,255)+"px";
- return this.setColor(color);
-
- },
-
- onOKClicked : function(ev)
- {
- var r = this.truncate(this.inputs.R.value,0,255);///255;
- var g = this.truncate(this.inputs.G.value,0,255);///255;
- var b = this.truncate(this.inputs.B.value,0,255);///255;
- var color = new Rico.Color(r,g,b);
- this.updateColor(color);
- this.inputs.oldColor.style.backgroundColor = color.asHex();
- this.hide(ev);
- },
-
- onInputChanged : function(ev, type)
- {
- if(this.isMouseDownOnColor || isMouseDownOnHue)
- return;
-
-
- switch(type)
- {
- case "H": case "S": case "V":
- var h = this.truncate(this.inputs.H.value,0,360)/360;
- var s = this.truncate(this.inputs.S.value,0,100)/100;
- var b = this.truncate(this.inputs.V.value,0,100)/100;
- var color = new Rico.Color();
- color.rgb = Rico.Color.HSBtoRGB(h,s,b);
- return this.setColor(color,true);
- case "R": case "G": case "B":
- var r = this.truncate(this.inputs.R.value,0,255);///255;
- var g = this.truncate(this.inputs.G.value,0,255);///255;
- var b = this.truncate(this.inputs.B.value,0,255);///255;
- var color = new Rico.Color(r,g,b);
- return this.setColor(color,true);
- case "HEX":
- var color = Rico.Color.createFromHex(this.inputs.HEX.value);
- return this.setColor(color,true);
- }
- },
-
- setColor : function(color, update)
- {
- var hsb = color.asHSB();
-
- this.inputs.H.value = parseInt(hsb.h*360);
- this.inputs.S.value = parseInt(hsb.s*100);
- this.inputs.V.value = parseInt(hsb.b*100);
- this.inputs.R.value = color.rgb.r;
- this.inputs.G.value = color.rgb.g;
- this.inputs.B.value = color.rgb.b;
- this.inputs.HEX.value = color.asHex().substring(1).toUpperCase();
-
- var images = Prado.WebUI.TColorPicker.UIImages;
-
- var changeCss = color.isBright() ? 'removeClassName' : 'addClassName';
- Element[changeCss](this.inputs.selector, 'target_white');
-
- if(update)
- this.updateSelectors(color);
- },
-
- updateSelectors : function(color)
- {
- var hsb = color.asHSB();
- var pos = [hsb.s*255, hsb.b*255, hsb.h*255];
-
- this.inputs.selector.style.left = this.truncate(pos[0],0,255)+"px";
- this.inputs.selector.style.top = this.truncate(255-pos[1],0,255)+"px";
- this.inputs.slider.style.top = this.truncate(255-pos[2],0,255)+"px";
-
- var hue = new Rico.Color(color.rgb.r,color.rgb.g,color.rgb.b);
- hue.setSaturation(1); hue.setBrightness(1);
- this.inputs.background.style.backgroundColor = hue.asHex();
- this.inputs.currentColor.style.backgroundColor = color.asHex();
- },
-
- truncate : function(value, min, max)
- {
- value = parseInt(value);
- return value < min ? min : value > max ? max : value;
- }
-});
+//-------------------- ricoColor.js
+if(typeof(Rico) == "undefined") Rico = {};
+
+Rico.Color = Class.create();
+
+Rico.Color.prototype = {
+
+ initialize: function(red, green, blue) {
+ this.rgb = { r: red, g : green, b : blue };
+ },
+
+ setRed: function(r) {
+ this.rgb.r = r;
+ },
+
+ setGreen: function(g) {
+ this.rgb.g = g;
+ },
+
+ setBlue: function(b) {
+ this.rgb.b = b;
+ },
+
+ setHue: function(h) {
+
+ // get an HSB model, and set the new hue...
+ var hsb = this.asHSB();
+ hsb.h = h;
+
+ // convert back to RGB...
+ this.rgb = Rico.Color.HSBtoRGB(hsb.h, hsb.s, hsb.b);
+ },
+
+ setSaturation: function(s) {
+ // get an HSB model, and set the new hue...
+ var hsb = this.asHSB();
+ hsb.s = s;
+
+ // convert back to RGB and set values...
+ this.rgb = Rico.Color.HSBtoRGB(hsb.h, hsb.s, hsb.b);
+ },
+
+ setBrightness: function(b) {
+ // get an HSB model, and set the new hue...
+ var hsb = this.asHSB();
+ hsb.b = b;
+
+ // convert back to RGB and set values...
+ this.rgb = Rico.Color.HSBtoRGB( hsb.h, hsb.s, hsb.b );
+ },
+
+ darken: function(percent) {
+ var hsb = this.asHSB();
+ this.rgb = Rico.Color.HSBtoRGB(hsb.h, hsb.s, Math.max(hsb.b - percent,0));
+ },
+
+ brighten: function(percent) {
+ var hsb = this.asHSB();
+ this.rgb = Rico.Color.HSBtoRGB(hsb.h, hsb.s, Math.min(hsb.b + percent,1));
+ },
+
+ blend: function(other) {
+ this.rgb.r = Math.floor((this.rgb.r + other.rgb.r)/2);
+ this.rgb.g = Math.floor((this.rgb.g + other.rgb.g)/2);
+ this.rgb.b = Math.floor((this.rgb.b + other.rgb.b)/2);
+ },
+
+ isBright: function() {
+ var hsb = this.asHSB();
+ return this.asHSB().b > 0.5;
+ },
+
+ isDark: function() {
+ return ! this.isBright();
+ },
+
+ asRGB: function() {
+ return "rgb(" + this.rgb.r + "," + this.rgb.g + "," + this.rgb.b + ")";
+ },
+
+ asHex: function() {
+ return "#" + this.rgb.r.toColorPart() + this.rgb.g.toColorPart() + this.rgb.b.toColorPart();
+ },
+
+ asHSB: function() {
+ return Rico.Color.RGBtoHSB(this.rgb.r, this.rgb.g, this.rgb.b);
+ },
+
+ toString: function() {
+ return this.asHex();
+ }
+
+};
+
+Rico.Color.createFromHex = function(hexCode) {
+
+ if ( hexCode.indexOf('#') == 0 )
+ hexCode = hexCode.substring(1);
+
+ var red = "ff", green = "ff", blue="ff";
+ if(hexCode.length > 4)
+ {
+ red = hexCode.substring(0,2);
+ green = hexCode.substring(2,4);
+ blue = hexCode.substring(4,6);
+ }
+ else if(hexCode.length > 0 & hexCode.length < 4)
+ {
+ var r = hexCode.substring(0,1);
+ var g = hexCode.substring(1,2);
+ var b = hexCode.substring(2);
+ red = r+r;
+ green = g+g;
+ blue = b+b;
+ }
+ return new Rico.Color( parseInt(red,16), parseInt(green,16), parseInt(blue,16) );
+};
+
+/**
+ * Factory method for creating a color from the background of
+ * an HTML element.
+ */
+Rico.Color.createColorFromBackground = function(elem) {
+
+ var actualColor = Element.getStyle($(elem), "background-color");
+ if ( actualColor == "transparent" && elem.parent )
+ return Rico.Color.createColorFromBackground(elem.parent);
+
+ if ( actualColor == null )
+ return new Rico.Color(255,255,255);
+
+ if ( actualColor.indexOf("rgb(") == 0 ) {
+ var colors = actualColor.substring(4, actualColor.length - 1 );
+ var colorArray = colors.split(",");
+ return new Rico.Color( parseInt( colorArray[0] ),
+ parseInt( colorArray[1] ),
+ parseInt( colorArray[2] ) );
+
+ }
+ else if ( actualColor.indexOf("#") == 0 ) {
+ return Rico.Color.createFromHex(actualColor);
+ }
+ else
+ return new Rico.Color(255,255,255);
+};
+
+Rico.Color.HSBtoRGB = function(hue, saturation, brightness) {
+
+ var red = 0;
+ var green = 0;
+ var blue = 0;
+
+ if (saturation == 0) {
+ red = parseInt(brightness * 255.0 + 0.5);
+ green = red;
+ blue = red;
+ }
+ else {
+ var h = (hue - Math.floor(hue)) * 6.0;
+ var f = h - Math.floor(h);
+ var p = brightness * (1.0 - saturation);
+ var q = brightness * (1.0 - saturation * f);
+ var t = brightness * (1.0 - (saturation * (1.0 - f)));
+
+ switch (parseInt(h)) {
+ case 0:
+ red = (brightness * 255.0 + 0.5);
+ green = (t * 255.0 + 0.5);
+ blue = (p * 255.0 + 0.5);
+ break;
+ case 1:
+ red = (q * 255.0 + 0.5);
+ green = (brightness * 255.0 + 0.5);
+ blue = (p * 255.0 + 0.5);
+ break;
+ case 2:
+ red = (p * 255.0 + 0.5);
+ green = (brightness * 255.0 + 0.5);
+ blue = (t * 255.0 + 0.5);
+ break;
+ case 3:
+ red = (p * 255.0 + 0.5);
+ green = (q * 255.0 + 0.5);
+ blue = (brightness * 255.0 + 0.5);
+ break;
+ case 4:
+ red = (t * 255.0 + 0.5);
+ green = (p * 255.0 + 0.5);
+ blue = (brightness * 255.0 + 0.5);
+ break;
+ case 5:
+ red = (brightness * 255.0 + 0.5);
+ green = (p * 255.0 + 0.5);
+ blue = (q * 255.0 + 0.5);
+ break;
+ }
+ }
+
+ return { r : parseInt(red), g : parseInt(green) , b : parseInt(blue) };
+};
+
+Rico.Color.RGBtoHSB = function(r, g, b) {
+
+ var hue;
+ var saturation;
+ var brightness;
+
+ var cmax = (r > g) ? r : g;
+ if (b > cmax)
+ cmax = b;
+
+ var cmin = (r < g) ? r : g;
+ if (b < cmin)
+ cmin = b;
+
+ brightness = cmax / 255.0;
+ if (cmax != 0)
+ saturation = (cmax - cmin)/cmax;
+ else
+ saturation = 0;
+
+ if (saturation == 0)
+ hue = 0;
+ else {
+ var redc = (cmax - r)/(cmax - cmin);
+ var greenc = (cmax - g)/(cmax - cmin);
+ var bluec = (cmax - b)/(cmax - cmin);
+
+ if (r == cmax)
+ hue = bluec - greenc;
+ else if (g == cmax)
+ hue = 2.0 + redc - bluec;
+ else
+ hue = 4.0 + greenc - redc;
+
+ hue = hue / 6.0;
+ if (hue < 0)
+ hue = hue + 1.0;
+ }
+
+ return { h : hue, s : saturation, b : brightness };
+};
+
+
+Prado.WebUI.TColorPicker = Class.create();
+
+Object.extend(Prado.WebUI.TColorPicker,
+{
+ palettes:
+ {
+ Small : [["fff", "fcc", "fc9", "ff9", "ffc", "9f9", "9ff", "cff", "ccf", "fcf"],
+ ["ccc", "f66", "f96", "ff6", "ff3", "6f9", "3ff", "6ff", "99f", "f9f"],
+ ["c0c0c0", "f00", "f90", "fc6", "ff0", "3f3", "6cc", "3cf", "66c", "c6c"],
+ ["999", "c00", "f60", "fc3", "fc0", "3c0", "0cc", "36f", "63f", "c3c"],
+ ["666", "900", "c60", "c93", "990", "090", "399", "33f", "60c", "939"],
+ ["333", "600", "930", "963", "660", "060", "366", "009", "339", "636"],
+ ["000", "300", "630", "633", "330", "030", "033", "006", "309", "303"]],
+
+ Tiny : [["ffffff"/*white*/, "00ff00"/*lime*/, "008000"/*green*/, "0000ff"/*blue*/],
+ ["c0c0c0"/*silver*/, "ffff00"/*yellow*/, "ff00ff"/*fuchsia*/, "000080"/*navy*/],
+ ["808080"/*gray*/, "ff0000"/*red*/, "800080"/*purple*/, "000000"/*black*/]]
+ },
+
+ UIImages :
+ {
+ 'button.gif' : 'button.gif',
+// 'target_black.gif' : 'target_black.gif',
+// 'target_white.gif' : 'target_white.gif',
+ 'background.png' : 'background.png'
+// 'slider.gif' : 'slider.gif',
+// 'hue.gif' : 'hue.gif'
+ }
+});
+
+Object.extend(Prado.WebUI.TColorPicker.prototype,
+{
+ initialize : function(options)
+ {
+ var basics =
+ {
+ Palette : 'Small',
+ ClassName : 'TColorPicker',
+ Mode : 'Basic',
+ OKButtonText : 'OK',
+ CancelButtonText : 'Cancel',
+ ShowColorPicker : true
+ }
+
+ this.element = null;
+ this.showing = false;
+
+ options = Object.extend(basics, options);
+ this.options = options;
+ this.input = $(options['ID']);
+ this.button = $(options['ID']+'_button');
+ this._buttonOnClick = this.buttonOnClick.bind(this);
+ if(options['ShowColorPicker'])
+ Event.observe(this.button, "click", this._buttonOnClick);
+ Event.observe(this.input, "change", this.updatePicker.bind(this));
+
+ Prado.Registry.set(options.ID, this);
+ },
+
+ updatePicker : function(e)
+ {
+ var color = Rico.Color.createFromHex(this.input.value);
+ this.button.style.backgroundColor = color.toString();
+ },
+
+ buttonOnClick : function(event)
+ {
+ var mode = this.options['Mode'];
+ if(this.element == null)
+ {
+ var constructor = mode == "Basic" ? "getBasicPickerContainer": "getFullPickerContainer"
+ this.element = this[constructor](this.options['ID'], this.options['Palette'])
+ this.input.parentNode.appendChild(this.element);
+ this.element.style.display = "none";
+
+ if(Prado.Browser().ie)
+ {
+ 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);
+ }
+ if(mode == "Full")
+ this.initializeFullPicker();
+ }
+ this.show(mode);
+ },
+
+ show : function(type)
+ {
+ if(!this.showing)
+ {
+ var pos = this.input.positionedOffset();
+ pos[1] += this.input.offsetHeight;
+
+ this.element.style.top = (pos[1]-1) + "px";
+ this.element.style.left = pos[0] + "px";
+ this.element.style.display = "block";
+
+ this.ieHack(type);
+
+ //observe for clicks on the document body
+ this._documentClickEvent = this.hideOnClick.bindEvent(this, type);
+ this._documentKeyDownEvent = this.keyPressed.bindEvent(this, type);
+ Event.observe(document.body, "click", this._documentClickEvent);
+ Event.observe(document,"keydown", this._documentKeyDownEvent);
+ this.showing = true;
+
+ if(type == "Full")
+ {
+ this.observeMouseMovement();
+ var color = Rico.Color.createFromHex(this.input.value);
+ this.inputs.oldColor.style.backgroundColor = color.asHex();
+ this.setColor(color,true);
+ }
+ }
+ },
+
+ hide : function(event)
+ {
+ if(this.showing)
+ {
+ if(this.iePopUp)
+ this.iePopUp.style.display = "none";
+
+ this.element.style.display = "none";
+ this.showing = false;
+ Event.stopObserving(document.body, "click", this._documentClickEvent);
+ Event.stopObserving(document,"keydown", this._documentKeyDownEvent);
+
+ if(this._observingMouseMove)
+ {
+ Event.stopObserving(document.body, "mousemove", this._onMouseMove);
+ this._observingMouseMove = false;
+ }
+ }
+ },
+
+ keyPressed : function(event,type)
+ {
+ if(Event.keyCode(event) == Event.KEY_ESC)
+ this.hide(event,type);
+ },
+
+ hideOnClick : function(ev)
+ {
+ if(!this.showing) return;
+ var el = Event.element(ev);
+ var within = false;
+ do
+ { within = within || String(el.className).indexOf('FullColorPicker') > -1
+ within = within || el == this.button;
+ within = within || el == this.input;
+ if(within) break;
+ el = el.parentNode;
+ }
+ while(el);
+ if(!within) this.hide(ev);
+ },
+
+ ieHack : function()
+ {
+ // IE hack
+ if(this.iePopUp)
+ {
+ this.iePopUp.style.display = "block";
+ this.iePopUp.style.top = (this.element.offsetTop) + "px";
+ this.iePopUp.style.left = (this.element.offsetLeft)+ "px";
+ this.iePopUp.style.width = Math.abs(this.element.offsetWidth)+ "px";
+ this.iePopUp.style.height = (this.element.offsetHeight + 1)+ "px";
+ }
+ },
+
+ getBasicPickerContainer : function(pickerID, palette)
+ {
+ var table = TABLE({className:'basic_colors palette_'+palette},TBODY());
+ var colors = Prado.WebUI.TColorPicker.palettes[palette];
+ var pickerOnClick = this.cellOnClick.bind(this);
+ colors.each(function(color)
+ {
+ var row = document.createElement("tr");
+ color.each(function(c)
+ {
+ var td = document.createElement("td");
+ var img = IMG({src:Prado.WebUI.TColorPicker.UIImages['button.gif'],width:16,height:16});
+ img.style.backgroundColor = "#"+c;
+ Event.observe(img,"click", pickerOnClick);
+ Event.observe(img,"mouseover", function(e)
+ {
+ Element.addClassName(Event.element(e), "pickerhover");
+ });
+ Event.observe(img,"mouseout", function(e)
+ {
+ Element.removeClassName(Event.element(e), "pickerhover");
+ });
+ td.appendChild(img);
+ row.appendChild(td);
+ });
+ table.childNodes[0].appendChild(row);
+ });
+ return DIV({className:this.options['ClassName']+" BasicColorPicker",
+ id:pickerID+"_picker"}, table);
+ },
+
+ cellOnClick : function(e)
+ {
+ var el = Event.element(e);
+ if(el.tagName.toLowerCase() != "img")
+ return;
+ var color = Rico.Color.createColorFromBackground(el);
+ this.updateColor(color);
+ },
+
+ updateColor : function(color)
+ {
+ this.input.value = color.toString().toUpperCase();
+ this.button.style.backgroundColor = color.toString();
+ if(typeof(this.onChange) == "function")
+ this.onChange(color);
+ if(this.options.OnColorSelected)
+ this.options.OnColorSelected(this,color);
+ },
+
+ getFullPickerContainer : function(pickerID)
+ {
+ //create the 3 buttons
+ this.buttons =
+ {
+ //Less : INPUT({value:'Less Colors', className:'button', type:'button'}),
+ OK : INPUT({value:this.options.OKButtonText, className:'button', type:'button'}),
+ Cancel : INPUT({value:this.options.CancelButtonText, className:'button', type:'button'})
+ };
+
+ //create the 6 inputs
+ var inputs = {};
+ ['H','S','V','R','G','B'].each(function(type)
+ {
+ inputs[type] = INPUT({type:'text',size:'3',maxlength:'3'});
+ });
+
+ //create the HEX input
+ inputs['HEX'] = INPUT({className:'hex',type:'text',size:'6',maxlength:'6'});
+ this.inputs = inputs;
+
+ var images = Prado.WebUI.TColorPicker.UIImages;
+
+ this.inputs['currentColor'] = SPAN({className:'currentColor'});
+ this.inputs['oldColor'] = SPAN({className:'oldColor'});
+
+ var inputsTable =
+ TABLE({className:'inputs'}, TBODY(null,
+ TR(null,
+ TD({className:'currentcolor',colSpan:2},
+ this.inputs['currentColor'], this.inputs['oldColor'])),
+
+ TR(null,
+ TD(null,'H:'),
+ TD(null,this.inputs['H'], '??')),
+
+ TR(null,
+ TD(null,'S:'),
+ TD(null,this.inputs['S'], '%')),
+
+ TR(null,
+ TD(null,'V:'),
+ TD(null,this.inputs['V'], '%')),
+
+ TR(null,
+ TD({className:'gap'},'R:'),
+ TD({className:'gap'},this.inputs['R'])),
+
+ TR(null,
+ TD(null,'G:'),
+ TD(null, this.inputs['G'])),
+
+ TR(null,
+ TD(null,'B:'),
+ TD(null, this.inputs['B'])),
+
+ TR(null,
+ TD({className:'gap'},'#'),
+ TD({className:'gap'},this.inputs['HEX']))
+ ));
+
+ var UIimages =
+ {
+ selector : SPAN({className:'selector'}),
+ background : SPAN({className:'colorpanel'}),
+ slider : SPAN({className:'slider'}),
+ hue : SPAN({className:'strip'})
+ }
+
+ //png alpha channels for IE
+ if(Prado.Browser().ie)
+ {
+ var filter = "filter:progid:DXImageTransform.Microsoft.AlphaImageLoader";
+ UIimages['background'] = SPAN({className:'colorpanel',style:filter+"(src='"+images['background.png']+"' sizingMethod=scale);"})
+ }
+
+ this.inputs = Object.extend(this.inputs, UIimages);
+
+ var pickerTable =
+ TABLE(null,TBODY(null,
+ TR({className:'selection'},
+ TD({className:'colors'},UIimages['selector'],UIimages['background']),
+ TD({className:'hue'},UIimages['slider'],UIimages['hue']),
+ TD({className:'inputs'}, inputsTable)
+ ),
+ TR({className:'options'},
+ TD({colSpan:3},
+ this.buttons['OK'],
+ this.buttons['Cancel'])
+ )
+ ));
+
+ return DIV({className:this.options['ClassName']+" FullColorPicker",
+ id:pickerID+"_picker"},pickerTable);
+ },
+
+ initializeFullPicker : function()
+ {
+ var color = Rico.Color.createFromHex(this.input.value);
+ this.inputs.oldColor.style.backgroundColor = color.asHex();
+ this.setColor(color,true);
+
+ var i = 0;
+ for(var type in this.inputs)
+ {
+ Event.observe(this.inputs[type], "change",
+ this.onInputChanged.bindEvent(this,type));
+ i++;
+
+ if(i > 6) break;
+ }
+
+ this.isMouseDownOnColor = false;
+ this.isMouseDownOnHue = false;
+
+ this._onColorMouseDown = this.onColorMouseDown.bind(this);
+ this._onHueMouseDown = this.onHueMouseDown.bind(this);
+ this._onMouseUp = this.onMouseUp.bind(this);
+ this._onMouseMove = this.onMouseMove.bind(this);
+
+ Event.observe(this.inputs.background, "mousedown", this._onColorMouseDown);
+ Event.observe(this.inputs.selector, "mousedown", this._onColorMouseDown);
+ Event.observe(this.inputs.hue, "mousedown", this._onHueMouseDown);
+ Event.observe(this.inputs.slider, "mousedown", this._onHueMouseDown);
+
+ Event.observe(document.body, "mouseup", this._onMouseUp);
+
+ this.observeMouseMovement();
+
+ Event.observe(this.buttons.Cancel, "click", this.hide.bindEvent(this,this.options['Mode']));
+ Event.observe(this.buttons.OK, "click", this.onOKClicked.bind(this));
+ },
+
+ observeMouseMovement : function()
+ {
+ if(!this._observingMouseMove)
+ {
+ Event.observe(document.body, "mousemove", this._onMouseMove);
+ this._observingMouseMove = true;
+ }
+ },
+
+ onColorMouseDown : function(ev)
+ {
+ this.isMouseDownOnColor = true;
+ this.onMouseMove(ev);
+ Event.stop(ev);
+ },
+
+ onHueMouseDown : function(ev)
+ {
+ this.isMouseDownOnHue = true;
+ this.onMouseMove(ev);
+ Event.stop(ev);
+ },
+
+ onMouseUp : function(ev)
+ {
+ this.isMouseDownOnColor = false;
+ this.isMouseDownOnHue = false;
+ Event.stop(ev);
+ },
+
+ onMouseMove : function(ev)
+ {
+ if(this.isMouseDownOnColor)
+ this.changeSV(ev);
+ if(this.isMouseDownOnHue)
+ this.changeH(ev);
+ Event.stop(ev);
+ },
+
+ changeSV : function(ev)
+ {
+ var px = Event.pointerX(ev);
+ var py = Event.pointerY(ev);
+ var pos = this.inputs.background.cumulativeOffset();
+
+ var x = this.truncate(px - pos[0],0,255);
+ var y = this.truncate(py - pos[1],0,255);
+
+
+ var s = x/255;
+ var b = (255-y)/255;
+
+ var current_s = parseInt(this.inputs.S.value);
+ var current_b = parseInt(this.inputs.V.value);
+
+ if(current_s == parseInt(s*100) && current_b == parseInt(b*100)) return;
+
+ var h = this.truncate(this.inputs.H.value,0,360)/360;
+
+ var color = new Rico.Color();
+ color.rgb = Rico.Color.HSBtoRGB(h,s,b);
+
+
+ this.inputs.selector.style.left = x+"px";
+ this.inputs.selector.style.top = y+"px";
+
+ this.inputs.currentColor.style.backgroundColor = color.asHex();
+
+ return this.setColor(color);
+ },
+
+ changeH : function(ev)
+ {
+ var py = Event.pointerY(ev);
+ var pos = this.inputs.background.cumulativeOffset();
+ var y = this.truncate(py - pos[1],0,255);
+
+ var h = (255-y)/255;
+ var current_h = this.truncate(this.inputs.H.value,0,360);
+ current_h = current_h == 0 ? 360 : current_h;
+ if(current_h == parseInt(h*360)) return;
+
+ var s = parseInt(this.inputs.S.value)/100;
+ var b = parseInt(this.inputs.V.value)/100;
+ var color = new Rico.Color();
+ color.rgb = Rico.Color.HSBtoRGB(h,s,b);
+
+ var hue = new Rico.Color(color.rgb.r,color.rgb.g,color.rgb.b);
+ hue.setSaturation(1); hue.setBrightness(1);
+
+ this.inputs.background.style.backgroundColor = hue.asHex();
+ this.inputs.currentColor.style.backgroundColor = color.asHex();
+
+ this.inputs.slider.style.top = this.truncate(y,0,255)+"px";
+ return this.setColor(color);
+
+ },
+
+ onOKClicked : function(ev)
+ {
+ var r = this.truncate(this.inputs.R.value,0,255);///255;
+ var g = this.truncate(this.inputs.G.value,0,255);///255;
+ var b = this.truncate(this.inputs.B.value,0,255);///255;
+ var color = new Rico.Color(r,g,b);
+ this.updateColor(color);
+ this.inputs.oldColor.style.backgroundColor = color.asHex();
+ this.hide(ev);
+ },
+
+ onInputChanged : function(ev, type)
+ {
+ if(this.isMouseDownOnColor || isMouseDownOnHue)
+ return;
+
+
+ switch(type)
+ {
+ case "H": case "S": case "V":
+ var h = this.truncate(this.inputs.H.value,0,360)/360;
+ var s = this.truncate(this.inputs.S.value,0,100)/100;
+ var b = this.truncate(this.inputs.V.value,0,100)/100;
+ var color = new Rico.Color();
+ color.rgb = Rico.Color.HSBtoRGB(h,s,b);
+ return this.setColor(color,true);
+ case "R": case "G": case "B":
+ var r = this.truncate(this.inputs.R.value,0,255);///255;
+ var g = this.truncate(this.inputs.G.value,0,255);///255;
+ var b = this.truncate(this.inputs.B.value,0,255);///255;
+ var color = new Rico.Color(r,g,b);
+ return this.setColor(color,true);
+ case "HEX":
+ var color = Rico.Color.createFromHex(this.inputs.HEX.value);
+ return this.setColor(color,true);
+ }
+ },
+
+ setColor : function(color, update)
+ {
+ var hsb = color.asHSB();
+
+ this.inputs.H.value = parseInt(hsb.h*360);
+ this.inputs.S.value = parseInt(hsb.s*100);
+ this.inputs.V.value = parseInt(hsb.b*100);
+ this.inputs.R.value = color.rgb.r;
+ this.inputs.G.value = color.rgb.g;
+ this.inputs.B.value = color.rgb.b;
+ this.inputs.HEX.value = color.asHex().substring(1).toUpperCase();
+
+ var images = Prado.WebUI.TColorPicker.UIImages;
+
+ var changeCss = color.isBright() ? 'removeClassName' : 'addClassName';
+ Element[changeCss](this.inputs.selector, 'target_white');
+
+ if(update)
+ this.updateSelectors(color);
+ },
+
+ updateSelectors : function(color)
+ {
+ var hsb = color.asHSB();
+ var pos = [hsb.s*255, hsb.b*255, hsb.h*255];
+
+ this.inputs.selector.style.left = this.truncate(pos[0],0,255)+"px";
+ this.inputs.selector.style.top = this.truncate(255-pos[1],0,255)+"px";
+ this.inputs.slider.style.top = this.truncate(255-pos[2],0,255)+"px";
+
+ var hue = new Rico.Color(color.rgb.r,color.rgb.g,color.rgb.b);
+ hue.setSaturation(1); hue.setBrightness(1);
+ this.inputs.background.style.backgroundColor = hue.asHex();
+ this.inputs.currentColor.style.backgroundColor = color.asHex();
+ },
+
+ truncate : function(value, min, max)
+ {
+ value = parseInt(value);
+ return value < min ? min : value > max ? max : value;
+ }
+});
diff --git a/framework/Web/Javascripts/source/prado/controls/controls.js b/framework/Web/Javascripts/source/prado/controls/controls.js
index bbc54e9e..fd8a4c91 100644
--- a/framework/Web/Javascripts/source/prado/controls/controls.js
+++ b/framework/Web/Javascripts/source/prado/controls/controls.js
@@ -1,517 +1,517 @@
-Prado.WebUI = Class.create();
-
-Prado.WebUI.Control = Class.create({
-
- initialize : function(options)
- {
- this.registered = false;
- this.ID = options.ID;
- this.element = $(this.ID);
- this.observers = new Array();
- this.intervals = new Array();
- var e;
- if (e = Prado.Registry.get(this.ID))
- this.replace(e, options);
- else
- this.register(options);
-
- if (this === Prado.Registry.get(this.ID))
- {
- this.registered = true;
- if(this.onInit)
- this.onInit(options);
- }
- },
-
- /**
- * Registers the control wrapper in the Prado client side control registry
- * @param array control wrapper options
- */
- register : function(options)
- {
- return Prado.Registry.set(options.ID, this);
- },
-
- /**
- * De-registers the control wrapper in the Prado client side control registry
- */
- deregister : function()
- {
- // extra check so we don't ever deregister another wrapper
- if (Prado.Registry.get(this.ID)===this)
- return Prado.Registry.unset(this.ID);
- else
- debugger; // invoke debugger - this should never happen
- },
-
- /**
- * Replaces and control wrapper for an already existing control in the Prado client side control registry
- * @param object reference to the old wrapper
- * @param array control wrapper options
- */
- replace : function(oldwrapper, options)
- {
- // if there's some advanced state management in the wrapper going on, then
- // this method could be used either to copy the current state of the control
- // from the old wrapper to this new one (which then could live on, while the old
- // one could get destroyed), or to copy the new, changed options to the old wrapper,
- // (which could then left intact to keep working, while this new wrapper could be
- // disposed of by exiting its initialization without installing any handlers or
- // leaving any references to it)
- //
-
- // for now this method is simply deinitializing and deregistering the old wrapper,
- // and then registering the new wrapper for the control id
-
- if (oldwrapper.deinitialize)
- oldwrapper.deinitialize();
-
- return this.register(options);
- },
-
- /**
- * Registers an event observer which will be automatically disposed of when the wrapper
- * is deregistered
- * @param element DOM element reference or id to attach the event handler to
- * @param string event name to observe
- * @param handler event handler function
- */
- observe: function(element, eventName, handler)
- {
- var e = { _element: element, _eventName: eventName, _handler: handler };
- this.observers.push(e);
- return Event.observe(e._element,e._eventName,e._handler);
- },
-
- /**
- * Checks whether an event observer is installed and returns its index
- * @param element DOM element reference or id the event handler was attached to
- * @param string event name observed
- * @param handler event handler function
- * @result int false if the event handler is not installed, or 1-based index when installed
- */
- findObserver: function(element, eventName, handler)
- {
- var e = { _element: element, _eventName: eventName, _handler: handler };
- var idx = -1;
- for(var i=0;i<this.observers.length;i++)
- {
- var o = this.observers[i];
- if ((o._element===element) && (o._eventName===eventName) && (o._handler===handler))
- {
- idx = i;
- break;
- }
- }
- return idx;
- },
-
-
- /**
- * Degisters an event observer from the list of automatically disposed handlers
- * @param element DOM element reference or id the event handler was attached to
- * @param string event name observed
- * @param handler event handler function
- */
- stopObserving: function(element, eventName, handler)
- {
- var idx = this.findObserver(element,eventName,handler);
- if (idx!=-1)
- this.observers = this.observers.without(this.observers[idx]);
- else
- debugger; // shouldn't happen
-
- return Event.stopObserving(element,eventName,handler);
- },
-
- /**
- * Registers a code snippet or function to be executed after a delay, if the
- * wrapper hasn't been destroyed in the meantime
- * @param code function or code snippet to execute
- * @param int number of milliseconds to wait before executing
- * @return int unique ID that can be used to cancel the scheduled execution
- */
- setTimeout: function(func, delay)
- {
- if (!Object.isFunction(func))
- {
- var expr = func;
- func = function() { return eval(expr); }
- };
- var obj = this;
- return window.setTimeout(function() {
- if (!obj.isLingering())
- func();
- obj = null;
- },delay);
- },
-
- /**
- * Cancels a previously scheduled code snippet or function
- * @param int unique ID returned by setTimeout()
- */
- clearTimeout: function(timeoutid)
- {
- return window.clearTimeout(timeoutid);
- },
-
- /**
- * Registers a code snippet or function to be executed periodically, up until the
- * wrapper gets destroyed or the schedule cancelled using cancelInterval()
- * @param code function or code snippet to execute
- * @param int number of milliseconds to wait before executing
- * @return int unique ID that can be used to cancel the interval (see clearInterval() method)
- */
- setInterval: function(func, delay)
- {
- if (!Object.isFunction(func)) func = function() { eval(func); };
- var obj = this;
- var h = window.setInterval(function() {
- if (!obj.isLingering())
- func();
- },delay);
- this.intervals.push(h);
- return h;
- },
-
- /**
- * Deregisters a snipper or function previously registered with setInterval()
- * @param int unique ID of interval (returned by setInterval() previously)
- */
- clearInterval: function(intervalid)
- {
- window.clearInterval(intervalid);
- this.intervals = this.intervals.without(intervalid);
- },
-
- /**
- * Tells whether this is a wrapper that has already been deregistered and is lingering
- * @return bool true if object
- */
- isLingering: function()
- {
- return !this.registered;
- },
-
- /**
- * Deinitializes the control wrapper by calling the onDone method and the deregistering it
- * @param array control wrapper options
- */
- deinitialize : function()
- {
- if (this.registered)
- {
- if(this.onDone)
- this.onDone();
-
- // automatically stop all intervals
- while (this.intervals.length>0)
- window.clearInterval(this.intervals.pop());
-
- // automatically deregister all installed observers
- while (this.observers.length>0)
- {
- var e = this.observers.pop();
- Event.stopObserving(e._element,e._eventName,e._handler);
- }
- }
- else
- debugger; // shouldn't happen
-
- this.deregister();
-
- this.registered = false;
- }
-
-});
-
-Prado.WebUI.PostBackControl = Class.create(Prado.WebUI.Control, {
-
- onInit : function(options)
- {
- this._elementOnClick = null;
-
- if (!this.element)
- debugger; // element not found
- else
- {
- //capture the element's onclick function
- if(typeof(this.element.onclick)=="function")
- {
- this._elementOnClick = this.element.onclick.bind(this.element);
- this.element.onclick = null;
- }
- this.observe(this.element, "click", this.elementClicked.bindEvent(this,options));
- }
- },
-
- elementClicked : function(event, options)
- {
- var src = Event.element(event);
- var doPostBack = true;
- var onclicked = null;
-
- if(this._elementOnClick)
- {
- var onclicked = this._elementOnClick(event);
- if(typeof(onclicked) == "boolean")
- doPostBack = onclicked;
- }
- if(doPostBack && !Prado.Element.isDisabled(src))
- this.onPostBack(event,options);
- if(typeof(onclicked) == "boolean" && !onclicked)
- Event.stop(event);
- },
-
- onPostBack : function(event, options)
- {
- Prado.PostBack(event,options);
- }
-
-});
-
-Prado.WebUI.TButton = Class.create(Prado.WebUI.PostBackControl);
-Prado.WebUI.TLinkButton = Class.create(Prado.WebUI.PostBackControl);
-Prado.WebUI.TCheckBox = Class.create(Prado.WebUI.PostBackControl);
-Prado.WebUI.TBulletedList = Class.create(Prado.WebUI.PostBackControl);
-Prado.WebUI.TImageMap = Class.create(Prado.WebUI.PostBackControl);
-
-/**
- * TImageButton client-side behaviour. With validation, Firefox needs
- * to capture the x,y point of the clicked image in hidden form fields.
- */
-Prado.WebUI.TImageButton = Class.create(Prado.WebUI.PostBackControl,
-{
- /**
- * Override parent onPostBack function, tried to add hidden forms
- * inputs to capture x,y clicked point.
- */
- onPostBack : function(event, options)
- {
- this.addXYInput(event,options);
- Prado.PostBack(event, options);
- this.removeXYInput(event,options);
- },
-
- /**
- * Add hidden inputs to capture the x,y point clicked on the image.
- * @param event DOM click event.
- * @param array image button options.
- */
- addXYInput : function(event,options)
- {
- var imagePos = this.element.cumulativeOffset();
- var clickedPos = [event.clientX, event.clientY];
- var x = clickedPos[0]-imagePos[0]+1;
- var y = clickedPos[1]-imagePos[1]+1;
- x = x < 0 ? 0 : x;
- y = y < 0 ? 0 : y;
- var id = options['EventTarget'];
- var x_input = $(id+"_x");
- var y_input = $(id+"_y");
- if(x_input)
- {
- x_input.value = x;
- }
- else
- {
- x_input = INPUT({type:'hidden',name:id+'_x','id':id+'_x',value:x});
- this.element.parentNode.appendChild(x_input);
- }
- if(y_input)
- {
- y_input.value = y;
- }
- else
- {
- y_input = INPUT({type:'hidden',name:id+'_y','id':id+'_y',value:y});
- this.element.parentNode.appendChild(y_input);
- }
- },
-
- /**
- * Remove hidden inputs for x,y-click capturing
- * @param event DOM click event.
- * @param array image button options.
- */
- removeXYInput : function(event,options)
- {
- var id = options['EventTarget'];
- this.element.parentNode.removeChild($(id+"_x"));
- this.element.parentNode.removeChild($(id+"_y"));
- }
-});
-
-
-/**
- * Radio button, only initialize if not already checked.
- */
-Prado.WebUI.TRadioButton = Class.create(Prado.WebUI.PostBackControl,
-{
- initialize : function($super, options)
- {
- this.element = $(options['ID']);
- if(this.element)
- {
- if(!this.element.checked)
- $super(options);
- }
- }
-});
-
-
-Prado.WebUI.TTextBox = Class.create(Prado.WebUI.PostBackControl,
-{
- onInit : function(options)
- {
- this.options=options;
- if(this.options['TextMode'] != 'MultiLine')
- this.observe(this.element, "keydown", this.handleReturnKey.bind(this));
- if(this.options['AutoPostBack']==true)
- this.observe(this.element, "change", Prado.PostBack.bindEvent(this,options));
- },
-
- handleReturnKey : function(e)
- {
- if(Event.keyCode(e) == Event.KEY_RETURN)
- {
- var target = Event.element(e);
- if(target)
- {
- if(this.options['AutoPostBack']==true)
- {
- Event.fireEvent(target, "change");
- Event.stop(e);
- }
- else
- {
- if(this.options['CausesValidation'] && typeof(Prado.Validation) != "undefined")
- {
- if(!Prado.Validation.validate(this.options['FormID'], this.options['ValidationGroup'], $(this.options['ID'])))
- return Event.stop(e);
- }
- }
- }
- }
- }
-});
-
-Prado.WebUI.TListControl = Class.create(Prado.WebUI.PostBackControl,
-{
- onInit : function(options)
- {
- this.observe(this.element, "change", Prado.PostBack.bindEvent(this,options));
- }
-});
-
-Prado.WebUI.TListBox = Class.create(Prado.WebUI.TListControl);
-Prado.WebUI.TDropDownList = Class.create(Prado.WebUI.TListControl);
-
-Prado.WebUI.DefaultButton = Class.create(Prado.WebUI.Control,
-{
- onInit : function(options)
- {
- this.options = options;
- this.observe(options['Panel'], 'keydown', this.triggerEvent.bindEvent(this));
- },
-
- triggerEvent : function(ev, target)
- {
- var enterPressed = Event.keyCode(ev) == Event.KEY_RETURN;
- var isTextArea = Event.element(ev).tagName.toLowerCase() == "textarea";
- var isValidButton = Event.element(ev).tagName.toLowerCase() == "input" && Event.element(ev).type.toLowerCase() == "submit";
-
- if(enterPressed && !isTextArea && !isValidButton)
- {
- var defaultButton = $(this.options['Target']);
- if(defaultButton)
- {
- this.triggered = true;
- Event.fireEvent(defaultButton, this.options['Event']);
- Event.stop(ev);
- }
- }
- }
-});
-
-Prado.WebUI.TTextHighlighter = Class.create();
-Prado.WebUI.TTextHighlighter.prototype =
-{
- initialize:function(id)
- {
- if(!window.clipboardData) return;
- var options =
- {
- href : 'javascript:;/'+'/copy code to clipboard',
- onclick : 'Prado.WebUI.TTextHighlighter.copy(this)',
- onmouseover : 'Prado.WebUI.TTextHighlighter.hover(this)',
- onmouseout : 'Prado.WebUI.TTextHighlighter.out(this)'
- }
- var div = DIV({className:'copycode'}, A(options, 'Copy Code'));
- document.write(DIV(null,div).innerHTML);
- }
-};
-
-Object.extend(Prado.WebUI.TTextHighlighter,
-{
- copy : function(obj)
- {
- var parent = obj.parentNode.parentNode.parentNode;
- var text = '';
- for(var i = 0; i < parent.childNodes.length; i++)
- {
- var node = parent.childNodes[i];
- if(node.innerText)
- text += node.innerText == 'Copy Code' ? '' : node.innerText;
- else
- text += node.nodeValue;
- }
- if(text.length > 0)
- window.clipboardData.setData("Text", text);
- },
-
- hover : function(obj)
- {
- obj.parentNode.className = "copycode copycode_hover";
- },
-
- out : function(obj)
- {
- obj.parentNode.className = "copycode";
- }
-});
-
-
-Prado.WebUI.TCheckBoxList = Base.extend(
-{
- constructor : function(options)
- {
- Prado.Registry.set(options.ListID, this);
- for(var i = 0; i<options.ItemCount; i++)
- {
- var checkBoxOptions = Object.extend(
- {
- ID : options.ListID+"_c"+i,
- EventTarget : options.ListName+"$c"+i
- }, options);
- new Prado.WebUI.TCheckBox(checkBoxOptions);
- }
- }
-});
-
-Prado.WebUI.TRadioButtonList = Base.extend(
-{
- constructor : function(options)
- {
- Prado.Registry.set(options.ListID, this);
- for(var i = 0; i<options.ItemCount; i++)
- {
- var radioButtonOptions = Object.extend(
- {
- ID : options.ListID+"_c"+i,
- EventTarget : options.ListName+"$c"+i
- }, options);
- new Prado.WebUI.TRadioButton(radioButtonOptions);
- }
- }
-});
+Prado.WebUI = Class.create();
+
+Prado.WebUI.Control = Class.create({
+
+ initialize : function(options)
+ {
+ this.registered = false;
+ this.ID = options.ID;
+ this.element = $(this.ID);
+ this.observers = new Array();
+ this.intervals = new Array();
+ var e;
+ if (e = Prado.Registry.get(this.ID))
+ this.replace(e, options);
+ else
+ this.register(options);
+
+ if (this === Prado.Registry.get(this.ID))
+ {
+ this.registered = true;
+ if(this.onInit)
+ this.onInit(options);
+ }
+ },
+
+ /**
+ * Registers the control wrapper in the Prado client side control registry
+ * @param array control wrapper options
+ */
+ register : function(options)
+ {
+ return Prado.Registry.set(options.ID, this);
+ },
+
+ /**
+ * De-registers the control wrapper in the Prado client side control registry
+ */
+ deregister : function()
+ {
+ // extra check so we don't ever deregister another wrapper
+ if (Prado.Registry.get(this.ID)===this)
+ return Prado.Registry.unset(this.ID);
+ else
+ debugger; // invoke debugger - this should never happen
+ },
+
+ /**
+ * Replaces and control wrapper for an already existing control in the Prado client side control registry
+ * @param object reference to the old wrapper
+ * @param array control wrapper options
+ */
+ replace : function(oldwrapper, options)
+ {
+ // if there's some advanced state management in the wrapper going on, then
+ // this method could be used either to copy the current state of the control
+ // from the old wrapper to this new one (which then could live on, while the old
+ // one could get destroyed), or to copy the new, changed options to the old wrapper,
+ // (which could then left intact to keep working, while this new wrapper could be
+ // disposed of by exiting its initialization without installing any handlers or
+ // leaving any references to it)
+ //
+
+ // for now this method is simply deinitializing and deregistering the old wrapper,
+ // and then registering the new wrapper for the control id
+
+ if (oldwrapper.deinitialize)
+ oldwrapper.deinitialize();
+
+ return this.register(options);
+ },
+
+ /**
+ * Registers an event observer which will be automatically disposed of when the wrapper
+ * is deregistered
+ * @param element DOM element reference or id to attach the event handler to
+ * @param string event name to observe
+ * @param handler event handler function
+ */
+ observe: function(element, eventName, handler)
+ {
+ var e = { _element: element, _eventName: eventName, _handler: handler };
+ this.observers.push(e);
+ return Event.observe(e._element,e._eventName,e._handler);
+ },
+
+ /**
+ * Checks whether an event observer is installed and returns its index
+ * @param element DOM element reference or id the event handler was attached to
+ * @param string event name observed
+ * @param handler event handler function
+ * @result int false if the event handler is not installed, or 1-based index when installed
+ */
+ findObserver: function(element, eventName, handler)
+ {
+ var e = { _element: element, _eventName: eventName, _handler: handler };
+ var idx = -1;
+ for(var i=0;i<this.observers.length;i++)
+ {
+ var o = this.observers[i];
+ if ((o._element===element) && (o._eventName===eventName) && (o._handler===handler))
+ {
+ idx = i;
+ break;
+ }
+ }
+ return idx;
+ },
+
+
+ /**
+ * Degisters an event observer from the list of automatically disposed handlers
+ * @param element DOM element reference or id the event handler was attached to
+ * @param string event name observed
+ * @param handler event handler function
+ */
+ stopObserving: function(element, eventName, handler)
+ {
+ var idx = this.findObserver(element,eventName,handler);
+ if (idx!=-1)
+ this.observers = this.observers.without(this.observers[idx]);
+ else
+ debugger; // shouldn't happen
+
+ return Event.stopObserving(element,eventName,handler);
+ },
+
+ /**
+ * Registers a code snippet or function to be executed after a delay, if the
+ * wrapper hasn't been destroyed in the meantime
+ * @param code function or code snippet to execute
+ * @param int number of milliseconds to wait before executing
+ * @return int unique ID that can be used to cancel the scheduled execution
+ */
+ setTimeout: function(func, delay)
+ {
+ if (!Object.isFunction(func))
+ {
+ var expr = func;
+ func = function() { return eval(expr); }
+ };
+ var obj = this;
+ return window.setTimeout(function() {
+ if (!obj.isLingering())
+ func();
+ obj = null;
+ },delay);
+ },
+
+ /**
+ * Cancels a previously scheduled code snippet or function
+ * @param int unique ID returned by setTimeout()
+ */
+ clearTimeout: function(timeoutid)
+ {
+ return window.clearTimeout(timeoutid);
+ },
+
+ /**
+ * Registers a code snippet or function to be executed periodically, up until the
+ * wrapper gets destroyed or the schedule cancelled using cancelInterval()
+ * @param code function or code snippet to execute
+ * @param int number of milliseconds to wait before executing
+ * @return int unique ID that can be used to cancel the interval (see clearInterval() method)
+ */
+ setInterval: function(func, delay)
+ {
+ if (!Object.isFunction(func)) func = function() { eval(func); };
+ var obj = this;
+ var h = window.setInterval(function() {
+ if (!obj.isLingering())
+ func();
+ },delay);
+ this.intervals.push(h);
+ return h;
+ },
+
+ /**
+ * Deregisters a snipper or function previously registered with setInterval()
+ * @param int unique ID of interval (returned by setInterval() previously)
+ */
+ clearInterval: function(intervalid)
+ {
+ window.clearInterval(intervalid);
+ this.intervals = this.intervals.without(intervalid);
+ },
+
+ /**
+ * Tells whether this is a wrapper that has already been deregistered and is lingering
+ * @return bool true if object
+ */
+ isLingering: function()
+ {
+ return !this.registered;
+ },
+
+ /**
+ * Deinitializes the control wrapper by calling the onDone method and the deregistering it
+ * @param array control wrapper options
+ */
+ deinitialize : function()
+ {
+ if (this.registered)
+ {
+ if(this.onDone)
+ this.onDone();
+
+ // automatically stop all intervals
+ while (this.intervals.length>0)
+ window.clearInterval(this.intervals.pop());
+
+ // automatically deregister all installed observers
+ while (this.observers.length>0)
+ {
+ var e = this.observers.pop();
+ Event.stopObserving(e._element,e._eventName,e._handler);
+ }
+ }
+ else
+ debugger; // shouldn't happen
+
+ this.deregister();
+
+ this.registered = false;
+ }
+
+});
+
+Prado.WebUI.PostBackControl = Class.create(Prado.WebUI.Control, {
+
+ onInit : function(options)
+ {
+ this._elementOnClick = null;
+
+ if (!this.element)
+ debugger; // element not found
+ else
+ {
+ //capture the element's onclick function
+ if(typeof(this.element.onclick)=="function")
+ {
+ this._elementOnClick = this.element.onclick.bind(this.element);
+ this.element.onclick = null;
+ }
+ this.observe(this.element, "click", this.elementClicked.bindEvent(this,options));
+ }
+ },
+
+ elementClicked : function(event, options)
+ {
+ var src = Event.element(event);
+ var doPostBack = true;
+ var onclicked = null;
+
+ if(this._elementOnClick)
+ {
+ var onclicked = this._elementOnClick(event);
+ if(typeof(onclicked) == "boolean")
+ doPostBack = onclicked;
+ }
+ if(doPostBack && !Prado.Element.isDisabled(src))
+ this.onPostBack(event,options);
+ if(typeof(onclicked) == "boolean" && !onclicked)
+ Event.stop(event);
+ },
+
+ onPostBack : function(event, options)
+ {
+ Prado.PostBack(event,options);
+ }
+
+});
+
+Prado.WebUI.TButton = Class.create(Prado.WebUI.PostBackControl);
+Prado.WebUI.TLinkButton = Class.create(Prado.WebUI.PostBackControl);
+Prado.WebUI.TCheckBox = Class.create(Prado.WebUI.PostBackControl);
+Prado.WebUI.TBulletedList = Class.create(Prado.WebUI.PostBackControl);
+Prado.WebUI.TImageMap = Class.create(Prado.WebUI.PostBackControl);
+
+/**
+ * TImageButton client-side behaviour. With validation, Firefox needs
+ * to capture the x,y point of the clicked image in hidden form fields.
+ */
+Prado.WebUI.TImageButton = Class.create(Prado.WebUI.PostBackControl,
+{
+ /**
+ * Override parent onPostBack function, tried to add hidden forms
+ * inputs to capture x,y clicked point.
+ */
+ onPostBack : function(event, options)
+ {
+ this.addXYInput(event,options);
+ Prado.PostBack(event, options);
+ this.removeXYInput(event,options);
+ },
+
+ /**
+ * Add hidden inputs to capture the x,y point clicked on the image.
+ * @param event DOM click event.
+ * @param array image button options.
+ */
+ addXYInput : function(event,options)
+ {
+ var imagePos = this.element.cumulativeOffset();
+ var clickedPos = [event.clientX, event.clientY];
+ var x = clickedPos[0]-imagePos[0]+1;
+ var y = clickedPos[1]-imagePos[1]+1;
+ x = x < 0 ? 0 : x;
+ y = y < 0 ? 0 : y;
+ var id = options['EventTarget'];
+ var x_input = $(id+"_x");
+ var y_input = $(id+"_y");
+ if(x_input)
+ {
+ x_input.value = x;
+ }
+ else
+ {
+ x_input = INPUT({type:'hidden',name:id+'_x','id':id+'_x',value:x});
+ this.element.parentNode.appendChild(x_input);
+ }
+ if(y_input)
+ {
+ y_input.value = y;
+ }
+ else
+ {
+ y_input = INPUT({type:'hidden',name:id+'_y','id':id+'_y',value:y});
+ this.element.parentNode.appendChild(y_input);
+ }
+ },
+
+ /**
+ * Remove hidden inputs for x,y-click capturing
+ * @param event DOM click event.
+ * @param array image button options.
+ */
+ removeXYInput : function(event,options)
+ {
+ var id = options['EventTarget'];
+ this.element.parentNode.removeChild($(id+"_x"));
+ this.element.parentNode.removeChild($(id+"_y"));
+ }
+});
+
+
+/**
+ * Radio button, only initialize if not already checked.
+ */
+Prado.WebUI.TRadioButton = Class.create(Prado.WebUI.PostBackControl,
+{
+ initialize : function($super, options)
+ {
+ this.element = $(options['ID']);
+ if(this.element)
+ {
+ if(!this.element.checked)
+ $super(options);
+ }
+ }
+});
+
+
+Prado.WebUI.TTextBox = Class.create(Prado.WebUI.PostBackControl,
+{
+ onInit : function(options)
+ {
+ this.options=options;
+ if(this.options['TextMode'] != 'MultiLine')
+ this.observe(this.element, "keydown", this.handleReturnKey.bind(this));
+ if(this.options['AutoPostBack']==true)
+ this.observe(this.element, "change", Prado.PostBack.bindEvent(this,options));
+ },
+
+ handleReturnKey : function(e)
+ {
+ if(Event.keyCode(e) == Event.KEY_RETURN)
+ {
+ var target = Event.element(e);
+ if(target)
+ {
+ if(this.options['AutoPostBack']==true)
+ {
+ Event.fireEvent(target, "change");
+ Event.stop(e);
+ }
+ else
+ {
+ if(this.options['CausesValidation'] && typeof(Prado.Validation) != "undefined")
+ {
+ if(!Prado.Validation.validate(this.options['FormID'], this.options['ValidationGroup'], $(this.options['ID'])))
+ return Event.stop(e);
+ }
+ }
+ }
+ }
+ }
+});
+
+Prado.WebUI.TListControl = Class.create(Prado.WebUI.PostBackControl,
+{
+ onInit : function(options)
+ {
+ this.observe(this.element, "change", Prado.PostBack.bindEvent(this,options));
+ }
+});
+
+Prado.WebUI.TListBox = Class.create(Prado.WebUI.TListControl);
+Prado.WebUI.TDropDownList = Class.create(Prado.WebUI.TListControl);
+
+Prado.WebUI.DefaultButton = Class.create(Prado.WebUI.Control,
+{
+ onInit : function(options)
+ {
+ this.options = options;
+ this.observe(options['Panel'], 'keydown', this.triggerEvent.bindEvent(this));
+ },
+
+ triggerEvent : function(ev, target)
+ {
+ var enterPressed = Event.keyCode(ev) == Event.KEY_RETURN;
+ var isTextArea = Event.element(ev).tagName.toLowerCase() == "textarea";
+ var isValidButton = Event.element(ev).tagName.toLowerCase() == "input" && Event.element(ev).type.toLowerCase() == "submit";
+
+ if(enterPressed && !isTextArea && !isValidButton)
+ {
+ var defaultButton = $(this.options['Target']);
+ if(defaultButton)
+ {
+ this.triggered = true;
+ Event.fireEvent(defaultButton, this.options['Event']);
+ Event.stop(ev);
+ }
+ }
+ }
+});
+
+Prado.WebUI.TTextHighlighter = Class.create();
+Prado.WebUI.TTextHighlighter.prototype =
+{
+ initialize:function(id)
+ {
+ if(!window.clipboardData) return;
+ var options =
+ {
+ href : 'javascript:;/'+'/copy code to clipboard',
+ onclick : 'Prado.WebUI.TTextHighlighter.copy(this)',
+ onmouseover : 'Prado.WebUI.TTextHighlighter.hover(this)',
+ onmouseout : 'Prado.WebUI.TTextHighlighter.out(this)'
+ }
+ var div = DIV({className:'copycode'}, A(options, 'Copy Code'));
+ document.write(DIV(null,div).innerHTML);
+ }
+};
+
+Object.extend(Prado.WebUI.TTextHighlighter,
+{
+ copy : function(obj)
+ {
+ var parent = obj.parentNode.parentNode.parentNode;
+ var text = '';
+ for(var i = 0; i < parent.childNodes.length; i++)
+ {
+ var node = parent.childNodes[i];
+ if(node.innerText)
+ text += node.innerText == 'Copy Code' ? '' : node.innerText;
+ else
+ text += node.nodeValue;
+ }
+ if(text.length > 0)
+ window.clipboardData.setData("Text", text);
+ },
+
+ hover : function(obj)
+ {
+ obj.parentNode.className = "copycode copycode_hover";
+ },
+
+ out : function(obj)
+ {
+ obj.parentNode.className = "copycode";
+ }
+});
+
+
+Prado.WebUI.TCheckBoxList = Base.extend(
+{
+ constructor : function(options)
+ {
+ Prado.Registry.set(options.ListID, this);
+ for(var i = 0; i<options.ItemCount; i++)
+ {
+ var checkBoxOptions = Object.extend(
+ {
+ ID : options.ListID+"_c"+i,
+ EventTarget : options.ListName+"$c"+i
+ }, options);
+ new Prado.WebUI.TCheckBox(checkBoxOptions);
+ }
+ }
+});
+
+Prado.WebUI.TRadioButtonList = Base.extend(
+{
+ constructor : function(options)
+ {
+ Prado.Registry.set(options.ListID, this);
+ for(var i = 0; i<options.ItemCount; i++)
+ {
+ var radioButtonOptions = Object.extend(
+ {
+ ID : options.ListID+"_c"+i,
+ EventTarget : options.ListName+"$c"+i
+ }, options);
+ new Prado.WebUI.TRadioButton(radioButtonOptions);
+ }
+ }
+});
diff --git a/framework/Web/Javascripts/source/prado/controls/htmlarea.js b/framework/Web/Javascripts/source/prado/controls/htmlarea.js
index 4cb37c6f..56d4cf16 100644
--- a/framework/Web/Javascripts/source/prado/controls/htmlarea.js
+++ b/framework/Web/Javascripts/source/prado/controls/htmlarea.js
@@ -1,149 +1,149 @@
-
-/*
- *
- * HtmlArea (tinyMCE) wrapper
- *
- * @author Gabor Berczi <gabor.berczi@devworx.hu>
- *
-*/
-
-
-Prado.WebUI.THtmlArea = Class.create(Prado.WebUI.Control,
-{
- initialize: function($super, options)
- {
- options.ID = options.EditorOptions.elements;
- $super(options);
- },
-
- onInit : function(options)
- {
- this.options = options;
-
- var obj = this;
- this.ajaxresponder = {
- onComplete : function(request)
- {
- if(request && (request instanceof Prado.AjaxRequest))
- obj.checkInstance();
- }
- };
- this.registerAjaxHook();
-
- this.registerInstance();
- },
-
- registerInstance: function()
- {
- if (typeof tinyMCE_GZ == 'undefined')
- {
- if (typeof tinyMCE == 'undefined')
- {
- if (typeof Prado.CallbackRequest != 'undefined')
- if (typeof Prado.CallbackRequest.transport != 'undefined')
- {
- // we're in a callback
- // try it again in some time, as tinyMCE is most likely still loading
- this.setTimeout(this.registerInstance.bind(this), 50);
- return;
- }
- throw "TinyMCE libraries must be loaded first";
- }
- Prado.WebUI.THtmlArea.tinyMCELoadState = 255;
- this.initInstance();
- }
- else
- if (Prado.WebUI.THtmlArea.tinyMCELoadState==255)
- this.initInstance();
- else
- {
- Prado.WebUI.THtmlArea.pendingRegistrations.push(this.options.ID);
- if (Prado.WebUI.THtmlArea.tinyMCELoadState==0)
- {
- Prado.WebUI.THtmlArea.tinyMCELoadState = 1;
- tinyMCE_GZ.init(
- this.options.CompressionOptions,
- this.compressedScriptsLoaded.bind(this)
- );
- }
- }
- },
-
- compressedScriptsLoaded: function()
- {
- Prado.WebUI.THtmlArea.tinyMCELoadState = 255;
- tinymce.dom.Event._pageInit();
- var wrapper;
- while(Prado.WebUI.THtmlArea.pendingRegistrations.length>0)
- if (wrapper = Prado.Registry.get(Prado.WebUI.THtmlArea.pendingRegistrations.pop()))
- wrapper.initInstance();
- },
-
- initInstance: function()
- {
- tinyMCE.init(this.options.EditorOptions);
- },
-
- checkInstance: function()
- {
- if (!document.getElementById(this.ID))
- this.deinitialize();
- },
-
- removePreviousInstance: function()
- {
- for(var i=0;i<tinyMCE.editors.length;i++)
- if (tinyMCE.editors[i].id==this.ID)
- {
- tinyMCE.editors.splice(i,1); // ugly hack, but works
- this.deRegisterAjaxHook();
- this.deregister();
- i--;
- }
- },
-
- registerAjaxHook: function()
- {
- if (typeof(Ajax)!="undefined")
- if (typeof(Ajax.Responders)!="undefined")
- Ajax.Responders.register(this.ajaxresponder);
- },
-
-
- deRegisterAjaxHook: function()
- {
- if (typeof(Ajax)!="undefined")
- if (typeof(Ajax.Responders)!="undefined")
- Ajax.Responders.unregister(this.ajaxresponder);
- },
-
- onDone: function()
- {
- // check for previous tinyMCE registration, and try to remove it gracefully first
- var prev = tinyMCE.get(this.ID);
- if (prev)
- try
- {
- tinyMCE.execCommand('mceFocus', false, this.ID);
- tinyMCE.execCommand('mceRemoveControl', false, this.ID);
- }
- catch (e)
- {
- // suppress error here in case editor can't be properly removed
- // (happens when <textarea> has been removed from DOM tree without deinitialzing the tinyMCE editor first)
- }
-
- // doublecheck editor instance here and remove manually from tinyMCE-registry if neccessary
- this.removePreviousInstance();
-
- this.deRegisterAjaxHook();
- }
-});
-
-Object.extend(Prado.WebUI.THtmlArea,
-{
- pendingRegistrations : [],
- tinyMCELoadState : 0
-});
-
-
+
+/*
+ *
+ * HtmlArea (tinyMCE) wrapper
+ *
+ * @author Gabor Berczi <gabor.berczi@devworx.hu>
+ *
+*/
+
+
+Prado.WebUI.THtmlArea = Class.create(Prado.WebUI.Control,
+{
+ initialize: function($super, options)
+ {
+ options.ID = options.EditorOptions.elements;
+ $super(options);
+ },
+
+ onInit : function(options)
+ {
+ this.options = options;
+
+ var obj = this;
+ this.ajaxresponder = {
+ onComplete : function(request)
+ {
+ if(request && (request instanceof Prado.AjaxRequest))
+ obj.checkInstance();
+ }
+ };
+ this.registerAjaxHook();
+
+ this.registerInstance();
+ },
+
+ registerInstance: function()
+ {
+ if (typeof tinyMCE_GZ == 'undefined')
+ {
+ if (typeof tinyMCE == 'undefined')
+ {
+ if (typeof Prado.CallbackRequest != 'undefined')
+ if (typeof Prado.CallbackRequest.transport != 'undefined')
+ {
+ // we're in a callback
+ // try it again in some time, as tinyMCE is most likely still loading
+ this.setTimeout(this.registerInstance.bind(this), 50);
+ return;
+ }
+ throw "TinyMCE libraries must be loaded first";
+ }
+ Prado.WebUI.THtmlArea.tinyMCELoadState = 255;
+ this.initInstance();
+ }
+ else
+ if (Prado.WebUI.THtmlArea.tinyMCELoadState==255)
+ this.initInstance();
+ else
+ {
+ Prado.WebUI.THtmlArea.pendingRegistrations.push(this.options.ID);
+ if (Prado.WebUI.THtmlArea.tinyMCELoadState==0)
+ {
+ Prado.WebUI.THtmlArea.tinyMCELoadState = 1;
+ tinyMCE_GZ.init(
+ this.options.CompressionOptions,
+ this.compressedScriptsLoaded.bind(this)
+ );
+ }
+ }
+ },
+
+ compressedScriptsLoaded: function()
+ {
+ Prado.WebUI.THtmlArea.tinyMCELoadState = 255;
+ tinymce.dom.Event._pageInit();
+ var wrapper;
+ while(Prado.WebUI.THtmlArea.pendingRegistrations.length>0)
+ if (wrapper = Prado.Registry.get(Prado.WebUI.THtmlArea.pendingRegistrations.pop()))
+ wrapper.initInstance();
+ },
+
+ initInstance: function()
+ {
+ tinyMCE.init(this.options.EditorOptions);
+ },
+
+ checkInstance: function()
+ {
+ if (!document.getElementById(this.ID))
+ this.deinitialize();
+ },
+
+ removePreviousInstance: function()
+ {
+ for(var i=0;i<tinyMCE.editors.length;i++)
+ if (tinyMCE.editors[i].id==this.ID)
+ {
+ tinyMCE.editors.splice(i,1); // ugly hack, but works
+ this.deRegisterAjaxHook();
+ this.deregister();
+ i--;
+ }
+ },
+
+ registerAjaxHook: function()
+ {
+ if (typeof(Ajax)!="undefined")
+ if (typeof(Ajax.Responders)!="undefined")
+ Ajax.Responders.register(this.ajaxresponder);
+ },
+
+
+ deRegisterAjaxHook: function()
+ {
+ if (typeof(Ajax)!="undefined")
+ if (typeof(Ajax.Responders)!="undefined")
+ Ajax.Responders.unregister(this.ajaxresponder);
+ },
+
+ onDone: function()
+ {
+ // check for previous tinyMCE registration, and try to remove it gracefully first
+ var prev = tinyMCE.get(this.ID);
+ if (prev)
+ try
+ {
+ tinyMCE.execCommand('mceFocus', false, this.ID);
+ tinyMCE.execCommand('mceRemoveControl', false, this.ID);
+ }
+ catch (e)
+ {
+ // suppress error here in case editor can't be properly removed
+ // (happens when <textarea> has been removed from DOM tree without deinitialzing the tinyMCE editor first)
+ }
+
+ // doublecheck editor instance here and remove manually from tinyMCE-registry if neccessary
+ this.removePreviousInstance();
+
+ this.deRegisterAjaxHook();
+ }
+});
+
+Object.extend(Prado.WebUI.THtmlArea,
+{
+ pendingRegistrations : [],
+ tinyMCELoadState : 0
+});
+
+
diff --git a/framework/Web/Javascripts/source/prado/controls/keyboard.js b/framework/Web/Javascripts/source/prado/controls/keyboard.js
index 5b8a6b15..25541074 100644
--- a/framework/Web/Javascripts/source/prado/controls/keyboard.js
+++ b/framework/Web/Javascripts/source/prado/controls/keyboard.js
@@ -1,161 +1,161 @@
-Prado.WebUI.TKeyboard = Class.create(Prado.WebUI.Control,
-{
- 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 &amp; 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', ', &lt; D', '. &gt; 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;
- }
- }
-});
+Prado.WebUI.TKeyboard = Class.create(Prado.WebUI.Control,
+{
+ 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 &amp; 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', ', &lt; D', '. &gt; 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;
+ }
+ }
+});
diff --git a/framework/Web/Javascripts/source/prado/controls/tabpanel.js b/framework/Web/Javascripts/source/prado/controls/tabpanel.js
index 157664e3..bd0a7494 100644
--- a/framework/Web/Javascripts/source/prado/controls/tabpanel.js
+++ b/framework/Web/Javascripts/source/prado/controls/tabpanel.js
@@ -1,60 +1,60 @@
-Prado.WebUI.TTabPanel = Class.create(Prado.WebUI.Control,
-{
- onInit : function(options)
- {
- this.views = options.Views;
- this.viewsvis = options.ViewsVis;
- this.hiddenField = $(options.ID+'_1');
- this.activeCssClass = options.ActiveCssClass;
- this.normalCssClass = options.NormalCssClass;
- var length = options.Views.length;
- for(var i = 0; i<length; i++)
- {
- var item = options.Views[i];
- var element = $(item+'_0');
- if (element && options.ViewsVis[i])
- {
- this.observe(element, "click", this.elementClicked.bindEvent(this,item));
- if (options.AutoSwitch)
- this.observe(element, "mouseenter", this.elementClicked.bindEvent(this,item));
- }
-
- if(element)
- {
- var view = $(options.Views[i]);
- if (view)
- if(this.hiddenField.value == i)
- {
- element.className=this.activeCssClass;
- view.show();
- } else {
- element.className=this.normalCssClass;
- view.hide();
- }
- }
- }
- },
-
- elementClicked : function(event,viewID)
- {
- var length = this.views.length;
- for(var i = 0; i<length; i++)
- {
- var item = this.views[i];
- if ($(item))
- {
- if(item == viewID)
- {
- $(item+'_0').className=this.activeCssClass;
- $(item).show();
- this.hiddenField.value=i;
- }
- else
- {
- $(item+'_0').className=this.normalCssClass;
- $(item).hide();
- }
- }
- }
- }
-});
+Prado.WebUI.TTabPanel = Class.create(Prado.WebUI.Control,
+{
+ onInit : function(options)
+ {
+ this.views = options.Views;
+ this.viewsvis = options.ViewsVis;
+ this.hiddenField = $(options.ID+'_1');
+ this.activeCssClass = options.ActiveCssClass;
+ this.normalCssClass = options.NormalCssClass;
+ var length = options.Views.length;
+ for(var i = 0; i<length; i++)
+ {
+ var item = options.Views[i];
+ var element = $(item+'_0');
+ if (element && options.ViewsVis[i])
+ {
+ this.observe(element, "click", this.elementClicked.bindEvent(this,item));
+ if (options.AutoSwitch)
+ this.observe(element, "mouseenter", this.elementClicked.bindEvent(this,item));
+ }
+
+ if(element)
+ {
+ var view = $(options.Views[i]);
+ if (view)
+ if(this.hiddenField.value == i)
+ {
+ element.className=this.activeCssClass;
+ view.show();
+ } else {
+ element.className=this.normalCssClass;
+ view.hide();
+ }
+ }
+ }
+ },
+
+ elementClicked : function(event,viewID)
+ {
+ var length = this.views.length;
+ for(var i = 0; i<length; i++)
+ {
+ var item = this.views[i];
+ if ($(item))
+ {
+ if(item == viewID)
+ {
+ $(item+'_0').className=this.activeCssClass;
+ $(item).show();
+ this.hiddenField.value=i;
+ }
+ else
+ {
+ $(item+'_0').className=this.normalCssClass;
+ $(item).hide();
+ }
+ }
+ }
+ }
+});
diff --git a/framework/Web/Javascripts/source/prado/datepicker/datepicker.js b/framework/Web/Javascripts/source/prado/datepicker/datepicker.js
index e92904c8..ad7eb019 100644
--- a/framework/Web/Javascripts/source/prado/datepicker/datepicker.js
+++ b/framework/Web/Javascripts/source/prado/datepicker/datepicker.js
@@ -1,790 +1,790 @@
-Prado.WebUI.TDatePicker = Class.create(Prado.WebUI.Control,
-{
- 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, // 0 for sunday
-
- ClassName : "",
-
- CalendarStyle : "default",
-
- FromYear : 2005, UpToYear: 2020,
-
- onInit : function(options)
- {
- this.options = options || [];
- this.control = $(options.ID);
- this.dateSlot = new Array(42);
- this.weekSlot = new Array(6);
- this.minimalDaysInFirstWeek = 4;
- this.positionMode = 'Bottom';
-
- Prado.Registry.set(options.ID, this);
-
- //which element to trigger to show the calendar
- 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";
- }
-
- // Popup position
- if(this.options.PositionMode == 'Top')
- {
- this.positionMode = this.options.PositionMode;
- }
-
- Object.extend(this,options);
- // generate default date _after_ extending options
- this.selectedDate = this.newDate();
-
- Event.observe(this.trigger, triggerEvent, this.show.bindEvent(this));
-
- // Listen to change event if needed
- if (typeof(this.options.OnDateChanged) == "function")
- {
- if(this.options.InputMode == "TextBox")
- {
- Event.observe(this.control, "change", this.onDateChanged.bindEvent(this));
- }
- else
- {
- var day = Prado.WebUI.TDatePicker.getDayListControl(this.control);
- var month = Prado.WebUI.TDatePicker.getMonthListControl(this.control);
- var year = Prado.WebUI.TDatePicker.getYearListControl(this.control);
- Event.observe (day, "change", this.onDateChanged.bindEvent(this));
- Event.observe (month, "change", this.onDateChanged.bindEvent(this));
- Event.observe (year, "change", this.onDateChanged.bindEvent(this));
-
- }
-
-
- }
-
- },
-
- create : function()
- {
- if(typeof(this._calDiv) != "undefined")
- return;
-
- var div;
- var table;
- var tbody;
- var tr;
- var td;
-
- // Create the top-level div element
- this._calDiv = document.createElement("div");
- this._calDiv.className = "TDatePicker_"+this.CalendarStyle+" "+this.ClassName;
- this._calDiv.style.display = "none";
- this._calDiv.style.position = "absolute"
-
- // header div
- 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);
-
- // Previous Month Button
- td = document.createElement("td");
- var previousMonth = document.createElement("input");
- previousMonth.className = "prevMonthButton button";
- previousMonth.type = "button"
- previousMonth.value = "<<";
- td.appendChild(previousMonth);
- tr.appendChild(td);
-
-
-
- //
- // Create the month drop down
- //
- 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);
- }
- td.appendChild(this._monthSelect);
-
-
- //
- // Create the year drop down
- //
- td = document.createElement("td");
- td.className = "labelContainer";
- tr.appendChild(td);
- this._yearSelect = document.createElement("select");
- for(var i=this.FromYear; i <= this.UpToYear; ++i) {
- var opt = document.createElement("option");
- opt.innerHTML = i;
- opt.value = i;
- if (i == this.selectedDate.getFullYear()) {
- opt.selected = false;
- }
- this._yearSelect.appendChild(opt);
- }
- 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);
-
- // Calendar body
- div = document.createElement("div");
- div.className = "calendarBody";
- this._calDiv.appendChild(div);
- var calendarBody = div;
-
- // Create the inside of calendar body
-
- 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);
- }
-
- // Date grid
- tbody = document.createElement("tbody");
- table.appendChild(tbody);
-
- for(var week=0; week<6; ++week) {
- tr = document.createElement("tr");
- tbody.appendChild(tr);
-
- for(var 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));
-
- }
- }
-
- // Calendar Footer
- 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"
- this.control.parentNode.appendChild(this.iePopUp);
- }
-
- this.control.parentNode.appendChild(this._calDiv);
-
- this.update();
- this.updateHeader();
-
- this.ieHack(true);
-
- // IE55+ extension
- previousMonth.hideFocus = true;
- nextMonth.hideFocus = true;
- todayButton.hideFocus = true;
- // end IE55+ extension
-
- // hook up events
- Event.observe(previousMonth, "click", this.prevMonth.bindEvent(this));
- Event.observe(nextMonth, "click", this.nextMonth.bindEvent(this));
- Event.observe(todayButton, "click", this.selectToday.bindEvent(this));
- //Event.observe(clearButton, "click", this.clearSelection.bindEvent(this));
- Event.observe(this._monthSelect, "change", this.monthSelect.bindEvent(this));
- Event.observe(this._yearSelect, "change", this.yearSelect.bindEvent(this));
-
- // ie, opera
- Event.observe(this._calDiv, "mousewheel", this.mouseWheelChange.bindEvent(this));
- // ff
- Event.observe(this._calDiv, "DOMMouseScroll", this.mouseWheelChange.bindEvent(this));
-
- Event.observe(calendarBody, "click", this.selectDate.bindEvent(this));
-
- Prado.Element.focus(this.control);
-
- },
-
- ieHack : function(cleanup)
- {
- // IE hack
- if(this.iePopUp)
- {
- this.iePopUp.style.display = "block";
- this.iePopUp.style.left = (this._calDiv.offsetLeft -1)+ "px";
- this.iePopUp.style.top = (this._calDiv.offsetTop -1 ) + "px";
- this.iePopUp.style.width = Math.abs(this._calDiv.offsetWidth -2)+ "px";
- this.iePopUp.style.height = (this._calDiv.offsetHeight + 1)+ "px";
- if(cleanup) this.iePopUp.style.display = "none";
- }
- },
-
- keyPressed : function(ev)
- {
- if(!this.showing) return;
- if (!ev) ev = document.parentWindow.event;
- var kc = ev.keyCode != null ? ev.keyCode : ev.charCode;
-
- if(kc == Event.KEY_RETURN || kc == Event.KEY_SPACEBAR || kc == Event.KEY_TAB)
- {
- this.setSelectedDate(this.selectedDate);
- Event.stop(ev);
- this.hide();
- }
- if(kc == Event.KEY_ESC)
- {
- Event.stop(ev); this.hide();
- }
-
- var getDaysPerMonth = function (nMonth, nYear)
- {
- nMonth = (nMonth + 12) % 12;
- var days= [31,28,31,30,31,30,31,31,30,31,30,31];
- var res = days[nMonth];
- if (nMonth == 1) //feburary, leap years has 29
- res += nYear % 4 == 0 && !(nYear % 400 == 0) ? 1 : 0;
- return res;
- }
-
- if(kc < 37 || kc > 40) return true;
-
- var current = this.selectedDate;
- var d = current.valueOf();
- if(kc == Event.KEY_LEFT)
- {
- if(ev.ctrlKey || ev.shiftKey) // -1 month
- {
- current.setDate( Math.min(current.getDate(), getDaysPerMonth(current.getMonth() - 1,current.getFullYear())) ); // no need to catch dec -> jan for the year
- d = current.setMonth( current.getMonth() - 1 );
- }
- else
- d -= 86400000; //-1 day
- }
- else if (kc == Event.KEY_RIGHT)
- {
- if(ev.ctrlKey || ev.shiftKey) // +1 month
- {
- current.setDate( Math.min(current.getDate(), getDaysPerMonth(current.getMonth() + 1,current.getFullYear())) ); // no need to catch dec -> jan for the year
- d = current.setMonth( current.getMonth() + 1 );
- }
- else
- d += 86400000; //+1 day
- }
- else if (kc == Event.KEY_UP)
- {
- if(ev.ctrlKey || ev.shiftKey) //-1 year
- {
- current.setDate( Math.min(current.getDate(), getDaysPerMonth(current.getMonth(),current.getFullYear() - 1)) ); // no need to catch dec -> jan for the year
- d = current.setFullYear( current.getFullYear() - 1 );
- }
- else
- d -= 604800000; // -7 days
- }
- else if (kc == Event.KEY_DOWN)
- {
- if(ev.ctrlKey || ev.shiftKey) // +1 year
- {
- current.setDate( Math.min(current.getDate(), getDaysPerMonth(current.getMonth(),current.getFullYear() + 1)) ); // no need to catch dec -> jan for the year
- d = current.setFullYear( current.getFullYear() + 1 );
- }
- else
- d += 7 * 24 * 61 * 60 * 1000; // +7 days
- }
- this.setSelectedDate(d);
- Event.stop(ev);
- },
-
- selectDate : function(ev)
- {
- var el = Event.element(ev);
- while (el.nodeType != 1)
- el = el.parentNode;
-
- while (el != null && el.tagName && el.tagName.toLowerCase() != "td")
- el = el.parentNode;
-
- // if no td found, return
- if (el == null || el.tagName == null || el.tagName.toLowerCase() != "td")
- return;
-
- var d = this.newDate(this.selectedDate);
- var n = Number(el.firstChild.data);
- if (isNaN(n) || n <= 0 || n == null)
- return;
-
- d.setDate(n);
- this.setSelectedDate(d);
- this.hide();
- },
-
- selectToday : function()
- {
- if(this.selectedDate.toISODate() == this.newDate().toISODate())
- this.hide();
-
- this.setSelectedDate(this.newDate());
- },
-
- clearSelection : function()
- {
- this.setSelectedDate(this.newDate());
- this.hide();
- },
-
- monthSelect : function(ev)
- {
- this.setMonth(Form.Element.getValue(Event.element(ev)));
- },
-
- yearSelect : function(ev)
- {
- this.setYear(Form.Element.getValue(Event.element(ev)));
- },
-
- mouseWheelChange : function (event)
- {
- var delta = 0;
- if (!event) event = document.parentWindow.event;
- if (event.wheelDelta) {
- delta = event.wheelDelta/120;
- if (window.opera) delta = -delta;
- } else if (event.detail) { delta = -event.detail/3; }
-
- var d = this.newDate(this.selectedDate);
- var m = d.getMonth() + Math.round(delta);
- this.setMonth(m,true);
- return false;
- },
-
- // Respond to change event on the textbox or dropdown list
- // This method raises OnDateChanged event on client side if it has been defined
- onDateChanged : function ()
- {
- if (this.options.OnDateChanged)
- {
- var date;
- if (this.options.InputMode == "TextBox")
- {
- date=this.control.value;
- }
- else
- {
- var day = Prado.WebUI.TDatePicker.getDayListControl(this.control).selectedIndex+1;
- var month = Prado.WebUI.TDatePicker.getMonthListControl(this.control).selectedIndex;
- var year = Prado.WebUI.TDatePicker.getYearListControl(this.control).value;
- date=new Date(year, month, day, 0,0,0).SimpleFormat(this.Format, this);
- }
- this.options.OnDateChanged(this, date);
- }
- },
-
- fireChangeEvent: function(element, capped)
- {
- if (capped)
- {
- var obj = this;
-
- if (typeof(obj.changeeventtimer)!="undefined")
- {
- clearTimeout(obj.changeeventtimer);
- obj.changeeventtimer = null;
- }
- obj.changeeventtimer = setTimeout(
- function() { obj.changeeventtimer = null; Event.fireEvent(element, "change"); },
- 1500
- );
- }
- else
- Event.fireEvent(element, "change");
- },
-
- onChange : function(ref, date, capevents)
- {
- if(this.options.InputMode == "TextBox")
- {
- this.control.value = this.formatDate();
- this.fireChangeEvent(this.control, capevents);
- }
- else
- {
- var day = Prado.WebUI.TDatePicker.getDayListControl(this.control);
- var month = Prado.WebUI.TDatePicker.getMonthListControl(this.control);
- var year = Prado.WebUI.TDatePicker.getYearListControl(this.control);
- var date = this.selectedDate;
- if(day)
- {
- day.selectedIndex = date.getDate()-1;
- }
- if(month)
- {
- month.selectedIndex = date.getMonth();
- }
- if(year)
- {
- var years = year.options;
- var currentYear = date.getFullYear();
- for(var i = 0; i < years.length; i++)
- years[i].selected = years[i].value.toInteger() == currentYear;
- }
- this.fireChangeEvent(day || month || year, capevents);
- }
- },
-
- formatDate : function()
- {
- return this.selectedDate ? this.selectedDate.SimpleFormat(this.Format,this) : '';
- },
-
- newDate : function(date)
- {
- if(!date)
- date = new Date();
- if(typeof(date) == "string" || typeof(date) == "number")
- date = new Date(date);
- return new Date(Math.min(Math.max(date.getFullYear(),this.FromYear),this.UpToYear), date.getMonth(), date.getDate(), 0,0,0);
- },
-
- setSelectedDate : function(date, capevents)
- {
- if (date == null)
- return;
- var old=this.selectedDate;
- this.selectedDate = this.newDate(date);
- var dateChanged=(old - this.selectedDate != 0) || ( this.options.InputMode == "TextBox" && this.control.value != this.formatDate());
-
- this.updateHeader();
- this.update();
- if (dateChanged && typeof(this.onChange) == "function")
- this.onChange(this, date, capevents);
- },
-
- getElement : function()
- {
- return this._calDiv;
- },
-
- getSelectedDate : function ()
- {
- return this.selectedDate == null ? null : this.newDate(this.selectedDate);
- },
-
- setYear : function(year)
- {
- var d = this.newDate(this.selectedDate);
- d.setFullYear(year);
- this.setSelectedDate(d);
- },
-
- setMonth : function (month, capevents)
- {
- var d = this.newDate(this.selectedDate);
- d.setDate(Math.min(d.getDate(), this.getDaysPerMonth(month,d.getFullYear())));
- d.setMonth(month);
- this.setSelectedDate(d,capevents);
- },
-
- nextMonth : function ()
- {
- this.setMonth(this.selectedDate.getMonth()+1);
- },
-
- prevMonth : function ()
- {
- this.setMonth(this.selectedDate.getMonth()-1);
- },
-
- getDaysPerMonth : function (month, year)
- {
- month = (Number(month)+12) % 12;
- var days = [31,28,31,30,31,30,31,31,30,31,30,31];
- var res = days[month];
- if (month == 1 && ((!(year % 4) && (year % 100)) || !(year % 400))) //feburary, leap years has 29
- res++;
- return res;
- },
-
- getDatePickerOffsetHeight : function()
- {
- if(this.options.InputMode == "TextBox")
- return this.control.offsetHeight;
-
- var control = Prado.WebUI.TDatePicker.getDayListControl(this.control);
- if(control) return control.offsetHeight;
-
- var control = Prado.WebUI.TDatePicker.getMonthListControl(this.control);
- if(control) return control.offsetHeight;
-
- var control = Prado.WebUI.TDatePicker.getYearListControl(this.control);
- if(control) return control.offsetHeight;
- return 0;
- },
-
- show : function()
- {
- this.create();
-
- if(!this.showing)
- {
- var pos = this.control.positionedOffset();
-
- pos[1] += this.getDatePickerOffsetHeight();
- this._calDiv.style.top = (pos[1]-1) + "px";
- this._calDiv.style.display = "block";
- this._calDiv.style.left = pos[0] + "px";
-
- this.documentClickEvent = this.hideOnClick.bindEvent(this);
- this.documentKeyDownEvent = this.keyPressed.bindEvent(this);
- Event.observe(document.body, "click", this.documentClickEvent);
- var date = this.getDateFromInput();
- if(date)
- {
- this.selectedDate = date;
- this.setSelectedDate(date);
- }
- Event.observe(document,"keydown", this.documentKeyDownEvent);
- this.showing = true;
-
- if(this.positionMode=='Top')
- {
- this._calDiv.style.top = ((pos[1]-1) - this.getDatePickerOffsetHeight() - this._calDiv.offsetHeight) + 'px';
- if(Prado.Browser().ie)
- this.iePopup = this._calDiv.style.top;
- }
- this.ieHack(false);
- }
- },
-
- getDateFromInput : function()
- {
- if(this.options.InputMode == "TextBox")
- return Date.SimpleParse($F(this.control), this.Format);
- else
- return Prado.WebUI.TDatePicker.getDropDownDate(this.control);
- },
-
- //hide the calendar when clicked outside any calendar
- hideOnClick : function(ev)
- {
- if(!this.showing) return;
- var el = Event.element(ev);
- var within = false;
- do
- {
- 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)
- this.iePopUp.style.display = "none";
- this.showing = false;
- Event.stopObserving(document.body, "click", this.documentClickEvent);
- Event.stopObserving(document,"keydown", this.documentKeyDownEvent);
- }
- },
-
- update : function()
- {
- // Calculate the number of days in the month for the selected date
- var date = this.selectedDate;
- var today = (this.newDate()).toISODate();
-
- var selected = date.toISODate();
- var d1 = new Date(date.getFullYear(), date.getMonth(), 1);
- var d2 = new Date(date.getFullYear(), date.getMonth()+1, 1);
- var monthLength = Math.round((d2 - d1) / (24 * 60 * 60 * 1000));
-
- // Find out the weekDay index for the first of this month
- var firstIndex = (d1.getDay() - this.FirstDayOfWeek) % 7 ;
- if (firstIndex < 0)
- firstIndex += 7;
-
- var index = 0;
- while (index < firstIndex) {
- this.dateSlot[index].value = -1;
- this.dateSlot[index].data.data = String.fromCharCode(160);
- this.dateSlot[index].data.parentNode.className = "empty";
- index++;
- }
-
- for (var i = 1; i <= monthLength; i++, index++) {
- var slot = this.dateSlot[index];
- var slotNode = slot.data.parentNode;
- slot.value = i;
- slot.data.data = i;
- slotNode.className = "date";
- //slotNode.style.color = "";
- if (d1.toISODate() == today) {
- slotNode.className += " today";
- }
- if (d1.toISODate() == selected) {
- // slotNode.style.color = "blue";
- slotNode.className += " selected";
- }
- d1 = new Date(d1.getFullYear(), d1.getMonth(), d1.getDate()+1);
- }
-
- var lastDateIndex = index;
-
- while(index < 42) {
- this.dateSlot[index].value = -1;
- this.dateSlot[index].data.data = String.fromCharCode(160);
- this.dateSlot[index].data.parentNode.className = "empty";
- ++index;
- }
-
- },
-
- hover : function(ev)
- {
- if(Event.element(ev).tagName)
- {
- if(ev.type == "mouseover")
- Event.element(ev).addClassName("hover");
- else
- Event.element(ev).removeClassName("hover");
- }
- },
-
- updateHeader : function () {
-
- var options = this._monthSelect.options;
- var m = this.selectedDate.getMonth();
- for(var i=0; i < options.length; ++i) {
- options[i].selected = false;
- if (options[i].value == m) {
- options[i].selected = true;
- }
- }
-
- options = this._yearSelect.options;
- var year = this.selectedDate.getFullYear();
- for(var i=0; i < options.length; ++i) {
- options[i].selected = false;
- if (options[i].value == year) {
- options[i].selected = true;
- }
- }
-
- }
-});
-
-Object.extend(Prado.WebUI.TDatePicker,
-{
- /**
- * @return Date the date from drop down list options.
- */
- getDropDownDate : function(control)
- {
- var now=new Date();
- var year=now.getFullYear();
- var month=now.getMonth();
- var day=1;
-
- var month_list = Prado.WebUI.TDatePicker.getMonthListControl(control);
- var day_list = Prado.WebUI.TDatePicker.getDayListControl(control);
- var year_list = Prado.WebUI.TDatePicker.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 = Class.create(Prado.WebUI.Control,
+{
+ 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, // 0 for sunday
+
+ ClassName : "",
+
+ CalendarStyle : "default",
+
+ FromYear : 2005, UpToYear: 2020,
+
+ onInit : function(options)
+ {
+ this.options = options || [];
+ this.control = $(options.ID);
+ this.dateSlot = new Array(42);
+ this.weekSlot = new Array(6);
+ this.minimalDaysInFirstWeek = 4;
+ this.positionMode = 'Bottom';
+
+ Prado.Registry.set(options.ID, this);
+
+ //which element to trigger to show the calendar
+ 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";
+ }
+
+ // Popup position
+ if(this.options.PositionMode == 'Top')
+ {
+ this.positionMode = this.options.PositionMode;
+ }
+
+ Object.extend(this,options);
+ // generate default date _after_ extending options
+ this.selectedDate = this.newDate();
+
+ Event.observe(this.trigger, triggerEvent, this.show.bindEvent(this));
+
+ // Listen to change event if needed
+ if (typeof(this.options.OnDateChanged) == "function")
+ {
+ if(this.options.InputMode == "TextBox")
+ {
+ Event.observe(this.control, "change", this.onDateChanged.bindEvent(this));
+ }
+ else
+ {
+ var day = Prado.WebUI.TDatePicker.getDayListControl(this.control);
+ var month = Prado.WebUI.TDatePicker.getMonthListControl(this.control);
+ var year = Prado.WebUI.TDatePicker.getYearListControl(this.control);
+ Event.observe (day, "change", this.onDateChanged.bindEvent(this));
+ Event.observe (month, "change", this.onDateChanged.bindEvent(this));
+ Event.observe (year, "change", this.onDateChanged.bindEvent(this));
+
+ }
+
+
+ }
+
+ },
+
+ create : function()
+ {
+ if(typeof(this._calDiv) != "undefined")
+ return;
+
+ var div;
+ var table;
+ var tbody;
+ var tr;
+ var td;
+
+ // Create the top-level div element
+ this._calDiv = document.createElement("div");
+ this._calDiv.className = "TDatePicker_"+this.CalendarStyle+" "+this.ClassName;
+ this._calDiv.style.display = "none";
+ this._calDiv.style.position = "absolute"
+
+ // header div
+ 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);
+
+ // Previous Month Button
+ td = document.createElement("td");
+ var previousMonth = document.createElement("input");
+ previousMonth.className = "prevMonthButton button";
+ previousMonth.type = "button"
+ previousMonth.value = "<<";
+ td.appendChild(previousMonth);
+ tr.appendChild(td);
+
+
+
+ //
+ // Create the month drop down
+ //
+ 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);
+ }
+ td.appendChild(this._monthSelect);
+
+
+ //
+ // Create the year drop down
+ //
+ td = document.createElement("td");
+ td.className = "labelContainer";
+ tr.appendChild(td);
+ this._yearSelect = document.createElement("select");
+ for(var i=this.FromYear; i <= this.UpToYear; ++i) {
+ var opt = document.createElement("option");
+ opt.innerHTML = i;
+ opt.value = i;
+ if (i == this.selectedDate.getFullYear()) {
+ opt.selected = false;
+ }
+ this._yearSelect.appendChild(opt);
+ }
+ 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);
+
+ // Calendar body
+ div = document.createElement("div");
+ div.className = "calendarBody";
+ this._calDiv.appendChild(div);
+ var calendarBody = div;
+
+ // Create the inside of calendar body
+
+ 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);
+ }
+
+ // Date grid
+ tbody = document.createElement("tbody");
+ table.appendChild(tbody);
+
+ for(var week=0; week<6; ++week) {
+ tr = document.createElement("tr");
+ tbody.appendChild(tr);
+
+ for(var 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));
+
+ }
+ }
+
+ // Calendar Footer
+ 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"
+ this.control.parentNode.appendChild(this.iePopUp);
+ }
+
+ this.control.parentNode.appendChild(this._calDiv);
+
+ this.update();
+ this.updateHeader();
+
+ this.ieHack(true);
+
+ // IE55+ extension
+ previousMonth.hideFocus = true;
+ nextMonth.hideFocus = true;
+ todayButton.hideFocus = true;
+ // end IE55+ extension
+
+ // hook up events
+ Event.observe(previousMonth, "click", this.prevMonth.bindEvent(this));
+ Event.observe(nextMonth, "click", this.nextMonth.bindEvent(this));
+ Event.observe(todayButton, "click", this.selectToday.bindEvent(this));
+ //Event.observe(clearButton, "click", this.clearSelection.bindEvent(this));
+ Event.observe(this._monthSelect, "change", this.monthSelect.bindEvent(this));
+ Event.observe(this._yearSelect, "change", this.yearSelect.bindEvent(this));
+
+ // ie, opera
+ Event.observe(this._calDiv, "mousewheel", this.mouseWheelChange.bindEvent(this));
+ // ff
+ Event.observe(this._calDiv, "DOMMouseScroll", this.mouseWheelChange.bindEvent(this));
+
+ Event.observe(calendarBody, "click", this.selectDate.bindEvent(this));
+
+ Prado.Element.focus(this.control);
+
+ },
+
+ ieHack : function(cleanup)
+ {
+ // IE hack
+ if(this.iePopUp)
+ {
+ this.iePopUp.style.display = "block";
+ this.iePopUp.style.left = (this._calDiv.offsetLeft -1)+ "px";
+ this.iePopUp.style.top = (this._calDiv.offsetTop -1 ) + "px";
+ this.iePopUp.style.width = Math.abs(this._calDiv.offsetWidth -2)+ "px";
+ this.iePopUp.style.height = (this._calDiv.offsetHeight + 1)+ "px";
+ if(cleanup) this.iePopUp.style.display = "none";
+ }
+ },
+
+ keyPressed : function(ev)
+ {
+ if(!this.showing) return;
+ if (!ev) ev = document.parentWindow.event;
+ var kc = ev.keyCode != null ? ev.keyCode : ev.charCode;
+
+ if(kc == Event.KEY_RETURN || kc == Event.KEY_SPACEBAR || kc == Event.KEY_TAB)
+ {
+ this.setSelectedDate(this.selectedDate);
+ Event.stop(ev);
+ this.hide();
+ }
+ if(kc == Event.KEY_ESC)
+ {
+ Event.stop(ev); this.hide();
+ }
+
+ var getDaysPerMonth = function (nMonth, nYear)
+ {
+ nMonth = (nMonth + 12) % 12;
+ var days= [31,28,31,30,31,30,31,31,30,31,30,31];
+ var res = days[nMonth];
+ if (nMonth == 1) //feburary, leap years has 29
+ res += nYear % 4 == 0 && !(nYear % 400 == 0) ? 1 : 0;
+ return res;
+ }
+
+ if(kc < 37 || kc > 40) return true;
+
+ var current = this.selectedDate;
+ var d = current.valueOf();
+ if(kc == Event.KEY_LEFT)
+ {
+ if(ev.ctrlKey || ev.shiftKey) // -1 month
+ {
+ current.setDate( Math.min(current.getDate(), getDaysPerMonth(current.getMonth() - 1,current.getFullYear())) ); // no need to catch dec -> jan for the year
+ d = current.setMonth( current.getMonth() - 1 );
+ }
+ else
+ d -= 86400000; //-1 day
+ }
+ else if (kc == Event.KEY_RIGHT)
+ {
+ if(ev.ctrlKey || ev.shiftKey) // +1 month
+ {
+ current.setDate( Math.min(current.getDate(), getDaysPerMonth(current.getMonth() + 1,current.getFullYear())) ); // no need to catch dec -> jan for the year
+ d = current.setMonth( current.getMonth() + 1 );
+ }
+ else
+ d += 86400000; //+1 day
+ }
+ else if (kc == Event.KEY_UP)
+ {
+ if(ev.ctrlKey || ev.shiftKey) //-1 year
+ {
+ current.setDate( Math.min(current.getDate(), getDaysPerMonth(current.getMonth(),current.getFullYear() - 1)) ); // no need to catch dec -> jan for the year
+ d = current.setFullYear( current.getFullYear() - 1 );
+ }
+ else
+ d -= 604800000; // -7 days
+ }
+ else if (kc == Event.KEY_DOWN)
+ {
+ if(ev.ctrlKey || ev.shiftKey) // +1 year
+ {
+ current.setDate( Math.min(current.getDate(), getDaysPerMonth(current.getMonth(),current.getFullYear() + 1)) ); // no need to catch dec -> jan for the year
+ d = current.setFullYear( current.getFullYear() + 1 );
+ }
+ else
+ d += 7 * 24 * 61 * 60 * 1000; // +7 days
+ }
+ this.setSelectedDate(d);
+ Event.stop(ev);
+ },
+
+ selectDate : function(ev)
+ {
+ var el = Event.element(ev);
+ while (el.nodeType != 1)
+ el = el.parentNode;
+
+ while (el != null && el.tagName && el.tagName.toLowerCase() != "td")
+ el = el.parentNode;
+
+ // if no td found, return
+ if (el == null || el.tagName == null || el.tagName.toLowerCase() != "td")
+ return;
+
+ var d = this.newDate(this.selectedDate);
+ var n = Number(el.firstChild.data);
+ if (isNaN(n) || n <= 0 || n == null)
+ return;
+
+ d.setDate(n);
+ this.setSelectedDate(d);
+ this.hide();
+ },
+
+ selectToday : function()
+ {
+ if(this.selectedDate.toISODate() == this.newDate().toISODate())
+ this.hide();
+
+ this.setSelectedDate(this.newDate());
+ },
+
+ clearSelection : function()
+ {
+ this.setSelectedDate(this.newDate());
+ this.hide();
+ },
+
+ monthSelect : function(ev)
+ {
+ this.setMonth(Form.Element.getValue(Event.element(ev)));
+ },
+
+ yearSelect : function(ev)
+ {
+ this.setYear(Form.Element.getValue(Event.element(ev)));
+ },
+
+ mouseWheelChange : function (event)
+ {
+ var delta = 0;
+ if (!event) event = document.parentWindow.event;
+ if (event.wheelDelta) {
+ delta = event.wheelDelta/120;
+ if (window.opera) delta = -delta;
+ } else if (event.detail) { delta = -event.detail/3; }
+
+ var d = this.newDate(this.selectedDate);
+ var m = d.getMonth() + Math.round(delta);
+ this.setMonth(m,true);
+ return false;
+ },
+
+ // Respond to change event on the textbox or dropdown list
+ // This method raises OnDateChanged event on client side if it has been defined
+ onDateChanged : function ()
+ {
+ if (this.options.OnDateChanged)
+ {
+ var date;
+ if (this.options.InputMode == "TextBox")
+ {
+ date=this.control.value;
+ }
+ else
+ {
+ var day = Prado.WebUI.TDatePicker.getDayListControl(this.control).selectedIndex+1;
+ var month = Prado.WebUI.TDatePicker.getMonthListControl(this.control).selectedIndex;
+ var year = Prado.WebUI.TDatePicker.getYearListControl(this.control).value;
+ date=new Date(year, month, day, 0,0,0).SimpleFormat(this.Format, this);
+ }
+ this.options.OnDateChanged(this, date);
+ }
+ },
+
+ fireChangeEvent: function(element, capped)
+ {
+ if (capped)
+ {
+ var obj = this;
+
+ if (typeof(obj.changeeventtimer)!="undefined")
+ {
+ clearTimeout(obj.changeeventtimer);
+ obj.changeeventtimer = null;
+ }
+ obj.changeeventtimer = setTimeout(
+ function() { obj.changeeventtimer = null; Event.fireEvent(element, "change"); },
+ 1500
+ );
+ }
+ else
+ Event.fireEvent(element, "change");
+ },
+
+ onChange : function(ref, date, capevents)
+ {
+ if(this.options.InputMode == "TextBox")
+ {
+ this.control.value = this.formatDate();
+ this.fireChangeEvent(this.control, capevents);
+ }
+ else
+ {
+ var day = Prado.WebUI.TDatePicker.getDayListControl(this.control);
+ var month = Prado.WebUI.TDatePicker.getMonthListControl(this.control);
+ var year = Prado.WebUI.TDatePicker.getYearListControl(this.control);
+ var date = this.selectedDate;
+ if(day)
+ {
+ day.selectedIndex = date.getDate()-1;
+ }
+ if(month)
+ {
+ month.selectedIndex = date.getMonth();
+ }
+ if(year)
+ {
+ var years = year.options;
+ var currentYear = date.getFullYear();
+ for(var i = 0; i < years.length; i++)
+ years[i].selected = years[i].value.toInteger() == currentYear;
+ }
+ this.fireChangeEvent(day || month || year, capevents);
+ }
+ },
+
+ formatDate : function()
+ {
+ return this.selectedDate ? this.selectedDate.SimpleFormat(this.Format,this) : '';
+ },
+
+ newDate : function(date)
+ {
+ if(!date)
+ date = new Date();
+ if(typeof(date) == "string" || typeof(date) == "number")
+ date = new Date(date);
+ return new Date(Math.min(Math.max(date.getFullYear(),this.FromYear),this.UpToYear), date.getMonth(), date.getDate(), 0,0,0);
+ },
+
+ setSelectedDate : function(date, capevents)
+ {
+ if (date == null)
+ return;
+ var old=this.selectedDate;
+ this.selectedDate = this.newDate(date);
+ var dateChanged=(old - this.selectedDate != 0) || ( this.options.InputMode == "TextBox" && this.control.value != this.formatDate());
+
+ this.updateHeader();
+ this.update();
+ if (dateChanged && typeof(this.onChange) == "function")
+ this.onChange(this, date, capevents);
+ },
+
+ getElement : function()
+ {
+ return this._calDiv;
+ },
+
+ getSelectedDate : function ()
+ {
+ return this.selectedDate == null ? null : this.newDate(this.selectedDate);
+ },
+
+ setYear : function(year)
+ {
+ var d = this.newDate(this.selectedDate);
+ d.setFullYear(year);
+ this.setSelectedDate(d);
+ },
+
+ setMonth : function (month, capevents)
+ {
+ var d = this.newDate(this.selectedDate);
+ d.setDate(Math.min(d.getDate(), this.getDaysPerMonth(month,d.getFullYear())));
+ d.setMonth(month);
+ this.setSelectedDate(d,capevents);
+ },
+
+ nextMonth : function ()
+ {
+ this.setMonth(this.selectedDate.getMonth()+1);
+ },
+
+ prevMonth : function ()
+ {
+ this.setMonth(this.selectedDate.getMonth()-1);
+ },
+
+ getDaysPerMonth : function (month, year)
+ {
+ month = (Number(month)+12) % 12;
+ var days = [31,28,31,30,31,30,31,31,30,31,30,31];
+ var res = days[month];
+ if (month == 1 && ((!(year % 4) && (year % 100)) || !(year % 400))) //feburary, leap years has 29
+ res++;
+ return res;
+ },
+
+ getDatePickerOffsetHeight : function()
+ {
+ if(this.options.InputMode == "TextBox")
+ return this.control.offsetHeight;
+
+ var control = Prado.WebUI.TDatePicker.getDayListControl(this.control);
+ if(control) return control.offsetHeight;
+
+ var control = Prado.WebUI.TDatePicker.getMonthListControl(this.control);
+ if(control) return control.offsetHeight;
+
+ var control = Prado.WebUI.TDatePicker.getYearListControl(this.control);
+ if(control) return control.offsetHeight;
+ return 0;
+ },
+
+ show : function()
+ {
+ this.create();
+
+ if(!this.showing)
+ {
+ var pos = this.control.positionedOffset();
+
+ pos[1] += this.getDatePickerOffsetHeight();
+ this._calDiv.style.top = (pos[1]-1) + "px";
+ this._calDiv.style.display = "block";
+ this._calDiv.style.left = pos[0] + "px";
+
+ this.documentClickEvent = this.hideOnClick.bindEvent(this);
+ this.documentKeyDownEvent = this.keyPressed.bindEvent(this);
+ Event.observe(document.body, "click", this.documentClickEvent);
+ var date = this.getDateFromInput();
+ if(date)
+ {
+ this.selectedDate = date;
+ this.setSelectedDate(date);
+ }
+ Event.observe(document,"keydown", this.documentKeyDownEvent);
+ this.showing = true;
+
+ if(this.positionMode=='Top')
+ {
+ this._calDiv.style.top = ((pos[1]-1) - this.getDatePickerOffsetHeight() - this._calDiv.offsetHeight) + 'px';
+ if(Prado.Browser().ie)
+ this.iePopup = this._calDiv.style.top;
+ }
+ this.ieHack(false);
+ }
+ },
+
+ getDateFromInput : function()
+ {
+ if(this.options.InputMode == "TextBox")
+ return Date.SimpleParse($F(this.control), this.Format);
+ else
+ return Prado.WebUI.TDatePicker.getDropDownDate(this.control);
+ },
+
+ //hide the calendar when clicked outside any calendar
+ hideOnClick : function(ev)
+ {
+ if(!this.showing) return;
+ var el = Event.element(ev);
+ var within = false;
+ do
+ {
+ 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)
+ this.iePopUp.style.display = "none";
+ this.showing = false;
+ Event.stopObserving(document.body, "click", this.documentClickEvent);
+ Event.stopObserving(document,"keydown", this.documentKeyDownEvent);
+ }
+ },
+
+ update : function()
+ {
+ // Calculate the number of days in the month for the selected date
+ var date = this.selectedDate;
+ var today = (this.newDate()).toISODate();
+
+ var selected = date.toISODate();
+ var d1 = new Date(date.getFullYear(), date.getMonth(), 1);
+ var d2 = new Date(date.getFullYear(), date.getMonth()+1, 1);
+ var monthLength = Math.round((d2 - d1) / (24 * 60 * 60 * 1000));
+
+ // Find out the weekDay index for the first of this month
+ var firstIndex = (d1.getDay() - this.FirstDayOfWeek) % 7 ;
+ if (firstIndex < 0)
+ firstIndex += 7;
+
+ var index = 0;
+ while (index < firstIndex) {
+ this.dateSlot[index].value = -1;
+ this.dateSlot[index].data.data = String.fromCharCode(160);
+ this.dateSlot[index].data.parentNode.className = "empty";
+ index++;
+ }
+
+ for (var i = 1; i <= monthLength; i++, index++) {
+ var slot = this.dateSlot[index];
+ var slotNode = slot.data.parentNode;
+ slot.value = i;
+ slot.data.data = i;
+ slotNode.className = "date";
+ //slotNode.style.color = "";
+ if (d1.toISODate() == today) {
+ slotNode.className += " today";
+ }
+ if (d1.toISODate() == selected) {
+ // slotNode.style.color = "blue";
+ slotNode.className += " selected";
+ }
+ d1 = new Date(d1.getFullYear(), d1.getMonth(), d1.getDate()+1);
+ }
+
+ var lastDateIndex = index;
+
+ while(index < 42) {
+ this.dateSlot[index].value = -1;
+ this.dateSlot[index].data.data = String.fromCharCode(160);
+ this.dateSlot[index].data.parentNode.className = "empty";
+ ++index;
+ }
+
+ },
+
+ hover : function(ev)
+ {
+ if(Event.element(ev).tagName)
+ {
+ if(ev.type == "mouseover")
+ Event.element(ev).addClassName("hover");
+ else
+ Event.element(ev).removeClassName("hover");
+ }
+ },
+
+ updateHeader : function () {
+
+ var options = this._monthSelect.options;
+ var m = this.selectedDate.getMonth();
+ for(var i=0; i < options.length; ++i) {
+ options[i].selected = false;
+ if (options[i].value == m) {
+ options[i].selected = true;
+ }
+ }
+
+ options = this._yearSelect.options;
+ var year = this.selectedDate.getFullYear();
+ for(var i=0; i < options.length; ++i) {
+ options[i].selected = false;
+ if (options[i].value == year) {
+ options[i].selected = true;
+ }
+ }
+
+ }
+});
+
+Object.extend(Prado.WebUI.TDatePicker,
+{
+ /**
+ * @return Date the date from drop down list options.
+ */
+ getDropDownDate : function(control)
+ {
+ var now=new Date();
+ var year=now.getFullYear();
+ var month=now.getMonth();
+ var day=1;
+
+ var month_list = Prado.WebUI.TDatePicker.getMonthListControl(control);
+ var day_list = Prado.WebUI.TDatePicker.getDayListControl(control);
+ var year_list = Prado.WebUI.TDatePicker.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");
+ }
}); \ No newline at end of file
diff --git a/framework/Web/Javascripts/source/prado/logger/logger.js b/framework/Web/Javascripts/source/prado/logger/logger.js
index a48f401a..55cc1aa3 100644
--- a/framework/Web/Javascripts/source/prado/logger/logger.js
+++ b/framework/Web/Javascripts/source/prado/logger/logger.js
@@ -1,753 +1,753 @@
-/*
-
-Created By: Corey Johnson
-E-mail: probablyCorey@gmail.com
-
-Requires: Prototype Javascript library (http://prototype.conio.net/)
-
-Use it all you want. Just remember to give me some credit :)
-
-*/
-
-// ------------
-// Custom Event
-// ------------
-
-CustomEvent = Class.create();
-CustomEvent.prototype = {
- initialize : function() {
- this.listeners = []
- },
-
- addListener : function(method) {
- this.listeners.push(method)
- },
-
- removeListener : function(method) {
- var foundIndexes = this._findListenerIndexes(method)
-
- for(var i = 0; i < foundIndexes.length; i++) {
- this.listeners.splice(foundIndexes[i], 1)
- }
- },
-
- dispatch : function(handler) {
- for(var i = 0; i < this.listeners.length; i++) {
- try {
- this.listeners[i](handler)
- }
- catch (e) {
- alert("Could not run the listener " + this.listeners[i] + ". " + e)
- }
- }
- },
-
- // Private Methods
- // ---------------
- _findListenerIndexes : function(method) {
- var indexes = []
- for(var i = 0; i < this.listeners.length; i++) {
- if (this.listeners[i] == method) {
- indexes.push(i)
- }
- }
-
- return indexes
- }
-};
-
-// ------
-// Cookie
-// ------
-
-var Cookie = {
- set : function(name, value, expirationInDays, path) {
- var cookie = escape(name) + "=" + escape(value)
-
- if (expirationInDays) {
- var date = new Date()
- date.setDate(date.getDate() + expirationInDays)
- cookie += "; expires=" + date.toGMTString()
- }
-
- if (path) {
- cookie += ";path=" + path
- }
-
- document.cookie = cookie
-
- if (value && (expirationInDays == undefined || expirationInDays > 0) && !this.get(name)) {
- Logger.error("Cookie (" + name + ") was not set correctly... The value was " + value.toString().length + " charachters long (This may be over the cookie limit)");
- }
- },
-
- get : function(name) {
- var pattern = "(^|;)\\s*" + escape(name) + "=([^;]+)"
-
- var m = document.cookie.match(pattern)
- if (m && m[2]) {
- return unescape(m[2])
- }
- else return null
- },
-
- getAll : function() {
- var cookies = document.cookie.split(';')
- var cookieArray = []
-
- for (var i = 0; i < cookies.length; i++) {
- try {
- var name = unescape(cookies[i].match(/^\s*([^=]+)/m)[1])
- var value = unescape(cookies[i].match(/=(.*$)/m)[1])
- }
- catch (e) {
- continue
- }
-
- cookieArray.push({name : name, value : value})
-
- if (cookieArray[name] != undefined) {
- Logger.waring("Trying to retrieve cookie named(" + name + "). There appears to be another property with this name though.");
- }
-
- cookieArray[name] = value
- }
-
- return cookieArray
- },
-
- clear : function(name) {
- this.set(name, "", -1)
- },
-
- clearAll : function() {
- var cookies = this.getAll()
-
- for(var i = 0; i < cookies.length; i++) {
- this.clear(cookies[i].name)
- }
-
- }
-};
-
-// ------
-// Logger
-// -----
-
-Logger = {
- logEntries : [],
-
- onupdate : new CustomEvent(),
- onclear : new CustomEvent(),
-
-
- // Logger output
- log : function(message, tag) {
- var logEntry = new LogEntry(message, tag || "info")
- this.logEntries.push(logEntry)
- this.onupdate.dispatch(logEntry)
- },
-
- info : function(message) {
- this.log(message, 'info')
- if(typeof(console) != "undefined")
- console.info(message);
- },
-
- debug : function(message) {
- this.log(message, 'debug')
- if(typeof(console) != "undefined")
- console.debug(message);
- },
-
- warn : function(message) {
- this.log(message, 'warning')
- if(typeof(console) != "undefined")
- console.warn(message);
- },
-
- error : function(message, error) {
- this.log(message + ": \n" + error, 'error')
- if(typeof(console) != "undefined")
- console.error(message + ": \n" + error);
-
- },
-
- clear : function () {
- this.logEntries = []
- this.onclear.dispatch()
- }
-};
-
-LogEntry = Class.create()
-LogEntry.prototype = {
- initialize : function(message, tag) {
- this.message = message
- this.tag = tag
- }
-};
-
-LogConsole = Class.create();
-LogConsole.prototype = {
-
- // Properties
- // ----------
- commandHistory : [],
- commandIndex : 0,
-
- hidden : true,
-
- // Methods
- // -------
-
- initialize : function(toggleKey) {
- this.outputCount = 0
- this.tagPattern = Cookie.get('tagPattern') || ".*"
-
- // I hate writing javascript in HTML... but what's a better alternative
- this.logElement = document.createElement('div')
- document.body.appendChild(this.logElement)
- Element.hide(this.logElement)
-
- this.logElement.style.position = "absolute"
- this.logElement.style.left = '0px'
- this.logElement.style.width = '100%'
-
- this.logElement.style.textAlign = "left"
- this.logElement.style.fontFamily = "lucida console"
- this.logElement.style.fontSize = "100%"
- this.logElement.style.backgroundColor = 'darkgray'
- this.logElement.style.opacity = 0.9
- this.logElement.style.zIndex = 2000
-
- // Add toolbarElement
- this.toolbarElement = document.createElement('div')
- this.logElement.appendChild(this.toolbarElement)
- this.toolbarElement.style.padding = "0 0 0 2px"
-
- // Add buttons
- this.buttonsContainerElement = document.createElement('span')
- this.toolbarElement.appendChild(this.buttonsContainerElement)
-
- this.buttonsContainerElement.innerHTML += '<button onclick="logConsole.toggle()" style="float:right;color:black">close</button>'
- this.buttonsContainerElement.innerHTML += '<button onclick="Logger.clear()" style="float:right;color:black">clear</button>'
- if(!Prado.Inspector.disabled)
- this.buttonsContainerElement.innerHTML += '<button onclick="Prado.Inspector.inspect()" style="float:right;color:black; margin-right:15px;">Object Tree</button>'
-
-
- //Add Tag Filter
- this.tagFilterContainerElement = document.createElement('span')
- this.toolbarElement.appendChild(this.tagFilterContainerElement)
- this.tagFilterContainerElement.style.cssFloat = 'left'
- this.tagFilterContainerElement.appendChild(document.createTextNode("Log Filter"))
-
- this.tagFilterElement = document.createElement('input')
- this.tagFilterContainerElement.appendChild(this.tagFilterElement)
- this.tagFilterElement.style.width = '200px'
- this.tagFilterElement.value = this.tagPattern
- this.tagFilterElement.setAttribute('autocomplete', 'off') // So Firefox doesn't flip out
-
- Event.observe(this.tagFilterElement, 'keyup', this.updateTags.bind(this))
- Event.observe(this.tagFilterElement, 'click', function() {this.tagFilterElement.select()}.bind(this))
-
- // Add outputElement
- this.outputElement = document.createElement('div')
- this.logElement.appendChild(this.outputElement)
- this.outputElement.style.overflow = "auto"
- this.outputElement.style.clear = "both"
- this.outputElement.style.height = "200px"
- this.outputElement.style.backgroundColor = 'black'
-
- this.inputContainerElement = document.createElement('div')
- this.inputContainerElement.style.width = "100%"
- this.logElement.appendChild(this.inputContainerElement)
-
- this.inputElement = document.createElement('input')
- this.inputContainerElement.appendChild(this.inputElement)
- this.inputElement.style.width = '100%'
- this.inputElement.style.borderWidth = '0px' // Inputs with 100% width always seem to be too large (I HATE THEM) they only work if the border, margin and padding are 0
- this.inputElement.style.margin = '0px'
- this.inputElement.style.padding = '0px'
- this.inputElement.value = 'Type command here'
- this.inputElement.setAttribute('autocomplete', 'off') // So Firefox doesn't flip out
-
- Event.observe(this.inputElement, 'keyup', this.handleInput.bind(this))
- Event.observe(this.inputElement, 'click', function() {this.inputElement.select()}.bind(this))
-
- if(document.all && !window.opera)
- {
- window.setInterval(this.repositionWindow.bind(this), 500)
- }
- else
- {
- this.logElement.style.position="fixed";
- this.logElement.style.bottom="0px";
- }
- var self=this;
- Event.observe(document, 'keydown', function(e)
- {
- if((e.altKey==true) && Event.keyCode(e) == toggleKey ) //Alt+J | Ctrl+J
- self.toggle();
- });
-
- // Listen to the logger....
- Logger.onupdate.addListener(this.logUpdate.bind(this))
- Logger.onclear.addListener(this.clear.bind(this))
-
- // Preload log element with the log entries that have been entered
- for (var i = 0; i < Logger.logEntries.length; i++) {
- this.logUpdate(Logger.logEntries[i])
- }
-
- // Feed all errors into the logger (For some unknown reason I can only get this to work
- // with an inline event declaration)
- Event.observe(window, 'error', function(msg, url, lineNumber) {Logger.error("Error in (" + (url || location) + ") on line "+lineNumber+"", msg)})
-
- // Allow acess key link
- var accessElement = document.createElement('span')
- accessElement.innerHTML = '<button style="position:absolute;top:-100px" onclick="javascript:logConsole.toggle()" accesskey="d"></button>'
- document.body.appendChild(accessElement)
-
- if (Cookie.get('ConsoleVisible') == 'true') {
- this.toggle()
- }
- },
-
- toggle : function() {
- if (this.logElement.style.display == 'none') {
- this.show()
- }
- else {
- this.hide()
- }
- },
-
- show : function() {
- Element.show(this.logElement)
- this.outputElement.scrollTop = this.outputElement.scrollHeight // Scroll to bottom when toggled
- if(document.all && !window.opera)
- this.repositionWindow();
- Cookie.set('ConsoleVisible', 'true')
- this.inputElement.select()
- this.hidden = false;
- },
-
- hide : function() {
- this.hidden = true;
- Element.hide(this.logElement)
- Cookie.set('ConsoleVisible', 'false')
- },
-
- output : function(message, style) {
- // If we are at the bottom of the window, then keep scrolling with the output
- var shouldScroll = (this.outputElement.scrollTop + (2 * this.outputElement.clientHeight)) >= this.outputElement.scrollHeight
-
- this.outputCount++
- style = (style ? style += ';' : '')
- style += 'padding:1px;margin:0 0 5px 0'
-
- if (this.outputCount % 2 == 0) style += ";background-color:#101010"
-
- message = message || "undefined"
- message = message.toString().escapeHTML()
-
- this.outputElement.innerHTML += "<pre style='" + style + "'>" + message + "</pre>"
-
- if (shouldScroll) {
- this.outputElement.scrollTop = this.outputElement.scrollHeight
- }
- },
-
- updateTags : function() {
- var pattern = this.tagFilterElement.value
-
- if (this.tagPattern == pattern) return
-
- try {
- new RegExp(pattern)
- }
- catch (e) {
- return
- }
-
- this.tagPattern = pattern
- Cookie.set('tagPattern', this.tagPattern)
-
- this.outputElement.innerHTML = ""
-
- // Go through each log entry again
- this.outputCount = 0;
- for (var i = 0; i < Logger.logEntries.length; i++) {
- this.logUpdate(Logger.logEntries[i])
- }
- },
-
- repositionWindow : function() {
- var offset = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop
- var pageHeight = self.innerHeight || document.documentElement.clientHeight || document.body.clientHeight
- this.logElement.style.top = (offset + pageHeight - Element.getHeight(this.logElement)) + "px"
- },
-
- // Event Handlers
- // --------------
-
- logUpdate : function(logEntry) {
- if (logEntry.tag.search(new RegExp(this.tagPattern, 'igm')) == -1) return
- var style = ''
- if (logEntry.tag.search(/error/) != -1) style += 'color:red'
- else if (logEntry.tag.search(/warning/) != -1) style += 'color:orange'
- else if (logEntry.tag.search(/debug/) != -1) style += 'color:green'
- else if (logEntry.tag.search(/info/) != -1) style += 'color:white'
- else style += 'color:yellow'
-
- this.output(logEntry.message, style)
- },
-
- clear : function(e) {
- this.outputElement.innerHTML = ""
- },
-
- handleInput : function(e) {
- if (e.keyCode == Event.KEY_RETURN ) {
- var command = this.inputElement.value
-
- switch(command) {
- case "clear":
- Logger.clear()
- break
-
- default:
- var consoleOutput = ""
-
- try {
- consoleOutput = eval(this.inputElement.value)
- }
- catch (e) {
- Logger.error("Problem parsing input <" + command + ">", e)
- break
- }
-
- Logger.log(consoleOutput)
- break
- }
-
- if (this.inputElement.value != "" && this.inputElement.value != this.commandHistory[0]) {
- this.commandHistory.unshift(this.inputElement.value)
- }
-
- this.commandIndex = 0
- this.inputElement.value = ""
- }
- else if (e.keyCode == Event.KEY_UP && this.commandHistory.length > 0) {
- this.inputElement.value = this.commandHistory[this.commandIndex]
-
- if (this.commandIndex < this.commandHistory.length - 1) {
- this.commandIndex += 1
- }
- }
- else if (e.keyCode == Event.KEY_DOWN && this.commandHistory.length > 0) {
- if (this.commandIndex > 0) {
- this.commandIndex -= 1
- }
-
- this.inputElement.value = this.commandHistory[this.commandIndex]
- }
- else {
- this.commandIndex = 0
- }
- }
-};
-
-
-// -------------------------
-// Helper Functions And Junk
-// -------------------------
-function inspect(o)
-{
- var objtype = typeof(o);
- if (objtype == "undefined") {
- return "undefined";
- } else if (objtype == "number" || objtype == "boolean") {
- return o + "";
- } else if (o === null) {
- return "null";
- }
-
- try {
- var ostring = (o + "");
- } catch (e) {
- return "[" + typeof(o) + "]";
- }
-
- if (typeof(o) == "function")
- {
- o = ostring.replace(/^\s+/, "");
- var idx = o.indexOf("{");
- if (idx != -1) {
- o = o.substr(0, idx) + "{...}";
- }
- return o;
- }
-
- var reprString = function (o)
- {
- return ('"' + o.replace(/(["\\])/g, '\\$1') + '"'
- ).replace(/[\f]/g, "\\f"
- ).replace(/[\b]/g, "\\b"
- ).replace(/[\n]/g, "\\n"
- ).replace(/[\t]/g, "\\t"
- ).replace(/[\r]/g, "\\r");
- };
-
- if (objtype == "string") {
- return reprString(o);
- }
- // recurse
- var me = arguments.callee;
- // short-circuit for objects that support "json" serialization
- // if they return "self" then just pass-through...
- var newObj;
- if (typeof(o.__json__) == "function") {
- newObj = o.__json__();
- if (o !== newObj) {
- return me(newObj);
- }
- }
- if (typeof(o.json) == "function") {
- newObj = o.json();
- if (o !== newObj) {
- return me(newObj);
- }
- }
- // array
- if (objtype != "function" && typeof(o.length) == "number") {
- var res = [];
- for (var i = 0; i < o.length; i++) {
- var val = me(o[i]);
- if (typeof(val) != "string") {
- val = "undefined";
- }
- res.push(val);
- }
- return "[" + res.join(", ") + "]";
- }
-
- // generic object code path
- res = [];
- for (var k in o) {
- var useKey;
- if (typeof(k) == "number") {
- useKey = '"' + k + '"';
- } else if (typeof(k) == "string") {
- useKey = reprString(k);
- } else {
- // skip non-string or number keys
- continue;
- }
- val = me(o[k]);
- if (typeof(val) != "string") {
- // skip non-serializable values
- continue;
- }
- res.push(useKey + ":" + val);
- }
- return "{" + res.join(", ") + "}";
-};
-
-Array.prototype.contains = function(object) {
- for(var i = 0; i < this.length; i++) {
- if (object == this[i]) return true
- }
-
- return false
-};
-
-// Helper Alias for simple logging
-var puts = function() {return Logger.log(arguments[0], arguments[1])};
-
-/*************************************
-
- Javascript Object Tree
- version 1.0
- last revision:04.11.2004
- steve@slayeroffice.com
- http://slayeroffice.com
-
- (c)2004 S.G. Chipman
-
- Please notify me of any modifications
- you make to this code so that I can
- update the version hosted on slayeroffice.com
-
-
-************************************/
-if(typeof Prado == "undefined")
- var Prado = {};
-Prado.Inspector =
-{
- d : document,
- types : new Array(),
- objs : new Array(),
- hidden : new Array(),
- opera : window.opera,
- displaying : '',
- nameList : new Array(),
-
- format : function(str) {
- if(typeof(str) != "string") return str;
- str=str.replace(/</g,"&lt;");
- str=str.replace(/>/g,"&gt;");
- return str;
- },
-
- parseJS : function(obj) {
- var name;
- if(typeof obj == "string") { name = obj; obj = eval(obj); }
- win= typeof obj == 'undefined' ? window : obj;
- this.displaying = name ? name : win.toString();
- for(js in win) {
- try {
- if(win[js] && js.toString().indexOf("Inspector")==-1 && (win[js]+"").indexOf("[native code]")==-1) {
-
- t=typeof(win[js]);
- if(!this.objs[t.toString()]) {
- this.types[this.types.length]=t;
- this.objs[t]={};
- this.nameList[t] = new Array();
- }
- this.nameList[t].push(js);
- this.objs[t][js] = this.format(win[js]+"");
- }
- } catch(err) { }
- }
-
- for(i=0;i<this.types.length;i++)
- this.nameList[this.types[i]].sort();
- },
-
- show : function(objID) {
- this.d.getElementById(objID).style.display=this.hidden[objID]?"none":"block";
- this.hidden[objID]=this.hidden[objID]?0:1;
- },
-
- changeSpan : function(spanID) {
- if(this.d.getElementById(spanID).innerHTML.indexOf("+")>-1){
- this.d.getElementById(spanID).innerHTML="[-]";
- } else {
- this.d.getElementById(spanID).innerHTML="[+]";
- }
- },
-
- buildInspectionLevel : function()
- {
- var display = this.displaying;
- var list = display.split(".");
- var links = ["<a href=\"javascript:var_dump()\">[object Window]</a>"];
- var name = '';
- if(display.indexOf("[object ") >= 0) return links.join(".");
- for(var i = 0; i < list.length; i++)
- {
- name += (name.length ? "." : "") + list[i];
- links[i+1] = "<a href=\"javascript:var_dump('"+name+"')\">"+list[i]+"</a>";
- }
- return links.join(".");
- },
-
- buildTree : function() {
- mHTML = "<div>Inspecting "+this.buildInspectionLevel()+"</div>";
- mHTML +="<ul class=\"topLevel\">";
- this.types.sort();
- var so_objIndex=0;
- for(i=0;i<this.types.length;i++)
- {
- mHTML+="<li style=\"cursor:pointer;\" onclick=\"Prado.Inspector.show('ul"+i+"');Prado.Inspector.changeSpan('sp" + i + "')\"><span id=\"sp" + i + "\">[+]</span><b>" + this.types[i] + "</b> (" + this.nameList[this.types[i]].length + ")</li><ul style=\"display:none;\" id=\"ul"+i+"\">";
- this.hidden["ul"+i]=0;
- for(e=0;e<this.nameList[this.types[i]].length;e++)
- {
- var prop = this.nameList[this.types[i]][e];
- var value = this.objs[this.types[i]][prop]
- var more = "";
- if(value.indexOf("[object ") >= 0 && /^[a-zA-Z_]/.test(prop))
- {
- if(this.displaying.indexOf("[object ") < 0)
- more = " <a href=\"javascript:var_dump('"+this.displaying+"."+prop+"')\"><b>more</b></a>";
- else if(this.displaying.indexOf("[object Window]") >= 0)
- more = " <a href=\"javascript:var_dump('"+prop+"')\"><b>more</b></a>";
- }
- mHTML+="<li style=\"cursor:pointer;\" onclick=\"Prado.Inspector.show('mul" + so_objIndex + "');Prado.Inspector.changeSpan('sk" + so_objIndex + "')\"><span id=\"sk" + so_objIndex + "\">[+]</span>" + prop + "</li><ul id=\"mul" + so_objIndex + "\" style=\"display:none;\"><li style=\"list-style-type:none;\"><pre>" + value + more + "</pre></li></ul>";
- this.hidden["mul"+so_objIndex]=0;
- so_objIndex++;
- }
- mHTML+="</ul>";
- }
- mHTML+="</ul>";
- this.d.getElementById("so_mContainer").innerHTML =mHTML;
- },
-
- handleKeyEvent : function(e) {
- keyCode=document.all?window.event.keyCode:e.keyCode;
- if(keyCode==27) {
- this.cleanUp();
- }
- },
-
- cleanUp : function()
- {
- if(this.d.getElementById("so_mContainer"))
- {
- this.d.body.removeChild(this.d.getElementById("so_mContainer"));
- this.d.body.removeChild(this.d.getElementById("so_mStyle"));
- if(typeof Event != "undefined")
- Event.stopObserving(this.d, "keydown", this.dKeyDownEvent);
- this.types = new Array();
- this.objs = new Array();
- this.hidden = new Array();
- }
- },
-
- disabled : document.all && !this.opera,
-
- inspect : function(obj)
- {
- if(this.disabled)return alert("Sorry, this only works in Mozilla and Firefox currently.");
- this.cleanUp();
- mObj=this.d.body.appendChild(this.d.createElement("div"));
- mObj.id="so_mContainer";
- sObj=this.d.body.appendChild(this.d.createElement("style"));
- sObj.id="so_mStyle";
- sObj.type="text/css";
- sObj.innerHTML = this.style;
- this.dKeyDownEvent = this.handleKeyEvent.bind(this);
- if(typeof Event != "undefined")
- Event.observe(this.d, "keydown", this.dKeyDownEvent);
-
- this.parseJS(obj);
- this.buildTree();
-
- cObj=mObj.appendChild(this.d.createElement("div"));
- cObj.className="credits";
- cObj.innerHTML = "<b>[esc] to <a href=\"javascript:Prado.Inspector.cleanUp();\">close</a></b><br />Javascript Object Tree V2.0.";
-
- window.scrollTo(0,0);
- },
-
- style : "#so_mContainer { position:absolute; top:5px; left:5px; background-color:#E3EBED; text-align:left; font:9pt verdana; width:85%; border:2px solid #000; padding:5px; z-index:1000; color:#000; } " +
- "#so_mContainer ul { padding-left:20px; } " +
- "#so_mContainer ul li { display:block; list-style-type:none; list-style-image:url(); line-height:2em; -moz-border-radius:.75em; font:10px verdana; padding:0; margin:2px; color:#000; } " +
- "#so_mContainer li:hover { background-color:#E3EBED; } " +
- "#so_mContainer ul li span { position:relative; width:15px; height:15px; margin-right:4px; } " +
- "#so_mContainer pre { background-color:#F9FAFB; border:1px solid #638DA1; height:auto; padding:5px; font:9px verdana; color:#000; } " +
- "#so_mContainer .topLevel { margin:0; padding:0; } " +
- "#so_mContainer .credits { float:left; width:200px; font:6.5pt verdana; color:#000; padding:2px; margin-left:5px; text-align:left; border-top:1px solid #000; margin-top:15px; width:75%; } " +
- "#so_mContainer .credits a { font:9px verdana; font-weight:bold; color:#004465; text-decoration:none; background-color:transparent; }"
-};
-
-//similar function to var_dump in PHP, brings up the javascript object tree UI.
-function var_dump(obj)
-{
- Prado.Inspector.inspect(obj);
-}
-
-//similar function to print_r for PHP
-var print_r = inspect;
-
+/*
+
+Created By: Corey Johnson
+E-mail: probablyCorey@gmail.com
+
+Requires: Prototype Javascript library (http://prototype.conio.net/)
+
+Use it all you want. Just remember to give me some credit :)
+
+*/
+
+// ------------
+// Custom Event
+// ------------
+
+CustomEvent = Class.create();
+CustomEvent.prototype = {
+ initialize : function() {
+ this.listeners = []
+ },
+
+ addListener : function(method) {
+ this.listeners.push(method)
+ },
+
+ removeListener : function(method) {
+ var foundIndexes = this._findListenerIndexes(method)
+
+ for(var i = 0; i < foundIndexes.length; i++) {
+ this.listeners.splice(foundIndexes[i], 1)
+ }
+ },
+
+ dispatch : function(handler) {
+ for(var i = 0; i < this.listeners.length; i++) {
+ try {
+ this.listeners[i](handler)
+ }
+ catch (e) {
+ alert("Could not run the listener " + this.listeners[i] + ". " + e)
+ }
+ }
+ },
+
+ // Private Methods
+ // ---------------
+ _findListenerIndexes : function(method) {
+ var indexes = []
+ for(var i = 0; i < this.listeners.length; i++) {
+ if (this.listeners[i] == method) {
+ indexes.push(i)
+ }
+ }
+
+ return indexes
+ }
+};
+
+// ------
+// Cookie
+// ------
+
+var Cookie = {
+ set : function(name, value, expirationInDays, path) {
+ var cookie = escape(name) + "=" + escape(value)
+
+ if (expirationInDays) {
+ var date = new Date()
+ date.setDate(date.getDate() + expirationInDays)
+ cookie += "; expires=" + date.toGMTString()
+ }
+
+ if (path) {
+ cookie += ";path=" + path
+ }
+
+ document.cookie = cookie
+
+ if (value && (expirationInDays == undefined || expirationInDays > 0) && !this.get(name)) {
+ Logger.error("Cookie (" + name + ") was not set correctly... The value was " + value.toString().length + " charachters long (This may be over the cookie limit)");
+ }
+ },
+
+ get : function(name) {
+ var pattern = "(^|;)\\s*" + escape(name) + "=([^;]+)"
+
+ var m = document.cookie.match(pattern)
+ if (m && m[2]) {
+ return unescape(m[2])
+ }
+ else return null
+ },
+
+ getAll : function() {
+ var cookies = document.cookie.split(';')
+ var cookieArray = []
+
+ for (var i = 0; i < cookies.length; i++) {
+ try {
+ var name = unescape(cookies[i].match(/^\s*([^=]+)/m)[1])
+ var value = unescape(cookies[i].match(/=(.*$)/m)[1])
+ }
+ catch (e) {
+ continue
+ }
+
+ cookieArray.push({name : name, value : value})
+
+ if (cookieArray[name] != undefined) {
+ Logger.waring("Trying to retrieve cookie named(" + name + "). There appears to be another property with this name though.");
+ }
+
+ cookieArray[name] = value
+ }
+
+ return cookieArray
+ },
+
+ clear : function(name) {
+ this.set(name, "", -1)
+ },
+
+ clearAll : function() {
+ var cookies = this.getAll()
+
+ for(var i = 0; i < cookies.length; i++) {
+ this.clear(cookies[i].name)
+ }
+
+ }
+};
+
+// ------
+// Logger
+// -----
+
+Logger = {
+ logEntries : [],
+
+ onupdate : new CustomEvent(),
+ onclear : new CustomEvent(),
+
+
+ // Logger output
+ log : function(message, tag) {
+ var logEntry = new LogEntry(message, tag || "info")
+ this.logEntries.push(logEntry)
+ this.onupdate.dispatch(logEntry)
+ },
+
+ info : function(message) {
+ this.log(message, 'info')
+ if(typeof(console) != "undefined")
+ console.info(message);
+ },
+
+ debug : function(message) {
+ this.log(message, 'debug')
+ if(typeof(console) != "undefined")
+ console.debug(message);
+ },
+
+ warn : function(message) {
+ this.log(message, 'warning')
+ if(typeof(console) != "undefined")
+ console.warn(message);
+ },
+
+ error : function(message, error) {
+ this.log(message + ": \n" + error, 'error')
+ if(typeof(console) != "undefined")
+ console.error(message + ": \n" + error);
+
+ },
+
+ clear : function () {
+ this.logEntries = []
+ this.onclear.dispatch()
+ }
+};
+
+LogEntry = Class.create()
+LogEntry.prototype = {
+ initialize : function(message, tag) {
+ this.message = message
+ this.tag = tag
+ }
+};
+
+LogConsole = Class.create();
+LogConsole.prototype = {
+
+ // Properties
+ // ----------
+ commandHistory : [],
+ commandIndex : 0,
+
+ hidden : true,
+
+ // Methods
+ // -------
+
+ initialize : function(toggleKey) {
+ this.outputCount = 0
+ this.tagPattern = Cookie.get('tagPattern') || ".*"
+
+ // I hate writing javascript in HTML... but what's a better alternative
+ this.logElement = document.createElement('div')
+ document.body.appendChild(this.logElement)
+ Element.hide(this.logElement)
+
+ this.logElement.style.position = "absolute"
+ this.logElement.style.left = '0px'
+ this.logElement.style.width = '100%'
+
+ this.logElement.style.textAlign = "left"
+ this.logElement.style.fontFamily = "lucida console"
+ this.logElement.style.fontSize = "100%"
+ this.logElement.style.backgroundColor = 'darkgray'
+ this.logElement.style.opacity = 0.9
+ this.logElement.style.zIndex = 2000
+
+ // Add toolbarElement
+ this.toolbarElement = document.createElement('div')
+ this.logElement.appendChild(this.toolbarElement)
+ this.toolbarElement.style.padding = "0 0 0 2px"
+
+ // Add buttons
+ this.buttonsContainerElement = document.createElement('span')
+ this.toolbarElement.appendChild(this.buttonsContainerElement)
+
+ this.buttonsContainerElement.innerHTML += '<button onclick="logConsole.toggle()" style="float:right;color:black">close</button>'
+ this.buttonsContainerElement.innerHTML += '<button onclick="Logger.clear()" style="float:right;color:black">clear</button>'
+ if(!Prado.Inspector.disabled)
+ this.buttonsContainerElement.innerHTML += '<button onclick="Prado.Inspector.inspect()" style="float:right;color:black; margin-right:15px;">Object Tree</button>'
+
+
+ //Add Tag Filter
+ this.tagFilterContainerElement = document.createElement('span')
+ this.toolbarElement.appendChild(this.tagFilterContainerElement)
+ this.tagFilterContainerElement.style.cssFloat = 'left'
+ this.tagFilterContainerElement.appendChild(document.createTextNode("Log Filter"))
+
+ this.tagFilterElement = document.createElement('input')
+ this.tagFilterContainerElement.appendChild(this.tagFilterElement)
+ this.tagFilterElement.style.width = '200px'
+ this.tagFilterElement.value = this.tagPattern
+ this.tagFilterElement.setAttribute('autocomplete', 'off') // So Firefox doesn't flip out
+
+ Event.observe(this.tagFilterElement, 'keyup', this.updateTags.bind(this))
+ Event.observe(this.tagFilterElement, 'click', function() {this.tagFilterElement.select()}.bind(this))
+
+ // Add outputElement
+ this.outputElement = document.createElement('div')
+ this.logElement.appendChild(this.outputElement)
+ this.outputElement.style.overflow = "auto"
+ this.outputElement.style.clear = "both"
+ this.outputElement.style.height = "200px"
+ this.outputElement.style.backgroundColor = 'black'
+
+ this.inputContainerElement = document.createElement('div')
+ this.inputContainerElement.style.width = "100%"
+ this.logElement.appendChild(this.inputContainerElement)
+
+ this.inputElement = document.createElement('input')
+ this.inputContainerElement.appendChild(this.inputElement)
+ this.inputElement.style.width = '100%'
+ this.inputElement.style.borderWidth = '0px' // Inputs with 100% width always seem to be too large (I HATE THEM) they only work if the border, margin and padding are 0
+ this.inputElement.style.margin = '0px'
+ this.inputElement.style.padding = '0px'
+ this.inputElement.value = 'Type command here'
+ this.inputElement.setAttribute('autocomplete', 'off') // So Firefox doesn't flip out
+
+ Event.observe(this.inputElement, 'keyup', this.handleInput.bind(this))
+ Event.observe(this.inputElement, 'click', function() {this.inputElement.select()}.bind(this))
+
+ if(document.all && !window.opera)
+ {
+ window.setInterval(this.repositionWindow.bind(this), 500)
+ }
+ else
+ {
+ this.logElement.style.position="fixed";
+ this.logElement.style.bottom="0px";
+ }
+ var self=this;
+ Event.observe(document, 'keydown', function(e)
+ {
+ if((e.altKey==true) && Event.keyCode(e) == toggleKey ) //Alt+J | Ctrl+J
+ self.toggle();
+ });
+
+ // Listen to the logger....
+ Logger.onupdate.addListener(this.logUpdate.bind(this))
+ Logger.onclear.addListener(this.clear.bind(this))
+
+ // Preload log element with the log entries that have been entered
+ for (var i = 0; i < Logger.logEntries.length; i++) {
+ this.logUpdate(Logger.logEntries[i])
+ }
+
+ // Feed all errors into the logger (For some unknown reason I can only get this to work
+ // with an inline event declaration)
+ Event.observe(window, 'error', function(msg, url, lineNumber) {Logger.error("Error in (" + (url || location) + ") on line "+lineNumber+"", msg)})
+
+ // Allow acess key link
+ var accessElement = document.createElement('span')
+ accessElement.innerHTML = '<button style="position:absolute;top:-100px" onclick="javascript:logConsole.toggle()" accesskey="d"></button>'
+ document.body.appendChild(accessElement)
+
+ if (Cookie.get('ConsoleVisible') == 'true') {
+ this.toggle()
+ }
+ },
+
+ toggle : function() {
+ if (this.logElement.style.display == 'none') {
+ this.show()
+ }
+ else {
+ this.hide()
+ }
+ },
+
+ show : function() {
+ Element.show(this.logElement)
+ this.outputElement.scrollTop = this.outputElement.scrollHeight // Scroll to bottom when toggled
+ if(document.all && !window.opera)
+ this.repositionWindow();
+ Cookie.set('ConsoleVisible', 'true')
+ this.inputElement.select()
+ this.hidden = false;
+ },
+
+ hide : function() {
+ this.hidden = true;
+ Element.hide(this.logElement)
+ Cookie.set('ConsoleVisible', 'false')
+ },
+
+ output : function(message, style) {
+ // If we are at the bottom of the window, then keep scrolling with the output
+ var shouldScroll = (this.outputElement.scrollTop + (2 * this.outputElement.clientHeight)) >= this.outputElement.scrollHeight
+
+ this.outputCount++
+ style = (style ? style += ';' : '')
+ style += 'padding:1px;margin:0 0 5px 0'
+
+ if (this.outputCount % 2 == 0) style += ";background-color:#101010"
+
+ message = message || "undefined"
+ message = message.toString().escapeHTML()
+
+ this.outputElement.innerHTML += "<pre style='" + style + "'>" + message + "</pre>"
+
+ if (shouldScroll) {
+ this.outputElement.scrollTop = this.outputElement.scrollHeight
+ }
+ },
+
+ updateTags : function() {
+ var pattern = this.tagFilterElement.value
+
+ if (this.tagPattern == pattern) return
+
+ try {
+ new RegExp(pattern)
+ }
+ catch (e) {
+ return
+ }
+
+ this.tagPattern = pattern
+ Cookie.set('tagPattern', this.tagPattern)
+
+ this.outputElement.innerHTML = ""
+
+ // Go through each log entry again
+ this.outputCount = 0;
+ for (var i = 0; i < Logger.logEntries.length; i++) {
+ this.logUpdate(Logger.logEntries[i])
+ }
+ },
+
+ repositionWindow : function() {
+ var offset = window.pageYOffset || document.documentElement.scrollTop || document.body.scrollTop
+ var pageHeight = self.innerHeight || document.documentElement.clientHeight || document.body.clientHeight
+ this.logElement.style.top = (offset + pageHeight - Element.getHeight(this.logElement)) + "px"
+ },
+
+ // Event Handlers
+ // --------------
+
+ logUpdate : function(logEntry) {
+ if (logEntry.tag.search(new RegExp(this.tagPattern, 'igm')) == -1) return
+ var style = ''
+ if (logEntry.tag.search(/error/) != -1) style += 'color:red'
+ else if (logEntry.tag.search(/warning/) != -1) style += 'color:orange'
+ else if (logEntry.tag.search(/debug/) != -1) style += 'color:green'
+ else if (logEntry.tag.search(/info/) != -1) style += 'color:white'
+ else style += 'color:yellow'
+
+ this.output(logEntry.message, style)
+ },
+
+ clear : function(e) {
+ this.outputElement.innerHTML = ""
+ },
+
+ handleInput : function(e) {
+ if (e.keyCode == Event.KEY_RETURN ) {
+ var command = this.inputElement.value
+
+ switch(command) {
+ case "clear":
+ Logger.clear()
+ break
+
+ default:
+ var consoleOutput = ""
+
+ try {
+ consoleOutput = eval(this.inputElement.value)
+ }
+ catch (e) {
+ Logger.error("Problem parsing input <" + command + ">", e)
+ break
+ }
+
+ Logger.log(consoleOutput)
+ break
+ }
+
+ if (this.inputElement.value != "" && this.inputElement.value != this.commandHistory[0]) {
+ this.commandHistory.unshift(this.inputElement.value)
+ }
+
+ this.commandIndex = 0
+ this.inputElement.value = ""
+ }
+ else if (e.keyCode == Event.KEY_UP && this.commandHistory.length > 0) {
+ this.inputElement.value = this.commandHistory[this.commandIndex]
+
+ if (this.commandIndex < this.commandHistory.length - 1) {
+ this.commandIndex += 1
+ }
+ }
+ else if (e.keyCode == Event.KEY_DOWN && this.commandHistory.length > 0) {
+ if (this.commandIndex > 0) {
+ this.commandIndex -= 1
+ }
+
+ this.inputElement.value = this.commandHistory[this.commandIndex]
+ }
+ else {
+ this.commandIndex = 0
+ }
+ }
+};
+
+
+// -------------------------
+// Helper Functions And Junk
+// -------------------------
+function inspect(o)
+{
+ var objtype = typeof(o);
+ if (objtype == "undefined") {
+ return "undefined";
+ } else if (objtype == "number" || objtype == "boolean") {
+ return o + "";
+ } else if (o === null) {
+ return "null";
+ }
+
+ try {
+ var ostring = (o + "");
+ } catch (e) {
+ return "[" + typeof(o) + "]";
+ }
+
+ if (typeof(o) == "function")
+ {
+ o = ostring.replace(/^\s+/, "");
+ var idx = o.indexOf("{");
+ if (idx != -1) {
+ o = o.substr(0, idx) + "{...}";
+ }
+ return o;
+ }
+
+ var reprString = function (o)
+ {
+ return ('"' + o.replace(/(["\\])/g, '\\$1') + '"'
+ ).replace(/[\f]/g, "\\f"
+ ).replace(/[\b]/g, "\\b"
+ ).replace(/[\n]/g, "\\n"
+ ).replace(/[\t]/g, "\\t"
+ ).replace(/[\r]/g, "\\r");
+ };
+
+ if (objtype == "string") {
+ return reprString(o);
+ }
+ // recurse
+ var me = arguments.callee;
+ // short-circuit for objects that support "json" serialization
+ // if they return "self" then just pass-through...
+ var newObj;
+ if (typeof(o.__json__) == "function") {
+ newObj = o.__json__();
+ if (o !== newObj) {
+ return me(newObj);
+ }
+ }
+ if (typeof(o.json) == "function") {
+ newObj = o.json();
+ if (o !== newObj) {
+ return me(newObj);
+ }
+ }
+ // array
+ if (objtype != "function" && typeof(o.length) == "number") {
+ var res = [];
+ for (var i = 0; i < o.length; i++) {
+ var val = me(o[i]);
+ if (typeof(val) != "string") {
+ val = "undefined";
+ }
+ res.push(val);
+ }
+ return "[" + res.join(", ") + "]";
+ }
+
+ // generic object code path
+ res = [];
+ for (var k in o) {
+ var useKey;
+ if (typeof(k) == "number") {
+ useKey = '"' + k + '"';
+ } else if (typeof(k) == "string") {
+ useKey = reprString(k);
+ } else {
+ // skip non-string or number keys
+ continue;
+ }
+ val = me(o[k]);
+ if (typeof(val) != "string") {
+ // skip non-serializable values
+ continue;
+ }
+ res.push(useKey + ":" + val);
+ }
+ return "{" + res.join(", ") + "}";
+};
+
+Array.prototype.contains = function(object) {
+ for(var i = 0; i < this.length; i++) {
+ if (object == this[i]) return true
+ }
+
+ return false
+};
+
+// Helper Alias for simple logging
+var puts = function() {return Logger.log(arguments[0], arguments[1])};
+
+/*************************************
+
+ Javascript Object Tree
+ version 1.0
+ last revision:04.11.2004
+ steve@slayeroffice.com
+ http://slayeroffice.com
+
+ (c)2004 S.G. Chipman
+
+ Please notify me of any modifications
+ you make to this code so that I can
+ update the version hosted on slayeroffice.com
+
+
+************************************/
+if(typeof Prado == "undefined")
+ var Prado = {};
+Prado.Inspector =
+{
+ d : document,
+ types : new Array(),
+ objs : new Array(),
+ hidden : new Array(),
+ opera : window.opera,
+ displaying : '',
+ nameList : new Array(),
+
+ format : function(str) {
+ if(typeof(str) != "string") return str;
+ str=str.replace(/</g,"&lt;");
+ str=str.replace(/>/g,"&gt;");
+ return str;
+ },
+
+ parseJS : function(obj) {
+ var name;
+ if(typeof obj == "string") { name = obj; obj = eval(obj); }
+ win= typeof obj == 'undefined' ? window : obj;
+ this.displaying = name ? name : win.toString();
+ for(js in win) {
+ try {
+ if(win[js] && js.toString().indexOf("Inspector")==-1 && (win[js]+"").indexOf("[native code]")==-1) {
+
+ t=typeof(win[js]);
+ if(!this.objs[t.toString()]) {
+ this.types[this.types.length]=t;
+ this.objs[t]={};
+ this.nameList[t] = new Array();
+ }
+ this.nameList[t].push(js);
+ this.objs[t][js] = this.format(win[js]+"");
+ }
+ } catch(err) { }
+ }
+
+ for(i=0;i<this.types.length;i++)
+ this.nameList[this.types[i]].sort();
+ },
+
+ show : function(objID) {
+ this.d.getElementById(objID).style.display=this.hidden[objID]?"none":"block";
+ this.hidden[objID]=this.hidden[objID]?0:1;
+ },
+
+ changeSpan : function(spanID) {
+ if(this.d.getElementById(spanID).innerHTML.indexOf("+")>-1){
+ this.d.getElementById(spanID).innerHTML="[-]";
+ } else {
+ this.d.getElementById(spanID).innerHTML="[+]";
+ }
+ },
+
+ buildInspectionLevel : function()
+ {
+ var display = this.displaying;
+ var list = display.split(".");
+ var links = ["<a href=\"javascript:var_dump()\">[object Window]</a>"];
+ var name = '';
+ if(display.indexOf("[object ") >= 0) return links.join(".");
+ for(var i = 0; i < list.length; i++)
+ {
+ name += (name.length ? "." : "") + list[i];
+ links[i+1] = "<a href=\"javascript:var_dump('"+name+"')\">"+list[i]+"</a>";
+ }
+ return links.join(".");
+ },
+
+ buildTree : function() {
+ mHTML = "<div>Inspecting "+this.buildInspectionLevel()+"</div>";
+ mHTML +="<ul class=\"topLevel\">";
+ this.types.sort();
+ var so_objIndex=0;
+ for(i=0;i<this.types.length;i++)
+ {
+ mHTML+="<li style=\"cursor:pointer;\" onclick=\"Prado.Inspector.show('ul"+i+"');Prado.Inspector.changeSpan('sp" + i + "')\"><span id=\"sp" + i + "\">[+]</span><b>" + this.types[i] + "</b> (" + this.nameList[this.types[i]].length + ")</li><ul style=\"display:none;\" id=\"ul"+i+"\">";
+ this.hidden["ul"+i]=0;
+ for(e=0;e<this.nameList[this.types[i]].length;e++)
+ {
+ var prop = this.nameList[this.types[i]][e];
+ var value = this.objs[this.types[i]][prop]
+ var more = "";
+ if(value.indexOf("[object ") >= 0 && /^[a-zA-Z_]/.test(prop))
+ {
+ if(this.displaying.indexOf("[object ") < 0)
+ more = " <a href=\"javascript:var_dump('"+this.displaying+"."+prop+"')\"><b>more</b></a>";
+ else if(this.displaying.indexOf("[object Window]") >= 0)
+ more = " <a href=\"javascript:var_dump('"+prop+"')\"><b>more</b></a>";
+ }
+ mHTML+="<li style=\"cursor:pointer;\" onclick=\"Prado.Inspector.show('mul" + so_objIndex + "');Prado.Inspector.changeSpan('sk" + so_objIndex + "')\"><span id=\"sk" + so_objIndex + "\">[+]</span>" + prop + "</li><ul id=\"mul" + so_objIndex + "\" style=\"display:none;\"><li style=\"list-style-type:none;\"><pre>" + value + more + "</pre></li></ul>";
+ this.hidden["mul"+so_objIndex]=0;
+ so_objIndex++;
+ }
+ mHTML+="</ul>";
+ }
+ mHTML+="</ul>";
+ this.d.getElementById("so_mContainer").innerHTML =mHTML;
+ },
+
+ handleKeyEvent : function(e) {
+ keyCode=document.all?window.event.keyCode:e.keyCode;
+ if(keyCode==27) {
+ this.cleanUp();
+ }
+ },
+
+ cleanUp : function()
+ {
+ if(this.d.getElementById("so_mContainer"))
+ {
+ this.d.body.removeChild(this.d.getElementById("so_mContainer"));
+ this.d.body.removeChild(this.d.getElementById("so_mStyle"));
+ if(typeof Event != "undefined")
+ Event.stopObserving(this.d, "keydown", this.dKeyDownEvent);
+ this.types = new Array();
+ this.objs = new Array();
+ this.hidden = new Array();
+ }
+ },
+
+ disabled : document.all && !this.opera,
+
+ inspect : function(obj)
+ {
+ if(this.disabled)return alert("Sorry, this only works in Mozilla and Firefox currently.");
+ this.cleanUp();
+ mObj=this.d.body.appendChild(this.d.createElement("div"));
+ mObj.id="so_mContainer";
+ sObj=this.d.body.appendChild(this.d.createElement("style"));
+ sObj.id="so_mStyle";
+ sObj.type="text/css";
+ sObj.innerHTML = this.style;
+ this.dKeyDownEvent = this.handleKeyEvent.bind(this);
+ if(typeof Event != "undefined")
+ Event.observe(this.d, "keydown", this.dKeyDownEvent);
+
+ this.parseJS(obj);
+ this.buildTree();
+
+ cObj=mObj.appendChild(this.d.createElement("div"));
+ cObj.className="credits";
+ cObj.innerHTML = "<b>[esc] to <a href=\"javascript:Prado.Inspector.cleanUp();\">close</a></b><br />Javascript Object Tree V2.0.";
+
+ window.scrollTo(0,0);
+ },
+
+ style : "#so_mContainer { position:absolute; top:5px; left:5px; background-color:#E3EBED; text-align:left; font:9pt verdana; width:85%; border:2px solid #000; padding:5px; z-index:1000; color:#000; } " +
+ "#so_mContainer ul { padding-left:20px; } " +
+ "#so_mContainer ul li { display:block; list-style-type:none; list-style-image:url(); line-height:2em; -moz-border-radius:.75em; font:10px verdana; padding:0; margin:2px; color:#000; } " +
+ "#so_mContainer li:hover { background-color:#E3EBED; } " +
+ "#so_mContainer ul li span { position:relative; width:15px; height:15px; margin-right:4px; } " +
+ "#so_mContainer pre { background-color:#F9FAFB; border:1px solid #638DA1; height:auto; padding:5px; font:9px verdana; color:#000; } " +
+ "#so_mContainer .topLevel { margin:0; padding:0; } " +
+ "#so_mContainer .credits { float:left; width:200px; font:6.5pt verdana; color:#000; padding:2px; margin-left:5px; text-align:left; border-top:1px solid #000; margin-top:15px; width:75%; } " +
+ "#so_mContainer .credits a { font:9px verdana; font-weight:bold; color:#004465; text-decoration:none; background-color:transparent; }"
+};
+
+//similar function to var_dump in PHP, brings up the javascript object tree UI.
+function var_dump(obj)
+{
+ Prado.Inspector.inspect(obj);
+}
+
+//similar function to print_r for PHP
+var print_r = inspect;
+
diff --git a/framework/Web/Javascripts/source/prado/prado.js b/framework/Web/Javascripts/source/prado/prado.js
index ce789456..2fcb2c1e 100644
--- a/framework/Web/Javascripts/source/prado/prado.js
+++ b/framework/Web/Javascripts/source/prado/prado.js
@@ -1,94 +1,94 @@
-/**
- * Prado base namespace
- * @namespace Prado
- */
-var Prado =
-{
- /**
- * Version of Prado clientscripts
- * @var Version
- */
- Version: '3.2',
-
- /**
- * Registry for Prado components
- * @var Registry
- */
- Registry: $H(),
-
- /**
- * Returns browser information.
- * <pre>
- * var browser = Prado.Browser();
- * alert(browser.ie); //should ouput true if IE, false otherwise
- * </pre>
- * @function {object} ?
- * @version 1.0
- * @returns browserinfo
- * @... {string} agent - Reported user agent
- * @... {string} ver - Reported agent version
- * @... {0|1} dom - 1 for DOM browsers
- * @... {0|1} ns4 - 1 for Netscape 4
- * @... {0|1} ns6 - 1 for Netscape 6 and Firefox
- * @... {boolean} ie3 - true for IE 3
- * @... {0|1} ie5 - 1 for IE 5
- * @... {0|1} ie6 - 1 for IE 6
- * @... {0|1} ie4 - 1 for IE 4
- * @... {0|1} ie - 1 for IE 4-6
- * @... {0|1} hotjava - 1 for HotJava
- * @... {0|1} ver3 - 1 for IE3 and HotJava
- * @... {0|1} opera - 1 for Opera
- * @... {boolean} opera7 - true for Opera 7
- * @... {0|1} operaOld - 1 for older Opera
- * @... {0|1} bw - 1 for IE 4-6, Netscape 4&6, Firefox and Opera
- * @... {boolean} mac - true for mac systems
- * @... {static} Version - Version of returned structure (1.0)
- */
- Browser : function()
- {
- var info = { Version : "1.0" };
- var is_major = parseInt( navigator.appVersion );
- info.nver = is_major;
- info.ver = navigator.appVersion;
- info.agent = navigator.userAgent;
- info.dom = document.getElementById ? 1 : 0;
- info.opera = window.opera ? 1 : 0;
- info.ie5 = ( info.ver.indexOf( "MSIE 5" ) > -1 && info.dom && !info.opera ) ? 1 : 0;
- info.ie6 = ( info.ver.indexOf( "MSIE 6" ) > -1 && info.dom && !info.opera ) ? 1 : 0;
- info.ie4 = ( document.all && !info.dom && !info.opera ) ? 1 : 0;
- info.ie = info.ie4 || info.ie5 || info.ie6;
- info.mac = info.agent.indexOf( "Mac" ) > -1;
- info.ns6 = ( info.dom && parseInt( info.ver ) >= 5 ) ? 1 : 0;
- info.ie3 = ( info.ver.indexOf( "MSIE" ) && ( is_major < 4 ) );
- info.hotjava = ( info.agent.toLowerCase().indexOf( 'hotjava' ) != -1 ) ? 1 : 0;
- info.ns4 = ( document.layers && !info.dom && !info.hotjava ) ? 1 : 0;
- info.bw = ( info.ie6 || info.ie5 || info.ie4 || info.ns4 || info.ns6 || info.opera );
- info.ver3 = ( info.hotjava || info.ie3 );
- info.opera7 = ( ( info.agent.toLowerCase().indexOf( 'opera 7' ) > -1 ) || ( info.agent.toLowerCase().indexOf( 'opera/7' ) > -1 ) );
- info.operaOld = info.opera && !info.opera7;
- return info;
- },
-
- /**
- * Import CSS from Url.
- * @function ?
- * @param doc - document DOM object
- * @param css_file - Url to CSS file
- */
- ImportCss : function(doc, css_file)
- {
- if (Prado.Browser().ie)
- var styleSheet = doc.createStyleSheet(css_file);
- else
- {
- var elm = doc.createElement("link");
-
- elm.rel = "stylesheet";
- elm.href = css_file;
- var headArr;
-
- if (headArr = doc.getElementsByTagName("head"))
- headArr[0].appendChild(elm);
- }
- }
-};
+/**
+ * Prado base namespace
+ * @namespace Prado
+ */
+var Prado =
+{
+ /**
+ * Version of Prado clientscripts
+ * @var Version
+ */
+ Version: '3.2',
+
+ /**
+ * Registry for Prado components
+ * @var Registry
+ */
+ Registry: $H(),
+
+ /**
+ * Returns browser information.
+ * <pre>
+ * var browser = Prado.Browser();
+ * alert(browser.ie); //should ouput true if IE, false otherwise
+ * </pre>
+ * @function {object} ?
+ * @version 1.0
+ * @returns browserinfo
+ * @... {string} agent - Reported user agent
+ * @... {string} ver - Reported agent version
+ * @... {0|1} dom - 1 for DOM browsers
+ * @... {0|1} ns4 - 1 for Netscape 4
+ * @... {0|1} ns6 - 1 for Netscape 6 and Firefox
+ * @... {boolean} ie3 - true for IE 3
+ * @... {0|1} ie5 - 1 for IE 5
+ * @... {0|1} ie6 - 1 for IE 6
+ * @... {0|1} ie4 - 1 for IE 4
+ * @... {0|1} ie - 1 for IE 4-6
+ * @... {0|1} hotjava - 1 for HotJava
+ * @... {0|1} ver3 - 1 for IE3 and HotJava
+ * @... {0|1} opera - 1 for Opera
+ * @... {boolean} opera7 - true for Opera 7
+ * @... {0|1} operaOld - 1 for older Opera
+ * @... {0|1} bw - 1 for IE 4-6, Netscape 4&6, Firefox and Opera
+ * @... {boolean} mac - true for mac systems
+ * @... {static} Version - Version of returned structure (1.0)
+ */
+ Browser : function()
+ {
+ var info = { Version : "1.0" };
+ var is_major = parseInt( navigator.appVersion );
+ info.nver = is_major;
+ info.ver = navigator.appVersion;
+ info.agent = navigator.userAgent;
+ info.dom = document.getElementById ? 1 : 0;
+ info.opera = window.opera ? 1 : 0;
+ info.ie5 = ( info.ver.indexOf( "MSIE 5" ) > -1 && info.dom && !info.opera ) ? 1 : 0;
+ info.ie6 = ( info.ver.indexOf( "MSIE 6" ) > -1 && info.dom && !info.opera ) ? 1 : 0;
+ info.ie4 = ( document.all && !info.dom && !info.opera ) ? 1 : 0;
+ info.ie = info.ie4 || info.ie5 || info.ie6;
+ info.mac = info.agent.indexOf( "Mac" ) > -1;
+ info.ns6 = ( info.dom && parseInt( info.ver ) >= 5 ) ? 1 : 0;
+ info.ie3 = ( info.ver.indexOf( "MSIE" ) && ( is_major < 4 ) );
+ info.hotjava = ( info.agent.toLowerCase().indexOf( 'hotjava' ) != -1 ) ? 1 : 0;
+ info.ns4 = ( document.layers && !info.dom && !info.hotjava ) ? 1 : 0;
+ info.bw = ( info.ie6 || info.ie5 || info.ie4 || info.ns4 || info.ns6 || info.opera );
+ info.ver3 = ( info.hotjava || info.ie3 );
+ info.opera7 = ( ( info.agent.toLowerCase().indexOf( 'opera 7' ) > -1 ) || ( info.agent.toLowerCase().indexOf( 'opera/7' ) > -1 ) );
+ info.operaOld = info.opera && !info.opera7;
+ return info;
+ },
+
+ /**
+ * Import CSS from Url.
+ * @function ?
+ * @param doc - document DOM object
+ * @param css_file - Url to CSS file
+ */
+ ImportCss : function(doc, css_file)
+ {
+ if (Prado.Browser().ie)
+ var styleSheet = doc.createStyleSheet(css_file);
+ else
+ {
+ var elm = doc.createElement("link");
+
+ elm.rel = "stylesheet";
+ elm.href = css_file;
+ var headArr;
+
+ if (headArr = doc.getElementsByTagName("head"))
+ headArr[0].appendChild(elm);
+ }
+ }
+};
diff --git a/framework/Web/Javascripts/source/prado/ratings/ratings.js b/framework/Web/Javascripts/source/prado/ratings/ratings.js
index c7322983..1369c740 100644
--- a/framework/Web/Javascripts/source/prado/ratings/ratings.js
+++ b/framework/Web/Javascripts/source/prado/ratings/ratings.js
@@ -1,206 +1,206 @@
-Prado.WebUI.TRatingList = Base.extend(
-{
- selectedIndex : -1,
- rating: -1,
- readOnly : false,
-
- constructor : function(options)
- {
- var cap = $(options.CaptionID);
- this.options = Object.extend(
- {
- caption : cap ? cap.innerHTML : ''
- }, options || {});
-
- Prado.WebUI.TRatingList.register(this);
- this._init();
- Prado.Registry.set(options.ListID, this);
- this.selectedIndex = options.SelectedIndex;
- this.rating = options.Rating;
- this.readOnly = options.ReadOnly
- if(options.Rating <= 0 && options.SelectedIndex >= 0)
- this.rating = options.SelectedIndex+1;
- this.setReadOnly(this.readOnly);
- },
-
- _init: function(options)
- {
- Element.addClassName($(this.options.ListID),this.options.Style);
- this.radios = new Array();
- this._mouseOvers = new Array();
- this._mouseOuts = new Array();
- this._clicks = new Array();
- var index=0;
- for(var i = 0; i<this.options.ItemCount; i++)
- {
- var radio = $(this.options.ListID+'_c'+i);
- var td = radio.parentNode.parentNode;
- if(radio && td.tagName.toLowerCase()=='td')
- {
- this.radios.push(radio);
- this._mouseOvers.push(this.hover.bindEvent(this,index));
- this._mouseOuts.push(this.recover.bindEvent(this,index));
- this._clicks.push(this.click.bindEvent(this,index));
- index++;
- Element.addClassName(td,"rating");
- }
- }
- },
-
- hover : function(ev,index)
- {
- if(this.readOnly==true) return;
- for(var i = 0; i<this.radios.length; i++)
- {
- var node = this.radios[i].parentNode.parentNode;
- var action = i <= index ? 'addClassName' : 'removeClassName'
- Element[action](node,"rating_hover");
- Element.removeClassName(node,"rating_selected");
- Element.removeClassName(node,"rating_half");
- }
- this.showCaption(this.getIndexCaption(index));
- },
-
- recover : function(ev,index)
- {
- if(this.readOnly==true) return;
- this.showRating(this.rating);
- this.showCaption(this.options.caption);
- },
-
- click : function(ev, index)
- {
- if(this.readOnly==true) return;
- for(var i = 0; i<this.radios.length; i++)
- this.radios[i].checked = (i == index);
- this.selectedIndex = index;
- this.setRating(index+1);
-
- if(this.options['AutoPostBack']==true){
- this.dispatchRequest(ev);
- }
- },
-
- dispatchRequest : function(ev)
- {
- var requestOptions = Object.extend(
- {
- ID : this.options.ListID+"_c"+this.selectedIndex,
- EventTarget : this.options.ListName+"$c"+this.selectedIndex
- },this.options);
- Prado.PostBack(ev, requestOptions);
- },
-
- setRating : function(value)
- {
- this.rating = value;
- var base = Math.floor(value-1);
- var remainder = value - base-1;
- var halfMax = this.options.HalfRating["1"];
- var index = remainder > halfMax ? base+1 : base;
- for(var i = 0; i<this.radios.length; i++)
- this.radios[i].checked = (i == index);
-
- var caption = this.getIndexCaption(index);
- this.setCaption(caption);
- this.showCaption(caption);
-
- this.showRating(this.rating);
- },
-
- showRating: function(value)
- {
- var base = Math.floor(value-1);
- var remainder = value - base-1;
- var halfMin = this.options.HalfRating["0"];
- var halfMax = this.options.HalfRating["1"];
- var index = remainder > halfMax ? base+1 : base;
- var hasHalf = remainder >= halfMin && remainder <= halfMax;
- for(var i = 0; i<this.radios.length; i++)
- {
- var node = this.radios[i].parentNode.parentNode;
- var action = i > index ? 'removeClassName' : 'addClassName';
- Element[action](node, "rating_selected");
- if(i==index+1 && hasHalf)
- Element.addClassName(node, "rating_half");
- else
- Element.removeClassName(node, "rating_half");
- Element.removeClassName(node,"rating_hover");
- }
- },
-
- getIndexCaption : function(index)
- {
- return index > -1 ? this.radios[index].value : this.options.caption;
- },
-
- showCaption : function(value)
- {
- var caption = $(this.options.CaptionID);
- if(caption) caption.innerHTML = value;
- $(this.options.ListID).title = value;
- },
-
- setCaption : function(value)
- {
- this.options.caption = value;
- this.showCaption(value);
- },
-
- setReadOnly : function(value)
- {
- this.readOnly = value;
- for(var i = 0; i<this.radios.length; i++)
- {
-
- var action = value ? 'addClassName' : 'removeClassName';
- Element[action](this.radios[i].parentNode.parentNode, "rating_disabled");
-
- var action = value ? 'stopObserving' : 'observe';
- var td = this.radios[i].parentNode.parentNode;
- Event[action](td, "mouseover", this._mouseOvers[i]);
- Event[action](td, "mouseout", this._mouseOuts[i]);
- Event[action](td, "click", this._clicks[i]);
- }
-
- this.showRating(this.rating);
- }
-},
-{
-ratings : {},
-register : function(rating)
-{
- Prado.WebUI.TRatingList.ratings[rating.options.ListID] = rating;
-},
-
-setReadOnly : function(id,value)
-{
- Prado.WebUI.TRatingList.ratings[id].setReadOnly(value);
-},
-
-setRating : function(id,value)
-{
- Prado.WebUI.TRatingList.ratings[id].setRating(value);
-},
-
-setCaption : function(id,value)
-{
- Prado.WebUI.TRatingList.ratings[id].setCaption(value);
-}
-});
-
-Prado.WebUI.TActiveRatingList = Prado.WebUI.TRatingList.extend(
-{
- dispatchRequest : function(ev)
- {
- var requestOptions = Object.extend(
- {
- ID : this.options.ListID+"_c"+this.selectedIndex,
- EventTarget : this.options.ListName+"$c"+this.selectedIndex
- },this.options);
- var request = new Prado.CallbackRequest(requestOptions.EventTarget, requestOptions);
- if(request.dispatch()==false)
- Event.stop(ev);
- }
-
-});
+Prado.WebUI.TRatingList = Base.extend(
+{
+ selectedIndex : -1,
+ rating: -1,
+ readOnly : false,
+
+ constructor : function(options)
+ {
+ var cap = $(options.CaptionID);
+ this.options = Object.extend(
+ {
+ caption : cap ? cap.innerHTML : ''
+ }, options || {});
+
+ Prado.WebUI.TRatingList.register(this);
+ this._init();
+ Prado.Registry.set(options.ListID, this);
+ this.selectedIndex = options.SelectedIndex;
+ this.rating = options.Rating;
+ this.readOnly = options.ReadOnly
+ if(options.Rating <= 0 && options.SelectedIndex >= 0)
+ this.rating = options.SelectedIndex+1;
+ this.setReadOnly(this.readOnly);
+ },
+
+ _init: function(options)
+ {
+ Element.addClassName($(this.options.ListID),this.options.Style);
+ this.radios = new Array();
+ this._mouseOvers = new Array();
+ this._mouseOuts = new Array();
+ this._clicks = new Array();
+ var index=0;
+ for(var i = 0; i<this.options.ItemCount; i++)
+ {
+ var radio = $(this.options.ListID+'_c'+i);
+ var td = radio.parentNode.parentNode;
+ if(radio && td.tagName.toLowerCase()=='td')
+ {
+ this.radios.push(radio);
+ this._mouseOvers.push(this.hover.bindEvent(this,index));
+ this._mouseOuts.push(this.recover.bindEvent(this,index));
+ this._clicks.push(this.click.bindEvent(this,index));
+ index++;
+ Element.addClassName(td,"rating");
+ }
+ }
+ },
+
+ hover : function(ev,index)
+ {
+ if(this.readOnly==true) return;
+ for(var i = 0; i<this.radios.length; i++)
+ {
+ var node = this.radios[i].parentNode.parentNode;
+ var action = i <= index ? 'addClassName' : 'removeClassName'
+ Element[action](node,"rating_hover");
+ Element.removeClassName(node,"rating_selected");
+ Element.removeClassName(node,"rating_half");
+ }
+ this.showCaption(this.getIndexCaption(index));
+ },
+
+ recover : function(ev,index)
+ {
+ if(this.readOnly==true) return;
+ this.showRating(this.rating);
+ this.showCaption(this.options.caption);
+ },
+
+ click : function(ev, index)
+ {
+ if(this.readOnly==true) return;
+ for(var i = 0; i<this.radios.length; i++)
+ this.radios[i].checked = (i == index);
+ this.selectedIndex = index;
+ this.setRating(index+1);
+
+ if(this.options['AutoPostBack']==true){
+ this.dispatchRequest(ev);
+ }
+ },
+
+ dispatchRequest : function(ev)
+ {
+ var requestOptions = Object.extend(
+ {
+ ID : this.options.ListID+"_c"+this.selectedIndex,
+ EventTarget : this.options.ListName+"$c"+this.selectedIndex
+ },this.options);
+ Prado.PostBack(ev, requestOptions);
+ },
+
+ setRating : function(value)
+ {
+ this.rating = value;
+ var base = Math.floor(value-1);
+ var remainder = value - base-1;
+ var halfMax = this.options.HalfRating["1"];
+ var index = remainder > halfMax ? base+1 : base;
+ for(var i = 0; i<this.radios.length; i++)
+ this.radios[i].checked = (i == index);
+
+ var caption = this.getIndexCaption(index);
+ this.setCaption(caption);
+ this.showCaption(caption);
+
+ this.showRating(this.rating);
+ },
+
+ showRating: function(value)
+ {
+ var base = Math.floor(value-1);
+ var remainder = value - base-1;
+ var halfMin = this.options.HalfRating["0"];
+ var halfMax = this.options.HalfRating["1"];
+ var index = remainder > halfMax ? base+1 : base;
+ var hasHalf = remainder >= halfMin && remainder <= halfMax;
+ for(var i = 0; i<this.radios.length; i++)
+ {
+ var node = this.radios[i].parentNode.parentNode;
+ var action = i > index ? 'removeClassName' : 'addClassName';
+ Element[action](node, "rating_selected");
+ if(i==index+1 && hasHalf)
+ Element.addClassName(node, "rating_half");
+ else
+ Element.removeClassName(node, "rating_half");
+ Element.removeClassName(node,"rating_hover");
+ }
+ },
+
+ getIndexCaption : function(index)
+ {
+ return index > -1 ? this.radios[index].value : this.options.caption;
+ },
+
+ showCaption : function(value)
+ {
+ var caption = $(this.options.CaptionID);
+ if(caption) caption.innerHTML = value;
+ $(this.options.ListID).title = value;
+ },
+
+ setCaption : function(value)
+ {
+ this.options.caption = value;
+ this.showCaption(value);
+ },
+
+ setReadOnly : function(value)
+ {
+ this.readOnly = value;
+ for(var i = 0; i<this.radios.length; i++)
+ {
+
+ var action = value ? 'addClassName' : 'removeClassName';
+ Element[action](this.radios[i].parentNode.parentNode, "rating_disabled");
+
+ var action = value ? 'stopObserving' : 'observe';
+ var td = this.radios[i].parentNode.parentNode;
+ Event[action](td, "mouseover", this._mouseOvers[i]);
+ Event[action](td, "mouseout", this._mouseOuts[i]);
+ Event[action](td, "click", this._clicks[i]);
+ }
+
+ this.showRating(this.rating);
+ }
+},
+{
+ratings : {},
+register : function(rating)
+{
+ Prado.WebUI.TRatingList.ratings[rating.options.ListID] = rating;
+},
+
+setReadOnly : function(id,value)
+{
+ Prado.WebUI.TRatingList.ratings[id].setReadOnly(value);
+},
+
+setRating : function(id,value)
+{
+ Prado.WebUI.TRatingList.ratings[id].setRating(value);
+},
+
+setCaption : function(id,value)
+{
+ Prado.WebUI.TRatingList.ratings[id].setCaption(value);
+}
+});
+
+Prado.WebUI.TActiveRatingList = Prado.WebUI.TRatingList.extend(
+{
+ dispatchRequest : function(ev)
+ {
+ var requestOptions = Object.extend(
+ {
+ ID : this.options.ListID+"_c"+this.selectedIndex,
+ EventTarget : this.options.ListName+"$c"+this.selectedIndex
+ },this.options);
+ var request = new Prado.CallbackRequest(requestOptions.EventTarget, requestOptions);
+ if(request.dispatch()==false)
+ Event.stop(ev);
+ }
+
+});
diff --git a/framework/Web/Javascripts/source/prado/scriptaculous-adapter.js b/framework/Web/Javascripts/source/prado/scriptaculous-adapter.js
index 2cdc34e6..c1b7f814 100644
--- a/framework/Web/Javascripts/source/prado/scriptaculous-adapter.js
+++ b/framework/Web/Javascripts/source/prado/scriptaculous-adapter.js
@@ -1,1396 +1,1396 @@
-/**
- * Utilities and extions to Prototype/Scriptaculous
- * @file scriptaculous-adapter.js
- */
-
-/**
- * Extension to
- * <a href="http://www.prototypejs.org/api/function" target="_blank">Prototype's Function</a>
- * @namespace Function
- */
-/**
- * Similar to bindAsEventLister, but takes additional arguments.
- * @function Function.bindEvent
- */
-Function.prototype.bindEvent = function()
-{
- var __method = this, args = $A(arguments), object = args.shift();
- return function(event)
- {
- return __method.apply(object, [event || window.event].concat(args));
- }
-};
-
-/**
- * Extension to
- * <a href="http://www.prototypejs.org/api/class" target="_blank">Prototype's Class</a>
- * @namespace Class
- */
-
-/**
- * Creates a new class by copying class definition from
- * the <tt>base</tt> and optional <tt>definition</tt>.
- * @function {Class} Class.extend
- * @param {function} base - Base class to copy from.
- * @param {optional Array} - Additional definition
- * @returns Constructor for the extended class
- */
-Class.extend = function(base, definition)
-{
- var component = Class.create();
- Object.extend(component.prototype, base.prototype);
- if(definition)
- Object.extend(component.prototype, definition);
- return component;
-};
-
-/**
- * Base, version 1.0.2
- * Copyright 2006, Dean Edwards
- * License: http://creativecommons.org/licenses/LGPL/2.1/
- * @class Base
- */
-var Base = function() {
- if (arguments.length) {
- if (this == window) { // cast an object to this class
- Base.prototype.extend.call(arguments[0], arguments.callee.prototype);
- } else {
- this.extend(arguments[0]);
- }
- }
-};
-
-Base.version = "1.0.2";
-
-Base.prototype = {
- extend: function(source, value) {
- var extend = Base.prototype.extend;
- if (arguments.length == 2) {
- var ancestor = this[source];
- // overriding?
- if ((ancestor instanceof Function) && (value instanceof Function) &&
- ancestor.valueOf() != value.valueOf() && /\bbase\b/.test(value)) {
- var method = value;
- // var _prototype = this.constructor.prototype;
- // var fromPrototype = !Base._prototyping && _prototype[source] == ancestor;
- value = function() {
- var previous = this.base;
- // this.base = fromPrototype ? _prototype[source] : ancestor;
- this.base = ancestor;
- var returnValue = method.apply(this, arguments);
- this.base = previous;
- return returnValue;
- };
- // point to the underlying method
- value.valueOf = function() {
- return method;
- };
- value.toString = function() {
- return String(method);
- };
- }
- return this[source] = value;
- } else if (source) {
- var _prototype = {toSource: null};
- // do the "toString" and other methods manually
- var _protected = ["toString", "valueOf"];
- // if we are prototyping then include the constructor
- if (Base._prototyping) _protected[2] = "constructor";
- var name;
- for (var i = 0; (name = _protected[i]); i++) {
- if (source[name] != _prototype[name]) {
- extend.call(this, name, source[name]);
- }
- }
- // copy each of the source object's properties to this object
- for (var name in source) {
- if (!_prototype[name]) {
- extend.call(this, name, source[name]);
- }
- }
- }
- return this;
- },
-
- base: function() {
- // call this method from any other method to invoke that method's ancestor
- }
-};
-
-Base.extend = function(_instance, _static) {
- var extend = Base.prototype.extend;
- if (!_instance) _instance = {};
- // build the prototype
- Base._prototyping = true;
- var _prototype = new this;
- extend.call(_prototype, _instance);
- var constructor = _prototype.constructor;
- _prototype.constructor = this;
- delete Base._prototyping;
- // create the wrapper for the constructor function
- var klass = function() {
- if (!Base._prototyping) constructor.apply(this, arguments);
- this.constructor = klass;
- };
- klass.prototype = _prototype;
- // build the class interface
- klass.extend = this.extend;
- klass.implement = this.implement;
- klass.toString = function() {
- return String(constructor);
- };
- extend.call(klass, _static);
- // single instance
- var object = constructor ? klass : _prototype;
- // class initialisation
- if (object.init instanceof Function) object.init();
- return object;
-};
-
-Base.implement = function(_interface) {
- if (_interface instanceof Function) _interface = _interface.prototype;
- this.prototype.extend(_interface);
-};
-
-/**
- * Performs a PostBack using javascript.
- * @function Prado.PostBack
- * @param event - Event that triggered this postback
- * @param options - Postback options
- * @... {string} FormID - Form that should be posted back
- * @... {optional boolean} CausesValidation - Validate before PostBack if true
- * @... {optional string} ValidationGroup - Group to Validate
- * @... {optional string} ID - Validation ID
- * @... {optional string} PostBackUrl - Postback URL
- * @... {optional boolean} TrackFocus - Keep track of focused element if true
- * @... {string} EventTarget - Id of element that triggered PostBack
- * @... {string} EventParameter - EventParameter for PostBack
- */
-Prado.PostBack = function(event,options)
-{
- var form = $(options['FormID']);
- var canSubmit = true;
-
- if(options['CausesValidation'] && typeof(Prado.Validation) != "undefined")
- {
- if(!Prado.Validation.validate(options['FormID'], options['ValidationGroup'], $(options['ID'])))
- return Event.stop(event);
- }
-
- if(options['PostBackUrl'] && options['PostBackUrl'].length > 0)
- form.action = options['PostBackUrl'];
-
- if(options['TrackFocus'])
- {
- var lastFocus = $('PRADO_LASTFOCUS');
- if(lastFocus)
- {
- var active = document.activeElement; //where did this come from
- if(active)
- lastFocus.value = active.id;
- else
- lastFocus.value = options['EventTarget'];
- }
- }
-
- $('PRADO_POSTBACK_TARGET').value = options['EventTarget'];
- $('PRADO_POSTBACK_PARAMETER').value = options['EventParameter'];
- /**
- * Since google toolbar prevents browser default action,
- * we will always disable default client-side browser action
- */
- /*if(options['StopEvent']) */
- Event.stop(event);
- Event.fireEvent(form,"submit");
-};
-
-/**
- * Prado utilities to manipulate DOM elements.
- * @object Prado.Element
- */
-Prado.Element =
-{
- /**
- * Set the value of a particular element.
- * @function ?
- * @param {string} element - Element id
- * @param {string} value - New element value
- */
- setValue : function(element, value)
- {
- var el = $(element);
- if(el && typeof(el.value) != "undefined")
- el.value = value;
- },
-
- /**
- * Select options from a selectable element.
- * @function ?
- * @param {string} element - Element id
- * @param {string} method - Name of any {@link Prado.Element.Selection} method
- * @param {array|boolean|string} value - Values that should be selected
- * @param {int} total - Number of elements
- */
- select : function(element, method, value, total)
- {
- var el = $(element);
- if(!el) return;
- var selection = Prado.Element.Selection;
- if(typeof(selection[method]) == "function")
- {
- var control = selection.isSelectable(el) ? [el] : selection.getListElements(element,total);
- selection[method](control, value);
- }
- },
-
- /**
- * Trigger a click event on a DOM element.
- * @function ?
- * @param {string} element - Element id
- */
- click : function(element)
- {
- var el = $(element);
- if(el)
- el.click();
- },
-
- /**
- * Check if an DOM element is disabled.
- * @function {boolean} ?
- * @param {string} element - Element id
- * @returns true if element is disabled
- */
- isDisabled : function(element)
- {
- if(!element.attributes['disabled']) //FF
- return false;
- var value = element.attributes['disabled'].nodeValue;
- if(typeof(value)=="string")
- return value.toLowerCase() == "disabled";
- else
- return value == true;
- },
-
- /**
- * Sets an attribute of a DOM element.
- * @function ?
- * @param {string} element - Element id
- * @param {string} attribute - Name of attribute
- * @param {string} value - Value of attribute
- */
- setAttribute : function(element, attribute, value)
- {
- var el = $(element);
- if(!el) return;
- if((attribute == "disabled" || attribute == "multiple") && value==false)
- el.removeAttribute(attribute);
- else if(attribute.match(/^on/i)) //event methods
- {
- try
- {
- eval("(func = function(event){"+value+"})");
- el[attribute] = func;
- }
- catch(e)
- {
- debugger;
- throw "Error in evaluating '"+value+"' for attribute "+attribute+" for element "+element.id;
- }
- }
- else
- el.setAttribute(attribute, value);
- },
-
- /**
- * Sets the options for a select element.
- * @function ?
- * @param {string} element - Element id
- * @param {array[]} options - Array of options, each an array of structure
- * [ "optionText" , "optionValue" , "optionGroup" ]
- */
- setOptions : function(element, options)
- {
- var el = $(element);
- if(!el) return;
- var previousGroup = null;
- var optGroup=null;
- if(el && el.tagName.toLowerCase() == "select")
- {
- while(el.childNodes.length > 0)
- el.removeChild(el.lastChild);
-
- var optDom = Prado.Element.createOptions(options);
- for(var i = 0; i < optDom.length; i++)
- el.appendChild(optDom[i]);
- }
- },
-
- /**
- * Create opt-group options from an array of options.
- * @function {array} ?
- * @param {array[]} options - Array of options, each an array of structure
- * [ "optionText" , "optionValue" , "optionGroup" ]
- * @returns Array of option DOM elements
- */
- createOptions : function(options)
- {
- var previousGroup = null;
- var optgroup=null;
- var result = [];
- for(var i = 0; i<options.length; i++)
- {
- var option = options[i];
- if(option.length > 2)
- {
- var group = option[2];
- if(group!=previousGroup)
- {
- if(previousGroup!=null && optgroup!=null)
- {
- result.push(optgroup);
- previousGroup=null;
- optgroup=null;
- }
- optgroup = document.createElement('optgroup');
- optgroup.label = group;
- previousGroup = group;
- }
- }
- var opt = document.createElement('option');
- opt.text = option[0];
- opt.innerText = option[0];
- opt.value = option[1];
- if(optgroup!=null)
- optgroup.appendChild(opt);
- else
- result.push(opt);
- }
- if(optgroup!=null)
- result.push(optgroup);
- return result;
- },
-
- /**
- * Set focus (delayed) on a particular element.
- * @function ?
- * @param {string} element - Element id
- */
- focus : function(element)
- {
- var obj = $(element);
- if(typeof(obj) != "undefined" && typeof(obj.focus) != "undefined")
- setTimeout(function(){ obj.focus(); }, 100);
- return false;
- },
-
- /**
- * Replace a DOM element either with given content or
- * with content from a CallBack response boundary
- * using a replacement method.
- * @function ?
- * @param {string|element} element - DOM element or element id
- * @param {string} method - Name of method to use for replacement
- * @param {optional string} content - New content of element
- * @param {optional string} boundary - Boundary of new content
- */
- replace : function(element, method, content, boundary)
- {
- if(boundary)
- {
- var result = Prado.Element.extractContent(this.transport.responseText, boundary);
- if(result != null)
- content = result;
- }
- if(typeof(element) == "string")
- {
- if($(element))
- method.toFunction().apply(this,[element,""+content]);
- }
- else
- {
- method.toFunction().apply(this,[""+content]);
- }
- },
-
- /**
- * Appends a javascript block to the document.
- * @function ?
- * @param {string} boundary - Boundary containing the javascript code
- */
- appendScriptBlock : function(boundary)
- {
- var content = Prado.Element.extractContent(this.transport.responseText, boundary);
- if(content == null)
- return;
-
- var el = document.createElement("script");
- el.type = "text/javascript";
- el.id = 'inline_' + boundary;
- el.text = content;
-
- (document.getElementsByTagName('head')[0] || document.documentElement).appendChild(el);
- el.parentNode.removeChild(el);
- },
-
- /**
- * Extract content from a text by its boundary id.
- * Boundaries have this form:
- * <pre>
- * &lt;!--123456--&gt;Democontent&lt;!--//123456--&gt;
- * </pre>
- * @function {string} ?
- * @param {string} text - Text that contains boundaries
- * @param {string} boundary - Boundary id
- * @returns Content from given boundaries
- */
- extractContent : function(text, boundary)
- {
- var tagStart = '<!--'+boundary+'-->';
- var tagEnd = '<!--//'+boundary+'-->';
- var start = text.indexOf(tagStart);
- if(start > -1)
- {
- start += tagStart.length;
- var end = text.indexOf(tagEnd,start);
- if(end > -1)
- return text.substring(start,end);
- }
- return null;
- /*var f = RegExp('(?:<!--'+boundary+'-->)((?:.|\n|\r)+?)(?:<!--//'+boundary+'-->)',"m");
- var result = text.match(f);
- if(result && result.length >= 2)
- return result[1];
- else
- return null;*/
- },
-
- /**
- * Evaluate a javascript snippet from a string.
- * @function ?
- * @param {string} content - String containing the script
- */
- evaluateScript : function(content)
- {
- try
- {
- content.evalScripts();
- }
- catch(e)
- {
- if(typeof(Logger) != "undefined")
- Logger.error('Error during evaluation of script "'+content+'"');
- else
- debugger;
- throw e;
- }
- },
-
- /**
- * Set CSS style with Camelized keys.
- * See <a href="http://www.prototypejs.org/api/element/setstyle" target="_blank">Prototype's
- * Element.setStyle</a> for details.
- * @function ?
- * @param {string|element} element - DOM element or element id
- * @param {object} styles - Object with style properties/values
- */
- setStyle : function (element, styles)
- {
- var s = {}
- // Camelize all styles keys
- for (var property in styles)
- {
- s[property.camelize()]=styles[property].camelize();
- }
- Element.setStyle(element, s);
- }
-};
-
-/**
- * Utilities for selections.
- * @object Prado.Element.Selection
- */
-Prado.Element.Selection =
-{
- /**
- * Check if an DOM element can be selected.
- * @function {boolean} ?
- * @param {element} el - DOM elemet
- * @returns true if element is selectable
- */
- isSelectable : function(el)
- {
- if(el && el.type)
- {
- switch(el.type.toLowerCase())
- {
- case 'checkbox':
- case 'radio':
- case 'select':
- case 'select-multiple':
- case 'select-one':
- return true;
- }
- }
- return false;
- },
-
- /**
- * Set checked attribute of a checkbox or radiobutton to value.
- * @function {boolean} ?
- * @param {element} el - DOM element
- * @param {boolean} value - New value of checked attribute
- * @returns New value of checked attribute
- */
- inputValue : function(el, value)
- {
- switch(el.type.toLowerCase())
- {
- case 'checkbox':
- case 'radio':
- return el.checked = value;
- }
- },
-
- /**
- * Set selected attribute for elements options by value.
- * If value is boolean, all elements options selected attribute will be set
- * to value. Otherwhise all options that have the given value will be selected.
- * @function ?
- * @param {element[]} elements - Array of selectable DOM elements
- * @param {boolean|string} value - Value of options that should be selected or boolean value of selection status
- */
- selectValue : function(elements, value)
- {
- elements.each(function(el)
- {
- $A(el.options).each(function(option)
- {
- if(typeof(value) == "boolean")
- option.selected = value;
- else if(option.value == value)
- option.selected = true;
- });
- })
- },
-
- /**
- * Set selected attribute for elements options by array of values.
- * @function ?
- * @param {element[]} elements - Array of selectable DOM elements
- * @param {string[]} value - Array of values to select
- */
- selectValues : function(elements, values)
- {
- var selection = this;
- values.each(function(value)
- {
- selection.selectValue(elements,value);
- })
- },
-
- /**
- * Set selected attribute for elements options by option index.
- * @function ?
- * @param {element[]} elements - Array of selectable DOM elements
- * @param {int} index - Index of option to select
- */
- selectIndex : function(elements, index)
- {
- elements.each(function(el)
- {
- if(el.type.toLowerCase() == 'select-one')
- el.selectedIndex = index;
- else
- {
- for(var i = 0; i<el.length; i++)
- {
- if(i == index)
- el.options[i].selected = true;
- }
- }
- })
- },
-
- /**
- * Set selected attribute to true for all elements options.
- * @function ?
- * @param {element[]} elements - Array of selectable DOM elements
- */
- selectAll : function(elements)
- {
- elements.each(function(el)
- {
- if(el.type.toLowerCase() != 'select-one')
- {
- $A(el.options).each(function(option)
- {
- option.selected = true;
- })
- }
- })
- },
-
- /**
- * Toggle the selected attribute for elements options.
- * @function ?
- * @param {element[]} elements - Array of selectable DOM elements
- */
- selectInvert : function(elements)
- {
- elements.each(function(el)
- {
- if(el.type.toLowerCase() != 'select-one')
- {
- $A(el.options).each(function(option)
- {
- option.selected = !options.selected;
- })
- }
- })
- },
-
- /**
- * Set selected attribute for elements options by array of option indices.
- * @function ?
- * @param {element[]} elements - Array of selectable DOM elements
- * @param {int[]} indices - Array of option indices to select
- */
- selectIndices : function(elements, indices)
- {
- var selection = this;
- indices.each(function(index)
- {
- selection.selectIndex(elements,index);
- })
- },
-
- /**
- * Unselect elements.
- * @function ?
- * @param {element[]} elements - Array of selectable DOM elements
- */
- selectClear : function(elements)
- {
- elements.each(function(el)
- {
- el.selectedIndex = -1;
- })
- },
-
- /**
- * Get list elements of an element.
- * @function {element[]} ?
- * @param {element[]} elements - Array of selectable DOM elements
- * @param {int} total - Number of list elements to return
- * @returns Array of list DOM elements
- */
- getListElements : function(element, total)
- {
- var elements = new Array();
- var el;
- for(var i = 0; i < total; i++)
- {
- el = $(element+"_c"+i);
- if(el)
- elements.push(el);
- }
- return elements;
- },
-
- /**
- * Set checked attribute of elements by value.
- * If value is boolean, checked attribute will be set to value.
- * Otherwhise all elements that have the given value will be checked.
- * @function ?
- * @param {element[]} elements - Array of checkable DOM elements
- * @param {boolean|String} value - Value that should be checked or boolean value of checked status
- *
- */
- checkValue : function(elements, value)
- {
- elements.each(function(el)
- {
- if(typeof(value) == "boolean")
- el.checked = value;
- else if(el.value == value)
- el.checked = true;
- });
- },
-
- /**
- * Set checked attribute of elements by array of values.
- * @function ?
- * @param {element[]} elements - Array of checkable DOM elements
- * @param {string[]} values - Values that should be checked
- *
- */
- checkValues : function(elements, values)
- {
- var selection = this;
- values.each(function(value)
- {
- selection.checkValue(elements, value);
- })
- },
-
- /**
- * Set checked attribute of elements by list index.
- * @function ?
- * @param {element[]} elements - Array of checkable DOM elements
- * @param {int} index - Index of element to set checked
- */
- checkIndex : function(elements, index)
- {
- for(var i = 0; i<elements.length; i++)
- {
- if(i == index)
- elements[i].checked = true;
- }
- },
-
- /**
- * Set checked attribute of elements by array of list indices.
- * @function ?
- * @param {element[]} elements - Array of selectable DOM elements
- * @param {int[]} indices - Array of list indices to set checked
- */
- checkIndices : function(elements, indices)
- {
- var selection = this;
- indices.each(function(index)
- {
- selection.checkIndex(elements, index);
- })
- },
-
- /**
- * Uncheck elements.
- * @function ?
- * @param {element[]} elements - Array of checkable DOM elements
- */
- checkClear : function(elements)
- {
- elements.each(function(el)
- {
- el.checked = false;
- });
- },
-
- /**
- * Set checked attribute of all elements to true.
- * @function ?
- * @param {element[]} elements - Array of checkable DOM elements
- */
- checkAll : function(elements)
- {
- elements.each(function(el)
- {
- el.checked = true;
- })
- },
-
- /**
- * Toggle the checked attribute of elements.
- * @function ?
- * @param {element[]} elements - Array of selectable DOM elements
- */
- checkInvert : function(elements)
- {
- elements.each(function(el)
- {
- el.checked != el.checked;
- })
- }
-};
-
-
-/**
- * Utilities for insertion.
- * @object Prado.Element.Insert
- */
-Prado.Element.Insert =
-{
- /**
- * Append content to element
- * @function ?
- * @param {element} element - DOM element that content should be appended to
- * @param {element} content - DOM element to append
- */
- append: function(element, content)
- {
- $(element).insert(content);
- },
-
- /**
- * Prepend content to element
- * @function ?
- * @param {element} element - DOM element that content should be prepended to
- * @param {element} content - DOM element to prepend
- */
- prepend: function(element, content)
- {
- $(element).insert({top:content});
- },
-
- /**
- * Insert content after element
- * @function ?
- * @param {element} element - DOM element that content should be inserted after
- * @param {element} content - DOM element to insert
- */
- after: function(element, content)
- {
- $(element).insert({after:content});
- },
-
- /**
- * Insert content before element
- * @function ?
- * @param {element} element - DOM element that content should be inserted before
- * @param {element} content - DOM element to insert
- */
- before: function(element, content)
- {
- $(element).insert({before:content});
- }
-};
-
-
-/**
- * Extension to
- * <a href="http://wiki.script.aculo.us/scriptaculous/show/builder" target="_blank">Scriptaculous' Builder</a>
- * @namespace Builder
- */
-
-Object.extend(Builder,
-{
- /**
- * Export scriptaculous builder utilities as window[functions]
- * @function ?
- */
- exportTags:function()
- {
- var tags=["BUTTON","TT","PRE","H1","H2","H3","BR","CANVAS","HR","LABEL","TEXTAREA","FORM","STRONG","SELECT","OPTION","OPTGROUP","LEGEND","FIELDSET","P","UL","OL","LI","TD","TR","THEAD","TBODY","TFOOT","TABLE","TH","INPUT","SPAN","A","DIV","IMG", "CAPTION"];
- tags.each(function(tag)
- {
- window[tag]=function()
- {
- var args=$A(arguments);
- if(args.length==0)
- return Builder.node(tag,null);
- if(args.length==1)
- return Builder.node(tag,args[0]);
- if(args.length>1)
- return Builder.node(tag,args.shift(),args);
-
- };
- });
- }
-});
-Builder.exportTags();
-
-/**
- * Extension to
- * <a href="http://www.prototypejs.org/api/string" target="_blank">Prototype's String</a>
- * @namespace String
- */
-Object.extend(String.prototype, {
-
- /**
- * Add padding to string
- * @function {string} ?
- * @param {string} side - "left" to pad the string on the left, "right" to pad right.
- * @param {int} len - Minimum string length.
- * @param {string} chr - Character(s) to pad
- * @returns Padded string
- */
- pad : function(side, len, chr) {
- if (!chr) chr = ' ';
- var s = this;
- var left = side.toLowerCase()=='left';
- while (s.length<len) s = left? chr + s : s + chr;
- return s;
- },
-
- /**
- * Add left padding to string
- * @function {string} ?
- * @param {int} len - Minimum string length.
- * @param {string} chr - Character(s) to pad
- * @returns Padded string
- */
- padLeft : function(len, chr) {
- return this.pad('left',len,chr);
- },
-
- /**
- * Add right padding to string
- * @function {string} ?
- * @param {int} len - Minimum string length.
- * @param {string} chr - Character(s) to pad
- * @returns Padded string
- */
- padRight : function(len, chr) {
- return this.pad('right',len,chr);
- },
-
- /**
- * Add zeros to the right of string
- * @function {string} ?
- * @param {int} len - Minimum string length.
- * @returns Padded string
- */
- zerofill : function(len) {
- return this.padLeft(len,'0');
- },
-
- /**
- * Remove white spaces from both ends of string.
- * @function {string} ?
- * @returns Trimmed string
- */
- trim : function() {
- return this.replace(/^\s+|\s+$/g,'');
- },
-
- /**
- * Remove white spaces from the left side of string.
- * @function {string} ?
- * @returns Trimmed string
- */
- trimLeft : function() {
- return this.replace(/^\s+/,'');
- },
-
- /**
- * Remove white spaces from the right side of string.
- * @function {string} ?
- * @returns Trimmed string
- */
- trimRight : function() {
- return this.replace(/\s+$/,'');
- },
-
- /**
- * Convert period separated function names into a function reference.
- * <br />Example:
- * <pre>
- * "Prado.AJAX.Callback.Action.setValue".toFunction()
- * </pre>
- * @function {function} ?
- * @returns Reference to the corresponding function
- */
- toFunction : function()
- {
- var commands = this.split(/\./);
- var command = window;
- commands.each(function(action)
- {
- if(command[new String(action)])
- command=command[new String(action)];
- });
- if(typeof(command) == "function")
- return command;
- else
- {
- if(typeof Logger != "undefined")
- Logger.error("Missing function", this);
-
- throw new Error ("Missing function '"+this+"'");
- }
- },
-
- /**
- * Convert string into integer, returns null if not integer.
- * @function {int} ?
- * @returns Integer, null if string does not represent an integer.
- */
- toInteger : function()
- {
- var exp = /^\s*[-\+]?\d+\s*$/;
- if (this.match(exp) == null)
- return null;
- var num = parseInt(this, 10);
- return (isNaN(num) ? null : num);
- },
-
- /**
- * Convert string into a double/float value. <b>Internationalization
- * is not supported</b>
- * @function {double} ?
- * @param {string} decimalchar - Decimal character, defaults to "."
- * @returns Double, null if string does not represent a float value
- */
- toDouble : function(decimalchar)
- {
- if(this.length <= 0) return null;
- decimalchar = decimalchar || ".";
- var exp = new RegExp("^\\s*([-\\+])?(\\d+)?(\\" + decimalchar + "(\\d+))?\\s*$");
- var m = this.match(exp);
-
- if (m == null)
- return null;
- m[1] = m[1] || "";
- m[2] = m[2] || "0";
- m[4] = m[4] || "0";
-
- var cleanInput = m[1] + (m[2].length>0 ? m[2] : "0") + "." + m[4];
- var num = parseFloat(cleanInput);
- return (isNaN(num) ? null : num);
- },
-
- /**
- * Convert strings that represent a currency value to float.
- * E.g. "10,000.50" will become "10000.50". The number
- * of dicimal digits, grouping and decimal characters can be specified.
- * <i>The currency input format is <b>very</b> strict, null will be returned if
- * the pattern does not match</i>.
- * @function {double} ?
- * @param {string} groupchar - Grouping character, defaults to ","
- * @param {int} digits - Number of decimal digits
- * @param {string} decimalchar - Decimal character, defaults to "."
- * @returns Double, null if string does not represent a currency value
- */
- toCurrency : function(groupchar, digits, decimalchar)
- {
- groupchar = groupchar || ",";
- decimalchar = decimalchar || ".";
- digits = typeof(digits) == "undefined" ? 2 : digits;
-
- var exp = new RegExp("^\\s*([-\\+])?(((\\d+)\\" + groupchar + ")*)(\\d+)"
- + ((digits > 0) ? "(\\" + decimalchar + "(\\d{1," + digits + "}))?" : "")
- + "\\s*$");
- var m = this.match(exp);
- if (m == null)
- return null;
- var intermed = m[2] + m[5] ;
- var cleanInput = m[1] + intermed.replace(
- new RegExp("(\\" + groupchar + ")", "g"), "")
- + ((digits > 0) ? "." + m[7] : "");
- var num = parseFloat(cleanInput);
- return (isNaN(num) ? null : num);
- },
-
- /**
- * Converts the string to a date by finding values that matches the
- * date format pattern.
- * @function {Date} ?
- * @param {string} format - Date format pattern, e.g. MM-dd-yyyy
- * @returns Date extracted from the string
- */
- toDate : function(format)
- {
- return Date.SimpleParse(this, format);
- }
-});
-
-/**
- * Extension to
- * <a href="http://www.prototypejs.org/api/event" target="_blank">Prototype's Event</a>
- * @namespace Event
- */
-Object.extend(Event,
-{
- /**
- * Register a function to be executed when the page is loaded.
- * Note that the page is only loaded if all resources (e.g. images)
- * are loaded.
- * <br />Example:
- * <br />Show an alert box with message "Page Loaded!" when the
- * page finished loading.
- * <pre>
- * Event.OnLoad(function(){ alert("Page Loaded!"); });
- * </pre>
- * @function ?
- * @param {function} fn - Function to execute when page is loaded.
- */
- OnLoad : function (fn)
- {
- // opera onload is in document, not window
- var w = document.addEventListener &&
- !window.addEventListener ? document : window;
- Event.observe(w,'load',fn);
- },
-
- /**
- * Returns the unicode character generated by key.
- * @param {event} e - Keyboard event
- * @function {int} ?
- * @returns Unicode character code generated by the key that was struck.
- */
- keyCode : function(e)
- {
- return e.keyCode != null ? e.keyCode : e.charCode
- },
-
- /**
- * Checks if an Event is of type HTMLEvent.
- * @function {boolean} ?
- * @param {string} type - Event type or event name.
- * @return true if event is of type HTMLEvent.
- */
- isHTMLEvent : function(type)
- {
- var events = ['abort', 'blur', 'change', 'error', 'focus',
- 'load', 'reset', 'resize', 'scroll', 'select',
- 'submit', 'unload'];
- return events.include(type);
- },
-
- /**
- * Checks if an Event is a mouse event.
- * @function {boolean} ?
- * @param {string} type - Event type or event name
- * @return true if event is of type MouseEvent.
- */
- isMouseEvent : function(type)
- {
- var events = ['click', 'mousedown', 'mousemove', 'mouseout',
- 'mouseover', 'mouseup'];
- return events.include(type);
- },
-
- /**
- * Dispatch the DOM event of a given <tt>type</tt> on a DOM
- * <tt>element</tt>. 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.
- * @function ?
- * @param {element|string} element - Element id string or DOM element.
- * @param {string} type - Event type to dispatch.
- */
- fireEvent : function(element,type)
- {
- element = $(element);
- if(type == "submit")
- return element.submit();
- if(document.createEvent)
- {
- if(Event.isHTMLEvent(type))
- {
- var event = document.createEvent('HTMLEvents');
- event.initEvent(type, true, true);
- }
- else if(Event.isMouseEvent(type))
- {
- var event = document.createEvent('MouseEvents');
- if (event.initMouseEvent)
- {
- event.initMouseEvent(type,true,true,
- document.defaultView, 1, 0, 0, 0, 0, false,
- false, false, false, 0, null);
- }
- else
- {
- // Safari
- // TODO we should be initialising other mouse-event related attributes here
- event.initEvent(type, true, true);
- }
- }
- element.dispatchEvent(event);
- }
- else if(document.createEventObject)
- {
- var evObj = document.createEventObject();
- element.fireEvent('on'+type, evObj);
- }
- else if(typeof(element['on'+type]) == "function")
- element['on'+type]();
- }
-});
-
-
-/**
- * Extension to
- * <a href="http://www.prototypejs.org/api/date" target="_blank">Prototype's Date</a>
- * @namespace Date
- */
-Object.extend(Date.prototype,
-{
- /**
- * SimpleFormat
- * @function ?
- * @param {string} format - TODO
- * @param {string} data - TODO
- * @returns TODO
- */
- SimpleFormat: function(format, data)
- {
- data = data || {};
- var bits = new Array();
- bits['d'] = this.getDate();
- bits['dd'] = String(this.getDate()).zerofill(2);
-
- bits['M'] = this.getMonth()+1;
- bits['MM'] = String(this.getMonth()+1).zerofill(2);
- if(data.AbbreviatedMonthNames)
- bits['MMM'] = data.AbbreviatedMonthNames[this.getMonth()];
- if(data.MonthNames)
- bits['MMMM'] = data.MonthNames[this.getMonth()];
- var yearStr = "" + this.getFullYear();
- yearStr = (yearStr.length == 2) ? '19' + yearStr: yearStr;
- bits['yyyy'] = yearStr;
- bits['yy'] = bits['yyyy'].toString().substr(2,2);
-
- // do some funky regexs to replace the format string
- // with the real values
- var frm = new String(format);
- for (var sect in bits)
- {
- var reg = new RegExp("\\b"+sect+"\\b" ,"g");
- frm = frm.replace(reg, bits[sect]);
- }
- return frm;
- },
-
- /**
- * toISODate
- * @function {string} ?
- * @returns TODO
- */
- toISODate : function()
- {
- var y = this.getFullYear();
- var m = String(this.getMonth() + 1).zerofill(2);
- var d = String(this.getDate()).zerofill(2);
- return String(y) + String(m) + String(d);
- }
-});
-
-Object.extend(Date,
-{
- /**
- * SimpleParse
- * @function ?
- * @param {string} format - TODO
- * @param {string} data - TODO
- * @returns TODO
- */
- SimpleParse: function(value, format)
- {
- var val=String(value);
- format=String(format);
-
- if(val.length <= 0) return null;
-
- if(format.length <= 0) return new Date(value);
-
- var isInteger = function (val)
- {
- var digits="1234567890";
- for (var i=0; i < val.length; i++)
- {
- if (digits.indexOf(val.charAt(i))==-1) { return false; }
- }
- return true;
- };
-
- var getInt = function(str,i,minlength,maxlength)
- {
- for (var x=maxlength; x>=minlength; x--)
- {
- var token=str.substring(i,i+x);
- if (token.length < minlength) { return null; }
- if (isInteger(token)) { return token; }
- }
- return null;
- };
-
- var i_val=0;
- var i_format=0;
- var c="";
- var token="";
- var token2="";
- var x,y;
- var now=new Date();
- var year=now.getFullYear();
- var month=now.getMonth()+1;
- var date=1;
-
- while (i_format < format.length)
- {
- // Get next token from format string
- c=format.charAt(i_format);
- token="";
- while ((format.charAt(i_format)==c) && (i_format < format.length))
- {
- token += format.charAt(i_format++);
- }
-
- // Extract contents of value based on format token
- if (token=="yyyy" || token=="yy" || token=="y")
- {
- if (token=="yyyy") { x=4;y=4; }
- if (token=="yy") { x=2;y=2; }
- if (token=="y") { x=2;y=4; }
- year=getInt(val,i_val,x,y);
- if (year==null) { return null; }
- i_val += year.length;
- if (year.length==2)
- {
- if (year > 70) { year=1900+(year-0); }
- else { year=2000+(year-0); }
- }
- }
-
- else if (token=="MM"||token=="M")
- {
- month=getInt(val,i_val,token.length,2);
- if(month==null||(month<1)||(month>12)){return null;}
- i_val+=month.length;
- }
- else if (token=="dd"||token=="d")
- {
- date=getInt(val,i_val,token.length,2);
- if(date==null||(date<1)||(date>31)){return null;}
- i_val+=date.length;
- }
- else
- {
- if (val.substring(i_val,i_val+token.length)!=token) {return null;}
- else {i_val+=token.length;}
- }
- }
-
- // If there are any trailing characters left in the value, it doesn't match
- if (i_val != val.length) { return null; }
-
- // Is date valid for month?
- if (month==2)
- {
- // Check for leap year
- if ( ( (year%4==0)&&(year%100 != 0) ) || (year%400==0) ) { // leap year
- if (date > 29){ return null; }
- }
- else { if (date > 28) { return null; } }
- }
-
- if ((month==4)||(month==6)||(month==9)||(month==11))
- {
- if (date > 30) { return null; }
- }
-
- var newdate=new Date(year,month-1,date, 0, 0, 0);
- return newdate;
- }
-});
-
-/**
- * Prado utilities for effects.
- * @object Prado.Effect
- */
-Prado.Effect =
-{
- /**
- * Highlights an element
- * @function ?
- * @param {element} element - DOM element to highlight
- * @param {optional object} options - Highlight options
- */
- Highlight : function (element,options)
- {
- new Effect.Highlight(element,options);
- }
-};
+/**
+ * Utilities and extions to Prototype/Scriptaculous
+ * @file scriptaculous-adapter.js
+ */
+
+/**
+ * Extension to
+ * <a href="http://www.prototypejs.org/api/function" target="_blank">Prototype's Function</a>
+ * @namespace Function
+ */
+/**
+ * Similar to bindAsEventLister, but takes additional arguments.
+ * @function Function.bindEvent
+ */
+Function.prototype.bindEvent = function()
+{
+ var __method = this, args = $A(arguments), object = args.shift();
+ return function(event)
+ {
+ return __method.apply(object, [event || window.event].concat(args));
+ }
+};
+
+/**
+ * Extension to
+ * <a href="http://www.prototypejs.org/api/class" target="_blank">Prototype's Class</a>
+ * @namespace Class
+ */
+
+/**
+ * Creates a new class by copying class definition from
+ * the <tt>base</tt> and optional <tt>definition</tt>.
+ * @function {Class} Class.extend
+ * @param {function} base - Base class to copy from.
+ * @param {optional Array} - Additional definition
+ * @returns Constructor for the extended class
+ */
+Class.extend = function(base, definition)
+{
+ var component = Class.create();
+ Object.extend(component.prototype, base.prototype);
+ if(definition)
+ Object.extend(component.prototype, definition);
+ return component;
+};
+
+/**
+ * Base, version 1.0.2
+ * Copyright 2006, Dean Edwards
+ * License: http://creativecommons.org/licenses/LGPL/2.1/
+ * @class Base
+ */
+var Base = function() {
+ if (arguments.length) {
+ if (this == window) { // cast an object to this class
+ Base.prototype.extend.call(arguments[0], arguments.callee.prototype);
+ } else {
+ this.extend(arguments[0]);
+ }
+ }
+};
+
+Base.version = "1.0.2";
+
+Base.prototype = {
+ extend: function(source, value) {
+ var extend = Base.prototype.extend;
+ if (arguments.length == 2) {
+ var ancestor = this[source];
+ // overriding?
+ if ((ancestor instanceof Function) && (value instanceof Function) &&
+ ancestor.valueOf() != value.valueOf() && /\bbase\b/.test(value)) {
+ var method = value;
+ // var _prototype = this.constructor.prototype;
+ // var fromPrototype = !Base._prototyping && _prototype[source] == ancestor;
+ value = function() {
+ var previous = this.base;
+ // this.base = fromPrototype ? _prototype[source] : ancestor;
+ this.base = ancestor;
+ var returnValue = method.apply(this, arguments);
+ this.base = previous;
+ return returnValue;
+ };
+ // point to the underlying method
+ value.valueOf = function() {
+ return method;
+ };
+ value.toString = function() {
+ return String(method);
+ };
+ }
+ return this[source] = value;
+ } else if (source) {
+ var _prototype = {toSource: null};
+ // do the "toString" and other methods manually
+ var _protected = ["toString", "valueOf"];
+ // if we are prototyping then include the constructor
+ if (Base._prototyping) _protected[2] = "constructor";
+ var name;
+ for (var i = 0; (name = _protected[i]); i++) {
+ if (source[name] != _prototype[name]) {
+ extend.call(this, name, source[name]);
+ }
+ }
+ // copy each of the source object's properties to this object
+ for (var name in source) {
+ if (!_prototype[name]) {
+ extend.call(this, name, source[name]);
+ }
+ }
+ }
+ return this;
+ },
+
+ base: function() {
+ // call this method from any other method to invoke that method's ancestor
+ }
+};
+
+Base.extend = function(_instance, _static) {
+ var extend = Base.prototype.extend;
+ if (!_instance) _instance = {};
+ // build the prototype
+ Base._prototyping = true;
+ var _prototype = new this;
+ extend.call(_prototype, _instance);
+ var constructor = _prototype.constructor;
+ _prototype.constructor = this;
+ delete Base._prototyping;
+ // create the wrapper for the constructor function
+ var klass = function() {
+ if (!Base._prototyping) constructor.apply(this, arguments);
+ this.constructor = klass;
+ };
+ klass.prototype = _prototype;
+ // build the class interface
+ klass.extend = this.extend;
+ klass.implement = this.implement;
+ klass.toString = function() {
+ return String(constructor);
+ };
+ extend.call(klass, _static);
+ // single instance
+ var object = constructor ? klass : _prototype;
+ // class initialisation
+ if (object.init instanceof Function) object.init();
+ return object;
+};
+
+Base.implement = function(_interface) {
+ if (_interface instanceof Function) _interface = _interface.prototype;
+ this.prototype.extend(_interface);
+};
+
+/**
+ * Performs a PostBack using javascript.
+ * @function Prado.PostBack
+ * @param event - Event that triggered this postback
+ * @param options - Postback options
+ * @... {string} FormID - Form that should be posted back
+ * @... {optional boolean} CausesValidation - Validate before PostBack if true
+ * @... {optional string} ValidationGroup - Group to Validate
+ * @... {optional string} ID - Validation ID
+ * @... {optional string} PostBackUrl - Postback URL
+ * @... {optional boolean} TrackFocus - Keep track of focused element if true
+ * @... {string} EventTarget - Id of element that triggered PostBack
+ * @... {string} EventParameter - EventParameter for PostBack
+ */
+Prado.PostBack = function(event,options)
+{
+ var form = $(options['FormID']);
+ var canSubmit = true;
+
+ if(options['CausesValidation'] && typeof(Prado.Validation) != "undefined")
+ {
+ if(!Prado.Validation.validate(options['FormID'], options['ValidationGroup'], $(options['ID'])))
+ return Event.stop(event);
+ }
+
+ if(options['PostBackUrl'] && options['PostBackUrl'].length > 0)
+ form.action = options['PostBackUrl'];
+
+ if(options['TrackFocus'])
+ {
+ var lastFocus = $('PRADO_LASTFOCUS');
+ if(lastFocus)
+ {
+ var active = document.activeElement; //where did this come from
+ if(active)
+ lastFocus.value = active.id;
+ else
+ lastFocus.value = options['EventTarget'];
+ }
+ }
+
+ $('PRADO_POSTBACK_TARGET').value = options['EventTarget'];
+ $('PRADO_POSTBACK_PARAMETER').value = options['EventParameter'];
+ /**
+ * Since google toolbar prevents browser default action,
+ * we will always disable default client-side browser action
+ */
+ /*if(options['StopEvent']) */
+ Event.stop(event);
+ Event.fireEvent(form,"submit");
+};
+
+/**
+ * Prado utilities to manipulate DOM elements.
+ * @object Prado.Element
+ */
+Prado.Element =
+{
+ /**
+ * Set the value of a particular element.
+ * @function ?
+ * @param {string} element - Element id
+ * @param {string} value - New element value
+ */
+ setValue : function(element, value)
+ {
+ var el = $(element);
+ if(el && typeof(el.value) != "undefined")
+ el.value = value;
+ },
+
+ /**
+ * Select options from a selectable element.
+ * @function ?
+ * @param {string} element - Element id
+ * @param {string} method - Name of any {@link Prado.Element.Selection} method
+ * @param {array|boolean|string} value - Values that should be selected
+ * @param {int} total - Number of elements
+ */
+ select : function(element, method, value, total)
+ {
+ var el = $(element);
+ if(!el) return;
+ var selection = Prado.Element.Selection;
+ if(typeof(selection[method]) == "function")
+ {
+ var control = selection.isSelectable(el) ? [el] : selection.getListElements(element,total);
+ selection[method](control, value);
+ }
+ },
+
+ /**
+ * Trigger a click event on a DOM element.
+ * @function ?
+ * @param {string} element - Element id
+ */
+ click : function(element)
+ {
+ var el = $(element);
+ if(el)
+ el.click();
+ },
+
+ /**
+ * Check if an DOM element is disabled.
+ * @function {boolean} ?
+ * @param {string} element - Element id
+ * @returns true if element is disabled
+ */
+ isDisabled : function(element)
+ {
+ if(!element.attributes['disabled']) //FF
+ return false;
+ var value = element.attributes['disabled'].nodeValue;
+ if(typeof(value)=="string")
+ return value.toLowerCase() == "disabled";
+ else
+ return value == true;
+ },
+
+ /**
+ * Sets an attribute of a DOM element.
+ * @function ?
+ * @param {string} element - Element id
+ * @param {string} attribute - Name of attribute
+ * @param {string} value - Value of attribute
+ */
+ setAttribute : function(element, attribute, value)
+ {
+ var el = $(element);
+ if(!el) return;
+ if((attribute == "disabled" || attribute == "multiple") && value==false)
+ el.removeAttribute(attribute);
+ else if(attribute.match(/^on/i)) //event methods
+ {
+ try
+ {
+ eval("(func = function(event){"+value+"})");
+ el[attribute] = func;
+ }
+ catch(e)
+ {
+ debugger;
+ throw "Error in evaluating '"+value+"' for attribute "+attribute+" for element "+element.id;
+ }
+ }
+ else
+ el.setAttribute(attribute, value);
+ },
+
+ /**
+ * Sets the options for a select element.
+ * @function ?
+ * @param {string} element - Element id
+ * @param {array[]} options - Array of options, each an array of structure
+ * [ "optionText" , "optionValue" , "optionGroup" ]
+ */
+ setOptions : function(element, options)
+ {
+ var el = $(element);
+ if(!el) return;
+ var previousGroup = null;
+ var optGroup=null;
+ if(el && el.tagName.toLowerCase() == "select")
+ {
+ while(el.childNodes.length > 0)
+ el.removeChild(el.lastChild);
+
+ var optDom = Prado.Element.createOptions(options);
+ for(var i = 0; i < optDom.length; i++)
+ el.appendChild(optDom[i]);
+ }
+ },
+
+ /**
+ * Create opt-group options from an array of options.
+ * @function {array} ?
+ * @param {array[]} options - Array of options, each an array of structure
+ * [ "optionText" , "optionValue" , "optionGroup" ]
+ * @returns Array of option DOM elements
+ */
+ createOptions : function(options)
+ {
+ var previousGroup = null;
+ var optgroup=null;
+ var result = [];
+ for(var i = 0; i<options.length; i++)
+ {
+ var option = options[i];
+ if(option.length > 2)
+ {
+ var group = option[2];
+ if(group!=previousGroup)
+ {
+ if(previousGroup!=null && optgroup!=null)
+ {
+ result.push(optgroup);
+ previousGroup=null;
+ optgroup=null;
+ }
+ optgroup = document.createElement('optgroup');
+ optgroup.label = group;
+ previousGroup = group;
+ }
+ }
+ var opt = document.createElement('option');
+ opt.text = option[0];
+ opt.innerText = option[0];
+ opt.value = option[1];
+ if(optgroup!=null)
+ optgroup.appendChild(opt);
+ else
+ result.push(opt);
+ }
+ if(optgroup!=null)
+ result.push(optgroup);
+ return result;
+ },
+
+ /**
+ * Set focus (delayed) on a particular element.
+ * @function ?
+ * @param {string} element - Element id
+ */
+ focus : function(element)
+ {
+ var obj = $(element);
+ if(typeof(obj) != "undefined" && typeof(obj.focus) != "undefined")
+ setTimeout(function(){ obj.focus(); }, 100);
+ return false;
+ },
+
+ /**
+ * Replace a DOM element either with given content or
+ * with content from a CallBack response boundary
+ * using a replacement method.
+ * @function ?
+ * @param {string|element} element - DOM element or element id
+ * @param {string} method - Name of method to use for replacement
+ * @param {optional string} content - New content of element
+ * @param {optional string} boundary - Boundary of new content
+ */
+ replace : function(element, method, content, boundary)
+ {
+ if(boundary)
+ {
+ var result = Prado.Element.extractContent(this.transport.responseText, boundary);
+ if(result != null)
+ content = result;
+ }
+ if(typeof(element) == "string")
+ {
+ if($(element))
+ method.toFunction().apply(this,[element,""+content]);
+ }
+ else
+ {
+ method.toFunction().apply(this,[""+content]);
+ }
+ },
+
+ /**
+ * Appends a javascript block to the document.
+ * @function ?
+ * @param {string} boundary - Boundary containing the javascript code
+ */
+ appendScriptBlock : function(boundary)
+ {
+ var content = Prado.Element.extractContent(this.transport.responseText, boundary);
+ if(content == null)
+ return;
+
+ var el = document.createElement("script");
+ el.type = "text/javascript";
+ el.id = 'inline_' + boundary;
+ el.text = content;
+
+ (document.getElementsByTagName('head')[0] || document.documentElement).appendChild(el);
+ el.parentNode.removeChild(el);
+ },
+
+ /**
+ * Extract content from a text by its boundary id.
+ * Boundaries have this form:
+ * <pre>
+ * &lt;!--123456--&gt;Democontent&lt;!--//123456--&gt;
+ * </pre>
+ * @function {string} ?
+ * @param {string} text - Text that contains boundaries
+ * @param {string} boundary - Boundary id
+ * @returns Content from given boundaries
+ */
+ extractContent : function(text, boundary)
+ {
+ var tagStart = '<!--'+boundary+'-->';
+ var tagEnd = '<!--//'+boundary+'-->';
+ var start = text.indexOf(tagStart);
+ if(start > -1)
+ {
+ start += tagStart.length;
+ var end = text.indexOf(tagEnd,start);
+ if(end > -1)
+ return text.substring(start,end);
+ }
+ return null;
+ /*var f = RegExp('(?:<!--'+boundary+'-->)((?:.|\n|\r)+?)(?:<!--//'+boundary+'-->)',"m");
+ var result = text.match(f);
+ if(result && result.length >= 2)
+ return result[1];
+ else
+ return null;*/
+ },
+
+ /**
+ * Evaluate a javascript snippet from a string.
+ * @function ?
+ * @param {string} content - String containing the script
+ */
+ evaluateScript : function(content)
+ {
+ try
+ {
+ content.evalScripts();
+ }
+ catch(e)
+ {
+ if(typeof(Logger) != "undefined")
+ Logger.error('Error during evaluation of script "'+content+'"');
+ else
+ debugger;
+ throw e;
+ }
+ },
+
+ /**
+ * Set CSS style with Camelized keys.
+ * See <a href="http://www.prototypejs.org/api/element/setstyle" target="_blank">Prototype's
+ * Element.setStyle</a> for details.
+ * @function ?
+ * @param {string|element} element - DOM element or element id
+ * @param {object} styles - Object with style properties/values
+ */
+ setStyle : function (element, styles)
+ {
+ var s = {}
+ // Camelize all styles keys
+ for (var property in styles)
+ {
+ s[property.camelize()]=styles[property].camelize();
+ }
+ Element.setStyle(element, s);
+ }
+};
+
+/**
+ * Utilities for selections.
+ * @object Prado.Element.Selection
+ */
+Prado.Element.Selection =
+{
+ /**
+ * Check if an DOM element can be selected.
+ * @function {boolean} ?
+ * @param {element} el - DOM elemet
+ * @returns true if element is selectable
+ */
+ isSelectable : function(el)
+ {
+ if(el && el.type)
+ {
+ switch(el.type.toLowerCase())
+ {
+ case 'checkbox':
+ case 'radio':
+ case 'select':
+ case 'select-multiple':
+ case 'select-one':
+ return true;
+ }
+ }
+ return false;
+ },
+
+ /**
+ * Set checked attribute of a checkbox or radiobutton to value.
+ * @function {boolean} ?
+ * @param {element} el - DOM element
+ * @param {boolean} value - New value of checked attribute
+ * @returns New value of checked attribute
+ */
+ inputValue : function(el, value)
+ {
+ switch(el.type.toLowerCase())
+ {
+ case 'checkbox':
+ case 'radio':
+ return el.checked = value;
+ }
+ },
+
+ /**
+ * Set selected attribute for elements options by value.
+ * If value is boolean, all elements options selected attribute will be set
+ * to value. Otherwhise all options that have the given value will be selected.
+ * @function ?
+ * @param {element[]} elements - Array of selectable DOM elements
+ * @param {boolean|string} value - Value of options that should be selected or boolean value of selection status
+ */
+ selectValue : function(elements, value)
+ {
+ elements.each(function(el)
+ {
+ $A(el.options).each(function(option)
+ {
+ if(typeof(value) == "boolean")
+ option.selected = value;
+ else if(option.value == value)
+ option.selected = true;
+ });
+ })
+ },
+
+ /**
+ * Set selected attribute for elements options by array of values.
+ * @function ?
+ * @param {element[]} elements - Array of selectable DOM elements
+ * @param {string[]} value - Array of values to select
+ */
+ selectValues : function(elements, values)
+ {
+ var selection = this;
+ values.each(function(value)
+ {
+ selection.selectValue(elements,value);
+ })
+ },
+
+ /**
+ * Set selected attribute for elements options by option index.
+ * @function ?
+ * @param {element[]} elements - Array of selectable DOM elements
+ * @param {int} index - Index of option to select
+ */
+ selectIndex : function(elements, index)
+ {
+ elements.each(function(el)
+ {
+ if(el.type.toLowerCase() == 'select-one')
+ el.selectedIndex = index;
+ else
+ {
+ for(var i = 0; i<el.length; i++)
+ {
+ if(i == index)
+ el.options[i].selected = true;
+ }
+ }
+ })
+ },
+
+ /**
+ * Set selected attribute to true for all elements options.
+ * @function ?
+ * @param {element[]} elements - Array of selectable DOM elements
+ */
+ selectAll : function(elements)
+ {
+ elements.each(function(el)
+ {
+ if(el.type.toLowerCase() != 'select-one')
+ {
+ $A(el.options).each(function(option)
+ {
+ option.selected = true;
+ })
+ }
+ })
+ },
+
+ /**
+ * Toggle the selected attribute for elements options.
+ * @function ?
+ * @param {element[]} elements - Array of selectable DOM elements
+ */
+ selectInvert : function(elements)
+ {
+ elements.each(function(el)
+ {
+ if(el.type.toLowerCase() != 'select-one')
+ {
+ $A(el.options).each(function(option)
+ {
+ option.selected = !options.selected;
+ })
+ }
+ })
+ },
+
+ /**
+ * Set selected attribute for elements options by array of option indices.
+ * @function ?
+ * @param {element[]} elements - Array of selectable DOM elements
+ * @param {int[]} indices - Array of option indices to select
+ */
+ selectIndices : function(elements, indices)
+ {
+ var selection = this;
+ indices.each(function(index)
+ {
+ selection.selectIndex(elements,index);
+ })
+ },
+
+ /**
+ * Unselect elements.
+ * @function ?
+ * @param {element[]} elements - Array of selectable DOM elements
+ */
+ selectClear : function(elements)
+ {
+ elements.each(function(el)
+ {
+ el.selectedIndex = -1;
+ })
+ },
+
+ /**
+ * Get list elements of an element.
+ * @function {element[]} ?
+ * @param {element[]} elements - Array of selectable DOM elements
+ * @param {int} total - Number of list elements to return
+ * @returns Array of list DOM elements
+ */
+ getListElements : function(element, total)
+ {
+ var elements = new Array();
+ var el;
+ for(var i = 0; i < total; i++)
+ {
+ el = $(element+"_c"+i);
+ if(el)
+ elements.push(el);
+ }
+ return elements;
+ },
+
+ /**
+ * Set checked attribute of elements by value.
+ * If value is boolean, checked attribute will be set to value.
+ * Otherwhise all elements that have the given value will be checked.
+ * @function ?
+ * @param {element[]} elements - Array of checkable DOM elements
+ * @param {boolean|String} value - Value that should be checked or boolean value of checked status
+ *
+ */
+ checkValue : function(elements, value)
+ {
+ elements.each(function(el)
+ {
+ if(typeof(value) == "boolean")
+ el.checked = value;
+ else if(el.value == value)
+ el.checked = true;
+ });
+ },
+
+ /**
+ * Set checked attribute of elements by array of values.
+ * @function ?
+ * @param {element[]} elements - Array of checkable DOM elements
+ * @param {string[]} values - Values that should be checked
+ *
+ */
+ checkValues : function(elements, values)
+ {
+ var selection = this;
+ values.each(function(value)
+ {
+ selection.checkValue(elements, value);
+ })
+ },
+
+ /**
+ * Set checked attribute of elements by list index.
+ * @function ?
+ * @param {element[]} elements - Array of checkable DOM elements
+ * @param {int} index - Index of element to set checked
+ */
+ checkIndex : function(elements, index)
+ {
+ for(var i = 0; i<elements.length; i++)
+ {
+ if(i == index)
+ elements[i].checked = true;
+ }
+ },
+
+ /**
+ * Set checked attribute of elements by array of list indices.
+ * @function ?
+ * @param {element[]} elements - Array of selectable DOM elements
+ * @param {int[]} indices - Array of list indices to set checked
+ */
+ checkIndices : function(elements, indices)
+ {
+ var selection = this;
+ indices.each(function(index)
+ {
+ selection.checkIndex(elements, index);
+ })
+ },
+
+ /**
+ * Uncheck elements.
+ * @function ?
+ * @param {element[]} elements - Array of checkable DOM elements
+ */
+ checkClear : function(elements)
+ {
+ elements.each(function(el)
+ {
+ el.checked = false;
+ });
+ },
+
+ /**
+ * Set checked attribute of all elements to true.
+ * @function ?
+ * @param {element[]} elements - Array of checkable DOM elements
+ */
+ checkAll : function(elements)
+ {
+ elements.each(function(el)
+ {
+ el.checked = true;
+ })
+ },
+
+ /**
+ * Toggle the checked attribute of elements.
+ * @function ?
+ * @param {element[]} elements - Array of selectable DOM elements
+ */
+ checkInvert : function(elements)
+ {
+ elements.each(function(el)
+ {
+ el.checked != el.checked;
+ })
+ }
+};
+
+
+/**
+ * Utilities for insertion.
+ * @object Prado.Element.Insert
+ */
+Prado.Element.Insert =
+{
+ /**
+ * Append content to element
+ * @function ?
+ * @param {element} element - DOM element that content should be appended to
+ * @param {element} content - DOM element to append
+ */
+ append: function(element, content)
+ {
+ $(element).insert(content);
+ },
+
+ /**
+ * Prepend content to element
+ * @function ?
+ * @param {element} element - DOM element that content should be prepended to
+ * @param {element} content - DOM element to prepend
+ */
+ prepend: function(element, content)
+ {
+ $(element).insert({top:content});
+ },
+
+ /**
+ * Insert content after element
+ * @function ?
+ * @param {element} element - DOM element that content should be inserted after
+ * @param {element} content - DOM element to insert
+ */
+ after: function(element, content)
+ {
+ $(element).insert({after:content});
+ },
+
+ /**
+ * Insert content before element
+ * @function ?
+ * @param {element} element - DOM element that content should be inserted before
+ * @param {element} content - DOM element to insert
+ */
+ before: function(element, content)
+ {
+ $(element).insert({before:content});
+ }
+};
+
+
+/**
+ * Extension to
+ * <a href="http://wiki.script.aculo.us/scriptaculous/show/builder" target="_blank">Scriptaculous' Builder</a>
+ * @namespace Builder
+ */
+
+Object.extend(Builder,
+{
+ /**
+ * Export scriptaculous builder utilities as window[functions]
+ * @function ?
+ */
+ exportTags:function()
+ {
+ var tags=["BUTTON","TT","PRE","H1","H2","H3","BR","CANVAS","HR","LABEL","TEXTAREA","FORM","STRONG","SELECT","OPTION","OPTGROUP","LEGEND","FIELDSET","P","UL","OL","LI","TD","TR","THEAD","TBODY","TFOOT","TABLE","TH","INPUT","SPAN","A","DIV","IMG", "CAPTION"];
+ tags.each(function(tag)
+ {
+ window[tag]=function()
+ {
+ var args=$A(arguments);
+ if(args.length==0)
+ return Builder.node(tag,null);
+ if(args.length==1)
+ return Builder.node(tag,args[0]);
+ if(args.length>1)
+ return Builder.node(tag,args.shift(),args);
+
+ };
+ });
+ }
+});
+Builder.exportTags();
+
+/**
+ * Extension to
+ * <a href="http://www.prototypejs.org/api/string" target="_blank">Prototype's String</a>
+ * @namespace String
+ */
+Object.extend(String.prototype, {
+
+ /**
+ * Add padding to string
+ * @function {string} ?
+ * @param {string} side - "left" to pad the string on the left, "right" to pad right.
+ * @param {int} len - Minimum string length.
+ * @param {string} chr - Character(s) to pad
+ * @returns Padded string
+ */
+ pad : function(side, len, chr) {
+ if (!chr) chr = ' ';
+ var s = this;
+ var left = side.toLowerCase()=='left';
+ while (s.length<len) s = left? chr + s : s + chr;
+ return s;
+ },
+
+ /**
+ * Add left padding to string
+ * @function {string} ?
+ * @param {int} len - Minimum string length.
+ * @param {string} chr - Character(s) to pad
+ * @returns Padded string
+ */
+ padLeft : function(len, chr) {
+ return this.pad('left',len,chr);
+ },
+
+ /**
+ * Add right padding to string
+ * @function {string} ?
+ * @param {int} len - Minimum string length.
+ * @param {string} chr - Character(s) to pad
+ * @returns Padded string
+ */
+ padRight : function(len, chr) {
+ return this.pad('right',len,chr);
+ },
+
+ /**
+ * Add zeros to the right of string
+ * @function {string} ?
+ * @param {int} len - Minimum string length.
+ * @returns Padded string
+ */
+ zerofill : function(len) {
+ return this.padLeft(len,'0');
+ },
+
+ /**
+ * Remove white spaces from both ends of string.
+ * @function {string} ?
+ * @returns Trimmed string
+ */
+ trim : function() {
+ return this.replace(/^\s+|\s+$/g,'');
+ },
+
+ /**
+ * Remove white spaces from the left side of string.
+ * @function {string} ?
+ * @returns Trimmed string
+ */
+ trimLeft : function() {
+ return this.replace(/^\s+/,'');
+ },
+
+ /**
+ * Remove white spaces from the right side of string.
+ * @function {string} ?
+ * @returns Trimmed string
+ */
+ trimRight : function() {
+ return this.replace(/\s+$/,'');
+ },
+
+ /**
+ * Convert period separated function names into a function reference.
+ * <br />Example:
+ * <pre>
+ * "Prado.AJAX.Callback.Action.setValue".toFunction()
+ * </pre>
+ * @function {function} ?
+ * @returns Reference to the corresponding function
+ */
+ toFunction : function()
+ {
+ var commands = this.split(/\./);
+ var command = window;
+ commands.each(function(action)
+ {
+ if(command[new String(action)])
+ command=command[new String(action)];
+ });
+ if(typeof(command) == "function")
+ return command;
+ else
+ {
+ if(typeof Logger != "undefined")
+ Logger.error("Missing function", this);
+
+ throw new Error ("Missing function '"+this+"'");
+ }
+ },
+
+ /**
+ * Convert string into integer, returns null if not integer.
+ * @function {int} ?
+ * @returns Integer, null if string does not represent an integer.
+ */
+ toInteger : function()
+ {
+ var exp = /^\s*[-\+]?\d+\s*$/;
+ if (this.match(exp) == null)
+ return null;
+ var num = parseInt(this, 10);
+ return (isNaN(num) ? null : num);
+ },
+
+ /**
+ * Convert string into a double/float value. <b>Internationalization
+ * is not supported</b>
+ * @function {double} ?
+ * @param {string} decimalchar - Decimal character, defaults to "."
+ * @returns Double, null if string does not represent a float value
+ */
+ toDouble : function(decimalchar)
+ {
+ if(this.length <= 0) return null;
+ decimalchar = decimalchar || ".";
+ var exp = new RegExp("^\\s*([-\\+])?(\\d+)?(\\" + decimalchar + "(\\d+))?\\s*$");
+ var m = this.match(exp);
+
+ if (m == null)
+ return null;
+ m[1] = m[1] || "";
+ m[2] = m[2] || "0";
+ m[4] = m[4] || "0";
+
+ var cleanInput = m[1] + (m[2].length>0 ? m[2] : "0") + "." + m[4];
+ var num = parseFloat(cleanInput);
+ return (isNaN(num) ? null : num);
+ },
+
+ /**
+ * Convert strings that represent a currency value to float.
+ * E.g. "10,000.50" will become "10000.50". The number
+ * of dicimal digits, grouping and decimal characters can be specified.
+ * <i>The currency input format is <b>very</b> strict, null will be returned if
+ * the pattern does not match</i>.
+ * @function {double} ?
+ * @param {string} groupchar - Grouping character, defaults to ","
+ * @param {int} digits - Number of decimal digits
+ * @param {string} decimalchar - Decimal character, defaults to "."
+ * @returns Double, null if string does not represent a currency value
+ */
+ toCurrency : function(groupchar, digits, decimalchar)
+ {
+ groupchar = groupchar || ",";
+ decimalchar = decimalchar || ".";
+ digits = typeof(digits) == "undefined" ? 2 : digits;
+
+ var exp = new RegExp("^\\s*([-\\+])?(((\\d+)\\" + groupchar + ")*)(\\d+)"
+ + ((digits > 0) ? "(\\" + decimalchar + "(\\d{1," + digits + "}))?" : "")
+ + "\\s*$");
+ var m = this.match(exp);
+ if (m == null)
+ return null;
+ var intermed = m[2] + m[5] ;
+ var cleanInput = m[1] + intermed.replace(
+ new RegExp("(\\" + groupchar + ")", "g"), "")
+ + ((digits > 0) ? "." + m[7] : "");
+ var num = parseFloat(cleanInput);
+ return (isNaN(num) ? null : num);
+ },
+
+ /**
+ * Converts the string to a date by finding values that matches the
+ * date format pattern.
+ * @function {Date} ?
+ * @param {string} format - Date format pattern, e.g. MM-dd-yyyy
+ * @returns Date extracted from the string
+ */
+ toDate : function(format)
+ {
+ return Date.SimpleParse(this, format);
+ }
+});
+
+/**
+ * Extension to
+ * <a href="http://www.prototypejs.org/api/event" target="_blank">Prototype's Event</a>
+ * @namespace Event
+ */
+Object.extend(Event,
+{
+ /**
+ * Register a function to be executed when the page is loaded.
+ * Note that the page is only loaded if all resources (e.g. images)
+ * are loaded.
+ * <br />Example:
+ * <br />Show an alert box with message "Page Loaded!" when the
+ * page finished loading.
+ * <pre>
+ * Event.OnLoad(function(){ alert("Page Loaded!"); });
+ * </pre>
+ * @function ?
+ * @param {function} fn - Function to execute when page is loaded.
+ */
+ OnLoad : function (fn)
+ {
+ // opera onload is in document, not window
+ var w = document.addEventListener &&
+ !window.addEventListener ? document : window;
+ Event.observe(w,'load',fn);
+ },
+
+ /**
+ * Returns the unicode character generated by key.
+ * @param {event} e - Keyboard event
+ * @function {int} ?
+ * @returns Unicode character code generated by the key that was struck.
+ */
+ keyCode : function(e)
+ {
+ return e.keyCode != null ? e.keyCode : e.charCode
+ },
+
+ /**
+ * Checks if an Event is of type HTMLEvent.
+ * @function {boolean} ?
+ * @param {string} type - Event type or event name.
+ * @return true if event is of type HTMLEvent.
+ */
+ isHTMLEvent : function(type)
+ {
+ var events = ['abort', 'blur', 'change', 'error', 'focus',
+ 'load', 'reset', 'resize', 'scroll', 'select',
+ 'submit', 'unload'];
+ return events.include(type);
+ },
+
+ /**
+ * Checks if an Event is a mouse event.
+ * @function {boolean} ?
+ * @param {string} type - Event type or event name
+ * @return true if event is of type MouseEvent.
+ */
+ isMouseEvent : function(type)
+ {
+ var events = ['click', 'mousedown', 'mousemove', 'mouseout',
+ 'mouseover', 'mouseup'];
+ return events.include(type);
+ },
+
+ /**
+ * Dispatch the DOM event of a given <tt>type</tt> on a DOM
+ * <tt>element</tt>. 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.
+ * @function ?
+ * @param {element|string} element - Element id string or DOM element.
+ * @param {string} type - Event type to dispatch.
+ */
+ fireEvent : function(element,type)
+ {
+ element = $(element);
+ if(type == "submit")
+ return element.submit();
+ if(document.createEvent)
+ {
+ if(Event.isHTMLEvent(type))
+ {
+ var event = document.createEvent('HTMLEvents');
+ event.initEvent(type, true, true);
+ }
+ else if(Event.isMouseEvent(type))
+ {
+ var event = document.createEvent('MouseEvents');
+ if (event.initMouseEvent)
+ {
+ event.initMouseEvent(type,true,true,
+ document.defaultView, 1, 0, 0, 0, 0, false,
+ false, false, false, 0, null);
+ }
+ else
+ {
+ // Safari
+ // TODO we should be initialising other mouse-event related attributes here
+ event.initEvent(type, true, true);
+ }
+ }
+ element.dispatchEvent(event);
+ }
+ else if(document.createEventObject)
+ {
+ var evObj = document.createEventObject();
+ element.fireEvent('on'+type, evObj);
+ }
+ else if(typeof(element['on'+type]) == "function")
+ element['on'+type]();
+ }
+});
+
+
+/**
+ * Extension to
+ * <a href="http://www.prototypejs.org/api/date" target="_blank">Prototype's Date</a>
+ * @namespace Date
+ */
+Object.extend(Date.prototype,
+{
+ /**
+ * SimpleFormat
+ * @function ?
+ * @param {string} format - TODO
+ * @param {string} data - TODO
+ * @returns TODO
+ */
+ SimpleFormat: function(format, data)
+ {
+ data = data || {};
+ var bits = new Array();
+ bits['d'] = this.getDate();
+ bits['dd'] = String(this.getDate()).zerofill(2);
+
+ bits['M'] = this.getMonth()+1;
+ bits['MM'] = String(this.getMonth()+1).zerofill(2);
+ if(data.AbbreviatedMonthNames)
+ bits['MMM'] = data.AbbreviatedMonthNames[this.getMonth()];
+ if(data.MonthNames)
+ bits['MMMM'] = data.MonthNames[this.getMonth()];
+ var yearStr = "" + this.getFullYear();
+ yearStr = (yearStr.length == 2) ? '19' + yearStr: yearStr;
+ bits['yyyy'] = yearStr;
+ bits['yy'] = bits['yyyy'].toString().substr(2,2);
+
+ // do some funky regexs to replace the format string
+ // with the real values
+ var frm = new String(format);
+ for (var sect in bits)
+ {
+ var reg = new RegExp("\\b"+sect+"\\b" ,"g");
+ frm = frm.replace(reg, bits[sect]);
+ }
+ return frm;
+ },
+
+ /**
+ * toISODate
+ * @function {string} ?
+ * @returns TODO
+ */
+ toISODate : function()
+ {
+ var y = this.getFullYear();
+ var m = String(this.getMonth() + 1).zerofill(2);
+ var d = String(this.getDate()).zerofill(2);
+ return String(y) + String(m) + String(d);
+ }
+});
+
+Object.extend(Date,
+{
+ /**
+ * SimpleParse
+ * @function ?
+ * @param {string} format - TODO
+ * @param {string} data - TODO
+ * @returns TODO
+ */
+ SimpleParse: function(value, format)
+ {
+ var val=String(value);
+ format=String(format);
+
+ if(val.length <= 0) return null;
+
+ if(format.length <= 0) return new Date(value);
+
+ var isInteger = function (val)
+ {
+ var digits="1234567890";
+ for (var i=0; i < val.length; i++)
+ {
+ if (digits.indexOf(val.charAt(i))==-1) { return false; }
+ }
+ return true;
+ };
+
+ var getInt = function(str,i,minlength,maxlength)
+ {
+ for (var x=maxlength; x>=minlength; x--)
+ {
+ var token=str.substring(i,i+x);
+ if (token.length < minlength) { return null; }
+ if (isInteger(token)) { return token; }
+ }
+ return null;
+ };
+
+ var i_val=0;
+ var i_format=0;
+ var c="";
+ var token="";
+ var token2="";
+ var x,y;
+ var now=new Date();
+ var year=now.getFullYear();
+ var month=now.getMonth()+1;
+ var date=1;
+
+ while (i_format < format.length)
+ {
+ // Get next token from format string
+ c=format.charAt(i_format);
+ token="";
+ while ((format.charAt(i_format)==c) && (i_format < format.length))
+ {
+ token += format.charAt(i_format++);
+ }
+
+ // Extract contents of value based on format token
+ if (token=="yyyy" || token=="yy" || token=="y")
+ {
+ if (token=="yyyy") { x=4;y=4; }
+ if (token=="yy") { x=2;y=2; }
+ if (token=="y") { x=2;y=4; }
+ year=getInt(val,i_val,x,y);
+ if (year==null) { return null; }
+ i_val += year.length;
+ if (year.length==2)
+ {
+ if (year > 70) { year=1900+(year-0); }
+ else { year=2000+(year-0); }
+ }
+ }
+
+ else if (token=="MM"||token=="M")
+ {
+ month=getInt(val,i_val,token.length,2);
+ if(month==null||(month<1)||(month>12)){return null;}
+ i_val+=month.length;
+ }
+ else if (token=="dd"||token=="d")
+ {
+ date=getInt(val,i_val,token.length,2);
+ if(date==null||(date<1)||(date>31)){return null;}
+ i_val+=date.length;
+ }
+ else
+ {
+ if (val.substring(i_val,i_val+token.length)!=token) {return null;}
+ else {i_val+=token.length;}
+ }
+ }
+
+ // If there are any trailing characters left in the value, it doesn't match
+ if (i_val != val.length) { return null; }
+
+ // Is date valid for month?
+ if (month==2)
+ {
+ // Check for leap year
+ if ( ( (year%4==0)&&(year%100 != 0) ) || (year%400==0) ) { // leap year
+ if (date > 29){ return null; }
+ }
+ else { if (date > 28) { return null; } }
+ }
+
+ if ((month==4)||(month==6)||(month==9)||(month==11))
+ {
+ if (date > 30) { return null; }
+ }
+
+ var newdate=new Date(year,month-1,date, 0, 0, 0);
+ return newdate;
+ }
+});
+
+/**
+ * Prado utilities for effects.
+ * @object Prado.Effect
+ */
+Prado.Effect =
+{
+ /**
+ * Highlights an element
+ * @function ?
+ * @param {element} element - DOM element to highlight
+ * @param {optional object} options - Highlight options
+ */
+ Highlight : function (element,options)
+ {
+ new Effect.Highlight(element,options);
+ }
+};
diff --git a/framework/Web/Javascripts/source/prado/validator/validation3.js b/framework/Web/Javascripts/source/prado/validator/validation3.js
index 597b4b5b..1fd1b570 100644
--- a/framework/Web/Javascripts/source/prado/validator/validation3.js
+++ b/framework/Web/Javascripts/source/prado/validator/validation3.js
@@ -1,1943 +1,1943 @@
-/**
- * Prado client-side javascript validation fascade.
- *
- * <p>There are 4 basic classes: {@link Prado.Validation},
- * {@link Prado.ValidationManager}, {@link Prado.WebUI.TValidationSummary}
- * and {@link Prado.WebUI.TBaseValidator},
- * that interact together to perform validation.
- * The {@link Prado.Validation} class co-ordinates together the
- * validation scheme and is responsible for maintaining references
- * to ValidationManagers.</p>
- *
- * <p>The {@link Prado.ValidationManager} class is responsible for
- * maintaining refereneces
- * to individual validators, validation summaries and their associated
- * groupings.</p>
- *
- * <p>The {@link Prado.WebUI.TValidationSummary} takes care of displaying
- * the validator error messages
- * as html output or an alert output.</p>
- *
- * <p>The {@link Prado.WebUI.TBaseValidator} is the base class for all
- * validators and contains
- * methods to interact with the actual inputs, data type conversion.</p>
- *
- * <p>An instance of {@link Prado.ValidationManager} must be instantiated first for a
- * particular form before instantiating validators and summaries.</p>
- *
- * <p>Usage example: adding a required field to a text box input with
- * ID "input1" in a form with ID "form1".</p>
- * <pre>
- * &lt;script type="text/javascript" src="../prado.js"&gt;&lt;/script&gt;
- * &lt;script type="text/javascript" src="../validator.js"&gt;&lt;/script&gt;
- * &lt;form id="form1" action="..."&gt;
- * &lt;div&gt;
- * &lt;input type="text" id="input1" /&gt;
- * &lt;span id="validator1" style="display:none; color:red"&gt;*&lt;/span&gt;
- * &lt;input type="submit text="submit" /&gt;
- * &lt;script type="text/javascript"&gt;
- * new Prado.ValidationManager({FormID : 'form1'});
- * var options =
- * {
- * ID : 'validator1',
- * FormID : 'form1',
- * ErrorMessage : '*',
- * ControlToValidate : 'input1'
- * }
- * new Prado.WebUI.TRequiredFieldValidator(options);
- * new Prado.WebUI.TValidationSummary({ID:'summary1',FormID:'form1'});
- *
- * //watch the form onsubmit event, check validators, stop if not valid.
- * Event.observe("form1", "submit" function(ev)
- * {
- * if(Prado.WebUI.Validation.isValid("form1") == false)
- * Event.stop(ev);
- * });
- * &lt;/script&gt;
- * &lt;/div&gt;
- * &lt;/form&gt;
- * </pre>
- *
- * @module validation
- */
-
-Prado.Validation = Class.create();
-
-/**
- * Global Validation Object.
- *
- * <p>To validate the inputs of a particular form, call
- * <code>{@link Prado.Validation.validate}(formID, groupID)</code>
- * where <tt>formID</tt> is the HTML form ID, and the optional
- * <tt>groupID</tt> if present will only validate the validators
- * in a particular group.</p>
- * <p>Use <code>{@link Prado.Validation.validateControl}(controlClientID)</code>
- * to trigger validation for a single control.</p>
- *
- * @object {static} Prado.Validation
- */
-Object.extend(Prado.Validation,
-{
- /**
- * Hash of registered validation managers
- * @var managers
- */
- managers : {},
-
- /**
- * Validate the validators (those that <strong>DO NOT</strong>
- * belong to a particular group) in the form specified by the
- * <tt>formID</tt> parameter. If <tt>groupID</tt> is specified
- * only validators belonging to that group will be validated.
- * @function {boolean} ?
- * @param {string} formID - ID of the form to validate
- * @param {string} groupID - ID of the ValidationGroup to validate.
- * @param {element} invoker - DOM element that calls for validation
- * @returns true if validation succeeded
- */
- validate : function(formID, groupID, invoker)
- {
- formID = formID || this.getForm();
- if(this.managers[formID])
- {
- return this.managers[formID].validate(groupID, invoker);
- }
- else
- {
- throw new Error("Form '"+formID+"' is not registered with Prado.Validation");
- }
- },
-
- /**
- * Validate all validators of a specific control.
- * @function {boolean} ?
- * @param {string} id - ID of DOM element to validate
- * @return true if all validators are valid or no validators present, false otherwise.
- */
- validateControl : function(id)
- {
- var formId=this.getForm();
-
- if (this.managers[formId])
- {
- return this.managers[formId].validateControl(id);
- } else {
- throw new Error("A validation manager needs to be created first.");
- }
- },
-
- /**
- * Return first registered form
- * @function {string} ?
- * @returns ID of first form.
- */
- getForm : function()
- {
- var keys = $H(this.managers).keys();
- return keys[0];
- },
-
- /**
- * Check if the validators are valid for a particular form (and group).
- * The validators states will not be changed.
- * The <tt>validate</tt> function should be called first.
- * @function {boolean} ?
- * @param {string} formID - ID of the form to validate
- * @param {string} groupID - ID of the ValiationGroup to validate.
- * @return true if form is valid
- */
- isValid : function(formID, groupID)
- {
- formID = formID || this.getForm();
- if(this.managers[formID])
- return this.managers[formID].isValid(groupID);
- return true;
- },
-
- /**
- * Reset the validators for a given group.
- * The group is searched in the first registered form.
- * @function ?
- * @param {string} groupID - ID of the ValidationGroup to reset.
- */
- reset : function(groupID)
- {
- var formID = this.getForm();
- if(this.managers[formID])
- this.managers[formID].reset(groupID);
- },
-
- /**
- * Add a new validator to a particular form.
- * @function {ValidationManager} ?
- * @param {string} formID - ID of the form that the validator belongs to.
- * @param {TBaseValidator} validator - Validator object
- * @return ValidationManager for the form
- */
- addValidator : function(formID, validator)
- {
- if(this.managers[formID])
- this.managers[formID].addValidator(validator);
- else
- throw new Error("A validation manager for form '"+formID+"' needs to be created first.");
- return this.managers[formID];
- },
-
- /**
- * Add a new validation summary.
- * @function {ValidationManager} ?
- * @param {string} formID - ID of the form that the validation summary belongs to.
- * @param {TValidationSummary} validator - TValidationSummary object
- * @return ValidationManager for the form
- */
- addSummary : function(formID, validator)
- {
- if(this.managers[formID])
- this.managers[formID].addSummary(validator);
- else
- throw new Error("A validation manager for form '"+formID+"' needs to be created first.");
- return this.managers[formID];
- },
-
- setErrorMessage : function(validatorID, message)
- {
- $H(Prado.Validation.managers).each(function(manager)
- {
- manager[1].validators.each(function(validator)
- {
- if(validator.options.ID == validatorID)
- {
- validator.options.ErrorMessage = message;
- $(validatorID).innerHTML = message;
- }
- });
- });
- },
-
- updateActiveCustomValidator : function(validatorID, isValid)
- {
- $H(Prado.Validation.managers).each(function(manager)
- {
- manager[1].validators.each(function(validator)
- {
- if(validator.options.ID == validatorID)
- {
- validator.updateIsValid(isValid);
- }
- });
- });
- }
-});
-
-/**
- * Manages validators for a particular HTML form.
- *
- * <p>The manager contains references to all the validators
- * summaries, and their groupings for a particular form.
- * Generally, {@link Prado.Validation} methods should be called rather
- * than calling directly the ValidationManager.</p>
- *
- * @class Prado.ValidationManager
- */
-Prado.ValidationManager = Class.create();
-Prado.ValidationManager.prototype =
-{
- /**
- * Hash of registered validators by control's clientID
- * @var controls
- */
- controls: {},
-
- /**
- * Initialize ValidationManager.
- * @constructor {protected} ?
- * @param {object} options - Options for initialization
- * @... {string} FormID - ID of form of this manager
- */
- initialize : function(options)
- {
- if(!Prado.Validation.managers[options.FormID])
- {
- /**
- * List of validators
- * @var {TBaseValidator[]} validators
- */
- this.validators = [];
- /**
- * List of validation summaries
- * @var {TValidationSummary[]} summaries
- */
- this.summaries = [];
- /**
- * List of ValidationGroups
- * @var {string[]} groups
- */
- this.groups = [];
- /**
- * Options of this ValidationManager
- * @var {object} options
- */
- this.options = {};
-
- this.options = options;
-
- Prado.Validation.managers[options.FormID] = this;
- }
- else
- {
- var manager = Prado.Validation.managers[options.FormID];
- this.validators = manager.validators;
- this.summaries = manager.summaries;
- this.groups = manager.groups;
- this.options = manager.options;
- }
- },
-
- /**
- * Reset all validators in the given group.
- * If group is null, validators without a group are used.
- * @function ?
- * @param {string} group - ID of ValidationGroup
- */
- reset : function(group)
- {
- this.validatorPartition(group)[0].invoke('reset');
- this.updateSummary(group, true);
- },
-
- /**
- * Validate the validators managed by this validation manager.
- * If group is set, only validate validators in that group.
- * @function {boolean} ?
- * @param {optional string} group - ID of ValidationGroup
- * @param {element} source - DOM element that calls for validation
- * @return true if all validators are valid, false otherwise.
- */
- validate : function(group, source)
- {
- var partition = this.validatorPartition(group);
- var valid = partition[0].invoke('validate', source).all();
- this.focusOnError(partition[0]);
- partition[1].invoke('hide');
- this.updateSummary(group, true);
- return valid;
- },
-
- /**
- * Perform validation for all validators of a single control.
- * @function {boolean} ?
- * @param {string} id - ID of DOM element to validate
- * @return true if all validators are valid or no validators present, false otherwise.
- */
- validateControl : function (id)
- {
- return this.controls[id] ? this.controls[id].invoke('validate',null).all() : true;
- },
-
- /**
- * Focus on the first validator that is invalid and options.FocusOnError is true.
- * @function ?
- * @param {TBaseValidator[]} validators - Array of validator objects
- */
- focusOnError : function(validators)
- {
- for(var i = 0; i < validators.length; i++)
- {
- if(!validators[i].isValid && validators[i].options.FocusOnError)
- return Prado.Element.focus(validators[i].options.FocusElementID);
- }
- },
-
- /**
- * Get all validators in a group and all other validators.
- * Returns an array with two arrays of validators. The first
- * array contains all validators in the group if group is given,
- * otherwhise all validators without a group. The second array
- * contains all other validators.
- * @function {[ TBaseValidator[] , TBaseValidator[] ]} ?
- * @param {optional string} group - ID of ValidationGroup
- * @return Array with two arrays of validators.
- */
- validatorPartition : function(group)
- {
- return group ? this.validatorsInGroup(group) : this.validatorsWithoutGroup();
- },
-
- /**
- * Get all validators in a group.
- * Returns an array with two arrays of validators. The first
- * array contains all validators in the group. The second array
- * contains all other validators.
- * @function {[ TBaseValidator[] , TBaseValidator[] ]} ?
- * @param {optional string} groupID - ID of ValidationGroup
- * @return Array with two arrays of validators.
- */
- validatorsInGroup : function(groupID)
- {
- if(this.groups.include(groupID))
- {
- return this.validators.partition(function(val)
- {
- return val.group == groupID;
- });
- }
- else
- return [[],[]];
- },
-
- /**
- * Get all validators without a group.
- * Returns an array with two arrays of validators. The first
- * array contains all validators without a group. The second
- * array contains all other validators.
- * @function {[ TBaseValidator[] , TBaseValidator[] ]} ?
- * @return Array with two arrays of validators: Array[0] has all
- * validators without a group, Array[1] all other validators.
- */
- validatorsWithoutGroup : function()
- {
- return this.validators.partition(function(val)
- {
- return !val.group;
- });
- },
-
- /**
- * Get the state of validators.
- * If group is set, only validators in that group are checked.
- * Otherwhise only validators without a group are checked.
- * @function {booelan} ?
- * @param {optional string} group - ID of ValidationGroup
- * @return true if all validators (in a group, if supplied) are valid.
- */
- isValid : function(group)
- {
- return this.validatorPartition(group)[0].pluck('isValid').all();
- },
-
- /**
- * Add a validator to this manager.
- * @function ?
- * @param {TBaseValidator} validator - Validator object
- */
- addValidator : function(validator)
- {
- // Remove previously registered validator with same ID
- // to prevent stale validators created by AJAX updates
- this.removeValidator(validator);
-
- this.validators.push(validator);
- if(validator.group && !this.groups.include(validator.group))
- this.groups.push(validator.group);
-
- if (typeof this.controls[validator.control.id] === 'undefined')
- this.controls[validator.control.id] = Array();
- this.controls[validator.control.id].push(validator);
- },
-
- /**
- * Add a validation summary.
- * @function ?
- * @param {TValidationSummary} summary - Validation summary.
- */
- addSummary : function(summary)
- {
- this.summaries.push(summary);
- },
-
- /**
- * Remove a validator from this manager
- * @function ?
- * @param {TBaseValidator} validator - Validator object
- */
- removeValidator : function(validator)
- {
- this.validators = this.validators.reject(function(v)
- {
- return (v.options.ID==validator.options.ID);
- });
- if (this.controls[validator.control.id])
- this.controls[validator.control.id].reject( function(v)
- {
- return (v.options.ID==validator.options.ID)
- });
- },
-
- /**
- * Gets validators with errors.
- * If group is set, only validators in that group are returned.
- * Otherwhise only validators without a group are returned.
- * @function {TBaseValidator[]} ?
- * @param {optional string} group - ID of ValidationGroup
- * @return array list of validators with error.
- */
- getValidatorsWithError : function(group)
- {
- return this.validatorPartition(group)[0].findAll(function(validator)
- {
- return !validator.isValid;
- });
- },
-
- /**
- * Update the summary of a particular group.
- * If group is set, only the summary for validators in that
- * group is updated. Otherwhise only the summary for validators
- * without a group is updated.
- * @function ?
- * @param {optional string} group - ID of ValidationGroup
- * @param {boolean} refresh - Wether the summary should be refreshed
- */
- updateSummary : function(group, refresh)
- {
- var validators = this.getValidatorsWithError(group);
- this.summaries.each(function(summary)
- {
- var inGroup = group && summary.group == group;
- var noGroup = !group || !summary.group;
- if(inGroup || noGroup)
- summary.updateSummary(validators, refresh);
- else
- summary.hideSummary(true);
- });
- }
-};
-
-/**
- * TValidationSummary displays a summary of validation errors.
- *
- * <p>The summary is displayed inline on a Web page,
- * in a message box, or both. By default, a validation summary will collect
- * <tt>ErrorMessage</tt> of all failed validators on the page. If
- * <tt>ValidationGroup</tt> is not empty, only those validators who belong
- * to the group will show their error messages in the summary.</p>
- *
- * <p>The summary can be displayed as a list, as a bulleted list, or as a single
- * paragraph based on the <tt>DisplayMode</tt> option.
- * The messages shown can be prefixed with <tt>HeaderText</tt>.</p>
- *
- * <p>The summary can be displayed on the Web page and in a message box by setting
- * the <tt>ShowSummary</tt> and <tt>ShowMessageBox</tt>
- * options, respectively.</p>
- *
- * @class Prado.WebUI.TValidationSummary
- */
-Prado.WebUI.TValidationSummary = Class.create();
-Prado.WebUI.TValidationSummary.prototype =
-{
- /**
- * Initialize TValidationSummary.
- * @constructor {protected} ?
- * @param {object} options - Options for initialization
- * @... {string} ID - ID of validation summary element
- * @... {string} FormID - ID of form of this manager
- * @... {optional string} ValidationGroup - ID of ValidationGroup.
- * @... {optional boolean} ShowMessageBox - true to show the summary in an alert box.
- * @... {optional boolean} ShowSummary - true to show the inline summary.
- * @... {optional string} HeaderText - Summary header text
- * @... {optional string} DisplayMode - Summary display style, 'BulletList', 'List', 'SingleParagraph'
- * @... {optional boolean} Refresh - true to update the summary upon validator state change.
- * @... {optional string} Display - Display mode, 'None', 'Fixed', 'Dynamic'.
- * @... {optional boolean} ScrollToSummary - true to scroll to the validation summary upon refresh.
- * @... {optional function} OnHideSummary - Called on hide event.
- * @... {optional function} OnShowSummary - Called on show event.
- */
- initialize : function(options)
- {
- /**
- * Validator options
- * @var {object} options
- */
- this.options = options;
- /**
- * ValidationGroup
- * @var {string} group
- */
- this.group = options.ValidationGroup;
- /**
- * Summary DOM element
- * @var {element} messages
- */
- this.messages = $(options.ID);
- Prado.Registry.set(options.ID, this);
- if(this.messages)
- {
- /**
- * Current visibility state of summary
- * @var {boolean} visible
- */
- this.visible = this.messages.style.visibility != "hidden"
- this.visible = this.visible && this.messages.style.display != "none";
- Prado.Validation.addSummary(options.FormID, this);
- }
- },
-
- /**
- * Update the validation summary.
- * @function ?
- * @param {TBaseValidator[]} validators - List of validators that failed validation.
- * @param {boolean} update - true if visible summary should be updated
- */
- updateSummary : function(validators, update)
- {
- if(validators.length <= 0)
- {
- if(update || this.options.Refresh != false)
- {
- return this.hideSummary(validators);
- }
- return;
- }
-
- var refresh = update || this.visible == false || this.options.Refresh != false;
- // Also, do not refresh summary if at least 1 validator is waiting for callback response.
- // This will avoid the flickering of summary if the validator passes its test
- refresh = refresh && validators.any(function(v) { return !v.requestDispatched; });
-
- if(this.options.ShowSummary != false && refresh)
- {
- this.updateHTMLMessages(this.getMessages(validators));
- this.showSummary(validators);
- }
-
- if(this.options.ScrollToSummary != false && refresh)
- window.scrollTo(this.messages.offsetLeft-20, this.messages.offsetTop-20);
-
- if(this.options.ShowMessageBox == true && refresh)
- {
- this.alertMessages(this.getMessages(validators));
- this.visible = true;
- }
- },
-
- /**
- * Display the validator error messages as inline HTML.
- * @function ?
- * @param {string[]} messages - Array of error messages.
- */
- updateHTMLMessages : function(messages)
- {
- while(this.messages.childNodes.length > 0)
- this.messages.removeChild(this.messages.lastChild);
- this.messages.insert(this.formatSummary(messages));
- },
-
- /**
- * Display the validator error messages as an alert box.
- * @function ?
- * @param {string[]} messages - Array of error messages.
- */
- alertMessages : function(messages)
- {
- var text = this.formatMessageBox(messages);
- setTimeout(function(){ alert(text); },20);
- },
-
- /**
- * Get messages from validators.
- * @function {string[]} ?
- * @param {TBaseValidator[]} validators - Array of validators.
- * @return Array of validator error messages.
- */
- getMessages : function(validators)
- {
- var messages = [];
- validators.each(function(validator)
- {
- var message = validator.getErrorMessage();
- if(typeof(message) == 'string' && message.length > 0)
- messages.push(message);
- })
- return messages;
- },
-
- /**
- * Hide the validation summary.
- * @function ?
- * @param {TBaseValidator[]} validators - Array of validators.
- */
- hideSummary : function(validators)
- { if(typeof(this.options.OnHideSummary) == "function")
- {
- this.messages.style.visibility="visible";
- this.options.OnHideSummary(this,validators)
- }
- else
- {
- this.messages.style.visibility="hidden";
- if(this.options.Display == "None" || this.options.Display == "Dynamic")
- this.messages.hide();
- }
- this.visible = false;
- },
-
- /**
- * Shows the validation summary.
- * @function ?
- * @param {TBaseValidator[]} validators - Array of validators.
- */
- showSummary : function(validators)
- {
- this.messages.style.visibility="visible";
- if(typeof(this.options.OnShowSummary) == "function")
- this.options.OnShowSummary(this,validators);
- else
- this.messages.show();
- this.visible = true;
- },
-
- /**
- * Return the format parameters for the summary.
- * @function {object} ?
- * @param {string} type - Format type: "List", "SingleParagraph", "HeaderOnly" or "BulletList" (default)
- * @return Object with format parameters:
- * @... {string} header - Text for header
- * @... {string} first - Text to prepend before message list
- * @... {string} pre - Text to prepend before each message
- * @... {string} post - Text to append after each message
- * @... {string} first - Text to append after message list
- */
- formats : function(type)
- {
- switch(type)
- {
- case "SimpleList":
- return { header : "<br />", first : "", pre : "", post : "<br />", last : ""};
- case "SingleParagraph":
- return { header : " ", first : "", pre : "", post : " ", last : "<br />"};
- case "HeaderOnly":
- return { header : "", first : "<!--", pre : "", post : "", last : "-->"};
- case "BulletList":
- default:
- return { header : "", first : "<ul>", pre : "<li>", post : "</li>", last : "</ul>"};
- }
- },
-
- /**
- * Format the message summary.
- * @function {string} ?
- * @param {string[]} messages - Array of error messages.
- * @return Formatted message
- */
- formatSummary : function(messages)
- {
- var format = this.formats(this.options.DisplayMode);
- var output = this.options.HeaderText ? this.options.HeaderText + format.header : "";
- output += format.first;
- messages.each(function(message)
- {
- output += message.length > 0 ? format.pre + message + format.post : "";
- });
-// for(var i = 0; i < messages.length; i++)
- // output += (messages[i].length>0) ? format.pre + messages[i] + format.post : "";
- output += format.last;
- return output;
- },
- /**
- * Format the message alert box.
- * @function {string} ?
- * @param {string[]} messages - Array of error messages.
- * @return Formatted message for alert
- */
- formatMessageBox : function(messages)
- {
- if(this.options.DisplayMode == 'HeaderOnly' && this.options.HeaderText)
- return this.options.HeaderText;
-
- var output = this.options.HeaderText ? this.options.HeaderText + "\n" : "";
- for(var i = 0; i < messages.length; i++)
- {
- switch(this.options.DisplayMode)
- {
- case "List":
- output += messages[i] + "\n";
- break;
- case "BulletList":
- default:
- output += " - " + messages[i] + "\n";
- break;
- case "SingleParagraph":
- output += messages[i] + " ";
- break;
- }
- }
- return output;
- }
-};
-
-/**
- * TBaseValidator serves as the base class for validator controls.
- *
- * <p>Validation is performed when a postback control, such as a TButton,
- * a TLinkButton or a TTextBox (under AutoPostBack mode) is submitting
- * the page and its <tt>CausesValidation</tt> option is true.
- * The input control to be validated is specified by <tt>ControlToValidate</tt>
- * option.</p>
- *
- * @class Prado.WebUI.TBaseValidator
- */
-Prado.WebUI.TBaseValidator = Class.create(Prado.WebUI.Control,
-{
- /**
- * Initialize TBaseValidator.
- * @constructor {protected} ?
- * @param {object} options - Options for initialization.
- * @... {string} ID - ID of validator
- * @... {string} FormID - ID of form of this manager.
- * @... {string} ControlToValidate - ID of control to validate.
- * @... {optional string} InitialValue - Initial value of control to validate.
- * @... {optional string} ErrorMessage - Validation error message.
- * @... {optional string} ValidationGroup - ID of ValidationGroup.
- * @... {optional string} Display - Display mode, 'None', 'Fixed', 'Dynamic'.
- * @... {optional boolean} ObserveChanges - True to observer changes of ControlToValidate
- * @... {optional boolean} FocusOnError - True to focus on validation error.
- * @... {optional string} FocusElementID - ID of element to focus on error.
- * @... {optional string} ControlCssClass - Css class to use on ControlToValidate on error
- * @... {optional function} OnValidate - Called immediately after validation.
- * @... {optional function} OnValidationSuccess - Called after successful validation.
- * @... {optional function} OnValidationError - Called after validation error.
- */
- initialize : function(options)
- {
- this.observers = new Array();
- this.intervals = new Array();
-
- /* options.OnValidate = options.OnValidate || Prototype.emptyFunction;
- options.OnSuccess = options.OnSuccess || Prototype.emptyFunction;
- options.OnError = options.OnError || Prototype.emptyFunction;
- */
- /**
- * Wether the validator is enabled (default true)
- * @var {boolean} enabled
- */
- this.enabled = options.Enabled;
- /**
- * Visibility state of validator(default false)
- * @var {boolean} visible
- */
- this.visible = false;
- /**
- * State of validation (default true)
- * @var {boolean} isValid
- */
- this.isValid = true;
- /**
- * DOM elements that are observed by this validator
- * @var {private element[]} _isObserving
- */
- this._isObserving = {};
- /**
- * ValidationGroup
- * @var {string} group
- */
- this.group = null;
- /**
- * Wether a request was dispatched (default false)
- * @var {boolean} requestDispatched
- */
- this.requestDispatched = false;
-
- /**
- * Validator options
- * @var {object} options
- */
- this.options = options;
- /**
- * DOM element of control to validate
- * @var {element} control
- */
- this.control = $(options.ControlToValidate);
- /**
- * DOM element of validator
- * @var {element} message
- */
- this.message = $(options.ID);
-
- Prado.Registry.set(options.ID, this);
-
- if (this.onInit) this.onInit();
-
- if(this.control && this.message)
- {
- this.group = options.ValidationGroup;
-
- /**
- * ValidationManager of this validator
- * @var {ValidationManager} manager
- */
- this.manager = Prado.Validation.addValidator(options.FormID, this);
- }
- },
-
- /**
- * Get error message.
- * @function {string} ?
- * @return Validation error message.
- */
- getErrorMessage : function()
- {
- return this.options.ErrorMessage;
- },
-
- /**
- * Update the validator.
- * Updating the validator control will set the validator
- * <tt>visible</tt> property to true.
- * @function ?
- */
- updateControl: function()
- {
- this.refreshControlAndMessage();
-
- //if(this.options.FocusOnError && !this.isValid )
- // Prado.Element.focus(this.options.FocusElementID);
-
- this.visible = true;
- },
-
- /**
- * Updates span and input CSS class.
- * @function ?
- */
- refreshControlAndMessage : function()
- {
- this.visible = true;
- if(this.message)
- {
- if(this.options.Display == "Dynamic")
- {
- var msg=this.message;
- this.isValid ? setTimeout(function() { msg.hide(); }, 250) : msg.show();
- }
- this.message.style.visibility = this.isValid ? "hidden" : "visible";
- }
- if(this.control)
- this.updateControlCssClass(this.control, this.isValid);
- },
-
- /**
- * Update CSS class of control to validate.
- * Add a css class to the input control if validator is invalid,
- * removes the css class if valid.
- * @function ?
- * @param {element} control - DOM element of control to validate
- * @param {boolean} valid - Validation state of control
- */
- updateControlCssClass : function(control, valid)
- {
- var CssClass = this.options.ControlCssClass;
- if(typeof(CssClass) == "string" && CssClass.length > 0)
- {
- if(valid)
- {
- if (control.lastValidator == this.options.ID)
- {
- control.lastValidator = null;
- control.removeClassName(CssClass);
- }
- }
- else
- {
- control.lastValidator = this.options.ID;
- control.addClassName(CssClass);
- }
- }
- },
-
- /**
- * Hide the validator messages and remove any validation changes.
- * @function ?
- */
- hide : function()
- {
- this.reset();
- this.visible = false;
- },
-
- /**
- * Reset validator.
- * Sets isValid = true and updates the validator display.
- * @function ?
- */
- reset : function()
- {
- this.isValid = true;
- this.updateControl();
- },
-
- /**
- * Perform validation.
- * Calls evaluateIsValid() function to set the value of isValid property.
- * Triggers onValidate event and onSuccess or onError event.
- * @function {boolean} ?
- * @param {element} invoker - DOM element that triggered validation
- * @return Valdation state of control.
- */
- validate : function(invoker)
- {
- //try to find the control.
- if(!this.control)
- this.control = $(this.options.ControlToValidate);
-
- if(!this.control || this.control.disabled)
- {
- this.isValid = true;
- return this.isValid;
- }
-
- if(typeof(this.options.OnValidate) == "function")
- {
- if(this.requestDispatched == false)
- this.options.OnValidate(this, invoker);
- }
-
- if(this.enabled && !this.control.getAttribute('disabled'))
- this.isValid = this.evaluateIsValid();
- else
- this.isValid = true;
-
- this.updateValidationDisplay(invoker);
- this.observeChanges(this.control);
-
- return this.isValid;
- },
-
- /**
- * Update validation display.
- * Updates the validation messages and the control to validate.
- * @param {element} invoker - DOM element that triggered validation
- */
- updateValidationDisplay : function(invoker)
- {
- if(this.isValid)
- {
- if(typeof(this.options.OnValidationSuccess) == "function")
- {
- if(this.requestDispatched == false)
- {
- this.refreshControlAndMessage();
- this.options.OnValidationSuccess(this, invoker);
- }
- }
- else
- this.updateControl();
- }
- else
- {
- if(typeof(this.options.OnValidationError) == "function")
- {
- if(this.requestDispatched == false)
- {
- this.refreshControlAndMessage();
- this.options.OnValidationError(this, invoker)
- }
- }
- else
- this.updateControl();
- }
- },
-
- /**
- * Add control to observe for changes.
- * Re-validates upon change. If the validator is not visible,
- * no updates are propagated.
- * @function ?
- * @param {element} control - DOM element of control to observe
- */
- observeChanges : function(control)
- {
- if(!control) return;
-
- var canObserveChanges = this.options.ObserveChanges != false;
- var currentlyObserving = this._isObserving[control.id+this.options.ID];
-
- if(canObserveChanges && !currentlyObserving)
- {
- var validator = this;
-
- this.observe(control, 'change', function()
- {
- if(validator.visible)
- {
- validator.validate();
- validator.manager.updateSummary(validator.group);
- }
- });
- this._isObserving[control.id+this.options.ID] = true;
- }
- },
-
- /**
- * Trim a string.
- * @function {string} ?
- * @param {string} value - String that should be trimmed.
- * @return Trimmed string, empty string if value is not string.
- */
- trim : function(value)
- {
- return typeof(value) == "string" ? value.trim() : "";
- },
-
- /**
- * Convert the value to a specific data type.
- * @function {mixed|null} ?
- * @param {string} dataType - Data type: "Integer", "Double", "Date" or "String"
- * @param {mixed} value - Value to convert.
- * @return Converted data value.
- */
- convert : function(dataType, value)
- {
- if(typeof(value) == "undefined")
- value = this.getValidationValue();
- var string = new String(value);
- switch(dataType)
- {
- case "Integer":
- return string.toInteger();
- case "Double" :
- case "Float" :
- return string.toDouble(this.options.DecimalChar);
- case "Date":
- if(typeof(value) != "string")
- return value;
- else
- {
- var value = string.toDate(this.options.DateFormat);
- if(value && typeof(value.getTime) == "function")
- return value.getTime();
- else
- return null;
- }
- case "String":
- return string.toString();
- }
- return value;
- },
-
- /**
- * Get value that should be validated.
- * The ControlType property comes from TBaseValidator::getClientControlClass()
- * Be sure to update the TBaseValidator::$_clientClass if new cases are added.
- * @function {mixed} ?
- * @param {optional element} control - Control to get value from (default: this.control)
- * @return Control value to validate
- */
- getRawValidationValue : function(control)
- {
- if(!control)
- control = this.control
- switch(this.options.ControlType)
- {
- case 'TDatePicker':
- if(control.type == "text")
- {
- var value = this.trim($F(control));
-
- if(this.options.DateFormat)
- {
- var date = value.toDate(this.options.DateFormat);
- return date == null ? value : date;
- }
- else
- return value;
- }
- else
- {
- this.observeDatePickerChanges();
-
- return Prado.WebUI.TDatePicker.getDropDownDate(control);//.getTime();
- }
- case 'THtmlArea':
- if(typeof tinyMCE != "undefined")
- tinyMCE.triggerSave();
- return $F(control);
- case 'TRadioButton':
- if(this.options.GroupName)
- return this.getRadioButtonGroupValue();
- default:
- if(this.isListControlType())
- return this.getFirstSelectedListValue();
- else
- return $F(control);
- }
- },
-
- /**
- * Get a trimmed value that should be validated.
- * The ControlType property comes from TBaseValidator::getClientControlClass()
- * Be sure to update the TBaseValidator::$_clientClass if new cases are added.
- * @function {mixed} ?
- * @param {optional element} control - Control to get value fron (default: this.control)
- * @return Control value to validate
- */
- getValidationValue : function(control)
- {
- var value = this.getRawValidationValue(control);
- if(!control)
- control = this.control
- switch(this.options.ControlType)
- {
- case 'TDatePicker':
- return value;
- case 'THtmlArea':
- return this.trim(value);
- case 'TRadioButton':
- return value;
- default:
- if(this.isListControlType())
- return value;
- else
- return this.trim(value);
- }
- },
-
- /**
- * Get value of radio button group
- * @function {string} ?
- * @return Value of a radio button group
- */
- getRadioButtonGroupValue : function()
- {
- var name = this.control.name;
- var value = "";
- $A(document.getElementsByName(name)).each(function(el)
- {
- if(el.checked)
- value = el.value;
- });
- return value;
- },
-
- /**
- * Observe changes in the drop down list date picker, IE only.
- * @function ?
- */
- observeDatePickerChanges : function()
- {
- if(Prado.Browser().ie)
- {
- var DatePicker = Prado.WebUI.TDatePicker;
- this.observeChanges(DatePicker.getDayListControl(this.control));
- this.observeChanges(DatePicker.getMonthListControl(this.control));
- this.observeChanges(DatePicker.getYearListControl(this.control));
- }
- },
-
- /**
- * Gets number of selections and their values.
- * @function {object} ?
- * @param {element[]} elements - Elements to get values from.
- * @param {string} initialValue - Initial value of element
- * @return Object:
- * @... {mixed[]} values - Array of selected values
- * @... {int} checks - Number of selections
- */
- getSelectedValuesAndChecks : function(elements, initialValue)
- {
- var checked = 0;
- var values = [];
- var isSelected = this.isCheckBoxType(elements[0]) ? 'checked' : 'selected';
- elements.each(function(element)
- {
- if(element[isSelected] && element.value != initialValue)
- {
- checked++;
- values.push(element.value);
- }
- });
- return {'checks' : checked, 'values' : values};
- },
-
- /**
- * Get list elements of TCheckBoxList or TListBox.
- * Gets an array of the list control item input elements, for TCheckBoxList
- * checkbox input elements are returned, for TListBox HTML option elements
- * are returned.
- * @function {element[]} ?
- * @return Array of list control option DOM elements.
- */
- getListElements : function()
- {
- switch(this.options.ControlType)
- {
- case 'TCheckBoxList': case 'TRadioButtonList':
- var elements = [];
- for(var i = 0; i < this.options.TotalItems; i++)
- {
- var element = $(this.options.ControlToValidate+"_c"+i);
- if(this.isCheckBoxType(element))
- elements.push(element);
- }
- return elements;
- case 'TListBox':
- var elements = [];
- var element = $(this.options.ControlToValidate);
- var type;
- if(element && (type = element.type.toLowerCase()))
- {
- if(type == "select-one" || type == "select-multiple")
- elements = $A(element.options);
- }
- return elements;
- default:
- return [];
- }
- },
-
- /**
- * Check if control is of type checkbox or radio.
- * @function {boolean} ?
- * @param {element} element - DOM element to check.
- * @return True if element is of checkbox or radio type.
- */
- isCheckBoxType : function(element)
- {
- if(element && element.type)
- {
- var type = element.type.toLowerCase();
- return type == "checkbox" || type == "radio";
- }
- return false;
- },
-
- /**
- * Check if control to validate is a TListControl type.
- * @function {boolean} ?
- * @return True if control to validate is a TListControl type.
- */
- isListControlType : function()
- {
- var list = ['TCheckBoxList', 'TRadioButtonList', 'TListBox'];
- return list.include(this.options.ControlType);
- },
-
- /**
- * Get first selected list value or initial value if none found.
- * @function {string} ?
- * @return First selected list value, initial value if none found.
- */
- getFirstSelectedListValue : function()
- {
- var initial = "";
- if(typeof(this.options.InitialValue) != "undefined")
- initial = this.options.InitialValue;
- var elements = this.getListElements();
- var selection = this.getSelectedValuesAndChecks(elements, initial);
- return selection.values.length > 0 ? selection.values[0] : initial;
- }
-});
-
-
-/**
- * TRequiredFieldValidator makes the associated input control a required field.
- *
- * <p>The input control fails validation if its value does not change from
- * the <tt>InitialValue</tt> option upon losing focus.</p>
- *
- * @class Prado.WebUI.TRequiredFieldValidator
- * @extends Prado.WebUI.TBaseValidator
- */
-Prado.WebUI.TRequiredFieldValidator = Class.extend(Prado.WebUI.TBaseValidator,
-{
- /**
- * Evaluate validation state
- * @function {boolean} ?
- * @return True if the input value is not empty nor equal to the initial value.
- */
- evaluateIsValid : function()
- {
- var a = this.getValidationValue();
- var b = this.trim(this.options.InitialValue);
- return(a != b);
- }
-});
-
-
-/**
- * TCompareValidator compares the value entered by the user into an input
- * control with the value entered into another input control or a constant value.
- *
- * <p>To compare the associated input control with another input control,
- * set the <tt>ControlToCompare</tt> option to the ID path
- * of the control to compare with. To compare the associated input control with
- * a constant value, specify the constant value to compare with by setting the
- * <tt>ValueToCompare</tt> option.</p>
- *
- * <p>The <tt>DataType</tt> property is used to specify the data type
- * of both comparison values. Both values are automatically converted to this data
- * type before the comparison operation is performed. The following value types are supported:
- * - <b>Integer</b> A 32-bit signed integer data type.
- * - <b>Float</b> A double-precision floating point number data type.
- * - <b>Date</b> A date data type. The format can be set by the <tt>DateFormat</tt> option.
- * - <b>String</b> A string data type.</p>
- *
- * Use the <tt>Operator</tt> property to specify the type of comparison
- * to perform. Valid operators include Equal, NotEqual, GreaterThan, GreaterThanEqual,
- * LessThan and LessThanEqual.
- *
- * @class Prado.WebUI.TCompareValidator
- * @extends Prado.WebUI.TBaseValidator
- */
-Prado.WebUI.TCompareValidator = Class.extend(Prado.WebUI.TBaseValidator,
-{
- /**
- * Additional constructor options.
- * @constructor initialize
- * @param {object} options - Additional constructor options:
- * @... {string} ControlToCompare - Control with compare value.
- * @... {string} ValueToCompare - Value to compare.
- * @... {string} Operator - Type of comparison: "Equal", "NotEqual", "GreaterThan",
- * "GreaterThanEqual", "LessThan" or "LessThanEqual".
- * @... {string} Type - Type of values: "Integer", "Float", "Date" or "String".
- * @... {string} DateFormat - Valid date format.
- */
-
- //_observingComparee : false,
-
- /**
- * Evaluate validation state
- * @function {boolean} ?
- * @return True if comparision condition is met.
- */
- evaluateIsValid : function()
- {
- var value = this.getValidationValue();
- if (value.length <= 0)
- return true;
-
- var comparee = $(this.options.ControlToCompare);
-
- if(comparee)
- var compareTo = this.getValidationValue(comparee);
- else
- var compareTo = this.options.ValueToCompare || "";
-
- var isValid = this.compare(value, compareTo);
-
- if(comparee)
- {
- this.updateControlCssClass(comparee, isValid);
- this.observeChanges(comparee);
- }
- return isValid;
- },
-
- /**
- * Compare two operands.
- * The operand values are casted to type defined
- * by <tt>DataType</tt> option. False is returned if the first
- * operand converts to null. Returns true if the second operand
- * converts to null. The comparision is done based on the
- * <tt>Operator</tt> option.
- * @function ?
- * @param {mixed} operand1 - First operand.
- * @param {mixed} operand2 - Second operand.
- */
- compare : function(operand1, operand2)
- {
- var op1, op2;
- if((op1 = this.convert(this.options.DataType, operand1)) == null)
- return false;
- if ((op2 = this.convert(this.options.DataType, operand2)) == null)
- return true;
- switch (this.options.Operator)
- {
- case "NotEqual":
- return (op1 != op2);
- case "GreaterThan":
- return (op1 > op2);
- case "GreaterThanEqual":
- return (op1 >= op2);
- case "LessThan":
- return (op1 < op2);
- case "LessThanEqual":
- return (op1 <= op2);
- default:
- return (op1 == op2);
- }
- }
-});
-
-/**
- * TCustomValidator performs user-defined client-side validation on an
- * input component.
- *
- * <p>To create a client-side validation function, add the client-side
- * validation javascript function to the page template.
- * The function should have the following signature:</p>
- *
- * <pre>
- * &lt;script type="text/javascript"&gt;
- * function ValidationFunctionName(sender, parameter)
- * {
- * if(parameter == ...)
- * return true;
- * else
- * return false;
- * }
- * &lt;/script&gt;
- * </pre>
- *
- * <p>Use the <tt>ClientValidationFunction</tt> option
- * to specify the name of the client-side validation script function associated
- * with the TCustomValidator.</p>
- *
- * @class Prado.WebUI.TCustomValidator
- * @extends Prado.WebUI.TBaseValidator
- */
-Prado.WebUI.TCustomValidator = Class.extend(Prado.WebUI.TBaseValidator,
-{
- /**
- * Additional constructor options.
- * @constructor initialize
- * @param {object} options - Additional constructor options:
- * @... {function} ClientValidationFunction - Custom validation function.
- */
-
- /**
- * Evaluate validation state
- * Returns true if no valid custom validation function is present.
- * @function {boolean} ?
- * @return True if custom validation returned true.
- */
- evaluateIsValid : function()
- {
- var value = this.getValidationValue();
- var clientFunction = this.options.ClientValidationFunction;
- if(typeof(clientFunction) == "string" && clientFunction.length > 0)
- {
- var validate = clientFunction.toFunction();
- return validate(this, value);
- }
- return true;
- }
-});
-
-/**
- * Uses callback request to perform validation.
- *
- * @class Prado.WebUI.TActiveCustomValidator
- * @extends Prado.WebUI.TBaseValidator
- */
-Prado.WebUI.TActiveCustomValidator = Class.extend(Prado.WebUI.TBaseValidator,
-{
- /**
- * Override the parent implementation to store the invoker, in order to
- * re-validate after the callback has returned
- * Calls evaluateIsValid() function to set the value of isValid property.
- * Triggers onValidate event and onSuccess or onError event.
- * @function {boolean} ?
- * @param {element} invoker - DOM element that triggered validation
- * @return True if valid.
- */
- validate : function(invoker)
- {
- this.invoker = invoker;
-
- //try to find the control.
- if(!this.control)
- this.control = $(this.options.ControlToValidate);
-
- if(!this.control || this.control.disabled)
- {
- this.isValid = true;
- return this.isValid;
- }
-
- if(typeof(this.options.OnValidate) == "function")
- {
- if(this.requestDispatched == false)
- this.options.OnValidate(this, invoker);
- }
-
- return true;
- },
-
- /**
- * Send CallBack to start serverside validation.
- * @function {boolean} ?
- * @return True if valid.
- */
- evaluateIsValid : function()
- {
- return this.isValid;
- },
-
- /**
- * Parse CallBack response data on success.
- * @function ?
- * @param {CallbackRequest} request - CallbackRequest.
- * @param {string} data - Response data.
- */
- updateIsValid : function(data)
- {
- this.isValid = data;
- this.requestDispatched = false;
- if(typeof(this.options.onSuccess) == "function")
- this.options.onSuccess(null,data);
- this.updateValidationDisplay();
- this.manager.updateSummary(this.group);
- }
-});
-
-/**
- * TRangeValidator tests whether an input value is within a specified range.
- *
- * <p>TRangeValidator uses three key properties to perform its validation.</p>
- *
- * <p>The <tt>MinValue</tt> and <tt>MaxValue</tt> options specify the minimum
- * and maximum values of the valid range.</p>
- * <p>The <tt>DataType</tt> option is
- * used to specify the data type of the value and the minimum and maximum range values.
- * The values are converted to this data type before the validation
- * operation is performed. The following value types are supported:</p>
- *
- * - <b>Integer</b> A 32-bit signed integer data type.<br />
- * - <b>Float</b> A double-precision floating point number data type.<br />
- * - <b>Date</b> A date data type. The date format can be specified by<br />
- * setting <tt>DateFormat</tt> option, which must be recognizable
- * by <tt>Date.SimpleParse</tt> javascript function.
- * - <b>String</b> A string data type.
- *
- * @class Prado.WebUI.TRangeValidator
- * @extends Prado.WebUI.TBaseValidator
- */
-Prado.WebUI.TRangeValidator = Class.extend(Prado.WebUI.TBaseValidator,
-{
- /**
- * Additional constructor options.
- * @constructor initialize
- * @param {object} options - Additional constructor options:
- * @... {string} MinValue - Minimum range value
- * @... {string} MaxValue - Maximum range value
- * @... {string} DataType - Value data type: "Integer", "Float", "Date" or "String"
- * @... {string} DateFormat - Date format for data type Date.
- */
-
- /**
- * Evaluate validation state
- * @function {boolean} ?
- * @return True if value is in range or value is empty,
- * false otherwhise and when type conversion failed.
- */
- evaluateIsValid : function()
- {
- var value = this.getValidationValue();
- if(value.length <= 0)
- return true;
- if(typeof(this.options.DataType) == "undefined")
- this.options.DataType = "String";
-
- if(this.options.DataType != "StringLength")
- {
- var min = this.convert(this.options.DataType, this.options.MinValue || null);
- var max = this.convert(this.options.DataType, this.options.MaxValue || null);
- value = this.convert(this.options.DataType, value);
- }
- else
- {
- var min = this.options.MinValue || 0;
- var max = this.options.MaxValue || Number.POSITIVE_INFINITY;
- value = value.length;
- }
-
- if(value == null)
- return false;
-
- var valid = true;
-
- if(min != null)
- valid = valid && (this.options.StrictComparison ? value > min : value >= min);
- if(max != null)
- valid = valid && (this.options.StrictComparison ? value < max : value <= max);
- return valid;
- }
-});
-
-/**
- * TRegularExpressionValidator validates whether the value of an associated
- * input component matches the pattern specified by a regular expression.
- *
- * @class Prado.WebUI.TRegularExpressionValidator
- * @extends Prado.WebUI.TBaseValidator
- */
-Prado.WebUI.TRegularExpressionValidator = Class.extend(Prado.WebUI.TBaseValidator,
-{
- /**
- * Additional constructor option.
- * @constructor initialize
- * @param {object} options - Additional constructor option:
- * @... {string} ValidationExpression - Regular expression to match against.
- * @... {string} PatternModifiers - Pattern modifiers: combinations of g, i, and m
- */
-
- /**
- * Evaluate validation state
- * @function {boolean} ?
- * @return True if value matches regular expression or value is empty.
- */
- evaluateIsValid : function()
- {
- var value = this.getRawValidationValue();
- if (value.length <= 0)
- return true;
-
- var rx = new RegExp('^'+this.options.ValidationExpression+'$',this.options.PatternModifiers);
- var matches = rx.exec(value);
- return (matches != null && value == matches[0]);
- }
-});
-
-/**
- * TEmailAddressValidator validates whether the value of an associated
- * input component is a valid email address.
- *
- * @class Prado.WebUI.TEmailAddressValidator
- * @extends Prado.WebUI.TRegularExpressionValidator
- */
-Prado.WebUI.TEmailAddressValidator = Prado.WebUI.TRegularExpressionValidator;
-
-
-/**
- * TListControlValidator checks the number of selection and their values
- * for a TListControl that allows multiple selections.
- *
- * @class Prado.WebUI.TListControlValidator
- * @extends Prado.WebUI.TBaseValidator
- */
-Prado.WebUI.TListControlValidator = Class.extend(Prado.WebUI.TBaseValidator,
-{
- /**
- * Evaluate validation state
- * @function {boolean} ?
- * @return True if number of selections and/or their values match requirements.
- */
- evaluateIsValid : function()
- {
- var elements = this.getListElements();
- if(elements && elements.length <= 0)
- return true;
-
- this.observeListElements(elements);
-
- var selection = this.getSelectedValuesAndChecks(elements);
- return this.isValidList(selection.checks, selection.values);
- },
-
- /**
- * Observe list elements for of changes (only IE)
- * @function ?
- * @param {element[]} elements - Array of DOM elements to observe
- */
- observeListElements : function(elements)
- {
- if(Prado.Browser().ie && this.isCheckBoxType(elements[0]))
- {
- var validator = this;
- elements.each(function(element)
- {
- validator.observeChanges(element);
- });
- }
- },
-
- /**
- * Check if list is valid.
- * Determine if the number of checked values and the checked values
- * satisfy the required number of checks and/or the checked values
- * equal to the required values.
- * @function {boolean} ?
- * @param {int} checked - Number of required checked values
- * @param {string[]} values - Array of required checked values
- * @return True if checked values and number of checks are satisfied.
- */
- isValidList : function(checked, values)
- {
- var exists = true;
-
- //check the required values
- var required = this.getRequiredValues();
- if(required.length > 0)
- {
- if(values.length < required.length)
- return false;
- required.each(function(requiredValue)
- {
- exists = exists && values.include(requiredValue);
- });
- }
-
- var min = typeof(this.options.Min) == "undefined" ?
- Number.NEGATIVE_INFINITY : this.options.Min;
- var max = typeof(this.options.Max) == "undefined" ?
- Number.POSITIVE_INFINITY : this.options.Max;
- return exists && checked >= min && checked <= max;
- },
-
- /**
- * Get list of required values.
- * @function {string[]} ?
- * @return Array of required values that must be selected.
- */
- getRequiredValues : function()
- {
- var required = [];
- if(this.options.Required && this.options.Required.length > 0)
- required = this.options.Required.split(/,\s*/);
- return required;
- }
-});
-
-
-/**
- * TDataTypeValidator verifies if the input data is of the type specified
- * by <tt>DataType</tt> option.
- *
- * <p>The following data types are supported:</p>
- *
- * - <b>Integer</b> A 32-bit signed integer data type.<br />
- * - <b>Float</b> A double-precision floating point number data type.<br />
- * - <b>Date</b> A date data type.<br />
- * - <b>String</b> A string data type.<br />
- *
- * <p>For <b>Date</b> type, the option <tt>DateFormat</tt>
- * will be used to determine how to parse the date string.</p>
- *
- * @class Prado.WebUI.TDataTypeValidator
- * @extends Prado.WebUI.TBaseValidator
- */
-Prado.WebUI.TDataTypeValidator = Class.extend(Prado.WebUI.TBaseValidator,
-{
- /**
- * Additional constructor option.
- * @constructor initialize
- * @param {object} options - Additional constructor option:
- * @... {string} DataType - Value data type: "Integer", "Float", "Date" or "String"
- * @... {string} DateFormat - Date format for data type Date.
- */
-
- /**
- * Evaluate validation state
- * @function {boolean} ?
- * @return True if value matches required data type.
- */
- evaluateIsValid : function()
- {
- var value = this.getValidationValue();
- if(value.length <= 0)
- return true;
- return this.convert(this.options.DataType, value) != null;
- }
-});
-
-/**
- * TCaptchaValidator verifies if the input data is the same as
- * the token shown in the associated CAPTCHA control.
- *
- * @class Prado.WebUI.TCaptchaValidator
- * @extends Prado.WebUI.TBaseValidator
- */
-Prado.WebUI.TCaptchaValidator = Class.extend(Prado.WebUI.TBaseValidator,
-{
- /**
- * Evaluate validation state
- * @function {boolean} ?
- * @return True if value matches captcha text
- */
- evaluateIsValid : function()
- {
- var a = this.getValidationValue();
- var h = 0;
- if (this.options.CaseSensitive==false)
- a = a.toUpperCase();
- for(var i = a.length-1; i >= 0; --i)
- h += a.charCodeAt(i);
- return h == this.options.TokenHash;
- },
-
- crc32 : function(str)
- {
- function Utf8Encode(string)
- {
- string = string.replace(/\r\n/g,"\n");
- var utftext = "";
-
- for (var n = 0; n < string.length; n++)
- {
- var c = string.charCodeAt(n);
-
- if (c < 128) {
- utftext += String.fromCharCode(c);
- }
- else if((c > 127) && (c < 2048)) {
- utftext += String.fromCharCode((c >> 6) | 192);
- utftext += String.fromCharCode((c & 63) | 128);
- }
- else {
- utftext += String.fromCharCode((c >> 12) | 224);
- utftext += String.fromCharCode(((c >> 6) & 63) | 128);
- utftext += String.fromCharCode((c & 63) | 128);
- }
- }
-
- return utftext;
- };
-
- str = Utf8Encode(str);
-
- var table = "00000000 77073096 EE0E612C 990951BA 076DC419 706AF48F E963A535 9E6495A3 0EDB8832 79DCB8A4 E0D5E91E 97D2D988 09B64C2B 7EB17CBD E7B82D07 90BF1D91 1DB71064 6AB020F2 F3B97148 84BE41DE 1ADAD47D 6DDDE4EB F4D4B551 83D385C7 136C9856 646BA8C0 FD62F97A 8A65C9EC 14015C4F 63066CD9 FA0F3D63 8D080DF5 3B6E20C8 4C69105E D56041E4 A2677172 3C03E4D1 4B04D447 D20D85FD A50AB56B 35B5A8FA 42B2986C DBBBC9D6 ACBCF940 32D86CE3 45DF5C75 DCD60DCF ABD13D59 26D930AC 51DE003A C8D75180 BFD06116 21B4F4B5 56B3C423 CFBA9599 B8BDA50F 2802B89E 5F058808 C60CD9B2 B10BE924 2F6F7C87 58684C11 C1611DAB B6662D3D 76DC4190 01DB7106 98D220BC EFD5102A 71B18589 06B6B51F 9FBFE4A5 E8B8D433 7807C9A2 0F00F934 9609A88E E10E9818 7F6A0DBB 086D3D2D 91646C97 E6635C01 6B6B51F4 1C6C6162 856530D8 F262004E 6C0695ED 1B01A57B 8208F4C1 F50FC457 65B0D9C6 12B7E950 8BBEB8EA FCB9887C 62DD1DDF 15DA2D49 8CD37CF3 FBD44C65 4DB26158 3AB551CE A3BC0074 D4BB30E2 4ADFA541 3DD895D7 A4D1C46D D3D6F4FB 4369E96A 346ED9FC AD678846 DA60B8D0 44042D73 33031DE5 AA0A4C5F DD0D7CC9 5005713C 270241AA BE0B1010 C90C2086 5768B525 206F85B3 B966D409 CE61E49F 5EDEF90E 29D9C998 B0D09822 C7D7A8B4 59B33D17 2EB40D81 B7BD5C3B C0BA6CAD EDB88320 9ABFB3B6 03B6E20C 74B1D29A EAD54739 9DD277AF 04DB2615 73DC1683 E3630B12 94643B84 0D6D6A3E 7A6A5AA8 E40ECF0B 9309FF9D 0A00AE27 7D079EB1 F00F9344 8708A3D2 1E01F268 6906C2FE F762575D 806567CB 196C3671 6E6B06E7 FED41B76 89D32BE0 10DA7A5A 67DD4ACC F9B9DF6F 8EBEEFF9 17B7BE43 60B08ED5 D6D6A3E8 A1D1937E 38D8C2C4 4FDFF252 D1BB67F1 A6BC5767 3FB506DD 48B2364B D80D2BDA AF0A1B4C 36034AF6 41047A60 DF60EFC3 A867DF55 316E8EEF 4669BE79 CB61B38C BC66831A 256FD2A0 5268E236 CC0C7795 BB0B4703 220216B9 5505262F C5BA3BBE B2BD0B28 2BB45A92 5CB36A04 C2D7FFA7 B5D0CF31 2CD99E8B 5BDEAE1D 9B64C2B0 EC63F226 756AA39C 026D930A 9C0906A9 EB0E363F 72076785 05005713 95BF4A82 E2B87A14 7BB12BAE 0CB61B38 92D28E9B E5D5BE0D 7CDCEFB7 0BDBDF21 86D3D2D4 F1D4E242 68DDB3F8 1FDA836E 81BE16CD F6B9265B 6FB077E1 18B74777 88085AE6 FF0F6A70 66063BCA 11010B5C 8F659EFF F862AE69 616BFFD3 166CCF45 A00AE278 D70DD2EE 4E048354 3903B3C2 A7672661 D06016F7 4969474D 3E6E77DB AED16A4A D9D65ADC 40DF0B66 37D83BF0 A9BCAE53 DEBB9EC5 47B2CF7F 30B5FFE9 BDBDF21C CABAC28A 53B39330 24B4A3A6 BAD03605 CDD70693 54DE5729 23D967BF B3667A2E C4614AB8 5D681B02 2A6F2B94 B40BBE37 C30C8EA1 5A05DF1B 2D02EF8D";
- var crc = 0;
- var x = 0;
- var y = 0;
-
- crc = crc ^ (-1);
- for( var i = 0, iTop = str.length; i < iTop; i++ )
- {
- y = ( crc ^ str.charCodeAt( i ) ) & 0xFF;
- x = "0x" + table.substr( y * 9, 8 );
- crc = ( crc >>> 8 ) ^ x;
- }
- return crc ^ (-1);
- }
-});
-
-
-/**
- * TReCaptchaValidator client-side control.
- *
- * @class Prado.WebUI.TReCaptchaValidator
- * @extends Prado.WebUI.TBaseValidator
- */
-Prado.WebUI.TReCaptchaValidator = Class.create(Prado.WebUI.TBaseValidator,
-{
- onInit : function()
- {
- var obj = this;
- var elements = document.getElementsByName(this.options.ResponseFieldName);
- if (elements)
- if (elements.length>=1)
- {
- this.observe(elements[0],'change',function() { obj.responseChanged() });
- this.observe(elements[0],'keydown',function() { obj.responseChanged() });
- }
- },
-
- responseChanged: function()
- {
- var field = $(this.options.ID+'_1');
- if (field.value=='1') return;
- field.value = '1';
- Prado.Validation.validateControl(this.options.ID);
- },
-
- /**
- * Evaluate validation state
- * @function {boolean} ?
- * @return True if the captcha has validate, False otherwise.
- */
- evaluateIsValid : function()
- {
- return ($(this.options.ID+'_1').value=='1');
- }
-});
-
+/**
+ * Prado client-side javascript validation fascade.
+ *
+ * <p>There are 4 basic classes: {@link Prado.Validation},
+ * {@link Prado.ValidationManager}, {@link Prado.WebUI.TValidationSummary}
+ * and {@link Prado.WebUI.TBaseValidator},
+ * that interact together to perform validation.
+ * The {@link Prado.Validation} class co-ordinates together the
+ * validation scheme and is responsible for maintaining references
+ * to ValidationManagers.</p>
+ *
+ * <p>The {@link Prado.ValidationManager} class is responsible for
+ * maintaining refereneces
+ * to individual validators, validation summaries and their associated
+ * groupings.</p>
+ *
+ * <p>The {@link Prado.WebUI.TValidationSummary} takes care of displaying
+ * the validator error messages
+ * as html output or an alert output.</p>
+ *
+ * <p>The {@link Prado.WebUI.TBaseValidator} is the base class for all
+ * validators and contains
+ * methods to interact with the actual inputs, data type conversion.</p>
+ *
+ * <p>An instance of {@link Prado.ValidationManager} must be instantiated first for a
+ * particular form before instantiating validators and summaries.</p>
+ *
+ * <p>Usage example: adding a required field to a text box input with
+ * ID "input1" in a form with ID "form1".</p>
+ * <pre>
+ * &lt;script type="text/javascript" src="../prado.js"&gt;&lt;/script&gt;
+ * &lt;script type="text/javascript" src="../validator.js"&gt;&lt;/script&gt;
+ * &lt;form id="form1" action="..."&gt;
+ * &lt;div&gt;
+ * &lt;input type="text" id="input1" /&gt;
+ * &lt;span id="validator1" style="display:none; color:red"&gt;*&lt;/span&gt;
+ * &lt;input type="submit text="submit" /&gt;
+ * &lt;script type="text/javascript"&gt;
+ * new Prado.ValidationManager({FormID : 'form1'});
+ * var options =
+ * {
+ * ID : 'validator1',
+ * FormID : 'form1',
+ * ErrorMessage : '*',
+ * ControlToValidate : 'input1'
+ * }
+ * new Prado.WebUI.TRequiredFieldValidator(options);
+ * new Prado.WebUI.TValidationSummary({ID:'summary1',FormID:'form1'});
+ *
+ * //watch the form onsubmit event, check validators, stop if not valid.
+ * Event.observe("form1", "submit" function(ev)
+ * {
+ * if(Prado.WebUI.Validation.isValid("form1") == false)
+ * Event.stop(ev);
+ * });
+ * &lt;/script&gt;
+ * &lt;/div&gt;
+ * &lt;/form&gt;
+ * </pre>
+ *
+ * @module validation
+ */
+
+Prado.Validation = Class.create();
+
+/**
+ * Global Validation Object.
+ *
+ * <p>To validate the inputs of a particular form, call
+ * <code>{@link Prado.Validation.validate}(formID, groupID)</code>
+ * where <tt>formID</tt> is the HTML form ID, and the optional
+ * <tt>groupID</tt> if present will only validate the validators
+ * in a particular group.</p>
+ * <p>Use <code>{@link Prado.Validation.validateControl}(controlClientID)</code>
+ * to trigger validation for a single control.</p>
+ *
+ * @object {static} Prado.Validation
+ */
+Object.extend(Prado.Validation,
+{
+ /**
+ * Hash of registered validation managers
+ * @var managers
+ */
+ managers : {},
+
+ /**
+ * Validate the validators (those that <strong>DO NOT</strong>
+ * belong to a particular group) in the form specified by the
+ * <tt>formID</tt> parameter. If <tt>groupID</tt> is specified
+ * only validators belonging to that group will be validated.
+ * @function {boolean} ?
+ * @param {string} formID - ID of the form to validate
+ * @param {string} groupID - ID of the ValidationGroup to validate.
+ * @param {element} invoker - DOM element that calls for validation
+ * @returns true if validation succeeded
+ */
+ validate : function(formID, groupID, invoker)
+ {
+ formID = formID || this.getForm();
+ if(this.managers[formID])
+ {
+ return this.managers[formID].validate(groupID, invoker);
+ }
+ else
+ {
+ throw new Error("Form '"+formID+"' is not registered with Prado.Validation");
+ }
+ },
+
+ /**
+ * Validate all validators of a specific control.
+ * @function {boolean} ?
+ * @param {string} id - ID of DOM element to validate
+ * @return true if all validators are valid or no validators present, false otherwise.
+ */
+ validateControl : function(id)
+ {
+ var formId=this.getForm();
+
+ if (this.managers[formId])
+ {
+ return this.managers[formId].validateControl(id);
+ } else {
+ throw new Error("A validation manager needs to be created first.");
+ }
+ },
+
+ /**
+ * Return first registered form
+ * @function {string} ?
+ * @returns ID of first form.
+ */
+ getForm : function()
+ {
+ var keys = $H(this.managers).keys();
+ return keys[0];
+ },
+
+ /**
+ * Check if the validators are valid for a particular form (and group).
+ * The validators states will not be changed.
+ * The <tt>validate</tt> function should be called first.
+ * @function {boolean} ?
+ * @param {string} formID - ID of the form to validate
+ * @param {string} groupID - ID of the ValiationGroup to validate.
+ * @return true if form is valid
+ */
+ isValid : function(formID, groupID)
+ {
+ formID = formID || this.getForm();
+ if(this.managers[formID])
+ return this.managers[formID].isValid(groupID);
+ return true;
+ },
+
+ /**
+ * Reset the validators for a given group.
+ * The group is searched in the first registered form.
+ * @function ?
+ * @param {string} groupID - ID of the ValidationGroup to reset.
+ */
+ reset : function(groupID)
+ {
+ var formID = this.getForm();
+ if(this.managers[formID])
+ this.managers[formID].reset(groupID);
+ },
+
+ /**
+ * Add a new validator to a particular form.
+ * @function {ValidationManager} ?
+ * @param {string} formID - ID of the form that the validator belongs to.
+ * @param {TBaseValidator} validator - Validator object
+ * @return ValidationManager for the form
+ */
+ addValidator : function(formID, validator)
+ {
+ if(this.managers[formID])
+ this.managers[formID].addValidator(validator);
+ else
+ throw new Error("A validation manager for form '"+formID+"' needs to be created first.");
+ return this.managers[formID];
+ },
+
+ /**
+ * Add a new validation summary.
+ * @function {ValidationManager} ?
+ * @param {string} formID - ID of the form that the validation summary belongs to.
+ * @param {TValidationSummary} validator - TValidationSummary object
+ * @return ValidationManager for the form
+ */
+ addSummary : function(formID, validator)
+ {
+ if(this.managers[formID])
+ this.managers[formID].addSummary(validator);
+ else
+ throw new Error("A validation manager for form '"+formID+"' needs to be created first.");
+ return this.managers[formID];
+ },
+
+ setErrorMessage : function(validatorID, message)
+ {
+ $H(Prado.Validation.managers).each(function(manager)
+ {
+ manager[1].validators.each(function(validator)
+ {
+ if(validator.options.ID == validatorID)
+ {
+ validator.options.ErrorMessage = message;
+ $(validatorID).innerHTML = message;
+ }
+ });
+ });
+ },
+
+ updateActiveCustomValidator : function(validatorID, isValid)
+ {
+ $H(Prado.Validation.managers).each(function(manager)
+ {
+ manager[1].validators.each(function(validator)
+ {
+ if(validator.options.ID == validatorID)
+ {
+ validator.updateIsValid(isValid);
+ }
+ });
+ });
+ }
+});
+
+/**
+ * Manages validators for a particular HTML form.
+ *
+ * <p>The manager contains references to all the validators
+ * summaries, and their groupings for a particular form.
+ * Generally, {@link Prado.Validation} methods should be called rather
+ * than calling directly the ValidationManager.</p>
+ *
+ * @class Prado.ValidationManager
+ */
+Prado.ValidationManager = Class.create();
+Prado.ValidationManager.prototype =
+{
+ /**
+ * Hash of registered validators by control's clientID
+ * @var controls
+ */
+ controls: {},
+
+ /**
+ * Initialize ValidationManager.
+ * @constructor {protected} ?
+ * @param {object} options - Options for initialization
+ * @... {string} FormID - ID of form of this manager
+ */
+ initialize : function(options)
+ {
+ if(!Prado.Validation.managers[options.FormID])
+ {
+ /**
+ * List of validators
+ * @var {TBaseValidator[]} validators
+ */
+ this.validators = [];
+ /**
+ * List of validation summaries
+ * @var {TValidationSummary[]} summaries
+ */
+ this.summaries = [];
+ /**
+ * List of ValidationGroups
+ * @var {string[]} groups
+ */
+ this.groups = [];
+ /**
+ * Options of this ValidationManager
+ * @var {object} options
+ */
+ this.options = {};
+
+ this.options = options;
+
+ Prado.Validation.managers[options.FormID] = this;
+ }
+ else
+ {
+ var manager = Prado.Validation.managers[options.FormID];
+ this.validators = manager.validators;
+ this.summaries = manager.summaries;
+ this.groups = manager.groups;
+ this.options = manager.options;
+ }
+ },
+
+ /**
+ * Reset all validators in the given group.
+ * If group is null, validators without a group are used.
+ * @function ?
+ * @param {string} group - ID of ValidationGroup
+ */
+ reset : function(group)
+ {
+ this.validatorPartition(group)[0].invoke('reset');
+ this.updateSummary(group, true);
+ },
+
+ /**
+ * Validate the validators managed by this validation manager.
+ * If group is set, only validate validators in that group.
+ * @function {boolean} ?
+ * @param {optional string} group - ID of ValidationGroup
+ * @param {element} source - DOM element that calls for validation
+ * @return true if all validators are valid, false otherwise.
+ */
+ validate : function(group, source)
+ {
+ var partition = this.validatorPartition(group);
+ var valid = partition[0].invoke('validate', source).all();
+ this.focusOnError(partition[0]);
+ partition[1].invoke('hide');
+ this.updateSummary(group, true);
+ return valid;
+ },
+
+ /**
+ * Perform validation for all validators of a single control.
+ * @function {boolean} ?
+ * @param {string} id - ID of DOM element to validate
+ * @return true if all validators are valid or no validators present, false otherwise.
+ */
+ validateControl : function (id)
+ {
+ return this.controls[id] ? this.controls[id].invoke('validate',null).all() : true;
+ },
+
+ /**
+ * Focus on the first validator that is invalid and options.FocusOnError is true.
+ * @function ?
+ * @param {TBaseValidator[]} validators - Array of validator objects
+ */
+ focusOnError : function(validators)
+ {
+ for(var i = 0; i < validators.length; i++)
+ {
+ if(!validators[i].isValid && validators[i].options.FocusOnError)
+ return Prado.Element.focus(validators[i].options.FocusElementID);
+ }
+ },
+
+ /**
+ * Get all validators in a group and all other validators.
+ * Returns an array with two arrays of validators. The first
+ * array contains all validators in the group if group is given,
+ * otherwhise all validators without a group. The second array
+ * contains all other validators.
+ * @function {[ TBaseValidator[] , TBaseValidator[] ]} ?
+ * @param {optional string} group - ID of ValidationGroup
+ * @return Array with two arrays of validators.
+ */
+ validatorPartition : function(group)
+ {
+ return group ? this.validatorsInGroup(group) : this.validatorsWithoutGroup();
+ },
+
+ /**
+ * Get all validators in a group.
+ * Returns an array with two arrays of validators. The first
+ * array contains all validators in the group. The second array
+ * contains all other validators.
+ * @function {[ TBaseValidator[] , TBaseValidator[] ]} ?
+ * @param {optional string} groupID - ID of ValidationGroup
+ * @return Array with two arrays of validators.
+ */
+ validatorsInGroup : function(groupID)
+ {
+ if(this.groups.include(groupID))
+ {
+ return this.validators.partition(function(val)
+ {
+ return val.group == groupID;
+ });
+ }
+ else
+ return [[],[]];
+ },
+
+ /**
+ * Get all validators without a group.
+ * Returns an array with two arrays of validators. The first
+ * array contains all validators without a group. The second
+ * array contains all other validators.
+ * @function {[ TBaseValidator[] , TBaseValidator[] ]} ?
+ * @return Array with two arrays of validators: Array[0] has all
+ * validators without a group, Array[1] all other validators.
+ */
+ validatorsWithoutGroup : function()
+ {
+ return this.validators.partition(function(val)
+ {
+ return !val.group;
+ });
+ },
+
+ /**
+ * Get the state of validators.
+ * If group is set, only validators in that group are checked.
+ * Otherwhise only validators without a group are checked.
+ * @function {booelan} ?
+ * @param {optional string} group - ID of ValidationGroup
+ * @return true if all validators (in a group, if supplied) are valid.
+ */
+ isValid : function(group)
+ {
+ return this.validatorPartition(group)[0].pluck('isValid').all();
+ },
+
+ /**
+ * Add a validator to this manager.
+ * @function ?
+ * @param {TBaseValidator} validator - Validator object
+ */
+ addValidator : function(validator)
+ {
+ // Remove previously registered validator with same ID
+ // to prevent stale validators created by AJAX updates
+ this.removeValidator(validator);
+
+ this.validators.push(validator);
+ if(validator.group && !this.groups.include(validator.group))
+ this.groups.push(validator.group);
+
+ if (typeof this.controls[validator.control.id] === 'undefined')
+ this.controls[validator.control.id] = Array();
+ this.controls[validator.control.id].push(validator);
+ },
+
+ /**
+ * Add a validation summary.
+ * @function ?
+ * @param {TValidationSummary} summary - Validation summary.
+ */
+ addSummary : function(summary)
+ {
+ this.summaries.push(summary);
+ },
+
+ /**
+ * Remove a validator from this manager
+ * @function ?
+ * @param {TBaseValidator} validator - Validator object
+ */
+ removeValidator : function(validator)
+ {
+ this.validators = this.validators.reject(function(v)
+ {
+ return (v.options.ID==validator.options.ID);
+ });
+ if (this.controls[validator.control.id])
+ this.controls[validator.control.id].reject( function(v)
+ {
+ return (v.options.ID==validator.options.ID)
+ });
+ },
+
+ /**
+ * Gets validators with errors.
+ * If group is set, only validators in that group are returned.
+ * Otherwhise only validators without a group are returned.
+ * @function {TBaseValidator[]} ?
+ * @param {optional string} group - ID of ValidationGroup
+ * @return array list of validators with error.
+ */
+ getValidatorsWithError : function(group)
+ {
+ return this.validatorPartition(group)[0].findAll(function(validator)
+ {
+ return !validator.isValid;
+ });
+ },
+
+ /**
+ * Update the summary of a particular group.
+ * If group is set, only the summary for validators in that
+ * group is updated. Otherwhise only the summary for validators
+ * without a group is updated.
+ * @function ?
+ * @param {optional string} group - ID of ValidationGroup
+ * @param {boolean} refresh - Wether the summary should be refreshed
+ */
+ updateSummary : function(group, refresh)
+ {
+ var validators = this.getValidatorsWithError(group);
+ this.summaries.each(function(summary)
+ {
+ var inGroup = group && summary.group == group;
+ var noGroup = !group || !summary.group;
+ if(inGroup || noGroup)
+ summary.updateSummary(validators, refresh);
+ else
+ summary.hideSummary(true);
+ });
+ }
+};
+
+/**
+ * TValidationSummary displays a summary of validation errors.
+ *
+ * <p>The summary is displayed inline on a Web page,
+ * in a message box, or both. By default, a validation summary will collect
+ * <tt>ErrorMessage</tt> of all failed validators on the page. If
+ * <tt>ValidationGroup</tt> is not empty, only those validators who belong
+ * to the group will show their error messages in the summary.</p>
+ *
+ * <p>The summary can be displayed as a list, as a bulleted list, or as a single
+ * paragraph based on the <tt>DisplayMode</tt> option.
+ * The messages shown can be prefixed with <tt>HeaderText</tt>.</p>
+ *
+ * <p>The summary can be displayed on the Web page and in a message box by setting
+ * the <tt>ShowSummary</tt> and <tt>ShowMessageBox</tt>
+ * options, respectively.</p>
+ *
+ * @class Prado.WebUI.TValidationSummary
+ */
+Prado.WebUI.TValidationSummary = Class.create();
+Prado.WebUI.TValidationSummary.prototype =
+{
+ /**
+ * Initialize TValidationSummary.
+ * @constructor {protected} ?
+ * @param {object} options - Options for initialization
+ * @... {string} ID - ID of validation summary element
+ * @... {string} FormID - ID of form of this manager
+ * @... {optional string} ValidationGroup - ID of ValidationGroup.
+ * @... {optional boolean} ShowMessageBox - true to show the summary in an alert box.
+ * @... {optional boolean} ShowSummary - true to show the inline summary.
+ * @... {optional string} HeaderText - Summary header text
+ * @... {optional string} DisplayMode - Summary display style, 'BulletList', 'List', 'SingleParagraph'
+ * @... {optional boolean} Refresh - true to update the summary upon validator state change.
+ * @... {optional string} Display - Display mode, 'None', 'Fixed', 'Dynamic'.
+ * @... {optional boolean} ScrollToSummary - true to scroll to the validation summary upon refresh.
+ * @... {optional function} OnHideSummary - Called on hide event.
+ * @... {optional function} OnShowSummary - Called on show event.
+ */
+ initialize : function(options)
+ {
+ /**
+ * Validator options
+ * @var {object} options
+ */
+ this.options = options;
+ /**
+ * ValidationGroup
+ * @var {string} group
+ */
+ this.group = options.ValidationGroup;
+ /**
+ * Summary DOM element
+ * @var {element} messages
+ */
+ this.messages = $(options.ID);
+ Prado.Registry.set(options.ID, this);
+ if(this.messages)
+ {
+ /**
+ * Current visibility state of summary
+ * @var {boolean} visible
+ */
+ this.visible = this.messages.style.visibility != "hidden"
+ this.visible = this.visible && this.messages.style.display != "none";
+ Prado.Validation.addSummary(options.FormID, this);
+ }
+ },
+
+ /**
+ * Update the validation summary.
+ * @function ?
+ * @param {TBaseValidator[]} validators - List of validators that failed validation.
+ * @param {boolean} update - true if visible summary should be updated
+ */
+ updateSummary : function(validators, update)
+ {
+ if(validators.length <= 0)
+ {
+ if(update || this.options.Refresh != false)
+ {
+ return this.hideSummary(validators);
+ }
+ return;
+ }
+
+ var refresh = update || this.visible == false || this.options.Refresh != false;
+ // Also, do not refresh summary if at least 1 validator is waiting for callback response.
+ // This will avoid the flickering of summary if the validator passes its test
+ refresh = refresh && validators.any(function(v) { return !v.requestDispatched; });
+
+ if(this.options.ShowSummary != false && refresh)
+ {
+ this.updateHTMLMessages(this.getMessages(validators));
+ this.showSummary(validators);
+ }
+
+ if(this.options.ScrollToSummary != false && refresh)
+ window.scrollTo(this.messages.offsetLeft-20, this.messages.offsetTop-20);
+
+ if(this.options.ShowMessageBox == true && refresh)
+ {
+ this.alertMessages(this.getMessages(validators));
+ this.visible = true;
+ }
+ },
+
+ /**
+ * Display the validator error messages as inline HTML.
+ * @function ?
+ * @param {string[]} messages - Array of error messages.
+ */
+ updateHTMLMessages : function(messages)
+ {
+ while(this.messages.childNodes.length > 0)
+ this.messages.removeChild(this.messages.lastChild);
+ this.messages.insert(this.formatSummary(messages));
+ },
+
+ /**
+ * Display the validator error messages as an alert box.
+ * @function ?
+ * @param {string[]} messages - Array of error messages.
+ */
+ alertMessages : function(messages)
+ {
+ var text = this.formatMessageBox(messages);
+ setTimeout(function(){ alert(text); },20);
+ },
+
+ /**
+ * Get messages from validators.
+ * @function {string[]} ?
+ * @param {TBaseValidator[]} validators - Array of validators.
+ * @return Array of validator error messages.
+ */
+ getMessages : function(validators)
+ {
+ var messages = [];
+ validators.each(function(validator)
+ {
+ var message = validator.getErrorMessage();
+ if(typeof(message) == 'string' && message.length > 0)
+ messages.push(message);
+ })
+ return messages;
+ },
+
+ /**
+ * Hide the validation summary.
+ * @function ?
+ * @param {TBaseValidator[]} validators - Array of validators.
+ */
+ hideSummary : function(validators)
+ { if(typeof(this.options.OnHideSummary) == "function")
+ {
+ this.messages.style.visibility="visible";
+ this.options.OnHideSummary(this,validators)
+ }
+ else
+ {
+ this.messages.style.visibility="hidden";
+ if(this.options.Display == "None" || this.options.Display == "Dynamic")
+ this.messages.hide();
+ }
+ this.visible = false;
+ },
+
+ /**
+ * Shows the validation summary.
+ * @function ?
+ * @param {TBaseValidator[]} validators - Array of validators.
+ */
+ showSummary : function(validators)
+ {
+ this.messages.style.visibility="visible";
+ if(typeof(this.options.OnShowSummary) == "function")
+ this.options.OnShowSummary(this,validators);
+ else
+ this.messages.show();
+ this.visible = true;
+ },
+
+ /**
+ * Return the format parameters for the summary.
+ * @function {object} ?
+ * @param {string} type - Format type: "List", "SingleParagraph", "HeaderOnly" or "BulletList" (default)
+ * @return Object with format parameters:
+ * @... {string} header - Text for header
+ * @... {string} first - Text to prepend before message list
+ * @... {string} pre - Text to prepend before each message
+ * @... {string} post - Text to append after each message
+ * @... {string} first - Text to append after message list
+ */
+ formats : function(type)
+ {
+ switch(type)
+ {
+ case "SimpleList":
+ return { header : "<br />", first : "", pre : "", post : "<br />", last : ""};
+ case "SingleParagraph":
+ return { header : " ", first : "", pre : "", post : " ", last : "<br />"};
+ case "HeaderOnly":
+ return { header : "", first : "<!--", pre : "", post : "", last : "-->"};
+ case "BulletList":
+ default:
+ return { header : "", first : "<ul>", pre : "<li>", post : "</li>", last : "</ul>"};
+ }
+ },
+
+ /**
+ * Format the message summary.
+ * @function {string} ?
+ * @param {string[]} messages - Array of error messages.
+ * @return Formatted message
+ */
+ formatSummary : function(messages)
+ {
+ var format = this.formats(this.options.DisplayMode);
+ var output = this.options.HeaderText ? this.options.HeaderText + format.header : "";
+ output += format.first;
+ messages.each(function(message)
+ {
+ output += message.length > 0 ? format.pre + message + format.post : "";
+ });
+// for(var i = 0; i < messages.length; i++)
+ // output += (messages[i].length>0) ? format.pre + messages[i] + format.post : "";
+ output += format.last;
+ return output;
+ },
+ /**
+ * Format the message alert box.
+ * @function {string} ?
+ * @param {string[]} messages - Array of error messages.
+ * @return Formatted message for alert
+ */
+ formatMessageBox : function(messages)
+ {
+ if(this.options.DisplayMode == 'HeaderOnly' && this.options.HeaderText)
+ return this.options.HeaderText;
+
+ var output = this.options.HeaderText ? this.options.HeaderText + "\n" : "";
+ for(var i = 0; i < messages.length; i++)
+ {
+ switch(this.options.DisplayMode)
+ {
+ case "List":
+ output += messages[i] + "\n";
+ break;
+ case "BulletList":
+ default:
+ output += " - " + messages[i] + "\n";
+ break;
+ case "SingleParagraph":
+ output += messages[i] + " ";
+ break;
+ }
+ }
+ return output;
+ }
+};
+
+/**
+ * TBaseValidator serves as the base class for validator controls.
+ *
+ * <p>Validation is performed when a postback control, such as a TButton,
+ * a TLinkButton or a TTextBox (under AutoPostBack mode) is submitting
+ * the page and its <tt>CausesValidation</tt> option is true.
+ * The input control to be validated is specified by <tt>ControlToValidate</tt>
+ * option.</p>
+ *
+ * @class Prado.WebUI.TBaseValidator
+ */
+Prado.WebUI.TBaseValidator = Class.create(Prado.WebUI.Control,
+{
+ /**
+ * Initialize TBaseValidator.
+ * @constructor {protected} ?
+ * @param {object} options - Options for initialization.
+ * @... {string} ID - ID of validator
+ * @... {string} FormID - ID of form of this manager.
+ * @... {string} ControlToValidate - ID of control to validate.
+ * @... {optional string} InitialValue - Initial value of control to validate.
+ * @... {optional string} ErrorMessage - Validation error message.
+ * @... {optional string} ValidationGroup - ID of ValidationGroup.
+ * @... {optional string} Display - Display mode, 'None', 'Fixed', 'Dynamic'.
+ * @... {optional boolean} ObserveChanges - True to observer changes of ControlToValidate
+ * @... {optional boolean} FocusOnError - True to focus on validation error.
+ * @... {optional string} FocusElementID - ID of element to focus on error.
+ * @... {optional string} ControlCssClass - Css class to use on ControlToValidate on error
+ * @... {optional function} OnValidate - Called immediately after validation.
+ * @... {optional function} OnValidationSuccess - Called after successful validation.
+ * @... {optional function} OnValidationError - Called after validation error.
+ */
+ initialize : function(options)
+ {
+ this.observers = new Array();
+ this.intervals = new Array();
+
+ /* options.OnValidate = options.OnValidate || Prototype.emptyFunction;
+ options.OnSuccess = options.OnSuccess || Prototype.emptyFunction;
+ options.OnError = options.OnError || Prototype.emptyFunction;
+ */
+ /**
+ * Wether the validator is enabled (default true)
+ * @var {boolean} enabled
+ */
+ this.enabled = options.Enabled;
+ /**
+ * Visibility state of validator(default false)
+ * @var {boolean} visible
+ */
+ this.visible = false;
+ /**
+ * State of validation (default true)
+ * @var {boolean} isValid
+ */
+ this.isValid = true;
+ /**
+ * DOM elements that are observed by this validator
+ * @var {private element[]} _isObserving
+ */
+ this._isObserving = {};
+ /**
+ * ValidationGroup
+ * @var {string} group
+ */
+ this.group = null;
+ /**
+ * Wether a request was dispatched (default false)
+ * @var {boolean} requestDispatched
+ */
+ this.requestDispatched = false;
+
+ /**
+ * Validator options
+ * @var {object} options
+ */
+ this.options = options;
+ /**
+ * DOM element of control to validate
+ * @var {element} control
+ */
+ this.control = $(options.ControlToValidate);
+ /**
+ * DOM element of validator
+ * @var {element} message
+ */
+ this.message = $(options.ID);
+
+ Prado.Registry.set(options.ID, this);
+
+ if (this.onInit) this.onInit();
+
+ if(this.control && this.message)
+ {
+ this.group = options.ValidationGroup;
+
+ /**
+ * ValidationManager of this validator
+ * @var {ValidationManager} manager
+ */
+ this.manager = Prado.Validation.addValidator(options.FormID, this);
+ }
+ },
+
+ /**
+ * Get error message.
+ * @function {string} ?
+ * @return Validation error message.
+ */
+ getErrorMessage : function()
+ {
+ return this.options.ErrorMessage;
+ },
+
+ /**
+ * Update the validator.
+ * Updating the validator control will set the validator
+ * <tt>visible</tt> property to true.
+ * @function ?
+ */
+ updateControl: function()
+ {
+ this.refreshControlAndMessage();
+
+ //if(this.options.FocusOnError && !this.isValid )
+ // Prado.Element.focus(this.options.FocusElementID);
+
+ this.visible = true;
+ },
+
+ /**
+ * Updates span and input CSS class.
+ * @function ?
+ */
+ refreshControlAndMessage : function()
+ {
+ this.visible = true;
+ if(this.message)
+ {
+ if(this.options.Display == "Dynamic")
+ {
+ var msg=this.message;
+ this.isValid ? setTimeout(function() { msg.hide(); }, 250) : msg.show();
+ }
+ this.message.style.visibility = this.isValid ? "hidden" : "visible";
+ }
+ if(this.control)
+ this.updateControlCssClass(this.control, this.isValid);
+ },
+
+ /**
+ * Update CSS class of control to validate.
+ * Add a css class to the input control if validator is invalid,
+ * removes the css class if valid.
+ * @function ?
+ * @param {element} control - DOM element of control to validate
+ * @param {boolean} valid - Validation state of control
+ */
+ updateControlCssClass : function(control, valid)
+ {
+ var CssClass = this.options.ControlCssClass;
+ if(typeof(CssClass) == "string" && CssClass.length > 0)
+ {
+ if(valid)
+ {
+ if (control.lastValidator == this.options.ID)
+ {
+ control.lastValidator = null;
+ control.removeClassName(CssClass);
+ }
+ }
+ else
+ {
+ control.lastValidator = this.options.ID;
+ control.addClassName(CssClass);
+ }
+ }
+ },
+
+ /**
+ * Hide the validator messages and remove any validation changes.
+ * @function ?
+ */
+ hide : function()
+ {
+ this.reset();
+ this.visible = false;
+ },
+
+ /**
+ * Reset validator.
+ * Sets isValid = true and updates the validator display.
+ * @function ?
+ */
+ reset : function()
+ {
+ this.isValid = true;
+ this.updateControl();
+ },
+
+ /**
+ * Perform validation.
+ * Calls evaluateIsValid() function to set the value of isValid property.
+ * Triggers onValidate event and onSuccess or onError event.
+ * @function {boolean} ?
+ * @param {element} invoker - DOM element that triggered validation
+ * @return Valdation state of control.
+ */
+ validate : function(invoker)
+ {
+ //try to find the control.
+ if(!this.control)
+ this.control = $(this.options.ControlToValidate);
+
+ if(!this.control || this.control.disabled)
+ {
+ this.isValid = true;
+ return this.isValid;
+ }
+
+ if(typeof(this.options.OnValidate) == "function")
+ {
+ if(this.requestDispatched == false)
+ this.options.OnValidate(this, invoker);
+ }
+
+ if(this.enabled && !this.control.getAttribute('disabled'))
+ this.isValid = this.evaluateIsValid();
+ else
+ this.isValid = true;
+
+ this.updateValidationDisplay(invoker);
+ this.observeChanges(this.control);
+
+ return this.isValid;
+ },
+
+ /**
+ * Update validation display.
+ * Updates the validation messages and the control to validate.
+ * @param {element} invoker - DOM element that triggered validation
+ */
+ updateValidationDisplay : function(invoker)
+ {
+ if(this.isValid)
+ {
+ if(typeof(this.options.OnValidationSuccess) == "function")
+ {
+ if(this.requestDispatched == false)
+ {
+ this.refreshControlAndMessage();
+ this.options.OnValidationSuccess(this, invoker);
+ }
+ }
+ else
+ this.updateControl();
+ }
+ else
+ {
+ if(typeof(this.options.OnValidationError) == "function")
+ {
+ if(this.requestDispatched == false)
+ {
+ this.refreshControlAndMessage();
+ this.options.OnValidationError(this, invoker)
+ }
+ }
+ else
+ this.updateControl();
+ }
+ },
+
+ /**
+ * Add control to observe for changes.
+ * Re-validates upon change. If the validator is not visible,
+ * no updates are propagated.
+ * @function ?
+ * @param {element} control - DOM element of control to observe
+ */
+ observeChanges : function(control)
+ {
+ if(!control) return;
+
+ var canObserveChanges = this.options.ObserveChanges != false;
+ var currentlyObserving = this._isObserving[control.id+this.options.ID];
+
+ if(canObserveChanges && !currentlyObserving)
+ {
+ var validator = this;
+
+ this.observe(control, 'change', function()
+ {
+ if(validator.visible)
+ {
+ validator.validate();
+ validator.manager.updateSummary(validator.group);
+ }
+ });
+ this._isObserving[control.id+this.options.ID] = true;
+ }
+ },
+
+ /**
+ * Trim a string.
+ * @function {string} ?
+ * @param {string} value - String that should be trimmed.
+ * @return Trimmed string, empty string if value is not string.
+ */
+ trim : function(value)
+ {
+ return typeof(value) == "string" ? value.trim() : "";
+ },
+
+ /**
+ * Convert the value to a specific data type.
+ * @function {mixed|null} ?
+ * @param {string} dataType - Data type: "Integer", "Double", "Date" or "String"
+ * @param {mixed} value - Value to convert.
+ * @return Converted data value.
+ */
+ convert : function(dataType, value)
+ {
+ if(typeof(value) == "undefined")
+ value = this.getValidationValue();
+ var string = new String(value);
+ switch(dataType)
+ {
+ case "Integer":
+ return string.toInteger();
+ case "Double" :
+ case "Float" :
+ return string.toDouble(this.options.DecimalChar);
+ case "Date":
+ if(typeof(value) != "string")
+ return value;
+ else
+ {
+ var value = string.toDate(this.options.DateFormat);
+ if(value && typeof(value.getTime) == "function")
+ return value.getTime();
+ else
+ return null;
+ }
+ case "String":
+ return string.toString();
+ }
+ return value;
+ },
+
+ /**
+ * Get value that should be validated.
+ * The ControlType property comes from TBaseValidator::getClientControlClass()
+ * Be sure to update the TBaseValidator::$_clientClass if new cases are added.
+ * @function {mixed} ?
+ * @param {optional element} control - Control to get value from (default: this.control)
+ * @return Control value to validate
+ */
+ getRawValidationValue : function(control)
+ {
+ if(!control)
+ control = this.control
+ switch(this.options.ControlType)
+ {
+ case 'TDatePicker':
+ if(control.type == "text")
+ {
+ var value = this.trim($F(control));
+
+ if(this.options.DateFormat)
+ {
+ var date = value.toDate(this.options.DateFormat);
+ return date == null ? value : date;
+ }
+ else
+ return value;
+ }
+ else
+ {
+ this.observeDatePickerChanges();
+
+ return Prado.WebUI.TDatePicker.getDropDownDate(control);//.getTime();
+ }
+ case 'THtmlArea':
+ if(typeof tinyMCE != "undefined")
+ tinyMCE.triggerSave();
+ return $F(control);
+ case 'TRadioButton':
+ if(this.options.GroupName)
+ return this.getRadioButtonGroupValue();
+ default:
+ if(this.isListControlType())
+ return this.getFirstSelectedListValue();
+ else
+ return $F(control);
+ }
+ },
+
+ /**
+ * Get a trimmed value that should be validated.
+ * The ControlType property comes from TBaseValidator::getClientControlClass()
+ * Be sure to update the TBaseValidator::$_clientClass if new cases are added.
+ * @function {mixed} ?
+ * @param {optional element} control - Control to get value fron (default: this.control)
+ * @return Control value to validate
+ */
+ getValidationValue : function(control)
+ {
+ var value = this.getRawValidationValue(control);
+ if(!control)
+ control = this.control
+ switch(this.options.ControlType)
+ {
+ case 'TDatePicker':
+ return value;
+ case 'THtmlArea':
+ return this.trim(value);
+ case 'TRadioButton':
+ return value;
+ default:
+ if(this.isListControlType())
+ return value;
+ else
+ return this.trim(value);
+ }
+ },
+
+ /**
+ * Get value of radio button group
+ * @function {string} ?
+ * @return Value of a radio button group
+ */
+ getRadioButtonGroupValue : function()
+ {
+ var name = this.control.name;
+ var value = "";
+ $A(document.getElementsByName(name)).each(function(el)
+ {
+ if(el.checked)
+ value = el.value;
+ });
+ return value;
+ },
+
+ /**
+ * Observe changes in the drop down list date picker, IE only.
+ * @function ?
+ */
+ observeDatePickerChanges : function()
+ {
+ if(Prado.Browser().ie)
+ {
+ var DatePicker = Prado.WebUI.TDatePicker;
+ this.observeChanges(DatePicker.getDayListControl(this.control));
+ this.observeChanges(DatePicker.getMonthListControl(this.control));
+ this.observeChanges(DatePicker.getYearListControl(this.control));
+ }
+ },
+
+ /**
+ * Gets number of selections and their values.
+ * @function {object} ?
+ * @param {element[]} elements - Elements to get values from.
+ * @param {string} initialValue - Initial value of element
+ * @return Object:
+ * @... {mixed[]} values - Array of selected values
+ * @... {int} checks - Number of selections
+ */
+ getSelectedValuesAndChecks : function(elements, initialValue)
+ {
+ var checked = 0;
+ var values = [];
+ var isSelected = this.isCheckBoxType(elements[0]) ? 'checked' : 'selected';
+ elements.each(function(element)
+ {
+ if(element[isSelected] && element.value != initialValue)
+ {
+ checked++;
+ values.push(element.value);
+ }
+ });
+ return {'checks' : checked, 'values' : values};
+ },
+
+ /**
+ * Get list elements of TCheckBoxList or TListBox.
+ * Gets an array of the list control item input elements, for TCheckBoxList
+ * checkbox input elements are returned, for TListBox HTML option elements
+ * are returned.
+ * @function {element[]} ?
+ * @return Array of list control option DOM elements.
+ */
+ getListElements : function()
+ {
+ switch(this.options.ControlType)
+ {
+ case 'TCheckBoxList': case 'TRadioButtonList':
+ var elements = [];
+ for(var i = 0; i < this.options.TotalItems; i++)
+ {
+ var element = $(this.options.ControlToValidate+"_c"+i);
+ if(this.isCheckBoxType(element))
+ elements.push(element);
+ }
+ return elements;
+ case 'TListBox':
+ var elements = [];
+ var element = $(this.options.ControlToValidate);
+ var type;
+ if(element && (type = element.type.toLowerCase()))
+ {
+ if(type == "select-one" || type == "select-multiple")
+ elements = $A(element.options);
+ }
+ return elements;
+ default:
+ return [];
+ }
+ },
+
+ /**
+ * Check if control is of type checkbox or radio.
+ * @function {boolean} ?
+ * @param {element} element - DOM element to check.
+ * @return True if element is of checkbox or radio type.
+ */
+ isCheckBoxType : function(element)
+ {
+ if(element && element.type)
+ {
+ var type = element.type.toLowerCase();
+ return type == "checkbox" || type == "radio";
+ }
+ return false;
+ },
+
+ /**
+ * Check if control to validate is a TListControl type.
+ * @function {boolean} ?
+ * @return True if control to validate is a TListControl type.
+ */
+ isListControlType : function()
+ {
+ var list = ['TCheckBoxList', 'TRadioButtonList', 'TListBox'];
+ return list.include(this.options.ControlType);
+ },
+
+ /**
+ * Get first selected list value or initial value if none found.
+ * @function {string} ?
+ * @return First selected list value, initial value if none found.
+ */
+ getFirstSelectedListValue : function()
+ {
+ var initial = "";
+ if(typeof(this.options.InitialValue) != "undefined")
+ initial = this.options.InitialValue;
+ var elements = this.getListElements();
+ var selection = this.getSelectedValuesAndChecks(elements, initial);
+ return selection.values.length > 0 ? selection.values[0] : initial;
+ }
+});
+
+
+/**
+ * TRequiredFieldValidator makes the associated input control a required field.
+ *
+ * <p>The input control fails validation if its value does not change from
+ * the <tt>InitialValue</tt> option upon losing focus.</p>
+ *
+ * @class Prado.WebUI.TRequiredFieldValidator
+ * @extends Prado.WebUI.TBaseValidator
+ */
+Prado.WebUI.TRequiredFieldValidator = Class.extend(Prado.WebUI.TBaseValidator,
+{
+ /**
+ * Evaluate validation state
+ * @function {boolean} ?
+ * @return True if the input value is not empty nor equal to the initial value.
+ */
+ evaluateIsValid : function()
+ {
+ var a = this.getValidationValue();
+ var b = this.trim(this.options.InitialValue);
+ return(a != b);
+ }
+});
+
+
+/**
+ * TCompareValidator compares the value entered by the user into an input
+ * control with the value entered into another input control or a constant value.
+ *
+ * <p>To compare the associated input control with another input control,
+ * set the <tt>ControlToCompare</tt> option to the ID path
+ * of the control to compare with. To compare the associated input control with
+ * a constant value, specify the constant value to compare with by setting the
+ * <tt>ValueToCompare</tt> option.</p>
+ *
+ * <p>The <tt>DataType</tt> property is used to specify the data type
+ * of both comparison values. Both values are automatically converted to this data
+ * type before the comparison operation is performed. The following value types are supported:
+ * - <b>Integer</b> A 32-bit signed integer data type.
+ * - <b>Float</b> A double-precision floating point number data type.
+ * - <b>Date</b> A date data type. The format can be set by the <tt>DateFormat</tt> option.
+ * - <b>String</b> A string data type.</p>
+ *
+ * Use the <tt>Operator</tt> property to specify the type of comparison
+ * to perform. Valid operators include Equal, NotEqual, GreaterThan, GreaterThanEqual,
+ * LessThan and LessThanEqual.
+ *
+ * @class Prado.WebUI.TCompareValidator
+ * @extends Prado.WebUI.TBaseValidator
+ */
+Prado.WebUI.TCompareValidator = Class.extend(Prado.WebUI.TBaseValidator,
+{
+ /**
+ * Additional constructor options.
+ * @constructor initialize
+ * @param {object} options - Additional constructor options:
+ * @... {string} ControlToCompare - Control with compare value.
+ * @... {string} ValueToCompare - Value to compare.
+ * @... {string} Operator - Type of comparison: "Equal", "NotEqual", "GreaterThan",
+ * "GreaterThanEqual", "LessThan" or "LessThanEqual".
+ * @... {string} Type - Type of values: "Integer", "Float", "Date" or "String".
+ * @... {string} DateFormat - Valid date format.
+ */
+
+ //_observingComparee : false,
+
+ /**
+ * Evaluate validation state
+ * @function {boolean} ?
+ * @return True if comparision condition is met.
+ */
+ evaluateIsValid : function()
+ {
+ var value = this.getValidationValue();
+ if (value.length <= 0)
+ return true;
+
+ var comparee = $(this.options.ControlToCompare);
+
+ if(comparee)
+ var compareTo = this.getValidationValue(comparee);
+ else
+ var compareTo = this.options.ValueToCompare || "";
+
+ var isValid = this.compare(value, compareTo);
+
+ if(comparee)
+ {
+ this.updateControlCssClass(comparee, isValid);
+ this.observeChanges(comparee);
+ }
+ return isValid;
+ },
+
+ /**
+ * Compare two operands.
+ * The operand values are casted to type defined
+ * by <tt>DataType</tt> option. False is returned if the first
+ * operand converts to null. Returns true if the second operand
+ * converts to null. The comparision is done based on the
+ * <tt>Operator</tt> option.
+ * @function ?
+ * @param {mixed} operand1 - First operand.
+ * @param {mixed} operand2 - Second operand.
+ */
+ compare : function(operand1, operand2)
+ {
+ var op1, op2;
+ if((op1 = this.convert(this.options.DataType, operand1)) == null)
+ return false;
+ if ((op2 = this.convert(this.options.DataType, operand2)) == null)
+ return true;
+ switch (this.options.Operator)
+ {
+ case "NotEqual":
+ return (op1 != op2);
+ case "GreaterThan":
+ return (op1 > op2);
+ case "GreaterThanEqual":
+ return (op1 >= op2);
+ case "LessThan":
+ return (op1 < op2);
+ case "LessThanEqual":
+ return (op1 <= op2);
+ default:
+ return (op1 == op2);
+ }
+ }
+});
+
+/**
+ * TCustomValidator performs user-defined client-side validation on an
+ * input component.
+ *
+ * <p>To create a client-side validation function, add the client-side
+ * validation javascript function to the page template.
+ * The function should have the following signature:</p>
+ *
+ * <pre>
+ * &lt;script type="text/javascript"&gt;
+ * function ValidationFunctionName(sender, parameter)
+ * {
+ * if(parameter == ...)
+ * return true;
+ * else
+ * return false;
+ * }
+ * &lt;/script&gt;
+ * </pre>
+ *
+ * <p>Use the <tt>ClientValidationFunction</tt> option
+ * to specify the name of the client-side validation script function associated
+ * with the TCustomValidator.</p>
+ *
+ * @class Prado.WebUI.TCustomValidator
+ * @extends Prado.WebUI.TBaseValidator
+ */
+Prado.WebUI.TCustomValidator = Class.extend(Prado.WebUI.TBaseValidator,
+{
+ /**
+ * Additional constructor options.
+ * @constructor initialize
+ * @param {object} options - Additional constructor options:
+ * @... {function} ClientValidationFunction - Custom validation function.
+ */
+
+ /**
+ * Evaluate validation state
+ * Returns true if no valid custom validation function is present.
+ * @function {boolean} ?
+ * @return True if custom validation returned true.
+ */
+ evaluateIsValid : function()
+ {
+ var value = this.getValidationValue();
+ var clientFunction = this.options.ClientValidationFunction;
+ if(typeof(clientFunction) == "string" && clientFunction.length > 0)
+ {
+ var validate = clientFunction.toFunction();
+ return validate(this, value);
+ }
+ return true;
+ }
+});
+
+/**
+ * Uses callback request to perform validation.
+ *
+ * @class Prado.WebUI.TActiveCustomValidator
+ * @extends Prado.WebUI.TBaseValidator
+ */
+Prado.WebUI.TActiveCustomValidator = Class.extend(Prado.WebUI.TBaseValidator,
+{
+ /**
+ * Override the parent implementation to store the invoker, in order to
+ * re-validate after the callback has returned
+ * Calls evaluateIsValid() function to set the value of isValid property.
+ * Triggers onValidate event and onSuccess or onError event.
+ * @function {boolean} ?
+ * @param {element} invoker - DOM element that triggered validation
+ * @return True if valid.
+ */
+ validate : function(invoker)
+ {
+ this.invoker = invoker;
+
+ //try to find the control.
+ if(!this.control)
+ this.control = $(this.options.ControlToValidate);
+
+ if(!this.control || this.control.disabled)
+ {
+ this.isValid = true;
+ return this.isValid;
+ }
+
+ if(typeof(this.options.OnValidate) == "function")
+ {
+ if(this.requestDispatched == false)
+ this.options.OnValidate(this, invoker);
+ }
+
+ return true;
+ },
+
+ /**
+ * Send CallBack to start serverside validation.
+ * @function {boolean} ?
+ * @return True if valid.
+ */
+ evaluateIsValid : function()
+ {
+ return this.isValid;
+ },
+
+ /**
+ * Parse CallBack response data on success.
+ * @function ?
+ * @param {CallbackRequest} request - CallbackRequest.
+ * @param {string} data - Response data.
+ */
+ updateIsValid : function(data)
+ {
+ this.isValid = data;
+ this.requestDispatched = false;
+ if(typeof(this.options.onSuccess) == "function")
+ this.options.onSuccess(null,data);
+ this.updateValidationDisplay();
+ this.manager.updateSummary(this.group);
+ }
+});
+
+/**
+ * TRangeValidator tests whether an input value is within a specified range.
+ *
+ * <p>TRangeValidator uses three key properties to perform its validation.</p>
+ *
+ * <p>The <tt>MinValue</tt> and <tt>MaxValue</tt> options specify the minimum
+ * and maximum values of the valid range.</p>
+ * <p>The <tt>DataType</tt> option is
+ * used to specify the data type of the value and the minimum and maximum range values.
+ * The values are converted to this data type before the validation
+ * operation is performed. The following value types are supported:</p>
+ *
+ * - <b>Integer</b> A 32-bit signed integer data type.<br />
+ * - <b>Float</b> A double-precision floating point number data type.<br />
+ * - <b>Date</b> A date data type. The date format can be specified by<br />
+ * setting <tt>DateFormat</tt> option, which must be recognizable
+ * by <tt>Date.SimpleParse</tt> javascript function.
+ * - <b>String</b> A string data type.
+ *
+ * @class Prado.WebUI.TRangeValidator
+ * @extends Prado.WebUI.TBaseValidator
+ */
+Prado.WebUI.TRangeValidator = Class.extend(Prado.WebUI.TBaseValidator,
+{
+ /**
+ * Additional constructor options.
+ * @constructor initialize
+ * @param {object} options - Additional constructor options:
+ * @... {string} MinValue - Minimum range value
+ * @... {string} MaxValue - Maximum range value
+ * @... {string} DataType - Value data type: "Integer", "Float", "Date" or "String"
+ * @... {string} DateFormat - Date format for data type Date.
+ */
+
+ /**
+ * Evaluate validation state
+ * @function {boolean} ?
+ * @return True if value is in range or value is empty,
+ * false otherwhise and when type conversion failed.
+ */
+ evaluateIsValid : function()
+ {
+ var value = this.getValidationValue();
+ if(value.length <= 0)
+ return true;
+ if(typeof(this.options.DataType) == "undefined")
+ this.options.DataType = "String";
+
+ if(this.options.DataType != "StringLength")
+ {
+ var min = this.convert(this.options.DataType, this.options.MinValue || null);
+ var max = this.convert(this.options.DataType, this.options.MaxValue || null);
+ value = this.convert(this.options.DataType, value);
+ }
+ else
+ {
+ var min = this.options.MinValue || 0;
+ var max = this.options.MaxValue || Number.POSITIVE_INFINITY;
+ value = value.length;
+ }
+
+ if(value == null)
+ return false;
+
+ var valid = true;
+
+ if(min != null)
+ valid = valid && (this.options.StrictComparison ? value > min : value >= min);
+ if(max != null)
+ valid = valid && (this.options.StrictComparison ? value < max : value <= max);
+ return valid;
+ }
+});
+
+/**
+ * TRegularExpressionValidator validates whether the value of an associated
+ * input component matches the pattern specified by a regular expression.
+ *
+ * @class Prado.WebUI.TRegularExpressionValidator
+ * @extends Prado.WebUI.TBaseValidator
+ */
+Prado.WebUI.TRegularExpressionValidator = Class.extend(Prado.WebUI.TBaseValidator,
+{
+ /**
+ * Additional constructor option.
+ * @constructor initialize
+ * @param {object} options - Additional constructor option:
+ * @... {string} ValidationExpression - Regular expression to match against.
+ * @... {string} PatternModifiers - Pattern modifiers: combinations of g, i, and m
+ */
+
+ /**
+ * Evaluate validation state
+ * @function {boolean} ?
+ * @return True if value matches regular expression or value is empty.
+ */
+ evaluateIsValid : function()
+ {
+ var value = this.getRawValidationValue();
+ if (value.length <= 0)
+ return true;
+
+ var rx = new RegExp('^'+this.options.ValidationExpression+'$',this.options.PatternModifiers);
+ var matches = rx.exec(value);
+ return (matches != null && value == matches[0]);
+ }
+});
+
+/**
+ * TEmailAddressValidator validates whether the value of an associated
+ * input component is a valid email address.
+ *
+ * @class Prado.WebUI.TEmailAddressValidator
+ * @extends Prado.WebUI.TRegularExpressionValidator
+ */
+Prado.WebUI.TEmailAddressValidator = Prado.WebUI.TRegularExpressionValidator;
+
+
+/**
+ * TListControlValidator checks the number of selection and their values
+ * for a TListControl that allows multiple selections.
+ *
+ * @class Prado.WebUI.TListControlValidator
+ * @extends Prado.WebUI.TBaseValidator
+ */
+Prado.WebUI.TListControlValidator = Class.extend(Prado.WebUI.TBaseValidator,
+{
+ /**
+ * Evaluate validation state
+ * @function {boolean} ?
+ * @return True if number of selections and/or their values match requirements.
+ */
+ evaluateIsValid : function()
+ {
+ var elements = this.getListElements();
+ if(elements && elements.length <= 0)
+ return true;
+
+ this.observeListElements(elements);
+
+ var selection = this.getSelectedValuesAndChecks(elements);
+ return this.isValidList(selection.checks, selection.values);
+ },
+
+ /**
+ * Observe list elements for of changes (only IE)
+ * @function ?
+ * @param {element[]} elements - Array of DOM elements to observe
+ */
+ observeListElements : function(elements)
+ {
+ if(Prado.Browser().ie && this.isCheckBoxType(elements[0]))
+ {
+ var validator = this;
+ elements.each(function(element)
+ {
+ validator.observeChanges(element);
+ });
+ }
+ },
+
+ /**
+ * Check if list is valid.
+ * Determine if the number of checked values and the checked values
+ * satisfy the required number of checks and/or the checked values
+ * equal to the required values.
+ * @function {boolean} ?
+ * @param {int} checked - Number of required checked values
+ * @param {string[]} values - Array of required checked values
+ * @return True if checked values and number of checks are satisfied.
+ */
+ isValidList : function(checked, values)
+ {
+ var exists = true;
+
+ //check the required values
+ var required = this.getRequiredValues();
+ if(required.length > 0)
+ {
+ if(values.length < required.length)
+ return false;
+ required.each(function(requiredValue)
+ {
+ exists = exists && values.include(requiredValue);
+ });
+ }
+
+ var min = typeof(this.options.Min) == "undefined" ?
+ Number.NEGATIVE_INFINITY : this.options.Min;
+ var max = typeof(this.options.Max) == "undefined" ?
+ Number.POSITIVE_INFINITY : this.options.Max;
+ return exists && checked >= min && checked <= max;
+ },
+
+ /**
+ * Get list of required values.
+ * @function {string[]} ?
+ * @return Array of required values that must be selected.
+ */
+ getRequiredValues : function()
+ {
+ var required = [];
+ if(this.options.Required && this.options.Required.length > 0)
+ required = this.options.Required.split(/,\s*/);
+ return required;
+ }
+});
+
+
+/**
+ * TDataTypeValidator verifies if the input data is of the type specified
+ * by <tt>DataType</tt> option.
+ *
+ * <p>The following data types are supported:</p>
+ *
+ * - <b>Integer</b> A 32-bit signed integer data type.<br />
+ * - <b>Float</b> A double-precision floating point number data type.<br />
+ * - <b>Date</b> A date data type.<br />
+ * - <b>String</b> A string data type.<br />
+ *
+ * <p>For <b>Date</b> type, the option <tt>DateFormat</tt>
+ * will be used to determine how to parse the date string.</p>
+ *
+ * @class Prado.WebUI.TDataTypeValidator
+ * @extends Prado.WebUI.TBaseValidator
+ */
+Prado.WebUI.TDataTypeValidator = Class.extend(Prado.WebUI.TBaseValidator,
+{
+ /**
+ * Additional constructor option.
+ * @constructor initialize
+ * @param {object} options - Additional constructor option:
+ * @... {string} DataType - Value data type: "Integer", "Float", "Date" or "String"
+ * @... {string} DateFormat - Date format for data type Date.
+ */
+
+ /**
+ * Evaluate validation state
+ * @function {boolean} ?
+ * @return True if value matches required data type.
+ */
+ evaluateIsValid : function()
+ {
+ var value = this.getValidationValue();
+ if(value.length <= 0)
+ return true;
+ return this.convert(this.options.DataType, value) != null;
+ }
+});
+
+/**
+ * TCaptchaValidator verifies if the input data is the same as
+ * the token shown in the associated CAPTCHA control.
+ *
+ * @class Prado.WebUI.TCaptchaValidator
+ * @extends Prado.WebUI.TBaseValidator
+ */
+Prado.WebUI.TCaptchaValidator = Class.extend(Prado.WebUI.TBaseValidator,
+{
+ /**
+ * Evaluate validation state
+ * @function {boolean} ?
+ * @return True if value matches captcha text
+ */
+ evaluateIsValid : function()
+ {
+ var a = this.getValidationValue();
+ var h = 0;
+ if (this.options.CaseSensitive==false)
+ a = a.toUpperCase();
+ for(var i = a.length-1; i >= 0; --i)
+ h += a.charCodeAt(i);
+ return h == this.options.TokenHash;
+ },
+
+ crc32 : function(str)
+ {
+ function Utf8Encode(string)
+ {
+ string = string.replace(/\r\n/g,"\n");
+ var utftext = "";
+
+ for (var n = 0; n < string.length; n++)
+ {
+ var c = string.charCodeAt(n);
+
+ if (c < 128) {
+ utftext += String.fromCharCode(c);
+ }
+ else if((c > 127) && (c < 2048)) {
+ utftext += String.fromCharCode((c >> 6) | 192);
+ utftext += String.fromCharCode((c & 63) | 128);
+ }
+ else {
+ utftext += String.fromCharCode((c >> 12) | 224);
+ utftext += String.fromCharCode(((c >> 6) & 63) | 128);
+ utftext += String.fromCharCode((c & 63) | 128);
+ }
+ }
+
+ return utftext;
+ };
+
+ str = Utf8Encode(str);
+
+ var table = "00000000 77073096 EE0E612C 990951BA 076DC419 706AF48F E963A535 9E6495A3 0EDB8832 79DCB8A4 E0D5E91E 97D2D988 09B64C2B 7EB17CBD E7B82D07 90BF1D91 1DB71064 6AB020F2 F3B97148 84BE41DE 1ADAD47D 6DDDE4EB F4D4B551 83D385C7 136C9856 646BA8C0 FD62F97A 8A65C9EC 14015C4F 63066CD9 FA0F3D63 8D080DF5 3B6E20C8 4C69105E D56041E4 A2677172 3C03E4D1 4B04D447 D20D85FD A50AB56B 35B5A8FA 42B2986C DBBBC9D6 ACBCF940 32D86CE3 45DF5C75 DCD60DCF ABD13D59 26D930AC 51DE003A C8D75180 BFD06116 21B4F4B5 56B3C423 CFBA9599 B8BDA50F 2802B89E 5F058808 C60CD9B2 B10BE924 2F6F7C87 58684C11 C1611DAB B6662D3D 76DC4190 01DB7106 98D220BC EFD5102A 71B18589 06B6B51F 9FBFE4A5 E8B8D433 7807C9A2 0F00F934 9609A88E E10E9818 7F6A0DBB 086D3D2D 91646C97 E6635C01 6B6B51F4 1C6C6162 856530D8 F262004E 6C0695ED 1B01A57B 8208F4C1 F50FC457 65B0D9C6 12B7E950 8BBEB8EA FCB9887C 62DD1DDF 15DA2D49 8CD37CF3 FBD44C65 4DB26158 3AB551CE A3BC0074 D4BB30E2 4ADFA541 3DD895D7 A4D1C46D D3D6F4FB 4369E96A 346ED9FC AD678846 DA60B8D0 44042D73 33031DE5 AA0A4C5F DD0D7CC9 5005713C 270241AA BE0B1010 C90C2086 5768B525 206F85B3 B966D409 CE61E49F 5EDEF90E 29D9C998 B0D09822 C7D7A8B4 59B33D17 2EB40D81 B7BD5C3B C0BA6CAD EDB88320 9ABFB3B6 03B6E20C 74B1D29A EAD54739 9DD277AF 04DB2615 73DC1683 E3630B12 94643B84 0D6D6A3E 7A6A5AA8 E40ECF0B 9309FF9D 0A00AE27 7D079EB1 F00F9344 8708A3D2 1E01F268 6906C2FE F762575D 806567CB 196C3671 6E6B06E7 FED41B76 89D32BE0 10DA7A5A 67DD4ACC F9B9DF6F 8EBEEFF9 17B7BE43 60B08ED5 D6D6A3E8 A1D1937E 38D8C2C4 4FDFF252 D1BB67F1 A6BC5767 3FB506DD 48B2364B D80D2BDA AF0A1B4C 36034AF6 41047A60 DF60EFC3 A867DF55 316E8EEF 4669BE79 CB61B38C BC66831A 256FD2A0 5268E236 CC0C7795 BB0B4703 220216B9 5505262F C5BA3BBE B2BD0B28 2BB45A92 5CB36A04 C2D7FFA7 B5D0CF31 2CD99E8B 5BDEAE1D 9B64C2B0 EC63F226 756AA39C 026D930A 9C0906A9 EB0E363F 72076785 05005713 95BF4A82 E2B87A14 7BB12BAE 0CB61B38 92D28E9B E5D5BE0D 7CDCEFB7 0BDBDF21 86D3D2D4 F1D4E242 68DDB3F8 1FDA836E 81BE16CD F6B9265B 6FB077E1 18B74777 88085AE6 FF0F6A70 66063BCA 11010B5C 8F659EFF F862AE69 616BFFD3 166CCF45 A00AE278 D70DD2EE 4E048354 3903B3C2 A7672661 D06016F7 4969474D 3E6E77DB AED16A4A D9D65ADC 40DF0B66 37D83BF0 A9BCAE53 DEBB9EC5 47B2CF7F 30B5FFE9 BDBDF21C CABAC28A 53B39330 24B4A3A6 BAD03605 CDD70693 54DE5729 23D967BF B3667A2E C4614AB8 5D681B02 2A6F2B94 B40BBE37 C30C8EA1 5A05DF1B 2D02EF8D";
+ var crc = 0;
+ var x = 0;
+ var y = 0;
+
+ crc = crc ^ (-1);
+ for( var i = 0, iTop = str.length; i < iTop; i++ )
+ {
+ y = ( crc ^ str.charCodeAt( i ) ) & 0xFF;
+ x = "0x" + table.substr( y * 9, 8 );
+ crc = ( crc >>> 8 ) ^ x;
+ }
+ return crc ^ (-1);
+ }
+});
+
+
+/**
+ * TReCaptchaValidator client-side control.
+ *
+ * @class Prado.WebUI.TReCaptchaValidator
+ * @extends Prado.WebUI.TBaseValidator
+ */
+Prado.WebUI.TReCaptchaValidator = Class.create(Prado.WebUI.TBaseValidator,
+{
+ onInit : function()
+ {
+ var obj = this;
+ var elements = document.getElementsByName(this.options.ResponseFieldName);
+ if (elements)
+ if (elements.length>=1)
+ {
+ this.observe(elements[0],'change',function() { obj.responseChanged() });
+ this.observe(elements[0],'keydown',function() { obj.responseChanged() });
+ }
+ },
+
+ responseChanged: function()
+ {
+ var field = $(this.options.ID+'_1');
+ if (field.value=='1') return;
+ field.value = '1';
+ Prado.Validation.validateControl(this.options.ID);
+ },
+
+ /**
+ * Evaluate validation state
+ * @function {boolean} ?
+ * @return True if the captcha has validate, False otherwise.
+ */
+ evaluateIsValid : function()
+ {
+ return ($(this.options.ID+'_1').value=='1');
+ }
+});
+