diff options
author | wei <> | 2007-03-27 02:23:20 +0000 |
---|---|---|
committer | wei <> | 2007-03-27 02:23:20 +0000 |
commit | 1b9b64637fe08848f610bbd19b80c031cb7dba63 (patch) | |
tree | 52f7486e911f60c9a91904c91e3944f4f4f27bca /framework/Web/Javascripts/js/debug | |
parent | c5d0cd2824e3c3bb2f6f3834177a71c1d7b78519 (diff) |
set prado trunk to use prototype.js v1.5.1rc2, script.aculo.us to v1.7.1beta
Diffstat (limited to 'framework/Web/Javascripts/js/debug')
-rw-r--r-- | framework/Web/Javascripts/js/debug/ajax.js | 2474 | ||||
-rw-r--r-- | framework/Web/Javascripts/js/debug/clientscripts.php | 2 | ||||
-rw-r--r-- | framework/Web/Javascripts/js/debug/effects.js | 126 | ||||
-rw-r--r-- | framework/Web/Javascripts/js/debug/prado.js | 280 | ||||
-rw-r--r-- | framework/Web/Javascripts/js/debug/validator.js | 158 |
5 files changed, 2884 insertions, 156 deletions
diff --git a/framework/Web/Javascripts/js/debug/ajax.js b/framework/Web/Javascripts/js/debug/ajax.js new file mode 100644 index 00000000..60956194 --- /dev/null +++ b/framework/Web/Javascripts/js/debug/ajax.js @@ -0,0 +1,2474 @@ +// script.aculo.us controls.js v1.7.1_beta1, Mon Mar 12 14:40:50 +0100 2007 + +// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) +// (c) 2005-2007 Ivan Krstic (http://blogs.law.harvard.edu/ivan) +// (c) 2005-2007 Jon Tirsen (http://www.tirsen.com) +// Contributors: +// Richard Livsey +// Rahul Bhargava +// Rob Wills +// +// script.aculo.us is freely distributable under the terms of an MIT-style license. +// For details, see the script.aculo.us web site: http://script.aculo.us/ + +// Autocompleter.Base handles all the autocompletion functionality +// that's independent of the data source for autocompletion. This +// includes drawing the autocompletion menu, observing keyboard +// and mouse events, and similar. +// +// Specific autocompleters need to provide, at the very least, +// a getUpdatedChoices function that will be invoked every time +// the text inside the monitored textbox changes. This method +// should get the text for which to provide autocompletion by +// invoking this.getToken(), NOT by directly accessing +// this.element.value. This is to allow incremental tokenized +// autocompletion. Specific auto-completion logic (AJAX, etc) +// belongs in getUpdatedChoices. +// +// Tokenized incremental autocompletion is enabled automatically +// when an autocompleter is instantiated with the 'tokens' option +// in the options parameter, e.g.: +// new Ajax.Autocompleter('id','upd', '/url/', { tokens: ',' }); +// will incrementally autocomplete with a comma as the token. +// Additionally, ',' in the above example can be replaced with +// a token array, e.g. { tokens: [',', '\n'] } which +// enables autocompletion on multiple tokens. This is most +// useful when one of the tokens is \n (a newline), as it +// allows smart autocompletion after linebreaks. + +if(typeof Effect == 'undefined') + throw("controls.js requires including script.aculo.us' effects.js library"); + +var Autocompleter = {} +Autocompleter.Base = function() {}; +Autocompleter.Base.prototype = { + baseInitialize: function(element, update, options) { + this.element = $(element); + this.update = $(update); + this.hasFocus = false; + this.changed = false; + this.active = false; + this.index = 0; + this.entryCount = 0; + + if(this.setOptions) + this.setOptions(options); + else + this.options = options || {}; + + this.options.paramName = this.options.paramName || this.element.name; + this.options.tokens = this.options.tokens || []; + this.options.frequency = this.options.frequency || 0.4; + this.options.minChars = this.options.minChars || 1; + this.options.onShow = this.options.onShow || + function(element, update){ + if(!update.style.position || update.style.position=='absolute') { + update.style.position = 'absolute'; + Position.clone(element, update, { + setHeight: false, + offsetTop: element.offsetHeight + }); + } + Effect.Appear(update,{duration:0.15}); + }; + this.options.onHide = this.options.onHide || + function(element, update){ new Effect.Fade(update,{duration:0.15}) }; + + if(typeof(this.options.tokens) == 'string') + this.options.tokens = new Array(this.options.tokens); + + this.observer = null; + + this.element.setAttribute('autocomplete','off'); + + Element.hide(this.update); + + Event.observe(this.element, "blur", this.onBlur.bindAsEventListener(this)); + Event.observe(this.element, "keypress", this.onKeyPress.bindAsEventListener(this)); + }, + + show: function() { + if(Element.getStyle(this.update, 'display')=='none') this.options.onShow(this.element, this.update); + if(!this.iefix && + (Prototype.Browser.IE) && + (Element.getStyle(this.update, 'position')=='absolute')) { + new Insertion.After(this.update, + '<iframe id="' + this.update.id + '_iefix" '+ + 'style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" ' + + 'src="javascript:false;" frameborder="0" scrolling="no"></iframe>'); + this.iefix = $(this.update.id+'_iefix'); + } + if(this.iefix) setTimeout(this.fixIEOverlapping.bind(this), 50); + }, + + fixIEOverlapping: function() { + Position.clone(this.update, this.iefix, {setTop:(!this.update.style.height)}); + this.iefix.style.zIndex = 1; + this.update.style.zIndex = 2; + Element.show(this.iefix); + }, + + hide: function() { + this.stopIndicator(); + if(Element.getStyle(this.update, 'display')!='none') this.options.onHide(this.element, this.update); + if(this.iefix) Element.hide(this.iefix); + }, + + startIndicator: function() { + if(this.options.indicator) Element.show(this.options.indicator); + }, + + stopIndicator: function() { + if(this.options.indicator) Element.hide(this.options.indicator); + }, + + onKeyPress: function(event) { + if(this.active) + switch(event.keyCode) { + case Event.KEY_TAB: + case Event.KEY_RETURN: + this.selectEntry(); + Event.stop(event); + case Event.KEY_ESC: + this.hide(); + this.active = false; + Event.stop(event); + return; + case Event.KEY_LEFT: + case Event.KEY_RIGHT: + return; + case Event.KEY_UP: + this.markPrevious(); + this.render(); + if(Prototype.Browser.WebKit) Event.stop(event); + return; + case Event.KEY_DOWN: + this.markNext(); + this.render(); + if(Prototype.Browser.WebKit) Event.stop(event); + return; + } + else + if(event.keyCode==Event.KEY_TAB || event.keyCode==Event.KEY_RETURN || + (Prototype.Browser.WebKit > 0 && event.keyCode == 0)) return; + + this.changed = true; + this.hasFocus = true; + + if(this.observer) clearTimeout(this.observer); + this.observer = + setTimeout(this.onObserverEvent.bind(this), this.options.frequency*1000); + }, + + activate: function() { + this.changed = false; + this.hasFocus = true; + this.getUpdatedChoices(); + }, + + onHover: function(event) { + var element = Event.findElement(event, 'LI'); + if(this.index != element.autocompleteIndex) + { + this.index = element.autocompleteIndex; + this.render(); + } + Event.stop(event); + }, + + onClick: function(event) { + var element = Event.findElement(event, 'LI'); + this.index = element.autocompleteIndex; + this.selectEntry(); + this.hide(); + }, + + onBlur: function(event) { + // needed to make click events working + setTimeout(this.hide.bind(this), 250); + this.hasFocus = false; + this.active = false; + }, + + render: function() { + if(this.entryCount > 0) { + for (var i = 0; i < this.entryCount; i++) + this.index==i ? + Element.addClassName(this.getEntry(i),"selected") : + Element.removeClassName(this.getEntry(i),"selected"); + + if(this.hasFocus) { + this.show(); + this.active = true; + } + } else { + this.active = false; + this.hide(); + } + }, + + markPrevious: function() { + if(this.index > 0) this.index-- + else this.index = this.entryCount-1; + this.getEntry(this.index).scrollIntoView(true); + }, + + markNext: function() { + if(this.index < this.entryCount-1) this.index++ + else this.index = 0; + this.getEntry(this.index).scrollIntoView(false); + }, + + getEntry: function(index) { + return this.update.firstChild.childNodes[index]; + }, + + getCurrentEntry: function() { + return this.getEntry(this.index); + }, + + selectEntry: function() { + this.active = false; + this.updateElement(this.getCurrentEntry()); + }, + + updateElement: function(selectedElement) { + if (this.options.updateElement) { + this.options.updateElement(selectedElement); + return; + } + var value = ''; + if (this.options.select) { + var nodes = document.getElementsByClassName(this.options.select, selectedElement) || []; + if(nodes.length>0) value = Element.collectTextNodes(nodes[0], this.options.select); + } else + value = Element.collectTextNodesIgnoreClass(selectedElement, 'informal'); + + var lastTokenPos = this.findLastToken(); + if (lastTokenPos != -1) { + var newValue = this.element.value.substr(0, lastTokenPos + 1); + var whitespace = this.element.value.substr(lastTokenPos + 1).match(/^\s+/); + if (whitespace) + newValue += whitespace[0]; + this.element.value = newValue + value; + } else { + this.element.value = value; + } + this.element.focus(); + + if (this.options.afterUpdateElement) + this.options.afterUpdateElement(this.element, selectedElement); + }, + + updateChoices: function(choices) { + if(!this.changed && this.hasFocus) { + this.update.innerHTML = choices; + Element.cleanWhitespace(this.update); + Element.cleanWhitespace(this.update.down()); + + if(this.update.firstChild && this.update.down().childNodes) { + this.entryCount = + this.update.down().childNodes.length; + for (var i = 0; i < this.entryCount; i++) { + var entry = this.getEntry(i); + entry.autocompleteIndex = i; + this.addObservers(entry); + } + } else { + this.entryCount = 0; + } + + this.stopIndicator(); + this.index = 0; + + if(this.entryCount==1 && this.options.autoSelect) { + this.selectEntry(); + this.hide(); + } else { + this.render(); + } + } + }, + + addObservers: function(element) { + Event.observe(element, "mouseover", this.onHover.bindAsEventListener(this)); + Event.observe(element, "click", this.onClick.bindAsEventListener(this)); + }, + + onObserverEvent: function() { + this.changed = false; + if(this.getToken().length>=this.options.minChars) { + this.startIndicator(); + this.getUpdatedChoices(); + } else { + this.active = false; + this.hide(); + } + }, + + getToken: function() { + var tokenPos = this.findLastToken(); + if (tokenPos != -1) + var ret = this.element.value.substr(tokenPos + 1).replace(/^\s+/,'').replace(/\s+$/,''); + else + var ret = this.element.value; + + return /\n/.test(ret) ? '' : ret; + }, + + findLastToken: function() { + var lastTokenPos = -1; + + for (var i=0; i<this.options.tokens.length; i++) { + var thisTokenPos = this.element.value.lastIndexOf(this.options.tokens[i]); + if (thisTokenPos > lastTokenPos) + lastTokenPos = thisTokenPos; + } + return lastTokenPos; + } +} + +Ajax.Autocompleter = Class.create(); +Object.extend(Object.extend(Ajax.Autocompleter.prototype, Autocompleter.Base.prototype), { + initialize: function(element, update, url, options) { + this.baseInitialize(element, update, options); + this.options.asynchronous = true; + this.options.onComplete = this.onComplete.bind(this); + this.options.defaultParams = this.options.parameters || null; + this.url = url; + }, + + getUpdatedChoices: function() { + entry = encodeURIComponent(this.options.paramName) + '=' + + encodeURIComponent(this.getToken()); + + this.options.parameters = this.options.callback ? + this.options.callback(this.element, entry) : entry; + + if(this.options.defaultParams) + this.options.parameters += '&' + this.options.defaultParams; + + new Ajax.Request(this.url, this.options); + }, + + onComplete: function(request) { + this.updateChoices(request.responseText); + } + +}); + +// The local array autocompleter. Used when you'd prefer to +// inject an array of autocompletion options into the page, rather +// than sending out Ajax queries, which can be quite slow sometimes. +// +// The constructor takes four parameters. The first two are, as usual, +// the id of the monitored textbox, and id of the autocompletion menu. +// The third is the array you want to autocomplete from, and the fourth +// is the options block. +// +// Extra local autocompletion options: +// - choices - How many autocompletion choices to offer +// +// - partialSearch - If false, the autocompleter will match entered +// text only at the beginning of strings in the +// autocomplete array. Defaults to true, which will +// match text at the beginning of any *word* in the +// strings in the autocomplete array. If you want to +// search anywhere in the string, additionally set +// the option fullSearch to true (default: off). +// +// - fullSsearch - Search anywhere in autocomplete array strings. +// +// - partialChars - How many characters to enter before triggering +// a partial match (unlike minChars, which defines +// how many characters are required to do any match +// at all). Defaults to 2. +// +// - ignoreCase - Whether to ignore case when autocompleting. +// Defaults to true. +// +// It's possible to pass in a custom function as the 'selector' +// option, if you prefer to write your own autocompletion logic. +// In that case, the other options above will not apply unless +// you support them. + +Autocompleter.Local = Class.create(); +Autocompleter.Local.prototype = Object.extend(new Autocompleter.Base(), { + initialize: function(element, update, array, options) { + this.baseInitialize(element, update, options); + this.options.array = array; + }, + + getUpdatedChoices: function() { + this.updateChoices(this.options.selector(this)); + }, + + setOptions: function(options) { + this.options = Object.extend({ + choices: 10, + partialSearch: true, + partialChars: 2, + ignoreCase: true, + fullSearch: false, + selector: function(instance) { + var ret = []; // Beginning matches + var partial = []; // Inside matches + var entry = instance.getToken(); + var count = 0; + + for (var i = 0; i < instance.options.array.length && + ret.length < instance.options.choices ; i++) { + + var elem = instance.options.array[i]; + var foundPos = instance.options.ignoreCase ? + elem.toLowerCase().indexOf(entry.toLowerCase()) : + elem.indexOf(entry); + + while (foundPos != -1) { + if (foundPos == 0 && elem.length != entry.length) { + ret.push("<li><strong>" + elem.substr(0, entry.length) + "</strong>" + + elem.substr(entry.length) + "</li>"); + break; + } else if (entry.length >= instance.options.partialChars && + instance.options.partialSearch && foundPos != -1) { + if (instance.options.fullSearch || /\s/.test(elem.substr(foundPos-1,1))) { + partial.push("<li>" + elem.substr(0, foundPos) + "<strong>" + + elem.substr(foundPos, entry.length) + "</strong>" + elem.substr( + foundPos + entry.length) + "</li>"); + break; + } + } + + foundPos = instance.options.ignoreCase ? + elem.toLowerCase().indexOf(entry.toLowerCase(), foundPos + 1) : + elem.indexOf(entry, foundPos + 1); + + } + } + if (partial.length) + ret = ret.concat(partial.slice(0, instance.options.choices - ret.length)) + return "<ul>" + ret.join('') + "</ul>"; + } + }, options || {}); + } +}); + +// AJAX in-place editor +// +// see documentation on http://wiki.script.aculo.us/scriptaculous/show/Ajax.InPlaceEditor + +// Use this if you notice weird scrolling problems on some browsers, +// the DOM might be a bit confused when this gets called so do this +// waits 1 ms (with setTimeout) until it does the activation +Field.scrollFreeActivate = function(field) { + setTimeout(function() { + Field.activate(field); + }, 1); +} + +Ajax.InPlaceEditor = Class.create(); +Ajax.InPlaceEditor.defaultHighlightColor = "#FFFF99"; +Ajax.InPlaceEditor.prototype = { + initialize: function(element, url, options) { + this.url = url; + this.element = $(element); + + this.options = Object.extend({ + paramName: "value", + okButton: true, + okLink: false, + okText: "ok", + cancelButton: false, + cancelLink: true, + cancelText: "cancel", + textBeforeControls: '', + textBetweenControls: '', + textAfterControls: '', + savingText: "Saving...", + clickToEditText: "Click to edit", + okText: "ok", + rows: 1, + onComplete: function(transport, element) { + new Effect.Highlight(element, {startcolor: this.options.highlightcolor}); + }, + onFailure: function(transport) { + alert("Error communicating with the server: " + transport.responseText.stripTags()); + }, + callback: function(form) { + return Form.serialize(form); + }, + handleLineBreaks: true, + loadingText: 'Loading...', + savingClassName: 'inplaceeditor-saving', + loadingClassName: 'inplaceeditor-loading', + formClassName: 'inplaceeditor-form', + highlightcolor: Ajax.InPlaceEditor.defaultHighlightColor, + highlightendcolor: "#FFFFFF", + externalControl: null, + submitOnBlur: false, + ajaxOptions: {}, + evalScripts: false + }, options || {}); + + if(!this.options.formId && this.element.id) { + this.options.formId = this.element.id + "-inplaceeditor"; + if ($(this.options.formId)) { + // there's already a form with that name, don't specify an id + this.options.formId = null; + } + } + + if (this.options.externalControl) { + this.options.externalControl = $(this.options.externalControl); + } + + this.originalBackground = Element.getStyle(this.element, 'background-color'); + if (!this.originalBackground) { + this.originalBackground = "transparent"; + } + + this.element.title = this.options.clickToEditText; + + this.onclickListener = this.enterEditMode.bindAsEventListener(this); + this.mouseoverListener = this.enterHover.bindAsEventListener(this); + this.mouseoutListener = this.leaveHover.bindAsEventListener(this); + Event.observe(this.element, 'click', this.onclickListener); + Event.observe(this.element, 'mouseover', this.mouseoverListener); + Event.observe(this.element, 'mouseout', this.mouseoutListener); + if (this.options.externalControl) { + Event.observe(this.options.externalControl, 'click', this.onclickListener); + Event.observe(this.options.externalControl, 'mouseover', this.mouseoverListener); + Event.observe(this.options.externalControl, 'mouseout', this.mouseoutListener); + } + }, + enterEditMode: function(evt) { + if (this.saving) return; + if (this.editing) return; + this.editing = true; + this.onEnterEditMode(); + if (this.options.externalControl) { + Element.hide(this.options.externalControl); + } + Element.hide(this.element); + this.createForm(); + this.element.parentNode.insertBefore(this.form, this.element); + if (!this.options.loadTextURL) Field.scrollFreeActivate(this.editField); + // stop the event to avoid a page refresh in Safari + if (evt) { + Event.stop(evt); + } + return false; + }, + createForm: function() { + this.form = document.createElement("form"); + this.form.id = this.options.formId; + Element.addClassName(this.form, this.options.formClassName) + this.form.onsubmit = this.onSubmit.bind(this); + + this.createEditField(); + + if (this.options.textarea) { + var br = document.createElement("br"); + this.form.appendChild(br); + } + + if (this.options.textBeforeControls) + this.form.appendChild(document.createTextNode(this.options.textBeforeControls)); + + if (this.options.okButton) { + var okButton = document.createElement("input"); + okButton.type = "submit"; + okButton.value = this.options.okText; + okButton.className = 'editor_ok_button'; + this.form.appendChild(okButton); + } + + if (this.options.okLink) { + var okLink = document.createElement("a"); + okLink.href = "#"; + okLink.appendChild(document.createTextNode(this.options.okText)); + okLink.onclick = this.onSubmit.bind(this); + okLink.className = 'editor_ok_link'; + this.form.appendChild(okLink); + } + + if (this.options.textBetweenControls && + (this.options.okLink || this.options.okButton) && + (this.options.cancelLink || this.options.cancelButton)) + this.form.appendChild(document.createTextNode(this.options.textBetweenControls)); + + if (this.options.cancelButton) { + var cancelButton = document.createElement("input"); + cancelButton.type = "submit"; + cancelButton.value = this.options.cancelText; + cancelButton.onclick = this.onclickCancel.bind(this); + cancelButton.className = 'editor_cancel_button'; + this.form.appendChild(cancelButton); + } + + if (this.options.cancelLink) { + var cancelLink = document.createElement("a"); + cancelLink.href = "#"; + cancelLink.appendChild(document.createTextNode(this.options.cancelText)); + cancelLink.onclick = this.onclickCancel.bind(this); + cancelLink.className = 'editor_cancel editor_cancel_link'; + this.form.appendChild(cancelLink); + } + + if (this.options.textAfterControls) + this.form.appendChild(document.createTextNode(this.options.textAfterControls)); + }, + hasHTMLLineBreaks: function(string) { + if (!this.options.handleLineBreaks) return false; + return string.match(/<br/i) || string.match(/<p>/i); + }, + convertHTMLLineBreaks: function(string) { + return string.replace(/<br>/gi, "\n").replace(/<br\/>/gi, "\n").replace(/<\/p>/gi, "\n").replace(/<p>/gi, ""); + }, + createEditField: function() { + var text; + if(this.options.loadTextURL) { + text = this.options.loadingText; + } else { + text = this.getText(); + } + + var obj = this; + + if (this.options.rows == 1 && !this.hasHTMLLineBreaks(text)) { + this.options.textarea = false; + var textField = document.createElement("input"); + textField.obj = this; + textField.type = "text"; + textField.name = this.options.paramName; + textField.value = text; + textField.style.backgroundColor = this.options.highlightcolor; + textField.className = 'editor_field'; + var size = this.options.size || this.options.cols || 0; + if (size != 0) textField.size = size; + if (this.options.submitOnBlur) + textField.onblur = this.onSubmit.bind(this); + this.editField = textField; + } else { + this.options.textarea = true; + var textArea = document.createElement("textarea"); + textArea.obj = this; + textArea.name = this.options.paramName; + textArea.value = this.convertHTMLLineBreaks(text); + textArea.rows = this.options.rows; + textArea.cols = this.options.cols || 40; + textArea.className = 'editor_field'; + if (this.options.submitOnBlur) + textArea.onblur = this.onSubmit.bind(this); + this.editField = textArea; + } + + if(this.options.loadTextURL) { + this.loadExternalText(); + } + this.form.appendChild(this.editField); + }, + getText: function() { + return this.element.innerHTML; + }, + loadExternalText: function() { + Element.addClassName(this.form, this.options.loadingClassName); + this.editField.disabled = true; + new Ajax.Request( + this.options.loadTextURL, + Object.extend({ + asynchronous: true, + onComplete: this.onLoadedExternalText.bind(this) + }, this.options.ajaxOptions) + ); + }, + onLoadedExternalText: function(transport) { + Element.removeClassName(this.form, this.options.loadingClassName); + this.editField.disabled = false; + this.editField.value = transport.responseText.stripTags(); + Field.scrollFreeActivate(this.editField); + }, + onclickCancel: function() { + this.onComplete(); + this.leaveEditMode(); + return false; + }, + onFailure: function(transport) { + this.options.onFailure(transport); + if (this.oldInnerHTML) { + this.element.innerHTML = this.oldInnerHTML; + this.oldInnerHTML = null; + } + return false; + }, + onSubmit: function() { + // onLoading resets these so we need to save them away for the Ajax call + var form = this.form; + var value = this.editField.value; + + // do this first, sometimes the ajax call returns before we get a chance to switch on Saving... + // which means this will actually switch on Saving... *after* we've left edit mode causing Saving... + // to be displayed indefinitely + this.onLoading(); + + if (this.options.evalScripts) { + new Ajax.Request( + this.url, Object.extend({ + parameters: this.options.callback(form, value), + onComplete: this.onComplete.bind(this), + onFailure: this.onFailure.bind(this), + asynchronous:true, + evalScripts:true + }, this.options.ajaxOptions)); + } else { + new Ajax.Updater( + { success: this.element, + // don't update on failure (this could be an option) + failure: null }, + this.url, Object.extend({ + parameters: this.options.callback(form, value), + onComplete: this.onComplete.bind(this), + onFailure: this.onFailure.bind(this) + }, this.options.ajaxOptions)); + } + // stop the event to avoid a page refresh in Safari + if (arguments.length > 1) { + Event.stop(arguments[0]); + } + return false; + }, + onLoading: function() { + this.saving = true; + this.removeForm(); + this.leaveHover(); + this.showSaving(); + }, + showSaving: function() { + this.oldInnerHTML = this.element.innerHTML; + this.element.innerHTML = this.options.savingText; + Element.addClassName(this.element, this.options.savingClassName); + this.element.style.backgroundColor = this.originalBackground; + Element.show(this.element); + }, + removeForm: function() { + if(this.form) { + if (this.form.parentNode) Element.remove(this.form); + this.form = null; + } + }, + enterHover: function() { + if (this.saving) return; + this.element.style.backgroundColor = this.options.highlightcolor; + if (this.effect) { + this.effect.cancel(); + } + Element.addClassName(this.element, this.options.hoverClassName) + }, + leaveHover: function() { + if (this.options.backgroundColor) { + this.element.style.backgroundColor = this.oldBackground; + } + Element.removeClassName(this.element, this.options.hoverClassName) + if (this.saving) return; + this.effect = new Effect.Highlight(this.element, { + startcolor: this.options.highlightcolor, + endcolor: this.options.highlightendcolor, + restorecolor: this.originalBackground + }); + }, + leaveEditMode: function() { + Element.removeClassName(this.element, this.options.savingClassName); + this.removeForm(); + this.leaveHover(); + this.element.style.backgroundColor = this.originalBackground; + Element.show(this.element); + if (this.options.externalControl) { + Element.show(this.options.externalControl); + } + this.editing = false; + this.saving = false; + this.oldInnerHTML = null; + this.onLeaveEditMode(); + }, + onComplete: function(transport) { + this.leaveEditMode(); + this.options.onComplete.bind(this)(transport, this.element); + }, + onEnterEditMode: function() {}, + onLeaveEditMode: function() {}, + dispose: function() { + if (this.oldInnerHTML) { + this.element.innerHTML = this.oldInnerHTML; + } + this.leaveEditMode(); + Event.stopObserving(this.element, 'click', this.onclickListener); + Event.stopObserving(this.element, 'mouseover', this.mouseoverListener); + Event.stopObserving(this.element, 'mouseout', this.mouseoutListener); + if (this.options.externalControl) { + Event.stopObserving(this.options.externalControl, 'click', this.onclickListener); + Event.stopObserving(this.options.externalControl, 'mouseover', this.mouseoverListener); + Event.stopObserving(this.options.externalControl, 'mouseout', this.mouseoutListener); + } + } +}; + +Ajax.InPlaceCollectionEditor = Class.create(); +Object.extend(Ajax.InPlaceCollectionEditor.prototype, Ajax.InPlaceEditor.prototype); +Object.extend(Ajax.InPlaceCollectionEditor.prototype, { + createEditField: function() { + if (!this.cached_selectTag) { + var selectTag = document.createElement("select"); + var collection = this.options.collection || []; + var optionTag; + collection.each(function(e,i) { + optionTag = document.createElement("option"); + optionTag.value = (e instanceof Array) ? e[0] : e; + if((typeof this.options.value == 'undefined') && + ((e instanceof Array) ? this.element.innerHTML == e[1] : e == optionTag.value)) optionTag.selected = true; + if(this.options.value==optionTag.value) optionTag.selected = true; + optionTag.appendChild(document.createTextNode((e instanceof Array) ? e[1] : e)); + selectTag.appendChild(optionTag); + }.bind(this)); + this.cached_selectTag = selectTag; + } + + this.editField = this.cached_selectTag; + if(this.options.loadTextURL) this.loadExternalText(); + this.form.appendChild(this.editField); + this.options.callback = function(form, value) { + return "value=" + encodeURIComponent(value); + } + } +}); + +// Delayed observer, like Form.Element.Observer, +// but waits for delay after last key input +// Ideal for live-search fields + +Form.Element.DelayedObserver = Class.create(); +Form.Element.DelayedObserver.prototype = { + initialize: function(element, delay, callback) { + this.delay = delay || 0.5; + this.element = $(element); + this.callback = callback; + this.timer = null; + this.lastValue = $F(this.element); + Event.observe(this.element,'keyup',this.delayedListener.bindAsEventListener(this)); + }, + delayedListener: function(event) { + if(this.lastValue == $F(this.element)) return; + if(this.timer) clearTimeout(this.timer); + this.timer = setTimeout(this.onTimerEvent.bind(this), this.delay * 1000); + this.lastValue = $F(this.element); + }, + onTimerEvent: function() { + this.timer = null; + this.callback(this.element, $F(this.element)); + } +}; + + +/*
+Copyright (c) 2005 JSON.org
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The Software shall be used for Good, not Evil.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
+*/
+
+Array.prototype.______array = '______array';
+
+Prado.JSON = {
+ org: 'http://www.JSON.org',
+ copyright: '(c)2005 JSON.org',
+ license: 'http://www.crockford.com/JSON/license.html',
+
+ stringify: function (arg) {
+ var c, i, l, s = '', v;
+
+ switch (typeof arg) {
+ case 'object':
+ if (arg) {
+ if (arg.______array == '______array') {
+ for (i = 0; i < arg.length; ++i) {
+ v = this.stringify(arg[i]);
+ if (s) {
+ s += ',';
+ }
+ s += v;
+ }
+ return '[' + s + ']';
+ } else if (typeof arg.toString != 'undefined') {
+ for (i in arg) {
+ v = arg[i];
+ if (typeof v != 'undefined' && typeof v != 'function') {
+ v = this.stringify(v);
+ if (s) {
+ s += ',';
+ }
+ s += this.stringify(i) + ':' + v;
+ }
+ }
+ return '{' + s + '}';
+ }
+ }
+ return 'null';
+ case 'number':
+ return isFinite(arg) ? String(arg) : 'null';
+ case 'string':
+ l = arg.length;
+ s = '"';
+ for (i = 0; i < l; i += 1) {
+ c = arg.charAt(i);
+ if (c >= ' ') {
+ if (c == '\\' || c == '"') {
+ s += '\\';
+ }
+ s += c;
+ } else {
+ switch (c) {
+ case '\b':
+ s += '\\b';
+ break;
+ case '\f':
+ s += '\\f';
+ break;
+ case '\n':
+ s += '\\n';
+ break;
+ case '\r':
+ s += '\\r';
+ break;
+ case '\t':
+ s += '\\t';
+ break;
+ default:
+ c = c.charCodeAt();
+ s += '\\u00' + Math.floor(c / 16).toString(16) +
+ (c % 16).toString(16);
+ }
+ }
+ }
+ return s + '"';
+ case 'boolean':
+ return String(arg);
+ default:
+ return 'null';
+ }
+ },
+ parse: function (text) {
+ var at = 0;
+ var ch = ' ';
+
+ function error(m) {
+ throw {
+ name: 'JSONError',
+ message: m,
+ at: at - 1,
+ text: text
+ };
+ }
+
+ function next() {
+ ch = text.charAt(at);
+ at += 1;
+ return ch;
+ }
+
+ function white() {
+ while (ch) {
+ if (ch <= ' ') {
+ next();
+ } else if (ch == '/') {
+ switch (next()) {
+ case '/':
+ while (next() && ch != '\n' && ch != '\r') {}
+ break;
+ case '*':
+ next();
+ for (;;) {
+ if (ch) {
+ if (ch == '*') {
+ if (next() == '/') {
+ next();
+ break;
+ }
+ } else {
+ next();
+ }
+ } else {
+ error("Unterminated comment");
+ }
+ }
+ break;
+ default:
+ error("Syntax error");
+ }
+ } else {
+ break;
+ }
+ }
+ }
+
+ function string() {
+ var i, s = '', t, u;
+
+ if (ch == '"') {
+outer: while (next()) {
+ if (ch == '"') {
+ next();
+ return s;
+ } else if (ch == '\\') {
+ switch (next()) {
+ case 'b':
+ s += '\b';
+ break;
+ case 'f':
+ s += '\f';
+ break;
+ case 'n':
+ s += '\n';
+ break;
+ case 'r':
+ s += '\r';
+ break;
+ case 't':
+ s += '\t';
+ break;
+ case 'u':
+ u = 0;
+ for (i = 0; i < 4; i += 1) {
+ t = parseInt(next(), 16);
+ if (!isFinite(t)) {
+ break outer;
+ }
+ u = u * 16 + t;
+ }
+ s += String.fromCharCode(u);
+ break;
+ default:
+ s += ch;
+ }
+ } else {
+ s += ch;
+ }
+ }
+ }
+ error("Bad string");
+ }
+
+ function array() {
+ var a = [];
+
+ if (ch == '[') {
+ next();
+ white();
+ if (ch == ']') {
+ next();
+ return a;
+ }
+ while (ch) {
+ a.push(value());
+ white();
+ if (ch == ']') {
+ next();
+ return a;
+ } else if (ch != ',') {
+ break;
+ }
+ next();
+ white();
+ }
+ }
+ error("Bad array");
+ }
+
+ function object() {
+ var k, o = {};
+
+ if (ch == '{') {
+ next();
+ white();
+ if (ch == '}') {
+ next();
+ return o;
+ }
+ while (ch) {
+ k = string();
+ white();
+ if (ch != ':') {
+ break;
+ }
+ next();
+ o[k] = value();
+ white();
+ if (ch == '}') {
+ next();
+ return o;
+ } else if (ch != ',') {
+ break;
+ }
+ next();
+ white();
+ }
+ }
+ error("Bad object");
+ }
+
+ function number() {
+ var n = '', v;
+ if (ch == '-') {
+ n = '-';
+ next();
+ }
+ while (ch >= '0' && ch <= '9') {
+ n += ch;
+ next();
+ }
+ if (ch == '.') {
+ n += '.';
+ while (next() && ch >= '0' && ch <= '9') {
+ n += ch;
+ }
+ }
+ if (ch == 'e' || ch == 'E') {
+ n += 'e';
+ next();
+ if (ch == '-' || ch == '+') {
+ n += ch;
+ next();
+ }
+ while (ch >= '0' && ch <= '9') {
+ n += ch;
+ next();
+ }
+ }
+ v = +n;
+ if (!isFinite(v)) {
+ ////error("Bad number");
+ } else {
+ return v;
+ }
+ }
+
+ function word() {
+ switch (ch) {
+ case 't':
+ if (next() == 'r' && next() == 'u' && next() == 'e') {
+ next();
+ return true;
+ }
+ break;
+ case 'f':
+ if (next() == 'a' && next() == 'l' && next() == 's' &&
+ next() == 'e') {
+ next();
+ return false;
+ }
+ break;
+ case 'n':
+ if (next() == 'u' && next() == 'l' && next() == 'l') {
+ next();
+ return null;
+ }
+ break;
+ }
+ error("Syntax error");
+ }
+
+ function value() {
+ white();
+ switch (ch) {
+ case '{':
+ return object();
+ case '[':
+ return array();
+ case '"':
+ return string();
+ case '-':
+ return number();
+ default:
+ return ch >= '0' && ch <= '9' ? number() : word();
+ }
+ }
+
+ return value();
+ }
+}; + +
+Prado.AjaxRequest = Class.create();
+Prado.AjaxRequest.prototype = Ajax.Request.prototype;
+
+
+/**
+ * Override Prototype's response implementation.
+ */
+Object.extend(Prado.AjaxRequest.prototype,
+{
+ /**
+ * 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);
+ Ajax.Responders.dispatch('on' + transport.status, this, transport, json);
+ Prado.CallbackRequest.dispatchActions(transport,this.getBodyDataPart(Prado.CallbackRequest.ACTION_HEADER));
+
+ (this.options['on' + this.transport.status]
+ || this.options['on' + (this.success() ? 'Success' : 'Failure')]
+ || Prototype.emptyFunction)(this, json);
+ } 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',
+
+ 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);
+ }
+ }
+ },
+
+ /**
+ * 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);
+ Logger.error("Callback Server Error "+e.code, this.formatException(e));
+ },
+
+ /**
+ * 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)
+ {
+ 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)
+ {
+ //Logger.info("dispatching normal request");
+ new Prado.AjaxRequest(callback.url, callback.options);
+ 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);
+ },
+
+ /**
+ * 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.options.EnablePageStateUpdate && request.options.HasPriority;
+ var aborted = 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.url, callback.options);
+ callback.timeout = setTimeout(function()
+ {
+ //Logger.warn("priority timeout");
+ self.abortRequest(callback.id);
+ },callback.options.RequestTimeOut);
+ //Logger.debug("dispatched "+self.currentRequest.id + " ...")
+ },
+
+ endCurrentRequest : function()
+ {
+ var self = Prado.CallbackRequest;
+ 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.request;
+ 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.options.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 =
+{
+
+ /**
+ * Prepare and inititate a callback request.
+ */
+ initialize : function(id, options)
+ {
+ /**
+ * Callback URL, same url as the current page.
+ */
+ this.url = this.getCallbackUrl();
+
+ /**
+ * Current callback request.
+ */
+ this.request = null;
+
+ this.Enabled = true;
+
+ this.id = id;
+ if(typeof(id)=="string")
+ Prado.CallbackRequest.requests[id] = this;
+
+ this.options = Object.extend(
+ {
+ RequestTimeOut : 30000, // 30 second timeout.
+ EnablePageStateUpdate : true,
+ HasPriority : true,
+ CausesValidation : true,
+ ValidationGroup : null,
+ PostInputs : true
+ }, options || {});
+ },
+
+ /**
+ * 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)
+ {
+ this.options['params'] = value;
+ },
+
+ /**
+ * @return {Object} request paramater value.
+ */
+ getCallbackParameter : function()
+ {
+ return this.options['params'];
+ },
+
+ /**
+ * Sets the callback request timeout.
+ * @param {integer} timeout in milliseconds
+ */
+ setRequestTimeOut : function(timeout)
+ {
+ this.options['RequestTimeOut'] = timeout;
+ },
+
+ /**
+ * @return {integer} request timeout in milliseconds
+ */
+ getRequestTimeOut : function()
+ {
+ return this.options['RequestTimeOut'];
+ },
+
+ /**
+ * Set true to enable validation on callback dispatch.
+ * @param {boolean} true to validate
+ */
+ setCausesValidation : function(validate)
+ {
+ this.options['CausesValidation'] = validate;
+ },
+
+ /**
+ * @return {boolean} validate on request dispatch
+ */
+ getCausesValidation : function()
+ {
+ return this.options['CausesValidation'];
+ },
+
+ /**
+ * Sets the validation group to validate during request dispatch.
+ * @param {string} validation group name
+ */
+ setValidationGroup : function(group)
+ {
+ this.options['ValidationGroup'] = group;
+ },
+
+ /**
+ * @return {string} validation group name.
+ */
+ getValidationGroup : function()
+ {
+ return this.options['ValidationGroup'];
+ },
+
+ /**
+ * Dispatch the callback request.
+ */
+ dispatch : function()
+ {
+ //Logger.info("dispatching request");
+ //trigger tinyMCE to save data.
+ if(typeof tinyMCE != "undefined")
+ tinyMCE.triggerSave();
+
+ //override parameter and postBody options.
+ Object.extend(this.options,
+ {
+// postBody : this._getPostData(),
+ parameters : ''
+ });
+
+ if(this.options.CausesValidation && typeof(Prado.Validation) != "undefined")
+ {
+ var form = this.options.Form || Prado.Validation.getForm();
+ if(Prado.Validation.validate(form,this.options.ValidationGroup,this) == false)
+ return false;
+ }
+
+ if(this.options.onPreDispatch)
+ this.options.onPreDispatch(this,null);
+
+ if(!this.Enabled)
+ return;
+
+ if(this.options.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.options.PostInputs != false)
+ {
+ callback.PostDataLoaders.each(function(name)
+ {
+ $A(document.getElementsByName(name)).each(function(element)
+ {
+ //IE will try to get elements with ID == name as well.
+ if(element.type && element.name == name)
+ {
+ value = $F(element);
+ if(typeof(value) != "undefined" && value != null)
+ data[name] = value;
+ }
+ })
+ })
+ }
+ if(typeof(this.options.params) != "undefined")
+ data[callback.FIELD_CALLBACK_PARAMETER] = callback.encode(this.options.params);
+ 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.options.EventTarget)
+ data[callback.FIELD_POSTBACK_TARGET] = this.options.EventTarget;
+ if(this.options.EventParameter)
+ data[callback.FIELD_POSTBACK_PARAMETER] = this.options.EventParameter;
+ return $H(data).toQueryString();
+ }
+}
+
+/**
+ * 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 =
+ {
+ 'params' : parameter || '',
+ 'onSuccess' : onSuccess || Prototype.emptyFunction
+ };
+
+ Object.extend(callback, options || {});
+
+ request = new Prado.CallbackRequest(UniqueID, callback);
+ request.dispatch();
+ return false;
+}
+ + +/**
+ * 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);
+ }
+});
+/**
+ * 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)
+ {
+ 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')
+ Event.observe(this.element, "keydown", this.handleReturnKey.bind(this));
+ if(this.options['AutoPostBack']==true)
+ Event.observe(this.element, "change", this.doCallback.bindEvent(this,options));
+ },
+
+ doCallback : function(event, options)
+ {
+ var request = new Prado.CallbackRequest(options.EventTarget, options);
+ request.dispatch();
+ 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.baseInitialize(options.ID, options.ResultPanel, options);
+ Object.extend(this.options,
+ {
+ onSuccess : this.onComplete.bind(this)
+ });
+
+ if(options.AutoPostBack)
+ this.onInit(options);
+ },
+
+ 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);
+ },
+
+ onComplete : function(request, boundary)
+ {
+ var result = Prado.Element.extractContent(request.transport.responseText, boundary);
+ if(typeof(result) == "string" && result.length > 0)
+ this.updateChoices(result);
+ }
+});
+
+/**
+ * Time Triggered Callback class.
+ */
+Prado.WebUI.TTimeTriggeredCallback = Base.extend(
+{
+ constructor : function(options)
+ {
+ this.options = Object.extend({ Interval : 1 }, options || {});
+ Prado.WebUI.TTimeTriggeredCallback.register(this);
+ },
+
+ startTimer : function()
+ {
+ setTimeout(this.onTimerEvent.bind(this), 100);
+ if(typeof(this.timer) == 'undefined' || this.timer == null)
+ this.timer = setInterval(this.onTimerEvent.bind(this),this.options.Interval*1000);
+ },
+
+ stopTimer : function()
+ {
+ if(typeof(this.timer) != 'undefined')
+ {
+ clearInterval(this.timer);
+ this.timer = null;
+ }
+ },
+
+ onTimerEvent : function()
+ {
+ var request = new Prado.CallbackRequest(this.options.EventTarget, this.options);
+ request.dispatch();
+ }
+},
+//class methods
+{
+ timers : {},
+
+ register : function(timer)
+ {
+ Prado.WebUI.TTimeTriggeredCallback.timers[timer.options.ID] = timer;
+ },
+
+ start : function(id)
+ {
+ Prado.WebUI.TTimeTriggeredCallback.timers[id].startTimer();
+ },
+
+ stop : function(id)
+ {
+ Prado.WebUI.TTimeTriggeredCallback.timers[id].stopTimer();
+ }
+});
+
+Prado.WebUI.ActiveListControl = Base.extend(
+{
+ constructor : function(options)
+ {
+ this.element = $(options.ID);
+ if(this.element)
+ {
+ this.options = options;
+ Event.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 = Prado.WebUI.ActiveListControl;
+Prado.WebUI.TActiveListBox = Prado.WebUI.ActiveListControl;
+
+/**
+ * Observe event of a particular control to trigger a callback request.
+ */
+Prado.WebUI.TEventTriggeredCallback = Base.extend(
+{
+ constructor : function(options)
+ {
+ this.options = options;
+ var element = $(options['ControlID']);
+ if(element)
+ Event.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 = Base.extend(
+{
+ count : 1,
+
+ observing : true,
+
+ constructor : 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()
+ {
+ clearTimeout(this.timer);
+ this.observing = false;
+ },
+
+ startObserving : function()
+ {
+ this.timer = 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 = 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();
+ }
+},
+//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.TInPlaceTextBox = Base.extend(
+{
+ isSaving : false,
+ isEditing : false,
+ editField : null,
+
+ constructor : function(options)
+ {
+ 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);
+ Event.observe(this.element, 'click', this.onclickListener);
+ if (this.options.ExternalControl)
+ Event.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) 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();
+ options = new Array('__InlineEditor_loadExternalText__', this.getText());
+ request = new Prado.CallbackRequest(this.options.EventTarget, this.options);
+ request.setCausesValidation(false);
+ request.setCallbackParameter(options);
+ request.options.onSuccess = this.onloadExternalTextSuccess.bind(this);
+ request.options.onFailure = this.onloadExternalTextFailure.bind(this);
+ request.dispatch();
+ },
+
+ /**
+ * Create a new input textbox or textarea
+ */
+ createTextBox : function()
+ {
+ cssClass= this.element.className || '';
+ inputName = this.options.EventTarget;
+ options = {'className' : cssClass, name : inputName, id : this.options.TextBoxID};
+ if(this.options.TextMode == 'SingleLine')
+ {
+ if(this.options.MaxLength > 0)
+ options['maxlength'] = this.options.MaxLength;
+ 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')
+ {
+ Event.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);
+ }
+ }
+ });
+ }
+
+ Event.observe(this.editField, "blur", this.onTextBoxBlur.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)
+ {
+ text = this.element.innerHTML;
+ if(this.options.AutoPostBack && text != this.editField.value)
+ this.onTextChanged(text);
+ else
+ {
+ this.element.innerHTML = this.editField.value;
+ this.isEditing = false;
+ if(this.options.AutoHide)
+ this.showLabel();
+ }
+ },
+
+ /**
+ * When the text input value has changed.
+ * @param {String} original text
+ */
+ onTextChanged : function(text)
+ {
+ request = new Prado.CallbackRequest(this.options.EventTarget, this.options);
+ request.setCallbackParameter(text);
+ request.options.onSuccess = this.onTextChangedSuccess.bind(this);
+ request.options.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);
+ }
+},
+{
+ 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);
+ }
+ }
+ }
+}); + diff --git a/framework/Web/Javascripts/js/debug/clientscripts.php b/framework/Web/Javascripts/js/debug/clientscripts.php index a0321bc2..3bc76734 100644 --- a/framework/Web/Javascripts/js/debug/clientscripts.php +++ b/framework/Web/Javascripts/js/debug/clientscripts.php @@ -12,7 +12,7 @@ $debugMode=(isset($_GET['mode']) && $_GET['mode']==='debug'); $expiresOffset = $debugMode ? -10000 : 3600 * 24 * 10; //no cache
//allowed libraries
-$library = array('prado', 'effects', 'validator', 'logger', 'datepicker', 'colorpicker');
+$library = array('prado', 'effects', 'validator', 'logger', 'datepicker', 'colorpicker', 'ajax');
$param = isset($_GET['js']) ? $_GET['js'] : '';
diff --git a/framework/Web/Javascripts/js/debug/effects.js b/framework/Web/Javascripts/js/debug/effects.js index 685e57ae..d306ae44 100644 --- a/framework/Web/Javascripts/js/debug/effects.js +++ b/framework/Web/Javascripts/js/debug/effects.js @@ -1,6 +1,6 @@ -// script.aculo.us effects.js v1.7.0, Fri Jan 19 19:16:36 CET 2007 +// script.aculo.us effects.js v1.7.1_beta1, Mon Mar 12 14:40:50 +0100 2007 -// Copyright (c) 2005, 2006 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) +// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) // Contributors: // Justin Palmer (http://encytemedia.com/) // Mark Pilgrim (http://diveintomark.org/) @@ -45,18 +45,10 @@ Element.collectTextNodesIgnoreClass = function(element, className) { Element.setContentZoom = function(element, percent) { element = $(element); element.setStyle({fontSize: (percent/100) + 'em'}); - if(navigator.appVersion.indexOf('AppleWebKit')>0) window.scrollBy(0,0); + if(Prototype.Browser.WebKit) window.scrollBy(0,0); return element; } -Element.getOpacity = function(element){ - return $(element).getStyle('opacity'); -} - -Element.setOpacity = function(element, value){ - return $(element).setStyle({opacity:value}); -} - Element.getInlineOpacity = function(element){ return $(element).style.opacity || ''; } @@ -89,7 +81,7 @@ var Effect = { throw("Effect.tagifyText requires including script.aculo.us' builder.js library"); var tagifyStyle = 'position:relative'; - if(/MSIE/.test(navigator.userAgent) && !window.opera) tagifyStyle += ';zoom:1'; + if(Prototype.Browser.IE) tagifyStyle += ';zoom:1'; element = $(element); $A(element.childNodes).each( function(child) { @@ -152,7 +144,8 @@ Effect.Transitions = { return 1-pos; }, flicker: function(pos) { - return ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4; + var pos = ((-Math.cos(pos*Math.PI)/4) + 0.75) + Math.random()/4; + return (pos > 1 ? 1 : pos); }, wobble: function(pos) { return (-Math.cos(pos*Math.PI*(9*pos))/2) + 0.5; @@ -179,7 +172,7 @@ Effect.ScopedQueue = Class.create(); Object.extend(Object.extend(Effect.ScopedQueue.prototype, Enumerable), { initialize: function() { this.effects = []; - this.interval = null; + this.interval = null; }, _each: function(iterator) { this.effects._each(iterator); @@ -213,7 +206,7 @@ Object.extend(Object.extend(Effect.ScopedQueue.prototype, Enumerable), { if(!effect.options.queue.limit || (this.effects.length < effect.options.queue.limit)) this.effects.push(effect); - if(!this.interval) + if(!this.interval) this.interval = setInterval(this.loop.bind(this), 15); }, remove: function(effect) { @@ -226,7 +219,7 @@ Object.extend(Object.extend(Effect.ScopedQueue.prototype, Enumerable), { loop: function() { var timePos = new Date().getTime(); for(var i=0, len=this.effects.length;i<len;i++) - if(this.effects[i]) this.effects[i].loop(timePos); + this.effects[i] && this.effects[i].loop(timePos); } }); @@ -246,7 +239,7 @@ Effect.Queue = Effect.Queues.get('global'); Effect.DefaultOptions = { transition: Effect.Transitions.sinoidal, duration: 1.0, // seconds - fps: 60.0, // max. 60fps due to Effect.Queue implementation + fps: 100, // 100= assume 66fps max. sync: false, // true for combining from: 0.0, to: 1.0, @@ -258,11 +251,35 @@ Effect.Base = function() {}; Effect.Base.prototype = { position: null, start: function(options) { + function codeForEvent(options,eventName){ + return ( + (options[eventName+'Internal'] ? 'this.options.'+eventName+'Internal(this);' : '') + + (options[eventName] ? 'this.options.'+eventName+'(this);' : '') + ); + } + if(options.transition === false) options.transition = Effect.Transitions.linear; this.options = Object.extend(Object.extend({},Effect.DefaultOptions), options || {}); this.currentFrame = 0; this.state = 'idle'; this.startOn = this.options.delay*1000; - this.finishOn = this.startOn + (this.options.duration*1000); + this.finishOn = this.startOn+(this.options.duration*1000); + this.fromToDelta = this.options.to-this.options.from; + this.totalTime = this.finishOn-this.startOn; + this.totalFrames = this.options.fps*this.options.duration; + + eval('this.render = function(pos){ '+ + 'if(this.state=="idle"){this.state="running";'+ + codeForEvent(options,'beforeSetup')+ + (this.setup ? 'this.setup();':'')+ + codeForEvent(options,'afterSetup')+ + '};if(this.state=="running"){'+ + 'pos=this.options.transition(pos)*'+this.fromToDelta+'+'+this.options.from+';'+ + 'this.position=pos;'+ + codeForEvent(options,'beforeUpdate')+ + (this.update ? 'this.update(pos);':'')+ + codeForEvent(options,'afterUpdate')+ + '}}'); + this.event('beforeStart'); if(!this.options.sync) Effect.Queues.get(typeof this.options.queue == 'string' ? @@ -278,31 +295,14 @@ Effect.Base.prototype = { this.event('afterFinish'); return; } - var pos = (timePos - this.startOn) / (this.finishOn - this.startOn); - var frame = Math.round(pos * this.options.fps * this.options.duration); + var pos = (timePos - this.startOn) / this.totalTime, + frame = Math.round(pos * this.totalFrames); if(frame > this.currentFrame) { this.render(pos); this.currentFrame = frame; } } }, - render: function(pos) { - if(this.state == 'idle') { - this.state = 'running'; - this.event('beforeSetup'); - if(this.setup) this.setup(); - this.event('afterSetup'); - } - if(this.state == 'running') { - if(this.options.transition) pos = this.options.transition(pos); - pos *= (this.options.to-this.options.from); - pos += this.options.from; - this.position = pos; - this.event('beforeUpdate'); - if(this.update) this.update(pos); - this.event('afterUpdate'); - } - }, cancel: function() { if(!this.options.sync) Effect.Queues.get(typeof this.options.queue == 'string' ? @@ -358,7 +358,7 @@ Object.extend(Object.extend(Effect.Opacity.prototype, Effect.Base.prototype), { this.element = $(element); if(!this.element) throw(Effect._elementDoesNotExistError); // make this work on IE on elements without 'layout' - if(/MSIE/.test(navigator.userAgent) && !window.opera && (!this.element.currentStyle.hasLayout)) + if(Prototype.Browser.IE && (!this.element.currentStyle.hasLayout)) this.element.setStyle({zoom: 1}); var options = Object.extend({ from: this.element.getOpacity() || 0.0, @@ -953,7 +953,7 @@ Object.extend(Object.extend(Effect.Morph.prototype, Effect.Base.prototype), { effect.element.addClassName(effect.options.style); effect.transforms.each(function(transform) { if(transform.style != 'opacity') - effect.element.style[transform.style.camelize()] = ''; + effect.element.style[transform.style] = ''; }); } } else this.style = options.style.parseStyle(); @@ -969,26 +969,28 @@ Object.extend(Object.extend(Effect.Morph.prototype, Effect.Base.prototype), { }); } this.transforms = this.style.map(function(pair){ - var property = pair[0].underscore().dasherize(), value = pair[1], unit = null; + var property = pair[0], value = pair[1], unit = null; if(value.parseColor('#zzzzzz') != '#zzzzzz') { value = value.parseColor(); unit = 'color'; } else if(property == 'opacity') { value = parseFloat(value); - if(/MSIE/.test(navigator.userAgent) && !window.opera && (!this.element.currentStyle.hasLayout)) + if(Prototype.Browser.IE && (!this.element.currentStyle.hasLayout)) this.element.setStyle({zoom: 1}); - } else if(Element.CSS_LENGTH.test(value)) - var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/), - value = parseFloat(components[1]), unit = (components.length == 3) ? components[2] : null; + } else if(Element.CSS_LENGTH.test(value)) { + var components = value.match(/^([\+\-]?[0-9\.]+)(.*)$/); + value = parseFloat(components[1]); + unit = (components.length == 3) ? components[2] : null; + } var originalValue = this.element.getStyle(property); - return $H({ - style: property, + return { + style: property.camelize(), originalValue: unit=='color' ? parseColor(originalValue) : parseFloat(originalValue || 0), targetValue: unit=='color' ? parseColor(value) : value, unit: unit - }); + }; }.bind(this)).reject(function(transform){ return ( (transform.originalValue == transform.targetValue) || @@ -1000,17 +1002,19 @@ Object.extend(Object.extend(Effect.Morph.prototype, Effect.Base.prototype), { }); }, update: function(position) { - var style = $H(), value = null; - this.transforms.each(function(transform){ - value = transform.unit=='color' ? - $R(0,2).inject('#',function(m,v,i){ - return m+(Math.round(transform.originalValue[i]+ - (transform.targetValue[i] - transform.originalValue[i])*position)).toColorPart() }) : + var style = {}, transform, i = this.transforms.length; + while(i--) + style[(transform = this.transforms[i]).style] = + transform.unit=='color' ? '#'+ + (Math.round(transform.originalValue[0]+ + (transform.targetValue[0]-transform.originalValue[0])*position)).toColorPart() + + (Math.round(transform.originalValue[1]+ + (transform.targetValue[1]-transform.originalValue[1])*position)).toColorPart() + + (Math.round(transform.originalValue[2]+ + (transform.targetValue[2]-transform.originalValue[2])*position)).toColorPart() : transform.originalValue + Math.round( ((transform.targetValue - transform.originalValue) * position) * 1000)/1000 + transform.unit; - style[transform.style] = value; - }); - this.element.setStyle(style); + this.element.setStyle(style, true); } }); @@ -1057,14 +1061,14 @@ Element.CSS_PROPERTIES = $w( Element.CSS_LENGTH = /^(([\+\-]?[0-9\.]+)(em|ex|px|in|cm|mm|pt|pc|\%))|0$/; String.prototype.parseStyle = function(){ - var element = Element.extend(document.createElement('div')); + var element = document.createElement('div'); element.innerHTML = '<div style="' + this + '"></div>'; - var style = element.down().style, styleRules = $H(); + var style = element.childNodes[0].style, styleRules = $H(); Element.CSS_PROPERTIES.each(function(property){ if(style[property]) styleRules[property] = style[property]; }); - if(/MSIE/.test(navigator.userAgent) && !window.opera && this.indexOf('opacity') > -1) { + if(Prototype.Browser.IE && this.indexOf('opacity') > -1) { styleRules.opacity = this.match(/opacity:\s*((?:0|1)?(?:\.\d*)?)/)[1]; } return styleRules; @@ -1075,13 +1079,13 @@ Element.morph = function(element, style) { return element; }; -['setOpacity','getOpacity','getInlineOpacity','forceRerendering','setContentZoom', +['getInlineOpacity','forceRerendering','setContentZoom', 'collectTextNodes','collectTextNodesIgnoreClass','morph'].each( function(f) { Element.Methods[f] = Element[f]; } ); Element.Methods.visualEffect = function(element, effect, options) { - s = effect.gsub(/_/, '-').camelize(); + s = effect.dasherize().camelize(); effect_class = s.charAt(0).toUpperCase() + s.substring(1); new Effect[effect_class](element, options); return $(element); diff --git a/framework/Web/Javascripts/js/debug/prado.js b/framework/Web/Javascripts/js/debug/prado.js index 87622c93..1388135d 100644 --- a/framework/Web/Javascripts/js/debug/prado.js +++ b/framework/Web/Javascripts/js/debug/prado.js @@ -3215,9 +3215,9 @@ if (Prototype.Browser.WebKit) { Element.addMethods(); -// script.aculo.us builder.js v1.7.0, Fri Jan 19 19:16:36 CET 2007 +// script.aculo.us builder.js v1.7.1_beta1, Mon Mar 12 14:40:50 +0100 2007 -// Copyright (c) 2005, 2006 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) +// Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us) // // script.aculo.us is freely distributable under the terms of an MIT-style license. // For details, see the script.aculo.us web site: http://script.aculo.us/ @@ -3265,7 +3265,8 @@ var Builder = { // attributes (or text) if(arguments[1]) if(this._isStringOrNumber(arguments[1]) || - (arguments[1] instanceof Array)) { + (arguments[1] instanceof Array) || + arguments[1].tagName) { this._children(element, arguments[1]); } else { var attrs = this._attributes(arguments[1]); @@ -3283,7 +3284,7 @@ var Builder = { } if(element.tagName.toUpperCase() != elementName) element = parentElement.getElementsByTagName(elementName)[0]; - } + } } // text, or array of children @@ -3309,6 +3310,10 @@ var Builder = { return attrs.join(" "); }, _children: function(element, children) { + if(children.tagName) { + element.appendChild(children); + return; + } if(typeof children=='object') { // array can hold nodes and text children.flatten().each( function(e) { if(typeof e=='object') @@ -3318,8 +3323,8 @@ var Builder = { element.appendChild(Builder._text(e)); }); } else - if(Builder._isStringOrNumber(children)) - element.appendChild(Builder._text(children)); + if(Builder._isStringOrNumber(children)) + element.appendChild(Builder._text(children)); }, _isStringOrNumber: function(param) { return(typeof param=='string' || typeof param=='number'); @@ -3584,9 +3589,6 @@ Prado.PostBack = function(event,options) Event.fireEvent(form,"submit");
}
-/**
- * Additional element utilities.
- */
Prado.Element =
{
/**
@@ -3601,15 +3603,16 @@ Prado.Element = el.value = value;
},
- select : function(element, method, value)
+ select : function(element, method, value, total)
{
var el = $(element);
- var isList = element.indexOf('[]') > -1;
- if(!el && !isList) return;
- method = isList ? 'check'+method : el.tagName.toLowerCase()+method;
+ if(!el) return;
var selection = Prado.Element.Selection;
- if(isFunction(selection[method]))
- selection[method](isList ? element : el,value);
+ if(typeof(selection[method]) == "function")
+ {
+ control = selection.isSelectable(el) ? [el] : selection.getListElements(element,total);
+ selection[method](control, value);
+ }
},
click : function(element)
@@ -3622,8 +3625,21 @@ Prado.Element = setAttribute : function(element, attribute, value)
{
var el = $(element);
- if(attribute == "disabled" && value==false)
+ 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)
+ {
+ throw "Error in evaluating '"+value+"' for attribute "+attribute+" for element "+element.id;
+ }
+ }
else
el.setAttribute(attribute, value);
},
@@ -3631,12 +3647,12 @@ Prado.Element = setOptions : function(element, options)
{
var el = $(element);
+ if(!el) return;
if(el && el.tagName.toLowerCase() == "select")
{
- while(el.length > 0)
- el.remove(0);
+ el.options.length = options.length;
for(var i = 0; i<options.length; i++)
- el.options[el.options.length] = new Option(options[i][0],options[i][1]);
+ el.options[i] = new Option(options[i][0],options[i][1]);
}
},
@@ -3650,14 +3666,62 @@ Prado.Element = if(typeof(obj) != "undefined" && typeof(obj.focus) != "undefined")
setTimeout(function(){ obj.focus(); }, 100);
return false;
+ },
+
+ replace : function(element, method, content, boundary)
+ {
+ if(boundary)
+ {
+ 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]);
+ }
+ },
+
+ extractContent : function(text, boundary)
+ {
+ var f = RegExp('(<!--'+boundary+'-->)([\\s\\S\\w\\W]*)(<!--//'+boundary+'-->)',"m");
+ var result = text.match(f);
+ if(result && result.length >= 2)
+ return result[2];
+ else
+ return null;
+ },
+
+ evaluateScript : function(content)
+ {
+ content.evalScripts();
}
}
-/**
- * Selectable element utilities
- */
Prado.Element.Selection =
{
+ 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;
+ },
+
inputValue : function(el, value)
{
switch(el.type.toLowerCase())
@@ -3668,61 +3732,125 @@ Prado.Element.Selection = }
},
- selectValue : function(el, value)
+ selectValue : function(elements, value)
{
- $A(el.options).each(function(option)
+ elements.each(function(el)
{
- option.selected = option.value == value;
- });
+ $A(el.options).each(function(option)
+ {
+ if(typeof(value) == "boolean")
+ options.selected = value;
+ else if(option.value == value)
+ option.selected = true;
+ });
+ })
},
- selectIndex : function(el, index)
+ selectValues : function(elements, values)
{
- if(el.type == 'select-one')
- el.selectedIndex = index;
- else
+ selection = this;
+ values.each(function(value)
+ {
+ selection.selectValue(elements,value);
+ })
+ },
+
+ selectIndex : function(elements, index)
+ {
+ elements.each(function(el)
{
- for(var i = 0; i<el.length; i++)
+ if(el.type.toLowerCase() == 'select-one')
+ el.selectedIndex = index;
+ else
{
- if(i == index)
- el.options[i].selected = true;
+ for(var i = 0; i<el.length; i++)
+ {
+ if(i == index)
+ el.options[i].selected = true;
+ }
}
- }
+ })
},
- selectClear : function(el)
+ selectAll : function(elements)
{
- el.selectedIndex = -1;
+ elements.each(function(el)
+ {
+ if(el.type.toLowerCase() != 'select-one')
+ {
+ $A(el.options).each(function(option)
+ {
+ option.selected = true;
+ })
+ }
+ })
},
- selectAll : function(el)
+ selectInvert : function(elements)
{
- $A(el.options).each(function(option)
+ elements.each(function(el)
{
- option.selected = true;
- Logger.warn(option.value);
- });
+ if(el.type.toLowerCase() != 'select-one')
+ {
+ $A(el.options).each(function(option)
+ {
+ option.selected = !options.selected;
+ })
+ }
+ })
},
- selectInvert : function(el)
+ selectIndices : function(elements, indices)
{
- $A(el.options).each(function(option)
+ selection = this;
+ indices.each(function(index)
{
- option.selected = !option.selected;
- });
+ selection.selectIndex(elements,index);
+ })
+ },
+
+ selectClear : function(elements)
+ {
+ elements.each(function(el)
+ {
+ el.selectedIndex = -1;
+ })
+ },
+
+ getListElements : function(element, total)
+ {
+ elements = new Array();
+ for(i = 0; i < total; i++)
+ {
+ el = $(element+"_c"+i);
+ if(el)
+ elements.push(el);
+ }
+ return elements;
},
- checkValue : function(name, value)
+ checkValue : function(elements, value)
{
- $A(document.getElementsByName(name)).each(function(el)
+ elements.each(function(el)
{
- el.checked = el.value == value
+ if(typeof(value) == "boolean")
+ el.checked = value;
+ else if(el.value == value)
+ el.checked = true;
});
},
- checkIndex : function(name, index)
+ checkValues : function(elements, values)
+ {
+ selection = this;
+ values.each(function(value)
+ {
+ selection.checkValue(elements, value);
+ })
+ },
+
+ checkIndex : function(elements, index)
{
- var elements = $A(document.getElementsByName(name));
for(var i = 0; i<elements.length; i++)
{
if(i == index)
@@ -3730,31 +3858,65 @@ Prado.Element.Selection = }
},
- checkClear : function(name)
+ checkIndices : function(elements, indices)
+ {
+ selection = this;
+ indices.each(function(index)
+ {
+ selection.checkIndex(elements, index);
+ })
+ },
+
+ checkClear : function(elements)
{
- $A(document.getElementsByName(name)).each(function(el)
+ elements.each(function(el)
{
el.checked = false;
});
},
- checkAll : function(name)
+ checkAll : function(elements)
{
- $A(document.getElementsByName(name)).each(function(el)
+ elements.each(function(el)
{
el.checked = true;
- });
+ })
},
- checkInvert : function(name)
+
+ checkInvert : function(elements)
{
- $A(document.getElementsByName(name)).each(function(el)
+ elements.each(function(el)
{
- el.checked = !el.checked;
- });
+ el.checked != el.checked;
+ })
}
};
+Prado.Element.Insert =
+{
+ append: function(element, content)
+ {
+ new Insertion.Bottom(element, content);
+ },
+
+ prepend: function(element, content)
+ {
+ new Insertion.Top(element, content);
+ },
+
+ after: function(element, content)
+ {
+ new Insertion.After(element, content);
+ },
+
+ before: function(element, content)
+ {
+ new Insertion.Before(element, content);
+ }
+}
+
+
/**
* Export scripaculous builder utilities as window[functions]
*/
diff --git a/framework/Web/Javascripts/js/debug/validator.js b/framework/Web/Javascripts/js/debug/validator.js index 170d7ff1..83453052 100644 --- a/framework/Web/Javascripts/js/debug/validator.js +++ b/framework/Web/Javascripts/js/debug/validator.js @@ -1,4 +1,3 @@ -
/**
* Prado client-side javascript validation fascade.
*
@@ -90,6 +89,15 @@ Object.extend(Prado.Validation, },
/**
+ * @return string first form ID.
+ */
+ 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.
@@ -131,6 +139,21 @@ Object.extend(Prado.Validation, 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;
+ }
+ });
+ });
}
});
@@ -144,11 +167,6 @@ Prado.ValidationManager = Class.create(); */
Prado.ValidationManager.prototype =
{
- validators : [], // list of validators
- summaries : [], // validation summaries
- groups : [], // validation groups
- options : {},
-
/**
* <code>
* options['FormID']* The ID of HTML form to manage.
@@ -156,6 +174,11 @@ Prado.ValidationManager.prototype = */
initialize : function(options)
{
+ this.validators = []; // list of validators
+ this.summaries = []; // validation summaries
+ this.groups = []; // validation groups
+ this.options = {};
+
this.options = options;
Prado.Validation.managers[options.FormID] = this;
},
@@ -333,11 +356,6 @@ Prado.ValidationManager.prototype = Prado.WebUI.TValidationSummary = Class.create();
Prado.WebUI.TValidationSummary.prototype =
{
- group : null,
- options : {},
- visible : false,
- messages : null,
-
/**
* <code>
* options['ID']* Validation summary ID, i.e., an HTML element ID
@@ -357,9 +375,12 @@ Prado.WebUI.TValidationSummary.prototype = this.options = options;
this.group = options.ValidationGroup;
this.messages = $(options.ID);
- this.visible = this.messages.style.visibility != "hidden"
- this.visible = this.visible && this.messages.style.display != "none";
- Prado.Validation.addSummary(options.FormID, this);
+ if(this.messages)
+ {
+ this.visible = this.messages.style.visibility != "hidden"
+ this.visible = this.visible && this.messages.style.display != "none";
+ Prado.Validation.addSummary(options.FormID, this);
+ }
},
/**
@@ -540,15 +561,6 @@ Prado.WebUI.TValidationSummary.prototype = Prado.WebUI.TBaseValidator = Class.create();
Prado.WebUI.TBaseValidator.prototype =
{
- enabled : true,
- visible : false,
- isValid : true,
- options : {},
- _isObserving : {},
- group : null,
- manager : null,
- message : null,
-
/**
* <code>
* options['ID']* Validator ID, e.g. span with message
@@ -561,8 +573,8 @@ Prado.WebUI.TBaseValidator.prototype = * options['ValidationGroup'] Validation group
* options['ControlCssClass'] Css class to use on the input upon error
* options['OnValidate'] Function to call immediately after validation
- * options['OnSuccess'] Function to call upon after successful validation
- * options['OnError'] Function to call upon after error in validation.
+ * options['OnValidationSuccess'] Function to call upon after successful validation
+ * options['OnValidationError'] Function to call upon after error in validation.
* options['ObserveChanges'] True to observe changes in input
* </code>
*/
@@ -572,12 +584,23 @@ Prado.WebUI.TBaseValidator.prototype = options.OnSuccess = options.OnSuccess || Prototype.emptyFunction;
options.OnError = options.OnError || Prototype.emptyFunction;
*/
+
+ this.enabled = true;
+ this.visible = false;
+ this.isValid = true;
+ this._isObserving = {};
+ this.group = null;
+ this.requestDispatched = false;
+
this.options = options;
this.control = $(options.ControlToValidate);
this.message = $(options.ID);
- this.group = options.ValidationGroup;
+ if(this.control && this.message)
+ {
+ this.group = options.ValidationGroup;
- this.manager = Prado.Validation.addValidator(options.FormID, this);
+ this.manager = Prado.Validation.addValidator(options.FormID, this);
+ }
},
/**
@@ -599,6 +622,8 @@ Prado.WebUI.TBaseValidator.prototype = if(this.options.FocusOnError && !this.isValid )
Prado.Element.focus(this.options.FocusElementID);
+
+ this.visible = true;
},
refreshControlAndMessage : function()
@@ -650,8 +675,21 @@ Prado.WebUI.TBaseValidator.prototype = */
validate : function(invoker)
{
+ //try to find the control.
+ if(!this.control)
+ this.control = $(this.options.ControlToValidate);
+
+ if(!this.control)
+ {
+ this.isValid = true;
+ return this.isValid;
+ }
+
if(typeof(this.options.OnValidate) == "function")
- this.options.OnValidate(this, invoker);
+ {
+ if(this.requestDispatched == false)
+ this.options.OnValidate(this, invoker);
+ }
if(this.enabled)
this.isValid = this.evaluateIsValid();
@@ -660,20 +698,26 @@ Prado.WebUI.TBaseValidator.prototype = if(this.isValid)
{
- if(typeof(this.options.OnSuccess) == "function")
+ if(typeof(this.options.OnValidationSuccess) == "function")
{
- this.refreshControlAndMessage();
- this.options.OnSuccess(this, invoker);
+ if(this.requestDispatched == false)
+ {
+ this.refreshControlAndMessage();
+ this.options.OnValidationSuccess(this, invoker);
+ }
}
else
this.updateControl();
}
else
{
- if(typeof(this.options.OnError) == "function")
+ if(typeof(this.options.OnValidationError) == "function")
{
- this.refreshControlAndMessage();
- this.options.OnError(this, invoker);
+ if(this.requestDispatched == false)
+ {
+ this.refreshControlAndMessage();
+ this.options.OnValidationError(this, invoker)
+ }
}
else
this.updateControl();
@@ -1081,6 +1125,51 @@ Prado.WebUI.TCustomValidator = Class.extend(Prado.WebUI.TBaseValidator, });
/**
+ * Uses callback request to perform validation.
+ */
+Prado.WebUI.TActiveCustomValidator = Class.extend(Prado.WebUI.TBaseValidator,
+{
+ validatingValue : null,
+
+ /**
+ * Calls custom validation function.
+ */
+ evaluateIsValid : function()
+ {
+ value = this.getValidationValue();
+ if(!this.requestDispatched && value != this.validatingValue)
+ {
+ this.validatingValue = value;
+ request = new Prado.CallbackRequest(this.options.EventTarget, this.options);
+ request.setCallbackParameter(value);
+ request.setCausesValidation(false);
+ request.options.onSuccess = this.callbackOnSuccess.bind(this);
+ request.options.onFailure = this.callbackOnFailure.bind(this);
+ request.dispatch();
+ this.requestDispatched = true;
+ return false;
+ }
+ return this.isValid;
+ },
+
+ callbackOnSuccess : function(request, data)
+ {
+ this.isValid = data;
+ this.requestDispatched = false;
+ if(typeof(this.options.onSuccess) == "function")
+ this.options.onSuccess(request,data);
+ Prado.Validation.validate(this.options.FormID, this.group,null);
+ },
+
+ callbackOnFailure : function(request, data)
+ {
+ this.requestDispatched = false;
+ if(typeof(this.options.onFailure) == "function")
+ this.options.onFailure(request,data);
+ }
+});
+
+/**
* TRangeValidator tests whether an input value is within a specified range.
*
* TRangeValidator uses three key properties to perform its validation.
@@ -1273,6 +1362,5 @@ Prado.WebUI.TDataTypeValidator = Class.extend(Prado.WebUI.TBaseValidator, return this.convert(this.options.DataType, value) != null;
}
});
-
|