/*
	Copyright (c) 2004-2012, The Dojo Foundation All Rights Reserved.
	Available via Academic Free License >= 2.1 OR the modified BSD license.
	see: http://dojotoolkit.org/license for details
*/


if(!dojo._hasResource["dojo.window"]){ //_hasResource checks added by build. Do not use _hasResource directly in your code.
dojo._hasResource["dojo.window"] = true;
dojo.provide("dojo.window");

dojo.getObject("window", true, dojo);

dojo.window.getBox = function(){
	// summary:
	//		Returns the dimensions and scroll position of the viewable area of a browser window

	var scrollRoot = (dojo.doc.compatMode == 'BackCompat') ? dojo.body() : dojo.doc.documentElement;

	// get scroll position
	var scroll = dojo._docScroll(); // scrollRoot.scrollTop/Left should work
	return { w: scrollRoot.clientWidth, h: scrollRoot.clientHeight, l: scroll.x, t: scroll.y };
};

dojo.window.get = function(doc){
	// summary:
	// 		Get window object associated with document doc

	// In some IE versions (at least 6.0), document.parentWindow does not return a
	// reference to the real window object (maybe a copy), so we must fix it as well
	// We use IE specific execScript to attach the real window reference to
	// document._parentWindow for later use
	if(dojo.isIE && window !== document.parentWindow){
		/*
		In IE 6, only the variable "window" can be used to connect events (others
		may be only copies).
		*/
		doc.parentWindow.execScript("document._parentWindow = window;", "Javascript");
		//to prevent memory leak, unset it after use
		//another possibility is to add an onUnload handler which seems overkill to me (liucougar)
		var win = doc._parentWindow;
		doc._parentWindow = null;
		return win;	//	Window
	}

	return doc.parentWindow || doc.defaultView;	//	Window
};

dojo.window.scrollIntoView = function(/*DomNode*/ node, /*Object?*/ pos){
	// summary:
	//		Scroll the passed node into view using minimal movement, if it is not already.

	// Don't rely on node.scrollIntoView working just because the function is there since
	// it forces the node to the page's bottom or top (and left or right in IE) without consideration for the minimal movement.
	// WebKit's node.scrollIntoViewIfNeeded doesn't work either for inner scrollbars in right-to-left mode
	// and when there's a fixed position scrollable element

	node = dojo.byId(node);
	var body, doc = node.ownerDocument || dojo.doc;

	// has() functions but without has() support
	if(!("rtl_adjust_position_for_verticalScrollBar" in dojo.window)){
		body = dojo.body();
		var	scrollable = dojo.create('div', {
				style: {overflow:'scroll', overflowX:'visible', direction:'rtl', visibility:'hidden', position:'absolute', left:'0', top:'0', width:'64px', height:'64px'}
			}, body, "last"),
			div = dojo.create('div', {
				style: {overflow:'hidden', direction:'ltr'}
			}, scrollable, "last");
		dojo.window.rtl_adjust_position_for_verticalScrollBar = dojo.position(div).x != 0;
		scrollable.removeChild(div);
		body.removeChild(scrollable);
	}

	if(!("position_fixed_support" in dojo.window)){
		// IE6, IE7+quirks, and some older mobile browsers don't support position:fixed
		body = dojo.body();
		var	outer = dojo.create('span', {
				style: {visibility:'hidden', position:'fixed', left:'1px', top:'1px'}
			}, body, "last"),
			inner = dojo.create('span', {
				style: {position:'fixed', left:'0', top:'0'}
			}, outer, "last");
		dojo.window.position_fixed_support = dojo.position(inner).x != dojo.position(outer).x;
		outer.removeChild(inner);
		body.removeChild(outer);
	}

	try{ // catch unexpected/unrecreatable errors (#7808) since we can recover using a semi-acceptable native method
		body = doc.body || doc.getElementsByTagName("body")[0];
		var	html = doc.documentElement || body.parentNode,
			isIE = dojo.isIE,
			isWK = dojo.isWebKit;
		// if an untested browser, then use the native method
		if(node == body || node == html){ return; }
		if(!(dojo.isMozilla || isIE || isWK || dojo.isOpera) && ("scrollIntoView" in node)){
			node.scrollIntoView(false); // short-circuit to native if possible
			return;
		}
		var	backCompat = doc.compatMode == 'BackCompat',
			rootWidth = Math.min(body.clientWidth || html.clientWidth, html.clientWidth || body.clientWidth),
			rootHeight = Math.min(body.clientHeight || html.clientHeight, html.clientHeight || body.clientHeight),
			scrollRoot = (isWK || backCompat) ? body : html,
			nodePos = pos || dojo.position(node),
			el = node.parentNode,
			isFixed = function(el){
				return (isIE <= 6 || (isIE == 7 && backCompat))
					? false
					: (dojo.window.position_fixed_support && (dojo.style(el, 'position').toLowerCase() == "fixed"));
			};
		if(isFixed(node)){ return; } // nothing to do
		while(el){
			if(el == body){ el = scrollRoot; }
			var	elPos = dojo.position(el),
				fixedPos = isFixed(el),
				rtl = dojo.getComputedStyle(el).direction.toLowerCase() == "rtl";

			if(el == scrollRoot){
				elPos.w = rootWidth; elPos.h = rootHeight;
				if(scrollRoot == html && isIE && rtl){ elPos.x += scrollRoot.offsetWidth-elPos.w; } // IE workaround where scrollbar causes negative x
				if(elPos.x < 0 || !isIE || isIE >= 9){ elPos.x = 0; } // older IE can have values > 0
				if(elPos.y < 0 || !isIE || isIE >= 9){ elPos.y = 0; }
			}else{
				var pb = dojo._getPadBorderExtents(el);
				elPos.w -= pb.w; elPos.h -= pb.h; elPos.x += pb.l; elPos.y += pb.t;
				var clientSize = el.clientWidth,
					scrollBarSize = elPos.w - clientSize;
				if(clientSize > 0 && scrollBarSize > 0){
					if(rtl && dojo.window.rtl_adjust_position_for_verticalScrollBar){
						elPos.x += scrollBarSize;
					}
					elPos.w = clientSize;
				}
				clientSize = el.clientHeight;
				scrollBarSize = elPos.h - clientSize;
				if(clientSize > 0 && scrollBarSize > 0){
					elPos.h = clientSize;
				}
			}
			if(fixedPos){ // bounded by viewport, not parents
				if(elPos.y < 0){
					elPos.h += elPos.y; elPos.y = 0;
				}
				if(elPos.x < 0){
					elPos.w += elPos.x; elPos.x = 0;
				}
				if(elPos.y + elPos.h > rootHeight){
					elPos.h = rootHeight - elPos.y;
				}
				if(elPos.x + elPos.w > rootWidth){
					elPos.w = rootWidth - elPos.x;
				}
			}
			// calculate overflow in all 4 directions
			var	l = nodePos.x - elPos.x, // beyond left: < 0
//						t = nodePos.y - Math.max(elPos.y, 0), // beyond top: < 0
				t = nodePos.y - elPos.y, // beyond top: < 0
				r = l + nodePos.w - elPos.w, // beyond right: > 0
				bot = t + nodePos.h - elPos.h; // beyond bottom: > 0
			var s, old;
			if(r * l > 0 && (!!el.scrollLeft || el == scrollRoot || el.scrollWidth > el.offsetHeight)){
				s = Math[l < 0? "max" : "min"](l, r);
				if(rtl && ((isIE == 8 && !backCompat) || isIE >= 9)){ s = -s; }
				old = el.scrollLeft;
				el.scrollLeft += s;
				s = el.scrollLeft - old;
				nodePos.x -= s;
			}
			if(bot * t > 0 && (!!el.scrollTop || el == scrollRoot || el.scrollHeight > el.offsetHeight)){
				s = Math.ceil(Math[t < 0? "max" : "min"](t, bot));
				old = el.scrollTop;
				el.scrollTop += s;
				s = el.scrollTop - old;
				nodePos.y -= s;
			}
			el = (el != scrollRoot) && !fixedPos && el.parentNode;
		}
	}catch(error){
		console.error('scrollIntoView: ' + error);
		node.scrollIntoView(false);
	}
};

}
