/************************************************************************************************************
Ajax form submit
Copyright (C) 2007 DTHMLGoodies.com, Alf Magne Kalleland
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
Dhtmlgoodies.com., hereby disclaims all copyright interest in this script
written by Alf Magne Kalleland.
Alf Magne Kalleland, 2007
Owner of DHTMLgoodies.com
************************************************************************************************************/
var DHTMLSuite = new Object();
DHTMLSuite.formUtil = function()
{
}
DHTMLSuite.getEl = function(elRef){
if(typeof elRef=='string'){
if(document.getElementById(elRef))return document.getElementById(elRef);
if(document.forms[elRef])return document.forms[elRef];
if(document[elRef])return document[elRef];
if(window[elRef])return window[elRef];
}
return elRef; // Return original ref.
}
DHTMLSuite.formUtil.prototype =
{
// {{{ getFamily
/**
* Return an array of elements with the same name
* @param Object el - Reference to form element
* @param Object formRef - Reference to form
*
* @public
*/
getFamily : function(el,formRef)
{
var els = formRef.elements;
var retArray = new Array();
for(var no=0;no<els.length;no++){
if(els[no].name == el.name)retArray[retArray.length] = els[no];
}
return retArray;
}
// }}}
,
// {{{ hasFileInputs()
/**
* Does the form has file inputs?
* @param Object formRef - Reference to form
*
* @public
*/
hasFileInputs : function(formRef)
{
var els = formRef.elements;
for(var no=0;no<els.length;no++){
if(els[no].tagName.toLowerCase()=='input' && els[no].type.toLowerCase()=='file')return true;
}
return false;
}
// }}}
,
// {{{ getValuesAsArray()
/**
* Return value of form as associative array
* @param Object formRef - Reference to form
*
* @public
*/
getValuesAsArray : function(formRef)
{
var retArray = new Object();
formRef = DHTMLSuite.getEl(formRef);
var els = formRef.elements;
for(var no=0;no<els.length;no++){
if(els[no].disabled)continue;
var tag = els[no].tagName.toLowerCase();
switch(tag){
case "input":
var type = els[no].type.toLowerCase();
if(!type)type='text';
switch(type){
case "text":
case "image":
case "hidden":
case "password":
retArray[els[no].name] = els[no].value;
break;
case "checkbox":
var boxes = this.getFamily(els[no],formRef);
if(boxes.length>1){
retArray[els[no].name] = new Array();
for(var no2=0;no2<boxes.length;no2++){
if(boxes[no2].checked){
var index = retArray[els[no].name].length;
retArray[els[no].name][index] = boxes[no2].value;
}
}
}else{
if(els[no].checked)retArray[els[no].name] = els[no].value;
}
break;
case "radio":
if(els[no].checked)retArray[els[no].name] = els[no].value;
break;
}
break;
case "select":
var string = '';
var mult = els[no].getAttribute('multiple');
if(mult || mult===''){
retArray[els[no].name] = new Array();
for(var no2=0;no2<els[no].options.length;no2++){
var index = retArray[els[no].name].length;
if(els[no].options[no2].selected)retArray[els[no].name][index] = els[no].options[no2].value;
}
}else{
retArray[els[no].name] = els[no].options[els[no].selectedIndex].value;
}
break;
case "textarea":
retArray[els[no].name] = els[no].value;
break;
}
}
return retArray;
}
// }}}
,
// {{{ getValue()
/**
* Return value of form element
* @param Object formEl - Reference to form element
*
* @public
*/
getValue : function(formEl)
{
switch(formEl.tagName.toLowerCase()){
case "input":
case "textarea": return formEl.value;
case "select": return formEl.options[formEl.selectedIndex].value;
}
}
// }}}
,
// {{{ areEqual()
/**
* Check if two form elements have the same value
* @param Object input1 - Reference to form element
* @param Object input2 - Reference to form element
*
* @public
*/
areEqual : function(input1,input2)
{
input1 = DHTMLSuite.getEl(input1);
input2 = DHTMLSuite.getEl(input2);
if(this.getValue(input1)==this.getValue(input2))return true;
return false;
}
}
/************************************************************************************************************
* Form submission class
*
* Created: March, 6th, 2007
* @class Purpose of class: Ajax form submission class
*
* Css files used by this script: form.css
*
* Demos of this class: demo-form-validator.html
*
* Update log:
*
************************************************************************************************************/
/**
* @constructor
* @class Form submission
* Demo: <a href="../../demos/demo-form-validator.html" target="_blank">demo-form-validator.html</a>
*
* @param Associative array of properties, possible keys: <br>
* formRef - Reference to form<br>
* method - How to send the form, "GET" or "POST", default is "POST"
* reponseEl - Where to display response from ajax
* action - Where to send form data
* responseFile - Alternative response file. This will be loaded dynamically once the script receives response from the file specified in "action".
*
* @version 1.0
* @version 1.0
* @author Alf Magne Kalleland(www.dhtmlgoodies.com)
**/
DHTMLSuite.variableStorage = new Object();
DHTMLSuite.variableStorage.arrayDSObjects = new Array();
DHTMLSuite.form = function(propArray)
{
var formRef;
var method;
var responseEl;
var action;
var responseFile;
var formUtil;
var objectIndex;
var sackObj;
var coverDiv;
var layoutCSS;
var iframeName;
this.method = 'POST';
this.sackObj = new Array();
this.formUtil = new DHTMLSuite.formUtil();
this.layoutCSS = 'form.css';
this.objectIndex = DHTMLSuite.variableStorage.arrayDSObjects.length;
DHTMLSuite.variableStorage.arrayDSObjects[this.objectIndex] = this;
if(propArray)this.__setInitProperties(propArray);
}
DHTMLSuite.form.prototype =
{
// {{{ submit()
/**
* Submits the form
*
* @public
*/
submit : function()
{
this.__createCoverDiv();
var index = this.sackObj.length;
if(this.formUtil.hasFileInputs(this.formRef)){
this.__createIframe();
this.formRef.submit();
}else{
this.__createSackObject(index);
this.__populateSack(index);
this.sackObj[index].runAJAX();
}
this.__positionCoverDiv();
return false;
}
// }}}
,
__createIframe : function()
{
if(this.iframeName)return;
var ind = this.objectIndex;
var div = document.createElement('DIV');
document.body.appendChild(div);
this.iframeName = 'DHTMLSuiteForm' + this.getUniqueId();
div.innerHTML = '<iframe style="visibility:hidden;width:5px;height:5px" id="' + this.iframeName + '" name="' + this.iframeName + '" onload="parent.DHTMLSuite.variableStorage.arrayDSObjects[' + ind + '].__getIframeResponse()"></iframe>';
this.formRef.method = this.method;
this.formRef.action = this.action;
this.formRef.target = this.iframeName;
if(!this.formRef.enctype)this.formRef.enctype = 'multipart/form-data';
}
,
// {{{ getUniqueId()
/**
*
* Returns a unique numeric id
*
*
*
* @public
*/
getUniqueId : function()
{
var no = Math.random() + '';
no = no.replace('.','');
var no2 = Math.random() + '';
no2 = no2.replace('.','');
return no + no2;
}
// }}}
,
// {{{ __getIframeResponse()
/**
* Form has been submitted to iframe - move content from iframe
*
* @private
*/
__getIframeResponse : function()
{
if(this.responseEl){
if(this.responseFile){
if(!this.responseEl.id)this.responseEl.id = 'DHTMLSuite_formResponse' + DHTMLSuite.getUniqueId();
var dynContent = new DHTMLSuite.dynamicContent();
dynContent.loadContent(this.responseEl.id,this.responseFile);
}else{
this.responseEl.innerHTML = self.frames[this.iframeName].document.body.innerHTML;
this.__evaluateJs(this.responseEl);
this.__evaluateCss(this.responseEl);
}
}
this.coverDiv.style.display='none';
this.__handleCallback('onComplete');
}
// }}}
,
// {{{ __positionCoverDiv()
/**
* Position cover div
*
* @private
*/
__positionCoverDiv : function()
{
if(!this.responseEl)return;
try{
var st = this.coverDiv.style;
st.left = this.getLeftPos(this.responseEl) + 'px';
st.top = this.getTopPos(this.responseEl) + 'px';
st.width = this.responseEl.offsetWidth + 'px';
st.height = this.responseEl.offsetHeight + 'px';
st.display='block';
}catch(e){
}
}
// }}}
,
// {{{ __createCoverDiv()
/**
* Submits the form
*
* @private
*/
__createCoverDiv : function()
{
if(this.coverDiv)return;
this.coverDiv = document.createElement('DIV');
var el = this.coverDiv;
el.style.overflow='hidden';
el.style.zIndex = 1000;
el.style.position = 'absolute';
document.body.appendChild(el);
var innerDiv = document.createElement('DIV');
innerDiv.style.width='105%';
innerDiv.style.height='105%';
innerDiv.className = 'DHTMLSuite_formCoverDiv';
innerDiv.style.opacity = '0.2';
innerDiv.style.filter = 'alpha(opacity=20)';
el.appendChild(innerDiv);
var ajaxLoad = document.createElement('DIV');
ajaxLoad.className = 'DHTMLSuite_formCoverDiv_ajaxLoader';
el.appendChild(ajaxLoad);
}
// }}}
,
// {{{ __createSackObject()
/**
* Create new sack object
*
* @private
*/
__createSackObject : function(ajaxIndex)
{
var ind = this.objectIndex;
this.sackObj[ajaxIndex] = new sack();
this.sackObj[ajaxIndex].requestFile = this.action;
this.sackObj[ajaxIndex].method = this.method;
this.sackObj[ajaxIndex].onCompletion = function(){ DHTMLSuite.variableStorage.arrayDSObjects[ind].__getResponse(ajaxIndex); }
}
// }}}
,
// {{{ __getResponse()
/**
* Get response from ajax
*
* @private
*/
__getResponse : function(ajaxIndex)
{
if(this.responseEl){
if(this.responseFile){
if(!this.responseEl.id)this.responseEl.id = 'DHTMLSuite_formResponse' + DHTMLSuite.getUniqueId();
var dynContent = new DHTMLSuite.dynamicContent();
dynContent.loadContent(this.responseEl.id,this.responseFile);
}else{
this.responseEl.innerHTML = this.sackObj[ajaxIndex].response;
this.__evaluateJs(this.responseEl);
this.__evaluateCss(this.responseEl);
}
}
this.coverDiv.style.display='none';
this.sackObj[ajaxIndex] = null;
this.__handleCallback('onComplete');
}
,
// {{{ isArray()
/**
* Return true if element is an array
*
* @param Object el = Reference to HTML element
* @public
*/
isArray : function(el)
{
if(el.constructor.toString().indexOf("Array") != -1)return true;
return false;
}
// }}}
,
// {{{ __populateSack()
/**
* Populate sack object with form data
* @param ajaxIndex - index of current sack object
*
* @private
*/
__populateSack : function(ajaxIndex)
{
var els = this.formUtil.getValuesAsArray(this.formRef);
for(var prop in els){
if(this.isArray(els[prop])){
for(var no=0;no<els[prop].length;no++){
var name = prop + '[' + no + ']';
if(prop.indexOf('[')>=0){ // The name of the form field is already indicating an array
name = prop.replace('[','[' + no);
}
this.sackObj[ajaxIndex].setVar(name,els[prop][no]);
}
}else{
this.sackObj[ajaxIndex].setVar(prop,els[prop]);
}
}
}
// }}}
,
// {{{ __setInitProperties()
/**
* Fill object with data sent to the constructor
* @param Array props - Associative Array("Object") of properties
*
* @private
*/
__setInitProperties : function(props)
{
if(props.formRef)this.formRef = DHTMLSuite.getEl(props.formRef);
if(props.method)this.method = props.method;
if(props.responseEl)this.responseEl = DHTMLSuite.getEl(props.responseEl);
if(props.action)this.action = props.action;
if(props.responseFile)this.responseFile = props.responseFile;
if(props.callbackOnComplete)this.callbackOnComplete = props.callbackOnComplete;
if(!this.action)this.action = this.formRef.action;
if(!this.method)this.method = this.formRef.method;
}
// }}}
,
// {{{ __handleCallback()
/**
* Execute callback
* @param String action - Which callback action
*
* @private
*/
__handleCallback : function(action)
{
var callbackString = '';
switch(action){
case "onComplete":
callbackString = this.callbackOnComplete;
break;
}
if(callbackString){
if(callbackString.indexOf('(')==-1)callbackString = callbackString + '("' + this.formRef.name + '")';
eval(callbackString);
}
}
,
// {{{ __evaluateJs()
/**
* Evaluate Javascript in the inserted content
*
* @private
*/
__evaluateJs : function(obj)
{
obj = DHTMLSuite.getEl(obj);
var scriptTags = obj.getElementsByTagName('SCRIPT');
var string = '';
var jsCode = '';
for(var no=0;no<scriptTags.length;no++){
if(scriptTags[no].src){
var head = document.getElementsByTagName("head")[0];
var scriptObj = document.createElement("script");
scriptObj.setAttribute("type", "text/javascript");
scriptObj.setAttribute("src", scriptTags[no].src);
}else{
if(DHTMLSuite.clientInfoObj.isOpera){
jsCode = jsCode + scriptTags[no].text + '\n';
}
else
jsCode = jsCode + scriptTags[no].innerHTML;
}
}
if(jsCode)this.__installScript(jsCode);
}
// }}}
,
// {{{ __installScript()
/**
* "Installs" the content of a <script> tag.
*
* @private
*/
__installScript : function ( script )
{
try{
if (!script)
return;
if (window.execScript){
window.execScript(script)
}else if(window.jQuery && jQuery.browser.safari){ // safari detection in jQuery
window.setTimeout(script,0);
}else{
window.setTimeout( script, 0 );
}
}catch(e){
}
}
// }}}
,
// {{{ __evaluateCss()
/**
* Evaluates css
*
* @private
*/
__evaluateCss : function(obj)
{
obj = DHTMLSuite.getEl(obj);
var cssTags = obj.getElementsByTagName('STYLE');
var head = document.getElementsByTagName('HEAD')[0];
for(var no=0;no<cssTags.length;no++){
head.appendChild(cssTags[no]);
}
}
// }}}
,
// {{{ getLeftPos()
/**
* This method will return the left coordinate(pixel) of an HTML element
*
* @param Object el = Reference to HTML element
* @public
*/
getLeftPos : function(el)
{
/*
if(el.getBoundingClientRect){ // IE
var box = el.getBoundingClientRect();
return (box.left/1 + Math.max(document.body.scrollLeft,document.documentElement.scrollLeft));
}
*/
if(document.getBoxObjectFor){
if(el.tagName!='INPUT' && el.tagName!='SELECT' && el.tagName!='TEXTAREA')return document.getBoxObjectFor(el).x
}
var returnValue = el.offsetLeft;
while((el = el.offsetParent) != null){
if(el.tagName!='HTML'){
returnValue += el.offsetLeft;
if(document.all)returnValue+=el.clientLeft;
}
}
return returnValue;
}
// }}}
,
// {{{ getTopPos()
/**
* This method will return the top coordinate(pixel) of an HTML element/tag
*
* @param Object el = Reference to HTML element
* @public
*/
getTopPos : function(el)
{
/*
if(el.getBoundingClientRect){ // IE
var box = el.getBoundingClientRect();
return (box.top/1 + Math.max(document.body.scrollTop,document.documentElement.scrollTop));
}
*/
if(document.getBoxObjectFor){
if(el.tagName!='INPUT' && el.tagName!='SELECT' && el.tagName!='TEXTAREA')return document.getBoxObjectFor(el).y
}
var returnValue = el.offsetTop;
while((el = el.offsetParent) != null){
if(el.tagName!='HTML'){
returnValue += (el.offsetTop - el.scrollTop);
if(document.all)returnValue+=el.clientTop;
}
}
return returnValue;
}
}