/*
 * Copyright (C) 2007 Diego Perini
 * All rights reserved.
 *
 * nwframes.js - IFrames and XFrames Manager
 *
 * Author: Diego Perini <diego.perini at gmail com>
 * Version: 0.98
 * Release: 20071102
 *
 * License:
 *   http://javascript.nwbox.com/NWFrames/MIT-LICENSE
 * Download:
 *   http://javascript.nwbox.com/NWFrames/nwframes.js
 */

NW.IFrame=function(){

	var version='0.98',

	// called before onload
	// on IE body is available
	// on FF/OP the DOM is ready
	preload=
		function(e){
			if(typeof this.onPreload=='function'){
				this.onPreload(e);
				this.Preloaded=true;
			}
		},

	// called before onload
	// elements/assets loaded
	postload=
		function(e){
			if(typeof this.onPostload=='function'){
				this.onPostload(e);
				this.Postloaded=true;
			}
		},

	// load event handler
	load=
		function(e){
			if((this.readyState&&this.readyState=='complete')||this.contentDocument){
				if(!this.Postloaded){
					postload.call(this,e);
				}
				if(typeof this.onLoad=='function'){
					this.onLoad(e);
				}
			}else{
				if(this.readyState&&!this.Preloaded){
					preload.call(this,e);
				}
			}
		},

	// reload content in the iframe window
	reload=
		function(e){
			NW.Event.removeListener(this,e.type,arguments.callee,false);
			var f=NW.browser.opera?this.parentWindow.frameElement:this.frameElement;
			f.Loaded=false;
			f.Preloaded=false;
			f.contentWindow.name='';
			if(typeof f.onUnload=='function'){f.onUnload();}
			NW.Event.appendListener(f,NW.browser.msie?'readystatechange':'load',load,false);//
		},

	// remove all iframes and event handlers
	// before the host document is unloaded
	unload=
		function(e){
			var i=0,f=parent.document.getElementsByTagName('iframe'),i=f.length;
			while(--i>=0){
				if(typeof f[i].onPreload!='undefined'){
					NW.IFrame.close(f[i]);
				}
			}
			NW.Event.removeListener(parent.document,'DOMFrameContentLoaded',preload);
		};

	return {

		close:
			function(f){
				if(f){
					NW.Event.removeListener(f,NW.browser.msie?'readystatechange':'load',load,false);
					f.parentNode.removeChild(f);
					f=null;
				}
				return f;
			},

		open:
			function(o){
				var f=null,d=o.document||(o.parent?NW.Dom.getDocument(o.parent):parent.document);
				if(parent.frames[o.id]){f=document.getElementById(o.id);}
				if(!f){
					if(d&&d.createElement){
						// default style
						var s='display:block;';
						f=d.createElement('iframe');
						f.id=o.id||('nwf-'+frames.length);
						f.name=o.id||('nwf-'+frames.length);
						// custom xframe events
						f.onLoad=o.onLoad||null;
						f.onUnload=o.onUnload||null;
						f.onPreload=o.onPreload||null;
						f.onPostload=o.onPostload||null;
						// iframe element properties
						f.scrolling=o.scrolling||'auto';
						f.frameBorder=o.frameBorder||'0';
						f.marginWidth=o.marginWidth||'0px';
						f.marginHeight=o.marginHeight||'0px';
						f.allowTransparency=o.transparent||false;
						// iframe style default preferences
						f.style.cssText=o.style||'display:block';
//						f.style.width=o.width;
//						f.style.height=o.height;
						f.style.width=o.width+((''+o.width).replace(/[0-9]/g,'')!==''?'':'px');
						f.style.height=o.height+((''+o.height).replace(/[0-9]/g,'')!==''?'':'px');
						(o.parent||d.body).appendChild(f);
						NW.Event.appendListener(f,
							NW.browser.msie
								?'readystatechange'
								:'load',
							load,
							false
						);
					}else{
						return null;
					}
				}
				f.src=(typeof o.src=='string'&&o.src.length>0)?o.src:'about:blank';

				// in FF/OP only attach this once in parent document
				if(!parent.document.DOMFrameEvent){
					parent.document.DOMFrameEvent=true;
					NW.Event.appendListener(parent.document,'DOMFrameContentLoaded',
						function(e){
							// call preload, pass iframe as scope
							try{
								if(e.target.id){
									preload.call(e.target,e);
								}
							}catch(e){
							}
						},false
					);
					NW.Event.appendListener(parent,'beforeunload',unload);
				}

				// return iframe element
				return f;
			},

		getWindow:
			function(f){
				return f.contentWindow||NW.win.frames[f.name];
			},

		getDocument:
			function(f){
				return f.contentDocument||f.contentWindow.document||f.document;
			}

	};

}();

