(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}}
var url=$.trim(this.attr('action'))
if(url){
url=(url.match(/^([^#]+)/)||[])[1]}
url=url || window.location.href || ''
options=$.extend(true,{
url: url,
type: this.attr('method')|| 'GET',
iframeSrc:/^https/i.test(window.location.href || '')? 'javascript:false' : 'about:blank'
},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}
if(options.beforeSerialize&&options.beforeSerialize(this,options)===false){
log('ajaxSubmit: submit aborted via beforeSerialize callback')
return this}
var n,v,a=this.formToArray(options.semantic)
if(options.data){
options.extraData=options.data
for(n in options.data){
if(options.data[n] instanceof Array){
for(var k in options.data[n]){
a.push({name: n,value: options.data[n][k]})}}
else{
v=options.data[n]
v=$.isFunction(v)? v(): v
a.push({name: n,value: v})}}}
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){
var fn=options.replaceTarget ? 'replaceWith' : 'html'
$(options.target)[fn](data).each(oldSuccess,arguments)
})}
else if(options.success){
callbacks.push(options.success)}
options.success=function(data,status,xhr){
var context=options.context || options
for(var i=0,max=callbacks.length;i<max;i++){
callbacks[i].apply(context,[data,status,xhr || $form,$form])}}
var fileInputs=$('input:file',this).length>0
var mp='multipart/form-data'
var multipart=($form.attr('enctype')==mp || $form.attr('encoding')==mp)
if(options.iframe !==false&&(fileInputs || options.iframe || multipart)){
if(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],:input[id=submit]',form).length){
alert('Error: Form elements must not have name or id of "submit".')
return}
var s=$.extend(true,{},$.ajaxSettings,options)
s.context=s.context || s
var id='jqFormIO'+(new Date().getTime()),fn='_'+id
window[fn]=function(){
var f=$io.data('form-plugin-onload')
if(f){
f()
window[fn]=undefined
try{delete window[fn];}catch(e){}}}
var $io=$('<iframe id="'+id+'" name="'+id+'" src="'+s.iframeSrc+'" onload="window[\'_\'+this.id]()" />')
var io=$io[0]
$io.css({position: 'absolute',top: '-1000px',left: '-1000px'})
var xhr={
aborted: 0,
responseText: null,
responseXML: null,
status: 0,
statusText: 'n/a',
getAllResponseHeaders: function(){},
getResponseHeader: function(){},
setRequestHeader: function(){},
abort: function(){
this.aborted=1
$io.attr('src',s.iframeSrc)}}
var g=s.global
if(g&&! $.active++){
$.event.trigger("ajaxStart")}
if(g){
$.event.trigger("ajaxSend",[xhr,s])}
if(s.beforeSend&&s.beforeSend.call(s.context,xhr,s)===false){
if(s.global){
$.active--}
return}
if(xhr.aborted){
return}
var cbInvoked=false
var timedOut=0
var sub=form.clk
if(sub){
var n=sub.name
if(n&&!sub.disabled){
s.extraData=s.extraData ||{}
s.extraData[n]=sub.value
if(sub.type=="image"){
s.extraData[n+'.x']=form.clk_x
s.extraData[n+'.y']=form.clk_y}}}
function doSubmit(){
var t=$form.attr('target'),a=$form.attr('action')
form.setAttribute('target',id)
if(form.getAttribute('method')!='POST'){
form.setAttribute('method','POST')}
if(form.getAttribute('action')!=s.url){
form.setAttribute('action',s.url)}
if(! s.skipEncodingOverride){
$form.attr({
encoding: 'multipart/form-data',
enctype: 'multipart/form-data'
})}
if(s.timeout){
setTimeout(function(){timedOut=true;cb();},s.timeout)}
var extraInputs=[]
try{
if(s.extraData){
for(var n in s.extraData){
extraInputs.push(
$('<input type="hidden" name="'+n+'" value="'+s.extraData[n]+'" />')
.appendTo(form)[0])}}
$io.appendTo('body')
$io.data('form-plugin-onload',cb)
form.submit()}
finally{
form.setAttribute('action',a)
if(t){
form.setAttribute('target',t)
}else{
$form.removeAttr('target')}
$(extraInputs).remove()}}
if(s.forceSync){
doSubmit()}
else{
setTimeout(doSubmit,10)}
var data,doc,domCheckCount=50
function cb(){
if(cbInvoked){
return}
$io.removeData('form-plugin-onload')
var ok=true
try{
if(timedOut){
throw 'timeout'}
doc=io.contentWindow ? io.contentWindow.document : io.contentDocument ? io.contentDocument : io.document
var isXml=s.dataType=='xml' || doc.XMLDocument || $.isXMLDoc(doc)
log('isXml='+isXml)
if(!isXml&&window.opera&&(doc.body==null || doc.body.innerHTML=='')){
if(--domCheckCount){
log('requeing onLoad callback, DOM not available')
setTimeout(cb,250)
return}}
cbInvoked=true
xhr.responseText=doc.documentElement ? doc.documentElement.innerHTML : null
xhr.responseXML=doc.XMLDocument ? doc.XMLDocument : doc
xhr.getResponseHeader=function(header){
var headers={'content-type': s.dataType}
return headers[header]}
var scr=/(json|script)/.test(s.dataType)
if(scr || s.textarea){
var ta=doc.getElementsByTagName('textarea')[0]
if(ta){
xhr.responseText=ta.value}
else if(scr){
var pre=doc.getElementsByTagName('pre')[0]
if(pre){
xhr.responseText=pre.innerHTML}}}
else if(s.dataType=='xml'&&!xhr.responseXML&&xhr.responseText !=null){
xhr.responseXML=toXml(xhr.responseText)}
data=$.httpData(xhr,s.dataType)}
catch(e){
log('error caught:',e)
ok=false
xhr.error=e
$.handleError(s,xhr,'error',e)}
if(ok){
s.success.call(s.context,data,'success',xhr)
if(g){
$.event.trigger("ajaxSuccess",[xhr,s])}}
if(g){
$.event.trigger("ajaxComplete",[xhr,s])}
if(g&&!--$.active){
$.event.trigger("ajaxStop")}
if(s.complete){
s.complete.call(s.context,xhr,ok ? 'success' : 'error')}
setTimeout(function(){
$io.removeData('form-plugin-onload')
$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){
if(this.length===0){
var o={s: this.selector,c: this.context}
if(!$.isReady&&o.s){
log('DOM not ready, queuing ajaxForm')
$(function(){
$(o.s,o.c).ajaxForm(options)
})
return this}
log('terminating; zero elements found by selector'+($.isReady ? '' : ' (DOM not ready)'))
return this}
return this.ajaxFormUnbind().bind('submit.form-plugin',function(e){
if(!e.isDefaultPrevented()){
e.preventDefault()
$(this).ajaxSubmit(options)}
}).bind('click.form-plugin',function(e){
var target=e.target
var $el=$(target)
if(!($el.is(":submit,input:image"))){
var t=$el.closest(':submit')
if(t.length==0){
return}
target=t[0]}
var form=this
form.clk=target
if(target.type=='image'){
if(e.offsetX !=undefined){
form.clk_x=e.offsetX
form.clk_y=e.offsetY
}else if(typeof $.fn.offset=='function'){
var offset=$el.offset()
form.clk_x=e.pageX-offset.left
form.clk_y=e.pageY-offset.top
}else{
form.clk_x=e.pageX-target.offsetLeft
form.clk_y=e.pageY-target.offsetTop}}
setTimeout(function(){form.clk=form.clk_x=form.clk_y=null;},100)
})}
$.fn.ajaxFormUnbind=function(){
return this.unbind('submit.form-plugin 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}
var i,j,n,v,el
for(i=0,max=els.length;i<max;i++){
el=els[i]
n=el.name
if(!n){
continue}
if(semantic&&form.clk&&el.type=="image"){
if(!el.disabled&&form.clk==el){
a.push({name: n,value: $(el).val()})
a.push({name: n+'.x',value: form.clk_x},{name: n+'.y',value: form.clk_y})}
continue}
v=$.fieldValue(el,true)
if(v&&v.constructor==Array){
for(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 $input=$(form.clk),input=$input[0]
n=input.name
if(n&&!input.disabled&&input.type=='image'){
a.push({name: n,value: $input.val()})
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(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=op.value
if(!v){
v=(op.attributes&&op.attributes['value']&&!(op.attributes['value'].specified))? op.text : op.value}
if(one){
return v}
a.push(v)}}
return a}
return $(el).val()}
$.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.selected=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').selected(false)}
this.selected=select}
})}
function log(){
if($.fn.ajaxSubmit.debug){
var msg='[jquery.form] '+Array.prototype.join.call(arguments,'')
if(window.console&&window.console.log){
window.console.log(msg)}
else if(window.opera&&window.opera.postError){
window.opera.postError(msg)}}}
})(jQuery)

