(function($){
$.fn.ajaxSubmit=function(options){
if(!this.length){
log('ajaxSubmit: skipping submit process - no element selected')
return this}
if(typeof options=='function')
options={success: options}
options=$.extend({
url: this.attr('action')|| window.location.toString(),
type: this.attr('method')|| 'GET'
},options ||{})
var veto={}
this.trigger('form-pre-serialize',[this,options,veto])
if(veto.veto){
log('ajaxSubmit: submit vetoed via form-pre-serialize trigger')
return this}
var a=this.formToArray(options.semantic)
if(options.data){
options.extraData=options.data
for(var n in options.data)
a.push({name: n,value: options.data[n]})}
if(options.beforeSubmit&&options.beforeSubmit(a,this,options)===false){
log('ajaxSubmit: submit aborted via beforeSubmit callback')
return this}
this.trigger('form-submit-validate',[a,this,options,veto])
if(veto.veto){
log('ajaxSubmit: submit vetoed via form-submit-validate trigger')
return this}
var q=$.param(a)
if(options.type.toUpperCase()=='GET'){
options.url+=(options.url.indexOf('?')>=0 ? '&' : '?')+q
options.data=null}
else
options.data=q
var $form=this,callbacks=[]
if(options.resetForm)callbacks.push(function(){$form.resetForm();})
if(options.clearForm)callbacks.push(function(){$form.clearForm();})
if(!options.dataType&&options.target){
var oldSuccess=options.success || function(){}
callbacks.push(function(data){
$(options.target).html(data).each(oldSuccess,arguments)
})}
else if(options.success)
callbacks.push(options.success)
options.success=function(data,status){
for(var i=0,max=callbacks.length;i<max;i++)
callbacks[i](data,status,$form)}
var files=$('input:file',this).fieldValue()
var found=false
for(var j=0;j<files.length;j++)
if(files[j])
found=true
if(options.iframe || found){
if($.browser.safari&&options.closeKeepAlive)
$.get(options.closeKeepAlive,fileUpload)
else
fileUpload()}
else
$.ajax(options)
this.trigger('form-submit-notify',[this,options])
return this
function fileUpload(){
var form=$form[0]
if($(':input[@name=submit]',form).length){
alert('Error: Form elements must not be named "submit".')
return}
var opts=$.extend({},$.ajaxSettings,options)
var id='jqFormIO'+(new Date().getTime())
var $io=$('<iframe id="'+id+'" name="'+id+'" />')
var io=$io[0]
if($.browser.msie || $.browser.opera)
io.src='javascript:false;document.write("");'
$io.css({position: 'absolute',top: '-1000px',left: '-1000px'})
var xhr={
responseText: null,
responseXML: null,
status: 0,
statusText: 'n/a',
getAllResponseHeaders: function(){},
getResponseHeader: function(){},
setRequestHeader: function(){}}
var g=opts.global
if(g&&! $.active++)$.event.trigger("ajaxStart")
if(g)$.event.trigger("ajaxSend",[xhr,opts])
var cbInvoked=0
var timedOut=0
var sub=form.clk
if(sub){
var n=sub.name
if(n&&!sub.disabled){
options.extraData=options.extraData ||{}
options.extraData[n]=sub.value
if(sub.type=="image"){
options.extraData[name+'.x']=form.clk_x
options.extraData[name+'.y']=form.clk_y}}}
setTimeout(function(){
var t=$form.attr('target'),a=$form.attr('action')
$form.attr({
target: id,
encoding: 'multipart/form-data',
enctype: 'multipart/form-data',
method: 'POST',
action: opts.url
})
if(opts.timeout)
setTimeout(function(){timedOut=true;cb();},opts.timeout)
var extraInputs=[]
try{
if(options.extraData)
for(var n in options.extraData)
extraInputs.push(
$('<input type="hidden" name="'+n+'" value="'+options.extraData[n]+'" />')
.appendTo(form)[0])
$io.appendTo('body')
io.attachEvent ? io.attachEvent('onload',cb): io.addEventListener('load',cb,false)
form.submit()}
finally{
$form.attr('action',a)
t ? $form.attr('target',t): $form.removeAttr('target')
$(extraInputs).remove()}
},10)
function cb(){
if(cbInvoked++)return
io.detachEvent ? io.detachEvent('onload',cb): io.removeEventListener('load',cb,false)
var operaHack=0
var ok=true
try{
if(timedOut)throw 'timeout'
var data,doc
doc=io.contentWindow ? io.contentWindow.document : io.contentDocument ? io.contentDocument : io.document
if(doc.body==null&&!operaHack&&$.browser.opera){
operaHack=1
cbInvoked--
setTimeout(cb,100)
return}
xhr.responseText=doc.body ? doc.body.innerHTML : null
xhr.responseXML=doc.XMLDocument ? doc.XMLDocument : doc
xhr.getResponseHeader=function(header){
var headers={'content-type': opts.dataType}
return headers[header]}
if(opts.dataType=='json' || opts.dataType=='script'){
var ta=doc.getElementsByTagName('textarea')[0]
xhr.responseText=ta ? ta.value : xhr.responseText}
else if(opts.dataType=='xml'&&!xhr.responseXML&&xhr.responseText !=null){
xhr.responseXML=toXml(xhr.responseText)}
data=$.httpData(xhr,opts.dataType)}
catch(e){
ok=false
$.handleError(opts,xhr,'error',e)}
if(ok){
opts.success(data,'success')
if(g)$.event.trigger("ajaxSuccess",[xhr,opts])}
if(g)$.event.trigger("ajaxComplete",[xhr,opts])
if(g&&!--$.active)$.event.trigger("ajaxStop")
if(opts.complete)opts.complete(xhr,ok ? 'success' : 'error')
setTimeout(function(){
$io.remove()
xhr.responseXML=null
},100)}
function toXml(s,doc){
if(window.ActiveXObject){
doc=new ActiveXObject('Microsoft.XMLDOM')
doc.async='false'
doc.loadXML(s)}
else
doc=(new DOMParser()).parseFromString(s,'text/xml')
return(doc&&doc.documentElement&&doc.documentElement.tagName !='parsererror')? doc : null}}}
$.fn.ajaxForm=function(options){
return this.ajaxFormUnbind().bind('submit.form-plugin',function(){
$(this).ajaxSubmit(options)
return false
}).each(function(){
$(":submit,input:image",this).bind('click.form-plugin',function(e){
var $form=this.form
$form.clk=this
if(this.type=='image'){
if(e.offsetX !=undefined){
$form.clk_x=e.offsetX
$form.clk_y=e.offsetY
}else if(typeof $.fn.offset=='function'){
var offset=$(this).offset()
$form.clk_x=e.pageX-offset.left
$form.clk_y=e.pageY-offset.top
}else{
$form.clk_x=e.pageX-this.offsetLeft
$form.clk_y=e.pageY-this.offsetTop}}
setTimeout(function(){$form.clk=$form.clk_x=$form.clk_y=null;},10)
})
})}
$.fn.ajaxFormUnbind=function(){
this.unbind('submit.form-plugin')
return this.each(function(){
$(":submit,input:image",this).unbind('click.form-plugin')
})}
$.fn.formToArray=function(semantic){
var a=[]
if(this.length==0)return a
var form=this[0]
var els=semantic ? form.getElementsByTagName('*'): form.elements
if(!els)return a
for(var i=0,max=els.length;i<max;i++){
var el=els[i]
var n=el.name
if(!n)continue
if(semantic&&form.clk&&el.type=="image"){
if(!el.disabled&&form.clk==el)
a.push({name: n+'.x',value: form.clk_x},{name: n+'.y',value: form.clk_y})
continue}
var v=$.fieldValue(el,true)
if(v&&v.constructor==Array){
for(var j=0,jmax=v.length;j<jmax;j++)
a.push({name: n,value: v[j]})}
else if(v !==null&&typeof v !='undefined')
a.push({name: n,value: v})}
if(!semantic&&form.clk){
var inputs=form.getElementsByTagName("input")
for(var i=0,max=inputs.length;i<max;i++){
var input=inputs[i]
var n=input.name
if(n&&!input.disabled&&input.type=="image"&&form.clk==input)
a.push({name: n+'.x',value: form.clk_x},{name: n+'.y',value: form.clk_y})}}
return a}
$.fn.formSerialize=function(semantic){
return $.param(this.formToArray(semantic))}
$.fn.fieldSerialize=function(successful){
var a=[]
this.each(function(){
var n=this.name
if(!n)return
var v=$.fieldValue(this,successful)
if(v&&v.constructor==Array){
for(var i=0,max=v.length;i<max;i++)
a.push({name: n,value: v[i]})}
else if(v !==null&&typeof v !='undefined')
a.push({name: this.name,value: v})
})
return $.param(a)}
$.fn.fieldValue=function(successful){
for(var val=[],i=0,max=this.length;i<max;i++){
var el=this[i]
var v=$.fieldValue(el,successful)
if(v===null || typeof v=='undefined' ||(v.constructor==Array&&!v.length))
continue
v.constructor==Array ? $.merge(val,v): val.push(v)}
return val}
$.fieldValue=function(el,successful){
var n=el.name,t=el.type,tag=el.tagName.toLowerCase()
if(typeof successful=='undefined')successful=true
if(successful&&(!n || el.disabled || t=='reset' || t=='button' ||
(t=='checkbox' || t=='radio')&&!el.checked ||
(t=='submit' || t=='image')&&el.form&&el.form.clk !=el ||
tag=='select'&&el.selectedIndex==-1))
return null
if(tag=='select'){
var index=el.selectedIndex
if(index<0)return null
var a=[],ops=el.options
var one=(t=='select-one')
var max=(one ? index+1 : ops.length)
for(var i=(one ? index : 0);i<max;i++){
var op=ops[i]
if(op.selected){
var v=$.browser.msie&&!(op.attributes['value'].specified)? op.text : op.value
if(one)return v
a.push(v)}}
return a}
return el.value}
$.fn.clearForm=function(){
return this.each(function(){
$('input,select,textarea',this).clearFields()
})}
$.fn.clearFields=$.fn.clearInputs=function(){
return this.each(function(){
var t=this.type,tag=this.tagName.toLowerCase()
if(t=='text' || t=='password' || tag=='textarea')
this.value=''
else if(t=='checkbox' || t=='radio')
this.checked=false
else if(tag=='select')
this.selectedIndex=-1
})}
$.fn.resetForm=function(){
return this.each(function(){
if(typeof this.reset=='function' ||(typeof this.reset=='object'&&!this.reset.nodeType))
this.reset()
})}
$.fn.enable=function(b){
if(b==undefined)b=true
return this.each(function(){
this.disabled=!b
})}
$.fn.select=function(select){
if(select==undefined)select=true
return this.each(function(){
var t=this.type
if(t=='checkbox' || t=='radio')
this.checked=select
else if(this.tagName.toLowerCase()=='option'){
var $sel=$(this).parent('select')
if(select&&$sel[0]&&$sel[0].type=='select-one'){
$sel.find('option').select(false)}
this.selected=select}
})}
function log(){
if($.fn.ajaxSubmit.debug&&window.console&&window.console.log)
window.console.log('[jquery.form] '+Array.prototype.join.call(arguments,''))}
})(jQuery)