NW.XFrame=function(){

	// define some html/css string constants
	var jType='',jMeta='',jRule='',jHtml='';
	jType+='<\x21DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" \n>\n';
	jMeta+='<meta http-equiv="Content-Type" content="text/html; charset=utf-8">';
	jRule+='html,body{background-color:transparent;margin:0px;padding:0px;overflow:hidden;}';
	jRule+='.nw_frames_theme{background: url('+NW.path+'img/nwframes1.gif) 0px -72px repeat;}';
	jHtml+='<html><head><title>BLANK</title>'+jMeta+'<style type="text/css">'+jRule+'</style></head><body></body></html>';

	return {

		items:[],

		open:
			function(url,title,w,h,x,y,callback){
				if(isNaN(w)||isNaN(h)||isNaN(x)||isNaN(y)){
					throw new Error('NW.XFrame: dimensions/positions must be integers.');
					return null;
				}
				return new this.create(url,title,w,h,x,y,callback);
			},

		close:
			function(o){
				if(o&&o.constructor==NW.XFrame.create){
					o.shut();
					o.hide();
					o.header.parentNode.removeChild(o.header);
					o.xframe.parentNode.removeChild(o.xframe);
					o.status.parentNode.removeChild(o.status);
					o.box.parentNode.removeChild(o.box);
					NW.XFrame.items.splice(NW.XFrame.has(o.title),1);
//alert(NW.XFrame.items.toSource());
				}
			},

		has:
			function(t){
				for(var w=this.items,i=0;w.length>i;i++){
					if(w[i].title==t){
						return w[i];
					}
				}
				return false;
			},

		create:
			function(url,title,w,h,x,y,callback){

				var o=this,i,
					d=NW.document,
					fn=null,count=0,
					dragStarted=false,
					resizeStarted=false,
					previous=NW.XFrame.has(title);

				if(previous){
					return previous.load();
				}else{
					NW.XFrame.items.push(o);
				}

				o.id='nw_frame_'+title.replace(/[^a-z0-9A-Z]/g,'_')+'_'+NW.XFrame.items.length;
				o.url=url;

				o.title=title;
				o.timer=null;

				o.headerHeight=18;
				o.xframeHeight=h;
				o.statusHeight=18;

				o.left=0;
				o.top=0;

				o.width=w+2;
				o.height=o.headerHeight+o.xframeHeight+o.statusHeight;

				// parent document
				o.root=/CSS/.test(d.compatMode)?d.documentElement:d.body;
				o.size=NW.Dom.getWindowSize(d);

				// current box position (moveto)
				o.posX=0;
				o.posY=0;

				// start box position (drag/resize)
				o.startX=0;
				o.startY=0;

				// offset box position (drag/resize)
				o.deltaX=0;
				o.deltaY=0;

				o.box=d.createElement('div');
				o.box.id=o.id+'_box';
				o.box.style.cssText=
					'position:'+(NW.browser.msie&&NW.browser.msie<7?'absolute':'fixed')+';top:-9999px;left:-9999px;visibility:hidden;';

				o.toBack=
					function(){
						for(var w=NW.XFrame.items,i=0;w.length>i;i++){
							w[i].box.style.zIndex=w[i].box==o.box?1001:1003;
						}
					};
				o.toFront=
					function(){
						for(var w=NW.XFrame.items,i=0;w.length>i;i++){
							w[i].box.style.zIndex=w[i].box==o.box?1003:1001;
						}
					};

				o.loadRect=
					function(){
						var c,v;
						c=NW.getCookie(o.title);
						o.top=(o.size.h-o.height)/2;
						o.left=(o.size.w-o.width)/2;
						if(c){
							v=c.split(' ');
							o.top=Math.max(0,Math.min(o.size.h-h,parseInt(v[0])));
							o.left=Math.max(0,Math.min(o.size.w-w,parseInt(v[1])));
							o.width=Math.max(w,Math.min(o.size.w-0,parseInt(v[2])));
							o.height=Math.max(h,Math.min(o.size.h-0,parseInt(v[3])));
						}
					};

				o.saveRect=
					function(){
						if(NW.browser.msie){
							o.left=o.box.offsetLeft-o.root.scrollLeft;
							o.top=o.box.offsetTop-o.root.scrollTop;
						}else{
							o.left=o.box.offsetLeft;
							o.top=o.box.offsetTop;
						}
						o.width=o.box.offsetWidth;
						o.height=o.box.offsetHeight-2;
						o.xframeHeight=o.xframe.offsetHeight;
						NW.setCookie(o.title,o.top+' '+o.left+' '+o.width+' '+o.height);
					};

				o.appendBox=
					function(){
						d.body.insertBefore(o.box,d.body.firstChild);
					};

				o.removeBox=
					function(){
						d.body.removeChild(o.box);
					};

				o.createTitle=
					function(d){
						var i,h=o.headerHeight,
							a,b=['mdihlp','mdimax','mdiend'],
							c='position:absolute;height:18px;';
						for(i=0;b.length>i;i++){
							o[b[i]]=d.createElement('div');
							o[b[i]].className='nw_frames_theme';
							o[b[i]].id=o.id+'_'+b[i];
							o[b[i]].style.cssText=c+
								'z-index:5;background-position:0px -'+((3-i)*h)+'px;'+
								'cursor:pointer;width:'+h+'px;right:'+((2-i)*h)+'px;';
							d.body.insertBefore(o[b[i]],null);
						}
						// title bar gradient
						o.mdibar=d.createElement('div');
						o.mdibar.className='nw_frames_theme';
						o.mdibar.style.cssText=c+'z-index:1;width:100%;background:url('+NW.path+'img/nwframes1.gif) 0px -72px repeat;'+(NW.browser.msie?'filter:alpha(opacity=60);':'opacity:0.60;');
						d.body.insertBefore(o.mdibar,d.body.firstChild);
						// text string for xframe title
						o.mditxt=d.createElement('div');
						o.mditxt.style.cssText=c+'z-index:2;font:normal 13px/'+(NW.browser.msie?'18':'16')+'px sans-serif;color:#fff;text-indent:4px;';
						o.mditxt.appendChild(d.createTextNode(o.title));
						d.body.insertBefore(o.mditxt,d.body.firstChild);
						// invisible iframe dragging handle
						o.handle=d.createElement('div');
						o.handle.style.cssText=c+'z-index:3;width:100%;font-size:2px;cursor:move;';
						o.handle.appendChild(d.createTextNode('\xa0'));
						d.body.insertBefore(o.handle,d.body.firstChild);
					};

				o.createStatus=
					function(d){
						var c='position:absolute;height:18px;';
						d.body.style.cssText='overflow:hidden;height:18px;';
						o.mdimsg=NW.addElement(d.body,'div','nw_status_notify','','Status Messages','Ready');
						o.mdimsg.style.cssText=c+'z-index:1;font:normal 11px/16px sans-serif;text-indent:4px;';
						o.mdibkg=NW.addElement(d.body,'div','nw_status_ground','nw_frames_theme','Status Bar','');
						o.mdibkg.style.cssText=c+'z-index:0;background-position:0px -90px;background-repeat:repeat-x;width:100%;';
						o.mdires=NW.addElement(d.body,'div','nw_resize_handle','nw_frames_theme','Resize Handle','\xa0');
						o.mdires.style.cssText=c+'z-index:2;background-position:0px -108px;font-size:2px;right:0px;cursor:nw-resize;width:18px;';
					};

				o.init=
					function(){
						var d,p=this.id.split('_'),t=p[p.length-1],v;
						switch(t){
							case 'header':
								o.createTitle(d=NW.IFrame.getDocument(this));
								// avoid select all (CTRL-A) on title text
								NW.Event.appendListener(d,'keydown',NW.Event.stop,false);
								// disable default context menu on this iframe
								NW.Event.appendListener(d,'contextmenu',NW.Event.stop,true);
								// handle mousedown/mouseup to perform the drag
								NW.Event.appendListener(o.handle,'mousedown',o.dragStart,false);
								NW.Event.appendListener(o.handle,'mouseup',o.dragStop,false);
								NW.Event.appendListener(o.mdihlp,'mouseup',o.gethelp,false);
								NW.Event.appendListener(o.mdimax,'mouseup',o.toggle,false);
								NW.Event.appendListener(o.mdiend,'mouseup',o.hide,false);
								break;
							case 'xframe':
								// URL not in the same domain as the host page will
								// not have script read/write access to this iframe
								if(typeof callback=='function'){callback(d);}
								break;
							case 'status':
								o.createStatus(d=NW.IFrame.getDocument(this));
								// avoid select all (CTRL-A) on status messages text
								NW.Event.appendListener(d,'keydown',NW.Event.stop,false);
								// disable default context menu on this iframe
								NW.Event.appendListener(d,'contextmenu',NW.Event.stop,true);
								// handle mousedown/mouseup to perform the resize
								NW.Event.appendListener(o.mdires,'mouseup',o.resizeStop,false);
								NW.Event.appendListener(o.mdires,'mousedown',o.resizeStart,false);
								// avoid mouse selection of status messages text
//								NW.Event.setSelection(o.mdimsg,false);
								break;
							default:
								break;
						}
					};

				o.shut=
					function(){
						var d,p=this.id.split('_'),t=p[p.length-1];
						switch(t){
							case 'header':
								d=getDocument(this);
								NW.Event.removeListener(o.mdiend,'mouseup',o.hide,false);
								NW.Event.removeListener(o.mdimax,'mouseup',o.toggle,false);
								NW.Event.removeListener(o.mdihlp,'mouseup',o.gethelp,false);
								NW.Event.removeListener(o.handle,'mouseup',o.dragStop,false);
								NW.Event.removeListener(o.handle,'mousedown',o.dragStart,false);
								NW.Event.removeListener(d,'contextmenu',NW.Event.stop,true);
								NW.Event.removeListener(d,'keydown',NW.Event.stop,false);
								break;
							case 'xframe':
								break;
							case 'status':
								d=getDocument(this);
								NW.Event.removeListener(o.mdires,'mousedown',o.resizeStart,false);
								NW.Event.removeListener(o.mdires,'mouseup',o.resizeStop,false);
								NW.Event.removeListener(d,'contextmenu',NW.Event.stop,true);
								NW.Event.removeListener(d,'keydown',NW.Event.stop,true);
								break;
							default:
								break;
						}
					};

				o.setCursor=
					function(t){
						var c=parent.document.body.style.cursor;
						if(c!=t){
							parent.document.body.style.cursor=t;
						}
					};

				o.close=
					function(){
						o.saveRect();
						o.removeBox();
					};

				o.load=
					function(){
						if(url.length>0){
							if(NW.browser.dom>2){
								return window.open(url,'','width='+o.width+',height='+o.height+',scrollbars=1');
							}
							o.xframe.src=o.url;
						}else if(typeof callback=='function'){
							callback();
						}
						o.toFront();
						o.show();
						return o;
					};

				o.gethelp=
					function(e){
						alert('Call your custom help system here !\n\nMaybe using an XFrame instance again ?');
					};

				o.maximize=
					function(){
						o.mdimax.style.backgroundPosition='0px -36px';
						o.box.style.height=o.height+'px';
						o.xframe.style.display='block';
						o.status.style.display='block';
					};

				o.minimize=
					function(){
						o.mdimax.style.backgroundPosition='0px 0px';
						o.box.style.height=o.headerHeight+'px';
						o.xframe.style.display='none';
						o.status.style.display='none';
					};

				o.toggle=
					function(e){
						if(o.xframe.style.display!='none'){
							o.minimize();
						}else{
							o.maximize();
						}
					};

				o.hide=
					function(e){
						if(typeof o.onBeforeHide=='function'){o.onBeforeHide();}
						o.box.style.visibility='hidden';
						o.box.style.display='none';
					};

				o.show=
					function(){
						if(typeof o.onBeforeShow=='function'){o.onBeforeShow();}
						o.box.style.visibility='visible';
						o.box.style.display='block';
					};

				o.moveTo=
					function(){
						o.posX=Math.max(0,Math.min(o.size.w-o.width-16,o.left+o.deltaX));
						o.posY=Math.max(0,Math.min(o.size.h-o.height,o.top+o.deltaY));
						// fixed position for older IE
						if(NW.browser.msie&&NW.browser.msie<7){
							o.box.style.setExpression('left',''+o.posX+'+((/CSS/).test(document.compatMode)?document.documentElement:document.body).scrollLeft');
							o.box.style.setExpression('top',''+o.posY+'+((/CSS/).test(document.compatMode)?document.documentElement:document.body).scrollTop');
						}else{
							o.box.style.left=o.posX+'px';
							o.box.style.top=o.posY+'px';
						}
					};

				o.resizeTo=
					function(){
						o.box.style.width=Math.max(w,o.width+o.deltaX)+'px';
						o.box.style.height=Math.max(h,o.height+o.deltaY)+'px';
						if(o.xframe.onResize){o.xframe.onResize.call(o.xframe,w,h);}
						o.xframe.style.height=Math.max(h-o.headerHeight-o.statusHeight,o.height+o.deltaY-o.headerHeight-o.statusHeight)+'px';
					};

				o.initValues=
					function(e){
						o.deltaX=o.deltaY=0;
						o.startX=e.screenX;
						o.startY=e.screenY;
					};

				o.dragStart=
					function(e){
						if(NW.Dom.getButton(e)=='l'&&dragStarted===false){
							dragStarted=true;
							if(typeof o.onBeforeDrag=='function'){o.onBeforeDrag();}
							o.mouseCapture(o.dragEvents);
							o.mouseStart(o.moveTo,50);
							o.initValues(e);
							o.toFront();
						}
					};

				o.dragStop=
					function(e){
						if(NW.Dom.getButton(e)=='l'&&dragStarted===true){
							dragStarted=false;
							if(typeof o.onAfterDrag=='function'){o.onAfterDrag();}
							o.mouseRelease(o.dragEvents);
							o.mouseStop();
							o.saveRect();
						}
					};

				o.resizeStart=
					function(e){
		                if(NW.Dom.getButton(e)=='l'&&resizeStarted===false){
							resizeStarted=true;
							if(typeof o.onBeforeResize=='function'){o.onBeforeResize();}
							o.mouseCapture(o.resizeEvents);
							o.mouseStart(o.resizeTo,50);
							o.initValues(e);
							o.toFront();
						}
					};

				o.resizeStop=
					function(e){
						if(NW.Dom.getButton(e)=='l'&&resizeStarted===true){
							resizeStarted=false;
							if(typeof o.onAfterResize=='function'){o.onAfterResize();}
							o.mouseRelease(o.resizeEvents);
							o.mouseStop();
							o.saveRect();
						}
					};

				// capture global mouse events in
				// multi-document environments (iframes)
				// @t array of chain types to capture
				o.mouseCapture=
					function(t){
						var i,j,f=NW.window.frames;
						for(i=0;f.length>i;i++){
							for(j in t){try{NW.Event.appendListener(f[i].document,j,t[j],false);}catch(e){}}
						}
					};

				// release global mouse events
				// multi-document environments (iframes)
				// @t array of chain types to release
				o.mouseRelease=
					function(t){
						var i,j,f=NW.window.frames;
						for(i=0;f.length>i;i++){
							for(j in t){try{NW.Event.removeListener(f[i].document,j,t[j],false);}catch(e){}}
						}
					};

				o.mouseStart=
					function(f,t){
						if(o.timer){
							o.mouseStop();
						}
						o.timer=setInterval(f,t);
					};

				o.mouseStop=
					function(){
						if(o.timer){
							o.timer=clearInterval(o.timer);
						}
					};

				o.mouseMove=
					function(e){
						o.deltaX=e.screenX-o.startX;
						o.deltaY=e.screenY-o.startY;
					};

				o.dragEvents={
					'mousemove':o.mouseMove,
					'mouseup':o.dragStop,
					'mousedown':NW.Event.stop,
					'mouseover':NW.Event.stop,
					'mouseout':NW.Event.stop
				};

				o.resizeEvents={
					'mousemove':o.mouseMove,
					'mouseup':o.resizeStop,
					'mousedown':NW.Event.stop,
					'mouseover':NW.Event.stop,
					'mouseout':NW.Event.stop
				};

				o.postload=
					function(e){
						if(this.src=='about:blank'){
							var w=this.contentWindow,d=w.document;
							w.Loaded=true;
							w.name=this.name;
							if(NW.browser.msie>=6&&d.execCommand){
								d.execCommand('BackgroundImageCache',false,true);
							}
							// inject base document if not done yet
							// this will fire onunload/onload events
							if(d.title!='BLANK'){
								d.open('text/html','replace');
								d.write(jType+jHtml);
								if(!NW.browser.msie){
									d.close();
								}
							}
						}
						this.Loaded=true;
						this.style.visibility='';
						if(count>0){
							count--;
						}
						if(count===0){
							fn.call(this,e);
							o.show();
						}
					};

				o.preload=
					function(e){
						this.Preloaded=true;
						if(this.src!='about:blank'){
							// do something for the content frame
							// restrictions maybe enforced by the
							// browser if not in the same domain
						}else{
							// title & status frames, restricions
							// are not enforced for blank frames
						}
					};

				o.Elms={
					header:{u:'',h:o.headerHeight},
					xframe:{u:url,h:o.xframeHeight},
					status:{u:'',h:o.statusHeight},
					onComplete:
						function(e){
							var xf=this.parentNode.getElementsByTagName('iframe');
							for(var n=0;n<xf.length;n++){
								xf[n].style.visibility='';
								xf[n].style.border='1px solid #333';
								xf[n].style.borderWidth='0px 1px 0px 1px';
							}
						}
				};

				for(i in o.Elms){
					if(typeof o.Elms[i]=='function'){
						fn=o.Elms[i];
					}else{
						count++;
					}
				}

				for(i in o.Elms){
					if(typeof o.Elms[i]=='object'){
						o[i]=NW.IFrame.open({
							id:o.id+'_'+i,
							document:d,
							parent:o.box,
							src:o.Elms[i].u,
							width:'100%',
							height:o.Elms[i].h,
							transparent:true,
							onLoad:o.init,
							onUnload:o.shut,
							onPreload:o.preload,
							onPostload:o.postload,
							style:'display: block;'
						});
					}
				}

				o.loadRect();
				o.appendBox();
				o.resizeTo();
				o.toFront();
				o.moveTo();
				return o;
			}
	};

}();
