X-Git-Url: https://scm.cri.ensmp.fr/git/Plinn.git/blobdiff_plain/3e0a2c257d49fb162da9c70d2f70194036235166..8f40b26abe44b2589a48b70865a1d4260f041ed4:/skins/ajax_scripts/ajax_form_manager.js diff --git a/skins/ajax_scripts/ajax_form_manager.js b/skins/ajax_scripts/ajax_form_manager.js index 9caf6e4..508a4f9 100644 --- a/skins/ajax_scripts/ajax_form_manager.js +++ b/skins/ajax_scripts/ajax_form_manager.js @@ -1,12 +1,15 @@ // (c) Benoît PIN 2006-2007 // http://plinn.org // Licence GPL -// $Id: ajax_form_manager.js 1470 2009-02-18 16:42:02Z pin $ -// $URL: http://svn.cri.ensmp.fr/svn/Plinn/branches/CMF-2.1/skins/ajax_scripts/ajax_form_manager.js $ +// +// +var FormManager; -function FormManager(form, responseTextDest, lazy) { - if (form.elements.namedItem("noAjax")) return; +(function(){ + +FormManager = function(form, responseTextDest, lazy) { + if (form.elements.namedItem("noAjax")) {return;} this.form = form; this.responseTextDest = responseTextDest; @@ -14,7 +17,6 @@ function FormManager(form, responseTextDest, lazy) { var thisManager = this; this.form.onsubmit = function(evt) { thisManager.submit(evt); }; this.form.onclick = function(evt) { thisManager.click(evt); }; - this.submitButton = null; /* raised on form submit */ this.onBeforeSubmit = null; @@ -26,21 +28,20 @@ function FormManager(form, responseTextDest, lazy) { this.submitButton = null; if (this.lazy) { - this.fieldTagName; - this.liveFormField; - this.pendingEvent; this.form.onclick = function(evt){ thisManager.replaceElementByField(evt); thisManager.click(evt); }; - if (browser.isDOM2Event) + if (browser.isDOM2Event) { this.form.onfocus = this.form.onclick; - else if (browser.isIE6up) + } + else if (browser.isIE6up) { this.form.onfocusin = this.form.onclick; + } this.onResponseLoad = function(req){ thisManager.restoreField(req); }; - this.lazyListeners = new Array(); + this.lazyListeners = []; } -} +}; FormManager.prototype.submit = function(evt) { var form = this.form; @@ -50,16 +51,19 @@ FormManager.prototype.submit = function(evt) { if (!this.onBeforeSubmit) { var onBeforeSubmit = form.elements.namedItem("onBeforeSubmit"); if (onBeforeSubmit) { - if (onBeforeSubmit.length) + if (onBeforeSubmit.length) { onBeforeSubmit = onBeforeSubmit[0]; + } + /*jslint evil: true */ this.onBeforeSubmit = eval(onBeforeSubmit.value); bsMessage = this.onBeforeSubmit(thisManager, evt); } } - else + else { bsMessage = this.onBeforeSubmit(thisManager, evt); + } - if (bsMessage == 'cancelSubmit') { + if (bsMessage === 'cancelSubmit') { try {disableDefault(evt);} catch (e){} return; @@ -67,41 +71,48 @@ FormManager.prototype.submit = function(evt) { if (!this.onResponseLoad) { var onResponseLoad = form.elements.namedItem("onResponseLoad"); - if (onResponseLoad) + if (onResponseLoad) { this.onResponseLoad = eval(onResponseLoad.value); - else + } + else { this.onResponseLoad = this.loadResponse; + } } var submitButton = this.submitButton; var queryInfo = this.formData2QueryString(); - var query = queryInfo['query']; - this.hasFile = queryInfo['hasFile']; + var query = queryInfo.query; + this.hasFile = queryInfo.hasFile; if (!this.onAfterPopulate) { var onAfterPopulate = form.elements.namedItem("onAfterPopulate"); - if (onAfterPopulate) + if (onAfterPopulate) { this.onAfterPopulate = onAfterPopulate.value; - else + } + else { this.onAfterPopulate = function() {}; + } } if (submitButton) { query += submitButton.name + '=' + submitButton.value + '&'; } - if (window.AJAX_CONFIG && (AJAX_CONFIG & 1 == 1)) { - if (form.method.toLowerCase() == 'post') + if (window.AJAX_CONFIG && ((AJAX_CONFIG & 1) === 1)) { + if (form.method.toLowerCase() === 'post') { this._post(query); - else - this._get(query) + } + else { + this._get(query); + } } - else + else { this._post(query); + } try {disableDefault(evt);} - catch (e){} + catch (e2){} }; FormManager.prototype._post = function(query) { @@ -117,11 +128,14 @@ FormManager.prototype._post = function(query) { break; case 4 : hideProgressImage(); - if (req.status == 200 || req.status == 204) + if (req.status === 200 || req.status === 204) { thisManager.onResponseLoad(req); - else + } + else { alert('Error: ' + req.status); - }; + } + break; + } }; var url = this.form.action; req.open("POST", url, true); @@ -132,14 +146,14 @@ FormManager.prototype._post = function(query) { FormManager.prototype._get = function(query) { // send form by browser location var url = this.form.action; - url += '?' + query + url += '?' + query; linkHandler.loadUrl(url); }; FormManager.prototype.click = function(evt) { var target = getTargetedObject(evt); - if(target.type == "submit" || target.type == "image") { + if(target.type === "submit" || target.type === "image") { this.submitButton = target; disablePropagation(evt); } @@ -149,9 +163,10 @@ FormManager.prototype.replaceElementByField = function(evt) { evt = getEventObject(evt); var ob = getTargetedObject(evt); var eventType = evt.type; - if (eventType == 'focus' || eventType == 'focusin') { - if (this.liveFormField && ob.tagName != 'INPUT') + if (eventType === 'focus' || eventType === 'focusin') { + if (this.liveFormField && ob.tagName !== 'INPUT') { this.pendingEvent = [ob, 'click']; + } return; } var fieldName = ob.getAttribute('id'); @@ -159,11 +174,15 @@ FormManager.prototype.replaceElementByField = function(evt) { this.fieldTagName = ob.tagName; var tabIndex = ob.tabIndex; var text; - if (ob.firstChild && ob.firstChild.className == 'hidden_value') + if (ob.firstChild && ob.firstChild.className === 'hidden_value') { text = ob.firstChild.innerHTML; - else + } + else { text = ob.innerHTML; + } disablePropagation(evt); + var parent; + thisManager = this; switch (ob.tagName) { case 'SPAN' : // create input element @@ -180,7 +199,7 @@ FormManager.prototype.replaceElementByField = function(evt) { //inputText.setAttribute("size", text.length); // replacement - var parent = ob.parentNode; + parent = ob.parentNode; parent.replaceChild(inputText, ob); inputText.focus(); @@ -189,7 +208,6 @@ FormManager.prototype.replaceElementByField = function(evt) { inputText.tabIndex = tabIndex; inputText.className = 'live_field'; this.liveFormField = inputText; - var thisManager = this; this.lazyListeners.push({'element': inputText, 'eventName' : 'blur', 'handler': function(){ thisManager.submit();}}); this.lazyListeners.push({'element': inputText, 'eventName' : 'keypress', 'handler': function(evt){ thisManager._fitField(evt);}}); this._addLazyListeners(); @@ -206,7 +224,7 @@ FormManager.prototype.replaceElementByField = function(evt) { ta.value = text; // replacement - var parent = ob.parentNode; + parent = ob.parentNode; parent.replaceChild(ta, ob); ta.focus(); @@ -214,27 +232,26 @@ FormManager.prototype.replaceElementByField = function(evt) { ta.setAttribute('name', fieldName); ta.tabIndex = tabIndex; this.liveFormField = ta; - var thisManager = this; this.lazyListeners.push({'element': ta, 'eventName' : 'blur', 'handler': function(){ thisManager.submit();}}); this._addLazyListeners(); break; - - - }; + } } }; FormManager.prototype._addLazyListeners = function() { - for (var i=0 ; i<this.lazyListeners.length ; i++) { - var handlerInfo = this.lazyListeners[i]; - addListener(handlerInfo['element'], handlerInfo['eventName'], handlerInfo['handler']); + var i, handlerInfo; + for (i=0 ; i<this.lazyListeners.length ; i++) { + handlerInfo = this.lazyListeners[i]; + addListener(handlerInfo.element, handlerInfo.eventName, handlerInfo.handler); } }; FormManager.prototype._removeLazyListeners = function() { - for (var i=0 ; i<this.lazyListeners.length ; i++) { - var handlerInfo = this.lazyListeners[i]; - removeListener(handlerInfo['element'], handlerInfo['eventName'], handlerInfo['handler']); + var i, handlerInfo; + for (i=0 ; i<this.lazyListeners.length ; i++) { + handlerInfo = this.lazyListeners[i]; + removeListener(handlerInfo.element, handlerInfo.eventName, handlerInfo.handler); } }; @@ -242,11 +259,12 @@ FormManager.prototype._removeLazyListeners = function() { FormManager.prototype.restoreField = function(req) { var text; var input = this.liveFormField; - if (req.status == 200) { - if (req.getResponseHeader('Content-Type').indexOf('text/xml') != -1) { + if (req.status === 200) { + if (req.getResponseHeader('Content-Type').indexOf('text/xml') !== -1) { var out = '..........'; - if (req.responseXML.documentElement.firstChild) + if (req.responseXML.documentElement.firstChild) { out = req.responseXML.documentElement.firstChild.nodeValue; + } switch (req.responseXML.documentElement.nodeName) { case 'computedField': @@ -259,18 +277,19 @@ FormManager.prototype.restoreField = function(req) { input.focus(); this._addLazyListeners(); return false; - break; } } else { text = req.responseText; } } - else + else { text = ''; + } - if (!text.match(/\w/)) + if (!text.match(/\w/)) { text = '..........'; + } var field = document.createElement(this.fieldTagName); field.innerHTML = text; @@ -282,8 +301,9 @@ FormManager.prototype.restoreField = function(req) { parent.replaceChild(field, input); this.liveFormField = null; - if (this.pendingEvent) + if (this.pendingEvent) { raiseMouseEvent(this.pendingEvent[0], this.pendingEvent[1]); + } return true; }; @@ -293,26 +313,29 @@ FormManager.prototype.formData2QueryString = function() { var form = this.form; var strSubmit = '', formElem, elements; var hasFile = false; + var i; - if (!this.lazy) + if (!this.lazy) { elements = form.elements; + } else { - elements = new Array(); + elements = []; var formElements = form.elements; - for (var i = 0; i < formElements.length; i++) { + for (i = 0; i < formElements.length; i++) { formElem = formElements[i]; switch (formElem.type) { case 'hidden': elements.push(formElem); break; default : - if (formElem == this.liveFormField) + if (formElem === this.liveFormField) { elements.push(formElem); - }; + } + } } } - - for (var i = 0; i < elements.length; i++) { + + for (i = 0; i < elements.length; i++) { formElem = elements[i]; switch (formElem.type) { // text, select, hidden, password, textarea elements @@ -325,28 +348,33 @@ FormManager.prototype.formData2QueryString = function() { break; case 'radio': case 'checkbox': - if (formElem.checked) + if (formElem.checked) { strSubmit += formElem.name + '=' + encodeURIComponent(formElem.value) + '&'; + } break; case 'select-multiple': var options = formElem.getElementsByTagName("OPTION"), option; - for (var j = 0 ; j < options.length ; j++) { + var j; + for (j = 0 ; j < options.length ; j++) { option = options[j]; - if (option.selected) + if (option.selected) { strSubmit += formElem.name + '=' + encodeURIComponent(option.value) + '&'; + } } break; case 'file': - if (formElem.value) + if (formElem.value) { hasFile = true; + } break; - }; + } } return {'query' : strSubmit, 'hasFile' : hasFile}; }; FormManager.prototype.loadResponse = function(req) { - if (req.getResponseHeader('Content-Type').indexOf('text/xml') != -1) { + var scripts; + if (req.getResponseHeader('Content-Type').indexOf('text/xml') !== -1) { switch(req.responseXML.documentElement.nodeName) { case 'fragments' : if (this.hasFile) { @@ -363,16 +391,19 @@ FormManager.prototype.loadResponse = function(req) { return; } var fragments = req.responseXML.documentElement.childNodes; - var fragment, dest, scripts; - for (var i=0 ; i<fragments.length ; i++) { + var fragment, dest; + var i; + for (i=0 ; i<fragments.length ; i++) { fragment = fragments[i]; - if (fragment.nodeName == 'fragment') { + if (fragment.nodeName === 'fragment') { dest = document.getElementById(fragment.getAttribute('id')); dest.innerHTML = fragment.firstChild.nodeValue; scripts = dest.getElementsByTagName('script'); - for (var j=0 ; j < scripts.length ; j++) + var j; + for (j=0 ; j < scripts.length ; j++) { globalScriptRegistry.loadScript(scripts[j]); + } } } break; @@ -383,18 +414,26 @@ FormManager.prototype.loadResponse = function(req) { } else { this.responseTextDest.innerHTML = req.responseText; - var scripts = this.responseTextDest.getElementsByTagName('script'); - for (var j=0 ; j < scripts.length ; j++) - globalScriptRegistry.loadScript(scripts[j]); + scripts = this.responseTextDest.getElementsByTagName('script'); + var k; + for (k=0 ; k < scripts.length ; k++) { + globalScriptRegistry.loadScript(scripts[k]); + } } var onAfterPopulate = this.onAfterPopulate; - if (typeof(onAfterPopulate) == "string") { - if (window.console) - console.warn('Deprecation WARNING onAfterPopulate: ' + onAfterPopulate); - onAfterPopulate = eval(onAfterPopulate); - } onAfterPopulate(); + this.scrollToPortalMessage(); + history.pushState(absolute_url(), document.title, absolute_url()); +}; + +FormManager.prototype.scrollToPortalMessage = function() { + var psm = document.getElementById('DesktopStatusBar'); + if (psm) { + var msgOffset = psm.offsetTop; + smoothScroll(window.scrollY, msgOffset); + shake(psm, 10, 1000); + } }; FormManager.prototype._fitField = function(evt) { @@ -405,14 +444,80 @@ FormManager.prototype._fitField = function(evt) { }; function initForms(baseElement, lazy) { - if (!baseElement) + if (!baseElement) { baseElement = document; + } var dest = document.getElementById("mainCell"); var forms = baseElement.getElementsByTagName("form"); - var f; - for (var i = 0 ; i < forms.length ; i++ ) + var f, i; + for (i = 0 ; i < forms.length ; i++ ) { f = new FormManager(forms[i], dest, lazy); + } +} + +function smoothScroll(from, to) { + var intervalId; + var step = 25; + var pos = from; + var dir; + if (to > from) { + dir = 1; + } + else { + dir = -1; + } + + var jump = function() { + window.scroll(0, pos); + pos = pos + step * dir; + if ((dir === 1 && pos >= to) || + (dir === -1 && pos <= to)) { + window.clearInterval(intervalId); + window.scroll(0, to); + } + }; + intervalId = window.setInterval(jump, 10); } +/* adapted from http://xahlee.info/js/js_shake_box.html */ +function shake(e, distance, time) { + // Handle arguments + if (!time) { time = 500; } + if (!distance) { distance = 5; } + + // Save the original style of e, Make e relatively positioned, Note the animation start time, Start the animation + var originalStyle = e.style.cssText; + e.style.position = "relative"; + var start = (new Date()).getTime(); + + // This function checks the elapsed time and updates the position of e. + // If the animation is complete, it restores e to its original state. + // Otherwise, it updates e's position and schedules itself to run again. + function animate() { + var now = (new Date()).getTime(); + // Get current time + var elapsed = now-start; + // How long since we started + var fraction = elapsed/time; + // What fraction of total time? + if (fraction < 1) { + // If the animation is not yet complete + // Compute the x position of e as a function of animation + // completion fraction. We use a sinusoidal function, and multiply + // the completion fraction by 4pi, so that it shakes back and + // forth twice. + var x = distance * Math.sin(fraction*8*Math.PI); + e.style.left = x + "px"; + // Try to run again in 25ms or at the end of the total time. + // We're aiming for a smooth 40 frames/second animation. + setTimeout(animate, Math.min(25, time-elapsed)); + } + else { + // Otherwise, the animation is complete + e.style.cssText = originalStyle; // Restore the original style + } + } + animate(); +} -//registerStartupFunction(initForms); \ No newline at end of file +}());