//# Well what can I say I write JS like I speak english, thats with an accent ( a py one for js) and yes I indent intetionnaly anything that closes...thats how I like it. 
//# PS if all of this anouyse the hell out of you well you can always download jspy2js.py it undoes all that I like to do

//alert('before jz2 load')
//##################################################################
//### Create jz Module    					 ###
//### the module is created 'by hand' because function 	    	 ###
//### Module not defined yet see OO section at bottom            ###
//##################################################################
jz=('jz'  in window)?jz:{}
jz.$ = jz //Use $ as refrence to current module ...

with(jz) { //### Use jz name space from here on .... dont indent the whole file ....


//##################################################################
//### onLoad handling 				                 ###
// on load some times is 'redfined' by other libraies
// such as goojle ajax loader or jQuery ready etc 
//##################################################################

if (!$.addOnLoadListener){
    $._waitingonload= []

    $.addOnLoadListener= function(fn,first){ first?jz._waitingonload.unshift(fn):jz._waitingonload.push(fn) }
	   
    // copied from below so we can use it right away
    $._removeListenerFromHandle = function(){ 
	    if (!this.obj) return
	    removeListener(this.obj,this.eventName,this.callBackFn)
	    this.obj=this.eventName=this.callBackFn=null
	    }

    //path this up wont wok with ie ...
    $.addListener= function(self,eventName,callBackFn) { 
	    self.addEventListener(eventName,callBackFn,false )
	    var handle = { obj:self, eventName:eventName, callBackFn:callBackFn, remove:_removeListenerFromHandle }
	    if (self.jz_Listeners) self.jz_Listeners.push(handle)
	    return  handle }

    $.addListener(document,'load',function(){
	    for (var x=0;x<jz._waitingonload.length;x++) setTimeout(jz._waitingonload[x],x)
	    jz.addOnLoadListener= function(fn){ setTimeout(fn,0) }
	    delete jz._waitingonload
	    })

    }

//##################################################################
//### Avoid python habits creating errors ....                   ###
//##################################################################

$.True	= true
$.False = false
$.None	= null

$.getattr	= function(self,name,noValue) { return self?(self[name] || noValue):noValue  }
$.setattr	= function(self,name,value) { return self[name]=value  }
$.range		= function(i) { var ret=new Array(i); for (var idx=0; idx<i;idx++) ret[idx]=idx; return ret }
$.str		= function(obj) {return obj } //return obj?(obj.toString?obj.toString():''+obj):''+obj }


//##################################################################
//### Add Dom helping functions                                  ###
//##################################################################

// Browser Id booleans
$._browserVer = parseFloat(navigator.appVersion) || 1.0
$.W3DOM 	= window['addEventListener']?_browserVer:false
$.IE 		= !window['addEventListener']?parseFloat(navigator.appVersion.substr(navigator.appVersion.indexOf('MSIE')+4)):false
$.KONQ 		= !(navigator.userAgent.indexOf('Konqueror')==-1)?_browserVer:false
//alert('appv='+navigator.appVersion+' IE='+IE+' W3DOM='+W3DOM+' KONQ='+KONQ)

//Event Listeners
$._removeListenerFromHandle = function(){ 
	if (!this.obj) return
 	removeListener(this.obj,this.eventName,this.callBackFn)
	this.obj=this.eventName=this.callBackFn=null
	}

$.addListener	 = function(self,eventName,callBackFn) { 
	self.addEventListener(eventName,callBackFn,false )
	var handle = { obj:self, eventName:eventName, callBackFn:callBackFn, remove:_removeListenerFromHandle }
	if (self.jz_Listeners) self.jz_Listeners.push(handle)
	return  handle }

$.removeListener = function(self,eventName,callBackFn) { return self.removeEventListener(eventName,callBackFn,false) }

$.removeObjListeners = function(self){ 
	if (!self.jz_Listeners) return 0
	for (var  cnt=0, handle,lst=self.jz_Listeners; handle=lst.pop() ; cnt++) handle.remove()
	return cnt
	}

$.stopEvt = function(evt){ evt.stopPropagation();evt.preventDefault() }


	//Dom manipulation helpers
	 
$._strAsSet = function(str){
		var ret={}
		dof(str.split(' '),function(s){ ret[s]=(ret[s]||0)+1 })
		return ret
		}

//Get Elements (nodes) in various forms
$.getId = function(name,doc) { 
		if (!doc) doc= document
		if (doc.getElementById) return doc.getElementById(name)
		//alert('get id doing scan for '+name+' ini '+doc)
		return firstf(doc.getElementsByTagName('*'),
			function(tag,idx,last){ return tag.getAttribute('id') == name })
		}
	 
$.getParentByTagName = function(self,tag) {
		for (var elem=self.parentNode,tag=tag.toUpperCase(); elem; elem=elem.parentNode) if (elem.nodeName==tag) return elem
		return false }

$.getElementsByTagNames = function(self,tagNames){
		var tags=tagNames
		if (!tagNames || tagNames=='*') return self.getElementsByTagName('*')
		var tagNames=_strAsSet(tagNames.toUpperCase()), ret=[]
		dof(self.getElementsByTagName('*'),function(tag){if (tag.nodeName in tagNames) ret.push(tag)})
		//Log('get Elements by tagsnames 2 tags='+tags+' returned='+ret)
		return ret }

$.getElementsByNames = function(self,names,tags) {
		//TODO: add prefix managment
		if (!names) return []
		var res=[], names=_strAsSet(names)
		dof(getElementsByTagNames(self,tags),function(tag){if (tag.getAttribute('name') in names) res.push(tag)})
		return res }

$.getElementsByClass = function(self,clsName,tags){
		var tagList=getElementsByTagNames(self,tags)
		if (!tagList || tagList.length<1) { return [] }
		var list=[], prefix=false, len1=clsName.length-1
		if (clsName.substr(len1,1)=='*') prefix=true, clsName=clsName.substr(0,len1)
			
		dof(tagList, function(elem){
			if (elem.className && (-1!=elem.className.indexOf(clsName))){ //mybe has className
				if (prefix){
					if (firstf(elem.className,function(cName){return cName.substr(0,len1)==clsName})) list.push(elem) }
				else { if (firstf(elem.className,function(cName){return cName==clsName})) list.push(elem) }
				}
			})
		//Log('get Elements by classame cls='+clsName+' tags='+tags+' returned='+list)
		return list }

$.innerText= function(self,doc){
		var ret= innerText2(self,doc)
		alert('inner text self='+self+' nodeName='+self.nodeType+' ret='+ret)
		return ret
		}

$.innerText= function(self,doc){//get inner text
		if (typeof self == 'string') self= getId(self,doc)
		if (!self) return ''
		if ('innerText' in self) return self.innerText
		if (self.nodeName == '#text') return self.nodeValue
		if (self.childNodes.length == 1 && self.firstChild.nodeName == '#text') return self.firstChild.nodeValue
		var ret= ''
		dof(self.childNodes,function(node){ ret+= innerText(node) })
		return ret
		}

$.innerHTML= function(self,doc){//get inner text
		if (typeof self == 'string') self= getId(self,doc)
		if (!self) return ''
		if (!self.innerHTML){//patch IE xml nodes dont have innerHTML ...
			var itxt= innerText(self,doc)
			return itxt.replace(/\n/g,'<br/>').replace(/km\s/g,'<br/>') //TODO: super patch cause i'm on vacation in an hour
			}
		return self.innerHTML
		}

//Move this into GMapUtils
$.setChildContent = function(self,childName,content,doPre){
		var elem = $.getElementsByNames(self,childName)
		if (!elem) return false
		elem=elem[0] // should do loop on elem
		if ((elem.tagName == 'INPUT') ||(elem.tagName== 'SELECT') ) {
			//alert(childName+' is a '+elem.tagName+' doing value='+content)
			elem.value=content }
		else { //alert(childName+' is a '+elem.tagName+' doing innerHTML='+content)
			if (doPre && elem.tagName!='TEXTAREA' && content ) content=content.replace('\n','<br />')
			elem.innerHTML=content }
		return true }

//CSS and Class
$.addCssCls = function(elem,className){
		var elemCls = ' ' + (elem.className || '') + ' '
		if (elemCls.indexOf(' '+className+' ')>-1) return false //already has class
		elem.className+=' '+className
		return true }

$.shiftCssCls = function(elem,className){
		var elemCls = ' ' + (elem.className || '') + ' '
		if (elemCls.indexOf(' '+className+' ')>-1) return false //already has class
		elem.className=className+' '+elem.className
		return true }

$.removeCssCls = function(elem,clsName){
		var len1= clsName.length-1, prefix= false
		if (clsName[len1]=='*') prefix=true, clsName=clsName.substr(0,len1)

		if (!elem.className || (-1 == elem.className.indexOf(clsName))) return False //nothing to remove

		var oldclassName= mapf(elem.className)
		if (prefix)
			elem.className= extractf(elem.className,function(cName){ return cName.substr(0,len1)!=clsName }).join(' ')
		else
			elem.className= extractf(elem.className,function(cName){ return cName!=clsName }).join(' ')

		return oldclassName != elem.className
		}

$.currentStyle= function(elem){
		if (window.getComputedStyle) return getComputedStyle(elem,'')
		return elem.currentStyle
		}


$.swapCssCls= function(elem,classname){
	if (addCssCls(elem,classname)) return true
	removeCssCls(elem,classname)
	return false
	}

$.enableCSS= function(styleSheetId){
	var css= jz.getId(styleSheetId)
	if (!css) return //could raise an error
	css.disabled= !css.disabled
	var carte= getId('carte')
	if (carte && carte.vMap) {
		carte.vMap.checkResize()
		if (jzGMap){
			jzGMap.doMoveEnd(carte,1)
			} 
		}
	}
	
$.scaletofit= function(elem){
		if (typeof elem == 'string') self= getId(elem)
		if (!elem) return ''
		var ew=elem.offsetWidth, eh=elem.offsetHeight 
		var pw=elem.offsetParent.offsetWidth
		var ph=elem.offsetParent.offsetHeight-12 /* margin */
		var scale= Math.min(pw/ew,ph/eh,2.)
		var nw,nh
		elem.style.width= nw= (Math.round(ew*scale)+'px')
		elem.style.height= nh= (Math.round(eh*scale)+'px')
		//alert([elem,ew,eh,elem.parentNode,pw,ph,'new',scale])
		return scale
		}
	

$.doit= function(self){
			var par= self.parentNode
			}

$.getCookie = function(name) {
		var reg = new RegExp(name+'=([^;]+)')
		var match = document.cookie.match(reg)
		if (!match) return ''
		return unescape(match[1]) }

$.setCookie = function(name,val) {document.cookie=(name+'='+escape(val.toString())+'; path=/')}

$.setCookieForever = function(name,val) {
	var expires= new Date()
	var plusunan= expires.getTime() + (365*24*60*60*1000)
	expires.setTime(plusunan)
	document.cookie= name+'='+escape(val.toString())+'; path=/; expires='+expires.toGMTString()
	}
	
$.encodeHTML = function(str) { return str.replace('<','&lt;').replace('>','&gt;')}

//Init JzClasses...
//$.findJzClasses = function(father,tags){ return getElementsByClass(father,'jz_*',tags) }
$,findJzClasses= function(elem,tags){ return domwalk(elem,function(elem,l,c){ if ((c=elem.className) && c.indexOf('jz_')>-1) l.push(elem)}) }
	
$.initJzClasses = function(elemList,ret){
		dof(elemList, function(elem) {
			var className=elem.className || '', idx=0, end=0, jzName, cls, val
			dof(className.split(' '),function(cls){
				if (cls.substr(0,3)=='jz_') {
					var val, jzName=cls.substr(3), jzCls=DomClasses[jzName]
					if (jzCls) {
						if (undefined!==(val=jzCls(elem))) {
							//init succeded
							elem.jz_data=val
							if (ret) ret.push(elem) } }
					else {} //Log('jz Dom Class '+jzName+' not found')
				} }) })
		return ret }

$._InitList = false

$._InitTime = {a:0.,b:0}

$.domwalk= function(elem,leafFn,inFn,outFn,arg){
    // walh the dom tree elem ignoring textnodes .... 

    if (inFn==undefined && outFn===undefined) outFn= leafFn
    if (arg===undefined) arg=[]
    var start= elem
    var fc

    while (true) {
	/* go down left side as far as possible */
	while ((fc=elem.firstChild) && (fc.nodeType!==3 || fc.nextSibling)) { //nodes with just text inside are leaves
	    /* enter branch elem */
	    if (inFn) inFn(elem,arg)
	    elem=fc
	    }

	/* leaf enter and exit */
	if (leafFn) leafFn(elem,arg)

	/* if at end of siblings go up rightside as far as possible (ie no siblings) */
	while (elem!==start && !elem.nextSibling ){
	    elem= elem.parentNode
	    /* exit branch */
	   if (outFn) outFn(elem,arg)
	   }
	if (elem===start) break

	/* not right side, not a left side, nextsibling of finished */
	do { elem=elem.nextSibling } while ( (elem.nodeType===3) && elem.nextSibling )
	}

    return arg
    }



$._startInitScan = function(){
		/*disable disabled style sheets */
		dof(document.getElementsByTagName('style'),function(style){
			if (style.getAttribute('disabled')) style.disabled= style.getAttribute('disabled')
			})

		/* scan head for jzClasses */
		var head=document.getElementsByTagName('head')[0]
		if (head) initJzClasses(findJzClasses(head))

		_InitTime.a = new Date()
		var list=findJzClasses(document,'div table')
		_InitTime.l= list.length
		if (list.length) {
			_InitList=list
			setTimeout(_doInitScan,100) // let other onloads execute ...
			}
		_InitTime.a = new Date()-_InitTime.a }

$._doInitScan = function(){
		//Log('start init items.length='+_InitList.length)
		_InitTime.b = new Date()
		initJzClasses(_InitList)
		_InitList=false
		_InitTime.b = new Date()-_InitTime.b
		//alert(_('a=$a b=$b l=$l',_InitTime))
		var ll=[]
		}

$._DomTxt = function(elem){ return elem.innerHTML }

$._DomEval = function(elem){ return eval(_DomTxt(elem),elem) }

$.DelaiedFactory = function(reader,cls){ 
		return function(elem){
			var data = reader(elem)
			data._elem= elem
			data.__delaiedInit__ = cls
			return data } }

$.DomClasses = {
	'alert' : function(){alert('got a jaze init class')} ,

	scanAll : function(elem){return; initJzClasses(findJzClasses(elem,'*'))} , //use this to force scanning of all sub elements //we now scan all

	onLoadDoer : function(elem){ //adds onload capabilitiy to any tag by adding class jz_onLoadDoer and onload=code
			var onload=elem.getAttribute('onload')
			if (onload) eval(onload,elem)
			return } ,

	onChangeDoer : function(elem){ //adds onchange capabilitiy to any tag by adding class jz.onLoadDoer and onload=code
			var onchange=elem.getAttribute('onchange')
			if (!onchange) return //do nothing if no onchange
			elem.onchange= "" //in case elem does implement onchange so it wont double up
			var f = Function('evt',onchange)
			if (IE){
			    //no onchange for most controls use onclick
			    dof(getElementsByTagNames(elem,'input text radio checkbox hidden password button'),
				function(tag){addListener(tag,'click',f) })
			    dof(getElementsByTagNames(elem,'textarea select'),
				function(tag){addListener(tag,'change',f) })
			    }
			else // others are ok 
			    dof(getElementsByTagNames(elem,'input text radio checkbox hidden password textarea button select'),
				function(tag){addListener(tag,'change',f) })
			} ,
	
	Data : 	function(elem){//
			var dataTags, data={}
			//dataTags = initJzClasses(findJzClasses(elem,'*'),[]) //now occures automtically
			dataTags= findJzClasses(elem)
			dof(dataTags,function(tag){
				var name=tag.getAttribute('name')
				if (name) data[name]=tag.jz_data
				})
			//alert('Got data for '+elem.getAttribute('id')+' data='+data)
			//LogObj(data)
			return data } ,

	DataAttr: function(elem){
			var data=DomClasses.Data(elem)
			if (IE) dof(elem.attributes,
				function(attr){ if (attr.specified && attr.nodeName.substr(0,3)=='jz:') data[attr.nodeName.substr(3)]=attr.nodeValue})
			else    dof(elem.attributes,
				function(attr){ if (attr.specified && attr.name.substr(0,3)=='jz:') data[attr.name.substr(3)]=attr.nodeValue })
			return data } ,

	Str	: innerText, //_DomTxt ,
	HTML	: _DomTxt ,
	Float	: function(elem){ return parseFloat(_DomTxt(elem))} ,
	Int	: function(elem){ return parseInt(_DomTxt(elem))} ,
	'Array'	: _DomEval ,
	HRef	: function(elem){
			var ret= elem.getAttribute('href')
			if (ret) ret= unescape(ret)
			//alert('get href for '+elem.name+' is '+ret)
			return ret
			},
	disabled: function(elem){elem.disabled='disabled'} }

$.Node= function(typ,content,ops){
		var node= document.createElement(typ)
		update(node,ops)
		if (content) node.innerHTML= content
		return node
		}


//###################################################################
//### Form help                                                   ###
//###################################################################


$.scanChecksFor = function(name,alltrueisstar){
	var elems=document.getElementsByName(name)
	var rep=[], alltrue=true, ret=''
	for (var i=0,elem; elem=elems[i]; i++) {
		if (elem.checked) rep.push(elem.value)
		else alltrue=false
		}
	if (rep.length>0) {
		if (alltrue && alltrueisstar) ret='*'
		else ret=rep.join(',')
		}
	//alert('return elems.length='+elems.length+' rep='+rep+' ret='+ret+' for name='+name)
	return ret
	}
window.scanChecksFor = scanChecksFor

//ie6 bug: functions return '' for ok or error mess '' is used instead of true cuase ie6 goes  bezurk on false ...
$.validate= function(form){ 
	var elements=form.getElementsByTagName('input')
	errs= []
	for (fidx in elements){
	    var field= elements[fidx]
		//alert('f='+field+' fid='+field.id)
		if (field.onchange){
			var ret=field.onchange()
		 	if (ret){
				ret= field.name+' '+ret
				if (!errs.length || errs[errs.length-1] != ret) errs.push(ret)
		 		}
			}
		}
	if (errs.length){
		if (errs.length>1)
			alert("Il y a "+errs.length+" erreurs dans votre formulaire")
		else
			alert("Il y a une erreur dans votre formulaire")
		}
	return errs.length==0
	}
			 
$.notempty= function(ctrl,mess){
	var val= ctrl.value
	var id= ctrl.id
	var errmess= mess || '** Champ obligatoire **'
	var err= getId(id+'_err')
	if (!val){
		if (err){
			err.innerHTML= errmess
			err.style.display='inline'
			}
		return errmess
		}
	if (err) err.style.display= 'none'
	return ''
	}
 
$.mustcheck= function(ctrl,mess){
	var val= ctrl.checked
	var id= ctrl.id
	var errmess= mess || '** Champ obligatoire **'
	var err= getId(id+'_err')
	if (!val){
		if (err){
			err.innerHTML= errmess
			err.style.display='inline'
			}
		return errmess
		}
	if (err) err.style.display= 'none'
	return ''
	}
	
$.mustselect= function(ctrl,mess){
	var name= ctrl.name
	var selected= scanChecksFor(name)
	var err= getId(name+'_err')
	var errmess= mess || '** Champ obligatoire **'
	if (!selected){
			if (err){
				err.innerHTML= errmess
				err.style.display='inline'
				}
		return errmess
		}
	if (err) err.style.display= 'none'
	return ''
	}

 
$.mustequal= function(ctrl,oid,mess){
	if (ctrl.mustequalloop) return false
	var val= ctrl.value
	var id= ctrl.id
	
	var octrl= getId(oid)
	if (!octrl) return false //cant compare just accept
	var oval= octrl.value

	var errmess= mess || '** Doit correspondre a '+(octrl.name || oid)+' **'
	
	var err= document.getElementById(id+'_err')
	if (val != oval){
		if (err){
			err.innerHTML= errmess
			err.style.display='inline'
			}
		return errmess
		}
	//else
	//
	
	ctrl.mustequalloop= true
	if (octrl.onchange){
		//Maybe octrl has error due to us ...
		ctrl.mustequalloop= true
		octrl.onchange()
		ctrl.mustequalloop= false
		}
	
	if (err) {
		err.innerHTML= ''
		err.style.display= 'none'
		}
	return ''
	}


//###################################################################
//### ILocation manipulation                                      ###
//###################################################################

/* currently in jzMapUtils cause uses wordconvert TODO:genralize and put here ...

$.updateChecksFor = function(field,name){

	var href = unescape(window.location.href)
	var pos = href.indexOf(field)
	var params={} //default value {}=none false=all
	if (pos>-1){
		pos+= 1+field.length
		var end = href.indexOf('&',pos)
		if (end<pos) end = href.length 
		var paramstr=href.substring(pos,end)
		if (paramstr=='*') params=false
		else {
			params={}
			dof(paramstr.split(','),function(word){
				if (word in wordconverter) word=wordconverter[word]
				params[word]=true
				})
			}
		}
	//var paramdump=''
	//jz.dof(params,function(v,k){paramdump+=k+'='+v+'\n'})
	//alert('update checks pos='+pos+' end='+end+' field='+field+'\n paramstr='+paramstr+'\n params='+params+'\n paramdump='+paramdump)
	var elems=document.getElementsByName(name)
	for (var i=0,elem; elem=elems[i]; i++) {
		//alert('elem val='+elem.value+' param='+params[elem.value])
		if ((!params || elem.value in params) != elem.checked) {
			//alert('changing '+name+'.'+elem.id+' from '+elem.checked+' to '+(!elem.checked)+' params='+params)
			// elem.checked=!elem.checked //only set if required ...
			}
//		if (!params || elem.value in params) elem.checked=true
//		else elem.checked=false
		}
	}
window.updateChecksFor = updateChecksFor

*/

$.formvars= function(name,defvals){
	var elem
	if (typeof name == 'string') elem=getId(name)
	else if (name) {
		elem= name
		name= elem.id || elem.name
		}
	var val=''

	if (elem){
		if ('jz_getter' in elem)
		    val= elem.jz_getter()
		else if ('value' in elem)
		    val= elem.value
		else val= innerText(elem)
		}
	else if (defvals && name in defvals){
		val= defvals[name]
		}
	//val= escape(val,1)
	//alert(name+'='+val)
	return val
	}
	

$.getHrefArgs = function(href){
	if (!href) href = window.location.href
	var pos = href.indexOf('?')
	if (pos<0) return ''
	return href.substr(pos)
	}
window.getHrefArgs = getHrefArgs

$.parseUrl= function(url){
	var args= {}
	if (!url) url = window.location.href
	var pos = url.indexOf('?')
	if (pos<0){
		//no args simple
		args['url']=url
		return args
		}

	args['url']= url.substring(0,pos)
	
	dof(url.substring(pos+1).split('&'),function(vargrp){
		var parts= vargrp.split('=')
		if (parts.length == 2) args[parts[0]]= parts[1]
		})
	return args
	}

$.getHrefFixedArgs = function(href){
	if (!href) href = window.location.href
	var pos = href.indexOf('&&')
	if (pos>-1) return href.substr(0,pos+2)
	pos = href.indexOf('?')
	if (pos>-1) return href.substr(0,pos+1)
	return href+'?'
	}
window.getHrefFixedArgs = getHrefFixedArgs

$.setlocvar= function(varname,value,returnurl){
		var newhref= sethrefvar(value,varname,location.href)
		location.href= newhref
		if (returnurl) return  newhref //by default return nothing so can be used in a href=javascript:setlocvar(...
		}

$.popuplocvar= function(varname,value,returnwindow){
		var newhref= sethrefvar(value,varname,location.href)
		var newwindow= window.open(newhref)
		if (returnwindow) return  newwindow //by default return nothing so can be used in a href=javascript:setlocvar(...
		}

$.popuphref= function(href,returnwindow){
		var newwindow= window.open(href)
		if (returnwindow) return  newwindow //by default return nothing so can be used in a href=javascript:setlocvar(...
		}



window.setlocvar= setlocvar

$.sethrefvar= function(value,varname,href){

		if (varname == 'url') return _seturl(value,href)
		varname= varname+'='
		var pos= href.indexOf('?'+varname)
		if (pos<0) pos= href.indexOf('&'+varname)
		if (pos<0){ // varname not in url just add it
			if (href.indexOf('?')<0)
					var sep= '?'
			else 	var sep= '&'
			var newhref= href+sep+varname+value
			}
		else { //varname already preesent replace value
			var endpos= href.indexOf('&',pos+1)
			if (endpos<0) endpos= href.length
			var newhref=href.substring(0,pos+1+varname.length)+value+href.substring(endpos)
			}
		//alert('href= '+href+'  nhr='+newhref+' val='+value+' var='+varname)
		return newhref
		}

$._seturl= function(url,href){
		var pos= href.indexOf('?')
		if (pos>-1) url+= href.substring(pos)
		return url
		}

$.sethrefvars= function(vars,href){
		if (href == undefined ) href= window.location.href
		var newhref= mapf(vars,sethrefvar,false,href)
		return newhref
		}

$.setlocvars= function(vars,href,returnurl){
		var newhref= sethrefvars(vars,href)
		location.href= newhref
		if (returnurl) return  newhref //by default return nothing so can be used in a href=javascript:setlocvar(...
		}

window.setlocvars= setlocvars



$.urlMerge= function(newurl,oldurl){
		var newargs= parseUrl(newurl)
		var oldargs= parseUrl(oldurl)
		update(oldargs,newargs)
		//t=mapf(oldargs,function(v,k,l){
		//	l+=k+'='+v+'\n'
		//	return l},false,'')
		//alert('old = '+t)
		var url= mapf(oldargs,_setlocvar,false,'')
		//alert('url='+url)
		return url
		}

$.urlMerge= function(newurl,oldurl){
		var url= parseUrl(oldurl)
		update(url,parseUrl(newurl))
		return urlFromParse(url)
		}


$.urlFromParse= function(vars){
		var url='',ops=''
		if (vars.url){
		    url=vars.url
		    delete vars.url
		    }
		ops=mapf(vars,function(v,k){return k+'='+v},[]).join('&')
		if (ops.length > 0) url=url+'?'+ops
		return url
		}
		
$.getfullurl= function(){
		var ops={}
		
		if (('jzGMap' in window) && jzGMap.unitname!='km') ops.unit=jzGMap.unitname

		if (mapDiv){ //got a mapget current zoom and pos
		    var map= mapDiv.vMap
		    ops.lat= map.getCenter().lat()
		    ops.lng= map.getCenter().lng()
		    ops.zoom= map.getZoom()
		    ops.force= 1

		    if (('router' in map) && map.router.markers && map.router.markers.length>0){
			var router= map.router
			ops.ewaypoints= router.getWpeTxt()
			if ('cost' in router) ops.cst= router.cost
			if ('speeds' in router)
			    ops.spd=mapf(jzGMap._speedKeys,function(v){return router.speeds[v]}).join(',')
			}
		    }

		return urlFromParse(update(parseUrl(location.href),ops))
		}
			
$.gotofullurl= function(){
		location.href= getfullurl()
		}

$._mailto= [
"mailto:?subject=Itinéraire+fait+sur+ViaExplora.com&body="+
"$url",
"Voici+le+lien+pour+un+itinéraire+sur+ViaExplora.com",
'<a+href="$url">Lien</a>',
"$url",
'Fait+a+partire+de+<a+href="http://viaexplora.com">ViaExplora.com</a>'
    ].join('<br+>\n')


$._mailto= "mailto:?subject=Itinéraire+fait+sur+ViaExplora.com&body=$url"

$.mailfullurl= function(){ 
	var url=getfullurl()
	url= url.replace(/&/g,'%26').replace(/\s/g,'+')
	if (url.indexOf('ewaypoints=')!=-1)
	    var mailurl= _("mailto:?subject=Mon%20itinéraire%20fait%20sur%20ViaExplora.com&body=Le%20voici:%0A$url",{url:url})
	else 
	    var mailurl= _("mailto:?subject=Carte%20des%20sentiers%20de%20motoneige%20sur%20ViaExplora.com&body=Le%20oici:%0A$url",{url:url})
	location.href=mailurl
	}


//###################################################################
//### Itirator, func programing etc                               ###
//### This code assumes no one is messing up object.protoype etc..###
//###################################################################

$.retVal= function(val) { return val } //Default function used in iterators
$.pass	= function() {} //Really do nothing function
$.sum	= function(val, key, last) { return (last!=null)?val+last:val }
$.max	= function(val, key, last) { return (last!=null)?Math.max(val,last):val }
$.min	= function(val, key, last) { return (last!=null)?Math.min(val,last):val }
$.multiply= function(val, key, last) { return (last!=null)?val*last:val }

$._doBREAK= new Object()
$._doIGNORE= new Object()
$._doCONTINUE= _doIGNORE

$.isArrayLike= function(obj){
	// For speed I inline this function I always keep isArrayLike( in comment

	//this defines what should be condidered an array like object 
	// obj instanceof Array //this does not work with certain dom objects ...
	// obj.length instanceof Number //this does not work in moz cause window was a length=0
	// obj.length // seams ok but fails on empty arrays
	// obj.length instanceof Number && obj!== window // good but slow for arrys
	// obj.push // does not work with readonly arrays in the dom objects I think ...
	return obj instanceof Array || ( obj && (typeof obj.length === 'number') && obj!== window )}
	
$.isArrayLikeWrite= function(obj){
	return obj && ( obj.push instanceof Function)
	}

$.strip= function(str){
	//dump all \s at begging and end 
	return /^\s*([\s\S]*?)\s*$/.exec(str)[1]
	}


$.words= function(str){
	if (typeof str != 'string') alert(' words typeof s='+(typeof str))
	return strip(str).split(/\s+/)
	}


//except continue and break ...
$._retFor= function(coll){
		var tcoll= typeof coll
		if (tcoll === 'string' || tcoll === 'number' || isArrayLike(coll) ) return []
		if (coll.__class__) return coll.__class__() //TODO: not sure of this
		return new coll.constructor()
		}

$.mapf = function(coll,valFunc,accum,last) { //coll..ection to loop over,func(val,key,last)tion that will be applied to each key of coll, [ret]urned collection, allocated if none, nothing returned if false, last)
		if (!coll) return accum?accum:last //focres a ret===false to undefined
		if (coll.jz_mapf) return coll.jz_mapf(valFunc,accum,last)
		if (typeof valFunc === 'string') valFunc = fn(valFunc)
		if (!valFunc) valFunc= retVal //Use default return value function
		if (accum === undefined ) accum= _retFor(coll) //
		var handler
		if (handler=_mapfHandlers[typeof coll]) return handler(coll,valFunc,accum,last)
		else return accum ? accum : last
		}

$._mapfHandlers = {
	'number' : function(num,func,accum,last) { 
			var doBreak= _doBREAK, doIgnore= _doIGNORE
			if (!accum){
				for (var i=num>0?0:num ; i<num ; ++i){
					ret= func(i,i,last)
					if (ret === doIgnore) continue
					if (ret === doBreak) break
					last= ret}
				return last }
			else if (isArrayLikeWrite(accum)){
				for (var i=num>0?0:num ; i<num ; ++i){
					ret= func(i,i,last)
					if (ret === doIgnore) continue
					if (ret === doBreak) break
					accum.push(last= ret)}
				return accum }
			else {
				for (var i=num>0?0:num ; i<num ; ++i){
					ret= func(i,i,last)
					if (ret === doIgnore) continue
					if (ret === doBreak) break
					accum[i]= last= ret}
				return accum }
			},
	
	'object' : function(obj,func,accum,last){
			if (isArrayLike(obj)) return _mapfHandlers['array'](obj,func,accum,last)
			var doBreak= _doBREAK, doIgnore= _doIGNORE
			if (!accum){
				for (var key in obj){
					ret= func(obj[key],key,last)
					if (ret === doIgnore) continue
					if (ret === doBreak) break
					last= ret}
				return last }
			else if (isArrayLikeWrite(accum)){
				for (var key in obj){
					ret= func(obj[key],key,last)
					if (ret === doIgnore) continue
					if (ret === doBreak) break
					accum.push(last= ret)}
				return accum }
			else {
				for (var key in obj){
					ret= func(obj[key],key,last)
					if (ret === doIgnore) continue
					if (ret === doBreak) break
					accum[key]= last= ret }
				return accum }
			},
	
	'string' : function(str,func,accum,last){ 
			return _mapfHandlers['array'](words(str),func,accum,last)} ,

	'array' : function(arr,func,accum,last){
			var doBreak= _doBREAK, doIgnore= _doIGNORE
			if (!accum){
				for (var i=0, stop=arr.length ; i<stop ; ++i){
					ret= func(arr[i],i,last)
					if (ret === doIgnore) continue
					if (ret === doBreak) break
					last= ret}
				return last }
			else if (isArrayLikeWrite(accum)){
				for (var i=0, stop=arr.length ; i<stop ; ++i){
					ret= func(arr[i],i,last)
					if (ret === doIgnore) continue
					if (ret === doBreak) break
					accum.push(last= ret)}
				return accum }
			else {
				for (var i=0, stop=arr.length ; i<stop ; ++i){
					ret= func(arr[i],i,last)
					if (ret === doIgnore) continue
					if (ret === doBreak) break
					accum[i]= last= ret}
				return accum }
			},

	'function' : function(fnc,func,accum,last){
			if (isArrayLike(fnc)) return _mapfHandlers['array'](fnc,func,accum,last) //In moz childNode is a function with len
			//What to do with a function ..nothing for now...
			return accum?accum:last }
	}

$.dof= function(coll,fnc){ mapf(coll,fnc,false) } //definition dof is a fast mapf without break,continue, last or accumalation

$.dof = function(coll,func) { // (coll {collection to loop over,func(key,val) {function that will be applied to each element
		// could be mapIf(coll,func,null,null,last)
		if (!coll || !func) return //Nothing todo ...
		if (coll.jz_dof) return coll.jz_dof(func)
		if (coll.jz_mapf) return coll.jz_mapf(func,false) //il mapf present probably requires special processing
		var handler
		if (handler=_dofHandlers[typeof coll]) return handler(coll,func)
		}

$._dofHandlers = {
	'number' : function(num,func){ for (var i=num>0?0:num ; i<num ; ++i) func(i,i) },
	'object' : function(obj,func){
			if (isArrayLike(obj)) return _dofHandlers['array'](obj,func)
			for (var key in obj) func(obj[key],key)
			},
	'string' : function(str,func){ _dofHandlers['array'](words(str),func) },
	'array'  : function(arr,func){ for (var i=0, stop=arr.length ; i<stop ; ++i) func(arr[i],i) },
	'function' : function(fnc,func){ if (isArrayLike(fnc)) return _dofHandlers['array'](fnc,func) }//In moz childNode is a function with len
	}
/*
$._dofHandlers = {
	'number' : function(num,func,accum,last) { 
			if (!accum){
				for (var i=num>0?0:num ; i<num ; ++i) last= func(i,i,last)
				return last }
			else if (accum instanceof Array){
				for (var i=num>0?0:num ; i<num ; ++i) accum.push(last= func(i,i,last))
				return accum }
			else {
				for (var i=num>0?0:num ; i<num ; ++i) accum[i]= last= func(i,i,last)
				return accum }
			} ,
	
	'object' : function(obj,func,accum,last){
			if (obj.length instanceof Number) return _dofHandlers['array'](obj,func,accum,last)
			if (!accum){
				for (var key in obj) last= func(obj[key],key,last)
				return last }
			else if (accum instanceof Array){
				for (var key in obj) accum.push(last= func(obj[key],key,last))
				return accum }
			else {
				for (var key in obj) accum[key]= last= func(obj[key],key,last)
				return accum }
			},
	
	'string' : function(str,func,accum,last){
			return _dofHandlers['array'](words(str),func,accum,last)
			},

	'array' : function(arr,func,accum,last){
			if (!accum){
				for (var i=0, stop=arr.length ; i<stop ; ++i) last= func(arr[i],i,last)
				return last }
			else if (accum instanceof Array){
				for (var i=0, stop=arr.length ; i<stop ; ++i) accum.push(last= func(arr[i],i,last))
				return accum }
			else {
				for (var i=0, stop=arr.length ; i<stop ; ++i) accum[i]= last= func(arr[i],i,last)
				return accum }
			},

	'function' : function(fnc,func,accum,last){
			if (fnc.length !== undefined) return _dofHandlers['array'](fnc,func,accum,last) //In moz childNode is a function with len
			//What to do with a function ..nothing for now...
			return accum?accum:last }
	}
*/


$.update = function(obj,coll,list) {
		if (!list) return mapf(coll,retVal,obj?obj:{})
		if (list == '*') list=coll['jz_all'] //If all is absent will default to everything in coll not prefixed with _
		if (!list) return mapf(coll,
					function(val,key){return  (key != '$' && key.charAt(0)!='_') ? val : _doIGNORE },
					obj?obj:{}) // a * but no __all__
		if (!obj) obj= {}
		dof(list, function(val){ obj[val]=coll[val]})
		return obj
		}

$.extractf = function(coll,func,ret,last){
		return mapf(coll, function(v,k,l){return func(v,k,l)?v:_doIGNORE}, ret?ret:_retFor(coll), last) }

$.firstf= function(coll,func,ret,last){//not sure about ,ret there so same signature as other {x}f functions but not used ...
		return mapf( coll,
				function(v,k,l){
					if (l) return _doBREAK
					return func(v,k,l)?v:_doIGNORE },
				false, last) }

$.fn= function(codeStr){
		var code=_fnCache[codeStr]
		if (code) return code
		code=new Function('self','with(self){ return '+codeStr+'}')
		return _fnCache[codeStr]=code
		}

$._fnCache={}


//##################################################################
//### List helpers, uses module_method pattern to allow overriding       ###
//##################################################################


$.append = function(list, seq) {//append sequence to end of coll
		if (list.jz_append) return list.jz_append(seq)
		var offset=list.length
		list.length+=seq.length
		if ((list instanceof Array) && (seq instanceof Array)) { //Commun case, optimisation}
			for (idx=0, stop=list.length; offset<stop; ++offset, ++idx) list[offset]=seq[idx] }
		else dof(seq, function(val) { list[offset++]=val }) //
		return list }

$.last = function(list ) { return list.jz_last ? list.jz_last() : (list.length ? list[list.length-1] : undefined ) }

$.at =  function(list, idx) { return list.jz_at ? list.jz_at(idx) : list[idx] } 

$.indexOf = function(list,obj) { //Notice exception looks for indexOf not __indexOf__ because in string, and in array for moz>=1.8
	if (list.indexOf) return list.indexOf(obj)
	for(var i=0,len=list.length; i<len; i++) if (list[i]===obj) return i
	return -1 }

$.contains= function(list,obj){ return indexOf(list,obj)>-1 }
	
$.pop= function(obj,key,ret){
	if (key in obj) {
		ret= obj[key]
		delete obj[key] }
	return ret
	}
	 
//##################################################################
//### I18N             						###
//##################################################################

$._messages= {}
$._cache= {}

$._ = function(messId,vars,defvars){//Later add keyword subsitution
	var template= _cache[messId]
	if (!template) {
		var tstr= _messages[messId]||messId 
		template= _cache[messId]= Template(tstr)
		}
	return _tjoin(template,vars,defvars)
	}

$._tjoin= function(template,vars,defvars){
	if (!template || typeof template == 'string' ) return template?template:''
	var ret= template.slice(0) //copy the array
	if (typeof(vars) === 'function'){
		for (var i=0,end=ret.length; i<end; i++){
			for(var r,rt; (rt= typeof (r=ret[i])) === 'string'; i++){}
			if (i>=end) break
			if (rt === 'function')
				 ret[i]= r(vars,defvars)
			else ret[i]= vars(r.varname,defvars)
			}
		}
	else {
		for (var i=0,end=ret.length; i<end; i++){
			for(var r,rt; (rt= typeof (r=ret[i])) === 'string'; i++){}
			if (i>=end) break
			if (rt === 'function')
				ret[i]= r(vars,defvars)
			else if (vars && (r.varname in vars))
				ret[i]= vars[r.varname]
			else if (defvars && (r.varname in defvars))
				ret[i]= defvars[r.varname]
			else ret[i]= '${'+r.varname+'}'
			}
		}
	return ret.join('')
	}


//TODO: make template a class
$.Template= function(s){
	var parser= /(?:\$(\$))|(?:\$([_a-zA-Z][\w|_]*))|(?:\$\{(.+?)\})/gm
	var ln=3
	var ret=s.split(parser)
	var items=[],c,v,last=''
	for (var p=0;p<ret.length;p=p+1+ln){
		c=ret[p]
		if (c) last+=c
		v= ret.slice(p+1,p+1+ln).join('')
		if (v == '$') last+=v
		else if (v){
			if (last) {
				items.push(last)
				last=''}
			items.push({varname:v})
			}
		}
	if (last) items.push(last)
	if (!items.length) return ''
	if (items.length==1 && (items[0] instanceof String)) return items[0]
	return items
	}

if (IE){
	$.Template= function(s){
		var x= /(?:\$(\$))|(?:\$([_a-zA-Z][\w|_]*))|(?:\$\{(.+?)\})/m
		var ln=3
		var items=[],c,v,last=''
		for (var r;r=x.exec(s);){
			c=s.substring(0,r.index)
			if (c) last+=c
			v= r.slice(1).join('')
			if (v == '$') last+=v
			else if (v){
				if (last) {
					items.push(last)
					last=''}
				items.push({varname:v})
				}
			s= s.substring(r.index+r[0].length)
			}
		if (s) last+=s
		if (last) items.push(last)
		if (!items.length) return ''
		if (items.length==1 && (items[0] instanceof String)) return items[0]
		return items
		}
	}



$.tparse= function(s){
	var x= /(?:\$(\$))|(?:\$([_a-zA-Z][\w|_]*))|(?:\$\{(.+?)\})/m
	var v=[]
	for (var r;r=x.exec(s);){
		var start= s.substring(0,r.index)
		var end=   s.substring(r.index+r[0].length)
		var token= r.slice(1).join('')
		v.push('s="'+start+'" end="'+end+'" t="'+token+'"')
		s= end
		}
	if (s) v.push(' end="'+end+'"')
	return v.join('\n')
	}
//##################################################################
//### jzon, json implementation extended with class              ###
//##################################################################

$.jzonStr = function(obj){
		var res=[]
		jzon(obj,res)
		return res.join('') }

$.jzon = function(obj,res){ return obj && obj.jzon_ ? obj.jzon_(res) : _jzonHandlers[typeof obj](obj,res) }

$._jzonToString = function(obj,res){ res.push(obj.toString()) }

$._jzonHandlers = {
	'object' : function(obj,res) {
			if (obj===null) {res.push('None'); return}
			if (obj instanceof Array) return  _jzonHandlers['array'](obj,res)
			res.push('{')
			dof(obj, function(value,key){ 
				jzon(key, res)
				res.push(':')
				jzon(value, res)
				res.push(',')
				})
			res.pop()
			res.push('}') } ,

	'array' : function(obj,res) { 
			res.push('[')
			dof(obj, function(value){ 
				jzon(value, res)
				res.push(',')
				})
			res.pop() //remove last comma
			res.push(']') } ,

	'string' : function(obj,res) { append(res,["'''",obj,"'''"]) } ,
	
	'undefined' : function(obj,res) { res.push('None')} ,
	'number'  :  _jzonToString ,
	'boolean' :  _jzonToString ,
	'function':  _jzonToString }

//##################################################################
//### Debuging                                                   ###
//##################################################################

$.Log	= function(txt) {
//		txt='\n'+encodeHTML(txt)
		if (!Log.on) return
		var time=new Date()
		txt=(time.toLocaleTimeString()+'.'+time.getMilliseconds())+': '+txt
		Log.logTxt(txt) }

update(Log,{
	Differed : [],
	on	: true,
	elem	: false,
	win	: false,
	retry	: 2,

	logTxt  : function(txt){ if (txt) Log.Differed.push(txt) },

	logOpened : function(){
			Log.logTxt=Log.logAddTxt
			dof(Log.Differed,Log.logTxt)
			Log.Differed=false } ,

	logAddTxt : function(txt){ //Do Log.addTxt = Log.addTxtReverse at load to log in reverse
			var e = Log.elem
			var doc=IE?e.document:e.ownerDocument, br=doc.createElement('br'), txtNode=doc.createTextNode(txt)
			e.appendChild(br)
			e.appendChild(txtNode) } ,

	logAddTxtReverse : function(txt){
			var e = Log.elem		
			var doc=IE?e.document:e.ownerDocument, br=doc.createElement('br'), txtNode=doc.createTextNode(txt)
			e.insertBefore(br ,e.childNodes[0])
			e.insertBefore(txtNode,e.childNodes[0]) } ,
	
	openLog : function(txt){
			if (txt) Log.Differed.push(txt)
			if (!Log.Differed.length){//Nothing to log yet, so wait for first element
				Log.logTxt = Log.openLog
				return
				}
			var elem
			if (Log.elem) return Log.logOpened()
			if (Log.elem=getId('log')) return Log.logOpened()
			//Cant find an element create one
			if (!Log.win) Log.win=window.open('','Log','resizable,scrollbars')
			if (!Log.win) {//cant even open a window so close log
				Log.on=false
				return
				} 
			if (Log.win.document && Log.win.document.body) {
				Log.elem=Log.win.document.body
				Log.logOpened()
				return
				}
			if (!(--Log.retry)) return //Could setup flush
			//OK lets retry once more
			setTimeout(function(){Log.openLog()},1000) //Cause iE is slowwww .... probably an other thread ....
			}
	})
			

//_.Log = function(){}
$.LogObj = function(obj) { 
		Log('Object: '+str(obj)); 
		if (obj===window) return 
		for (var x in obj) Log('...'+x+':'+str(obj[x]))
		}

/*
	Log.Win=window.open('','Log','resizable,scrollbars')
	addListener(Log.Win,'load',function() { 
		Log.Elem=Log.Win.document.body
		dof(Log.Differed,function(mess){ Log(mess) })
		})
	})
*/
//window.Log=Log //expose logger globaly
//window.LogObj=LogObj //expose logger globaly


//##################################################################
//### OOfunctionality including Modules                          ###
//##################################################################


$.Module = function(content) { 
		if (!content) content={}
		content.$=content
		update(content,jz,__builtins__)
		return content
		}

$.importFrom = function(module,list){ update(this,module,list?list:'*') }

//From: http://www.howtocreate.co.uk/loadingExternalData.html
$.load = function(url){
		var scriptElem = document.createElement('script')
		scriptElem.setAttribute('src',url)
		scriptElem.setAttribute('type','text/javascript')
		document.getElementsByTagName('head')[0].appendChild(scriptElem) }

$.__builtins__ = 'importFrom' //names that are available in all modules

Module(window) //Make window a jzModule ... this adds $ as a global ...

$.Class = function(father,content) {
		if (!content) content={}

		function cfunc(){ //this is the constructor 
			var ret, obj=(this instanceof cfunc)?this:new cfunc(cfunc) //allows calling of constructor without new
			//WARNING contray to python if __init__ returns 'something'
			//then the object returned is returned as a result of the constructor<
			//this allows init to override alocation etc (avoiding a __new__)
			if (arguments[0]!==cfunc) {//test for cfunv(cfunc) so not to call __init__ twice 
				obj.constructor=cfunc
				if (obj.jz_init) ret=obj.jz_init.apply(obj,arguments)
				else dof(arguments,function(vars){update(obj,vars)}) //default init
				}
			return (ret===undefined)?obj:ret
			}
		if (content.jz_constructor) {
			cfunc=content.jz_constructor
			delete content.jz_constructor
			}
		if (father instanceof Function){
			if (father.jz_iscls) cfunc.prototype=new father(father) //One of our classes cfunc as arg to cfunc means dont init
			else cfunc.prototype=new father() //father is prbably a normal js constructor 
			}
		else if (father) cfunc.prototype=father //Hey! this is js you can inherit from an object ...
		for (var key in content) cfunc.prototype[key]=content[key]
		//update(cfunc,content) //Not sure here this everyting added to prototype available in constructor ...
		cfunc.jz_iscls= true
		cfunc.jz_superCls= father
		cfunc.jz_superP=   father.prototype
		if (content['_clsname']) cfunc.jz_clsname=content['_clsname']
		return cfunc
		}

	
$.superCls = function(cls,method){ //find method of self staring at class cls and execute
		if (!(cls instanceof Function)) cls=cls.constructor
		var sCls
		if (cls.jz_iscls) sCls= cls.jz_superCls
		else sCls= cls.prototype.constructor
		if (!method) return sCls
		var fn=sCls.prototype[method]
		return fn?fn:function(){}
		}

$.superClsP= function(cls){ return superCls(cls).prototype }

$.superClsCall= function(cls,method,obj){
		var fn=superCls(cls,method)
		var args= superClsCall.arguments, arg2
		if (args.length>3)
			 arg3= mapf(args.length-3,function(idx){ return args[idx+3]},[]) //simulate a slice
		else arg3= [] 
		return fn.apply(obj,arg3)
		},

$.warnUnload = false
$._warnUnload = function(evt){
		if (!warnUnload) return //ignore warning
		stopEvt(evt)
		return warnUnload //alows ie to display message
		}

//####################################################################
//### XHTTPREQUEST (Ajax)                                          ###
//## inspired from:                                                ###
//##  Javascript:The Defenitive Guide, 5th edition, chapter 20.1.1 ###
//##  TODO: autor etc ...
//####################################################################


$._xhrfactories= [
	function(){ return new XMLHttpRequest() },
/*	function(){
		// saw this acticex often but dont know if it works here ...
		// not sure if REQUIRED: this will make the request look like a nornal js object so you can add attributes to it 
		return XMLHTTPProxy(new ActiveXObject('Msxml2.XMLHTTP'))
		}, */
	function(){
		// not sure if REQUIRED: this will make the request look like a nornal js object so you can add attributes to it 
		return XMLHTTPProxy(new ActiveXObject('Msxml.XMLHTTP'))
		},
	function(){
		// REQUIRED: this will make the request look like a nornal js object so you can add attributes to it .. 
		return XMLHTTPProxy(new ActiveXObject('Microsoft.XMLHTTP'))
		},
	function(){ return false }
	]

//This API is minimal as used by jzMRouter3 ... TODO: Complet XHR api ...
$.XMLHTTPProxy= Class(Object,{
	id:0,
	rq:	false,
	query: '',
	mode: '',
	status:	0,
	readyState:	0,
	onreadystatechange: false,
	responseXML: false,
	
	jz_init: function(rq){
				this.rq= rq
				this.id= XMLHTTPProxy.count+= 1
				var self= this
				rq.onreadystatechange=function(){
					self.readyState= rq.readyState
					try {
						if ('status' in rq) self.status= rq.status
						if ('responseXML' in rq){
							self.responseXML= rq.responseXML
							//alert('got response'+self.responseXML)
							}
						}
					catch(e) {}
					//alert('id='+self.id+' r='+self.readyState+' s='+self.status+' x='+self.responseXML+' q='+self.query)
					if (self.onreadystatechange) self.onreadystatechange()
					}
				},

	open:	function(mode,query){
		this.mode=mode
		this.query=query
		return this.rq.open(mode,query) },

	send: function(arg){ return this.rq.send(arg) }

	} )
$.XMLHTTPProxy.count=0



$.newXMLHttpRequest= firstf(_xhrfactories,function(xhrf){
	try {
		var req= xhrf()
		if (req != null) return xhrf
		}
	catch(e) {}
	return false
	})
	
/*
if (!XMLHttpRequest) {
	if (ActiveXObject) {
		try: xhr = new ActiveXObject('msxml1')
		except: xhr = undefined
		if (xhr) { 

$.XHR =	Class(XMLHttpRequest,{/ *any jz xhr methods here * /})
*/
//##################################################################
//### IE Patches                                                 ###
//##################################################################
$.AjaxReq= Class(Object,{

	mode: 'get',
	query: '',
	error: function(){ alert(_('ajax succes on $mode $query',this))},
	succes: function(){ alert(_('ajax error on $mode $query',this))},
	jz_init : function(ops){}
	})



if (IE) { //Redefine helper methods for IE see originalfor spec
	
	$._IEevent = Class(Object,{
			jz_init	: function(){
				var event = window.event
				this.evt 	= event
				this.target	= event.srcElement
				this.layerX	= event.x
				this.layerY	= event.y
				this.clientX = event.clientX
				this.clientY = event.clientY
				this.button	= event.button
				this.type	= event.type
				this.keyCode	= event.keyCode
				this.shiftKey	= event.shiftKey
				this.altKey	= event.altKey
				this.ctrlKey	= event.ctrlKey
				//this.cancelBuble= event.cancelBuble
				},
			//returnValue : undefined,
			cancelBubble : undefined,
			returnValue  : true,

			preventDefault  : function(){ this.returnValue = false },
			stopPropagation : function(){ 
				//jz.Log('IE Event proxy direct call to stopPropagatoion set evt cancelBubble to true')
				this.cancelBubble = true },

			exit	: function(ret){
				if (this.cancelBubble ) {
					this.evt.cancelBubble = this.cancelBubble
					//jz.Log('IE Event proxy set cancelBubble to '+this.cancelBubble)
					}
				if (this.returnValue!==true){
					this.evt.returnValue = this.returnValue
					//jz.Log('IE Event proxy set returnValue to '+this.returnValue)
					}
				if (ret===true){
					ret=false
					//jz.Log('IE Event proxy inverting ret from true to false '+ret)
					}
				return ret
				}
			})
				 
	$._IEeventpatch = {
			preventDefault  : function(){ this.returnValue = false },
			stopPropagation : function(){ this.cancelBubble = true }
			}

	$.IEDOMevent =  function(){
			var evt= window.event
			update(evt,_IEeventpatch)
			evt.target	= evt.srcElement
			evt.layerX	= evt.x
			evt.layerY	= evt.y
			//TODO: calc and add pageX and Y
			return evt
			}

	$.addListener    = function(self,eventName,callBackFn) { 
				var func=function(){ callBackFn.call(self,IEDOMevent()) }
				self.attachEvent('on'+eventName,func) //self.addEventListener(eventName,callBackFn,false )
				var handle = { obj:self, eventName:eventName, callBackFn:func, remove:_removeListenerFromHandle }
				if (self.jz_Listeners) {
					self.jz_Listeners.push(handle)
					//Log('pushed '+handle+' for IE '+eventName)
					 }
				//else Log('no jzlist in '+self+' for IE '+eventName)
				return  handle }

	$.addListenerold   = function(self,eventName,callBackFn) { 
				var func=function(){
					var e=_IEevent()
					var ret = callBackFn.call(self,e)
					if (ret!==undefined) {}// Log('IE Event '+eventName+' proxy for '+self+' before exit retuning '+(typeof ret)+':'+ret)
					ret = e.exit(ret)
					if (ret!==undefined) {}//Log('IE Event '+eventName+' proxy for '+self+' after exit retuning '+(typeof ret)+':'+ret)
					 }
				self.attachEvent('on'+eventName,func) //self.addEventListener(eventName,callBackFn,false )
				var handle = { obj:self, eventName:eventName, callBackFn:func, remove:_removeListenerFromHandle }
				if (self.jz_Listeners) {
					self.jz_Listeners.push(handle)
					//Log('pushed '+handle+' for IE '+eventName)
					 }
				//else Log('no jzlist in '+self+' for IE '+eventName)
				return  handle }
				
	$.removeListener = function(self,eventName,callBackFn) { return self.detachEvent('on'+eventName, callBackFn) }
	//$.stopEvt	 = function(evt){ event.returnValue = false }

// 	var xhrtest, XHRBase = XHR
// 	try {/*inspired from from Pragmatic Ajax, Pragmatic Bookshelf page 75 */
// 		xhrtest = new ActiveXObject("Msxml2.XMLHTTP")

	}

//############# Listenners

//_doAddLoadListeners1()
addOnLoadListener(function(){Log.openLog()})//Make sure there are no arguments
addOnLoadListener(function() {_startInitScan(document)})

addListener(window,'beforeunload',_warnUnload)



if (IE && IE < 7){

	$.fixeRightBottom= function(){
	
		dof(getElementsByTagNames(document,'div ul'),function(elem){
			var cs= currentStyle(elem)
			var right=cs.right!='auto'?cs.right:false, bottom=cs.bottom!='auto'?cs.bottom:false
			if (!right && !bottom) return _doIGNORE
			
			if (right && (elem.jz_resizewidth || cs.width=='auto')){
				var newwidth= elem.offsetParent.clientWidth-parseInt(right)-elem.offsetLeft
				//Log(_("$tagName $id ol=$offsetLeft ot=$offsetTop ow=$offsetWidth oh=$offsetHeight oldwidth=$oldw parentwidth=$pw new width=$nw right=$right rw=$jz_resizewidth",
				//	elem,{nw:newwidth, pw:elem.offsetParent.clientWidth, right:right, oldw:cs.width}))
				elem.jz_resizewidth= true
				elem.style.width= str(newwidth)+'px'
				}
			if (bottom && (elem.jz_resizeheight || cs.height=='auto')){
				var newheight= elem.offsetParent.clientHeight-parseInt(bottom)-elem.offsetTop
				//Log(_("$tagName $id ol=$offsetLeft ot=$offsetTop ow=$offsetWidth oh=$offsetHeight oldheight=$oldh parentwidth=$ph   new height=$nh bottom=$bottom rh=$jz_resizeheight",
				//	elem,{nh:newheight, ph:elem.offsetParent.clientHeight, bottom:bottom, oldh:cs.height}))
				elem.jz_resizeheight= true
				elem.style.height= str(newheight)+'px'
				}
			})
		}
	addListener(window,'load',fixeRightBottom)
	addListener(window,'resize',fixeRightBottom)
	}
	




//Log('loaded jz')



//if (W3DOM && !KONQ){ //Moz patch
	/*jz.dof =  function(coll,func,last) { // (coll {collection to loop over,func(key,val) {function that will be applied to each element
			// could be mapIf(coll,func,null,null,last)
			if (!coll || !func) return last //Nothing todo ...
			if (coll.jz_dof) return coll.jz_dof(func,last)
			var handler
			if (handler=jz._dofHandlers[typeof coll]) return handler(coll,func,last)
			else return last
			}

	$._dofHandlers = {
		'number' : function(num,func,last) {
				var f={func:func}
				for (var i=num>0?0:num ; i<num ; ++i) last=f.func(i,i,last)
				return last
				},
		'object' : function(obj,func,last){
				if (obj.length !== undefined) return _dofHandlers['array'](obj,func,last)
				var f={func:func}
				for (var key in obj) last=f.func(obj[key],key,last)
				return last
				},
		'string' : function(str,func,last){
				var arr=words(str), ix=arr[0]?0:1, len=arr.length, stop=arr[len-1]?len:len-1
				var f={func:func}
				for (var i=ix ; i<stop ; ++i) last=f.func(arr[i],i-ix,last)
				return last
				},
		'array' : function(arr,func,last){
				var f={func:func}
				for (var i=0, stop=arr.length ; i<stop ; ++i) last=f.func(arr[i],i,last)
				return last
				},
		'function' : function(fnc,func,last){
				if (fnc.length !== undefined) return _dofHandlers['array'](fnc,func,last) //In moz childNode is a function with len
				//What to do with a function ..nothing for now...
				return last
				}
	*/
		//TODO define a handler for string (by char or split(delim)
	//	}
	//}
} //Close jz name space usage
