/*********************************************************************************/
/**			copyright (c) PlanetCalc.com, 2007  			**/
/**		    	browser specific function				*/
/*********************************************************************************/

function BSAdviseEvent( eventsource, eventtype, eventhandler, eventsourceid ) {
	if ( window.addEventListener ) { // Safari, Firefox
		eventsource.addEventListener( eventtype, function(event) { eventhandler(eventsourceid);  return BSPreventDefaultAction( event ); } , false );
	} else { // IE, Opera
		eventsource.attachEvent( "on" + eventtype, function(event) { eventhandler(eventsourceid); return BSPreventDefaultAction( event );  } );
	}            
}

function BSCreateXMLHttpRequest( ) {
	if (window.XMLHttpRequest) {
		return new XMLHttpRequest();
	} else if (window.ActiveXObject) {
		return new ActiveXObject("Microsoft.XMLHTTP");
	}
}

function BSGetDataSourceDomain() {
	if ( typeof(dataSourceDomain)!='undefined' ) {
		return dataSourceDomain;
	}
	return document.domain;
}

function BSAlert( txt ) {
	alert( txt );
}

function BSJson2Object( js ) {
	return eval('(' + js + ')');		
}


function ProcessResponseError( callback, err ) {
	if ( null!= callback.OnError ) {
		callback.OnError( err );
	} else {
		BSAlert("Error occured:" + err );
	}
}
function ProcessResponseData( callback, obj ) {
	if ( obj.error ) {
		ProcessResponseError( callback, obj.error );
	} else {
		callback.OnResponse( obj );								
	}
}


function BrowserResponse ( req, cb ) {
	var request = req;
	var callback = cb;
	this.OnResponse = function() {
		if ( request.readyState == 4) { // "loaded"
			if ( request.status == 200) { //"OK"
				if ( callback.OnResponseText ) {
					callback.OnResponseText( request.responseText );
				} else {
					var obj = BSJson2Object( request.responseText );
					ProcessResponseData( callback, obj );
				}
			} else {
				BSAlert("There was a problem retrieving the data from server:\n" + request.statusText);
			}
		}
	}
}


function GGResponse( cb ) {
	var callback = cb;
	this.OnResponse= function( o ) { 
		if ( !o.text || o.text=='' ) {
			ProcessResponseError( callback, o.errors );
			return;
		}			
		if ( callback.OnResponseText ) {
			callback.OnResponseText( o.text );
		} else {
			ProcessResponseData( callback,  o.data  );
			gadgets.window.adjustHeight();
		}
	}
}


function BSMakePOSTRequest( url, callback, params ) {
	if ( typeof(gadgets)!='undefined' ) { 
		var requestParams = {};
		requestParams[gadgets.io.RequestParameters.METHOD] = gadgets.io.MethodType.POST;
		var encodedParams  = gadgets.io.encodeValues(params);
		requestParams[gadgets.io.RequestParameters.POST_DATA]= encodedParams;
		requestParams[gadgets.io.RequestParameters.CONTENT_TYPE] = gadgets.io.ContentType.JSON
		gadgets.io.makeRequest(url, new GGResponse( callback ).OnResponse , requestParams ); 
		return;
	}

	var req = BSCreateXMLHttpRequest();	
	req.onreadystatechange  = new BrowserResponse( req, callback ).OnResponse;
	req.open( "POST", url , true );
	req.setRequestHeader("Content-Type", "application/x-www-form-urlencoded");
	req.send( params? SaveObjectToURLParams(params) : null );
	
}


function BSPoint(x,y) {
	this.x = x;
	this.y = y;
	this.xpx = x + "px";
	this.ypx = y + "px";
}

function BSGetMouseXYFromEvent(evt) { 
    if (!evt) 
	evt = window.event; // works on IE, but not NS (we rely on NS passing us the event)

    var mousex = 0;
    var mousey = 0;
    if (evt) { 
	if (evt.pageX || evt.pageY) { // this doesn't work on IE6!! (works on FF,Moz,Opera7)
	    mousex = evt.pageX;
	    mousey = evt.pageY;
	} else if (evt.clientX || evt.clientY) { // works on IE6,FF,Moz,Opera7
            mousex = evt.clientX + document.body.scrollLeft;
	    mousey = evt.clientY + document.body.scrollTop;
	}  
    }
    return new BSPoint(mousex, mousey);
}                       

function BSGetWindowSize() {
	var width = 0, height = 0;
	if( typeof( window.innerWidth ) == 'number' ) {
		//Non-IE
		width = window.innerWidth;
		height = window.innerHeight;
	} else if ( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) {
		//IE 6+ in 'standards compliant mode'
		width = document.documentElement.clientWidth;
		height = document.documentElement.clientHeight;
	} else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
		//IE 4 compatible
		width = document.body.clientWidth;
		height = document.body.clientHeight;
	}
	return new BSPoint(width, height);
}                   

function BSGetScroll(){
	var scrOfX = 0, scrOfY = 0;
	if( typeof( window.pageYOffset ) == 'number' ) {
	    //Netscape compliant
    	scrOfY = window.pageYOffset;
	    scrOfX = window.pageXOffset;
	} else if( document.body && ( document.body.scrollLeft || document.body.scrollTop ) ) {
	    //DOM compliant
    	scrOfY = document.body.scrollTop;
	    scrOfX = document.body.scrollLeft;
	} else if( document.documentElement && ( document.documentElement.scrollLeft || document.documentElement.scrollTop ) ) {
    	//IE6 standards compliant mode
	    scrOfY = document.documentElement.scrollTop;
    	scrOfX = document.documentElement.scrollLeft;
	}
	return new BSPoint(scrOfX, scrOfY);
}

function BSSetScroll( pos ){
	window.scrollTo(pos.x, pos.y);
}


function BSGetPageSize(){
	var xScroll, yScroll;
	var pageHeight, pageWidth;
	
	if (window.innerHeight && window.scrollMaxY) {	
		xScroll = document.body.scrollWidth;
		yScroll = window.innerHeight + window.scrollMaxY;
	} else if (document.body.scrollHeight > document.body.offsetHeight){ // all but Explorer Mac
		xScroll = document.body.scrollWidth;
		yScroll = document.body.scrollHeight;
	} else { // Explorer Mac...would also work in Explorer 6 Strict, Mozilla and Safari
		xScroll = document.body.offsetWidth;
		yScroll = document.body.offsetHeight;
	}

	var windowSize = BSGetWindowSize();	

	// for small pages with total height less then height of the viewport
	if(yScroll < windowSize.y){
		pageHeight = windowSize.y;
	} else { 
		pageHeight = yScroll;
	}

	// for small pages with total width less then width of the viewport
	if(xScroll < windowSize.x){	
		pageWidth = windowSize.x;
	} else {
		pageWidth = xScroll;
	}

	return new BSPoint(pageWidth, pageHeight);
}

function BSGetElementSize( element ) {
	return new BSPoint(element.clientWidth, element.clientHeight);
}

function BSGetEventTarget( evt ) {
	var theTarget = evt.target ? evt.target : evt.srcElement;
	if( theTarget && ( theTarget.nodeType == 3 || theTarget.nodeType == 4 ) ) {
		theTarget = theTarget.parentNode;
	}
	return theTarget;
}

function BSPreventDefaultAction( evt ) {
	if ( evt.preventDefault ) {
		evt.preventDefault(); // DOM Style
	}
	return false; // event handler must return false too!!!
}

function BSSetDimmedSELECTsVisibility( dialogElem, show ) {
    if ( document.all ) { // Only do this for IE

		var selects = document.getElementsByTagName("SELECT");
		for (var i = 0; i < selects.length; ++i) {
			selects[i].style.display = show?"inline":"none";
		}
	
		var dialogSelects= dialogElem.getElementsByTagName("SELECT");
		for (var j = 0; j < dialogSelects.length; ++j) {		
			dialogSelects[j].style.display = show?"none":"inline";
		}
    }
}

/// Returns object with two properties: 'selectionStart', 'selectionEnd' = text selection range
function BSGetTextSelection( element ) {
	var retval = new Object();
	if ( typeof(element.selectionStart)!='undefined' ) {
		retval.selectionStart = element.selectionStart;
		retval.selectionEnd = element.selectionEnd;
	} else { // IE
		element.focus();
		var range = element.createTextRange();
		range.moveToBookmark(document.selection.createRange().getBookmark());
		var textlen = range.text.length;
		var elementValue = element.value;
		var elementLength = elementValue.length;
		for( var i = elementLength-1;i>=0;--i ) {
			var ch = elementValue.charCodeAt(i);			
			if ( ch==10 || ch==13 ) {
				elementLength--;
			} else {
				break;
			}
		}
		range.moveEnd('character',element.value.length);
		retval.selectionStart = elementLength - range.text.length;				
		range.moveEnd('character', - range.text.length + textlen);
		retval.selectionEnd = retval.selectionStart + textlen;
	}
	return retval;
}

function BSTextAreaInsert(element, inserttext)
{
	element.focus();
	var sel = BSGetTextSelection(element);

	var selectedtext = inserttext;
	var scrollTop = element.scrollTop;
	element.value = element.value.substring(0, sel.selectionStart) + selectedtext + element.value.substring(sel.selectionEnd, element.value.length);
	element.focus();
	element.scrollTop = scrollTop;

	//restore selection
	if ( typeof(element.selectionStart)!='undefined' ) {
		var pos = sel.selectionStart + selectedtext.length;
		element.selectionStart = pos;
		element.selectionEnd = pos;
	} else { // IE
		var range = element.createTextRange();
		range.collapse();
		var rangeAdvance = sel.selectionStart;
		var end = rangeAdvance;
		for( var i = 0; i < end; ++i ) {
			var ch = element.value.charCodeAt(i);			
			if ( ch==10 ) {
				rangeAdvance--;
			} 
		}
   		range.moveStart('character', rangeAdvance + selectedtext.length);		
		range.select();
	}
}

function BSTextAreaInsertMarks( element, markOpen, insertsample, markClose ) {
	element.focus();
	var sel = BSGetTextSelection(element);

	var replaced = false;
	var selectedtext = insertsample;
	if (sel.selectionEnd - sel.selectionStart) {
		selectedtext = (element.value).substring(sel.selectionStart, sel.selectionEnd);
		replaced = true;
	}

	if (selectedtext.charAt(selectedtext.length - 1) == " ") { // exclude ending space char, if any
		selectedtext = markOpen + selectedtext.substring(0, (selectedtext.length - 1)) + markClose + " ";
	} else {
		selectedtext = markOpen + selectedtext + markClose;
	}

	var scrollTop = element.scrollTop;
	element.value = element.value.substring(0, sel.selectionStart) + selectedtext + element.value.substring(sel.selectionEnd, element.value.length);
	element.focus();
	element.scrollTop = scrollTop;

	//restore selection
	if ( typeof(element.selectionStart)!='undefined' ) {
		if (replaced) {
			var pos = sel.selectionStart + selectedtext.length;
			element.selectionStart = pos;
			element.selectionEnd = pos;
		} else {
			element.selectionStart = sel.selectionStart + markOpen.length;
			element.selectionEnd = element.selectionStart + insertsample.length;
		}
	} else { // IE
		var range = element.createTextRange();
		range.collapse();
		var rangeAdvance = sel.selectionStart;
		var end = rangeAdvance;
		for( var i = 0; i < end; ++i ) {
			var ch = element.value.charCodeAt(i);			
			if ( ch==10 ) {
				rangeAdvance--;
			} 
		}
		if (replaced) {
    		range.moveStart('character', rangeAdvance + selectedtext.length);		
		} else {
    		range.moveStart('character', rangeAdvance + markOpen.length);		
			range.moveEnd('character', insertsample.length);					
		}
		range.select();
	}
}

/// Returns ASCII code of a key in keypress event
function BSGetPressedKeyCode( evt ) {
	if ( window.event ) { // IE
		return evt.keyCode;
	} else if( evt.which ) { // Netscape/Firefox/Opera
		return evt.which;
	}
}

var DOMVirtualKeys = new Array("DOM_VK_UNDEFINED","DOM_VK_RIGHT_ALT","DOM_VK_LEFT_ALT","DOM_VK_LEFT_CONTROL","DOM_VK_RIGHT_CONTROL","DOM_VK_LEFT_SHIFT"
		,"DOM_VK_RIGHT_SHIFT","DOM_VK_LEFT_META","DOM_VK_RIGHT_META","DOM_VK_CAPS_LOCK","DOM_VK_DELETE","DOM_VK_END","DOM_VK_ENTER","DOM_VK_ESCAPE"
		,"DOM_VK_HOME","DOM_VK_INSERT","DOM_VK_NUM_LOCK","DOM_VK_PAUSE","DOM_VK_PRINTSCREEN","DOM_VK_SCROLL_LOCK","DOM_VK_LEFT","DOM_VK_RIGHT"
		,"DOM_VK_UP","DOM_VK_DOWN","DOM_VK_PAGE_DOWN","DOM_VK_PAGE_UP","DOM_VK_F1","DOM_VK_F2","DOM_VK_F3","DOM_VK_F4","DOM_VK_F5","DOM_VK_F6"
		,"DOM_VK_F7","DOM_VK_F8","DOM_VK_F9","DOM_VK_F10","DOM_VK_F11","DOM_VK_F12","DOM_VK_F13","DOM_VK_F14","DOM_VK_F15","DOM_VK_F16","DOM_VK_F17","DOM_VK_F18"
		,"DOM_VK_F19","DOM_VK_F20","DOM_VK_F21","DOM_VK_F22","DOM_VK_F23","DOM_VK_F24");


function BSGetPressedKey( evt ) {

	var result = {};
	if( typeof(evt.which)!='undefined' ) { // Netscape/Firefox/Opera
		result.charCode = evt.which;
	} else if ( window.event ) { // IE
		result.charCode = evt.keyCode;
	} else {
		for( var i =0;i<DOMVirtualKeys.length;++i ) {
			if ( evt[DOMVirtualKeys[i]] == evt.keyCode ) {
				result.vk = DOMVirtualKeys[i];
			}
		}
	}
	return result;
	
}

function BSGetElementTextNS(local, parentElem, index) {
	var result = parentElem.getElementsByTagName(local)[index];
	if (result) {
		// get text, accounting for possible
		// whitespace (carriage return) text nodes
		if (result.childNodes.length > 1) {
			return result.childNodes[1].nodeValue;
		} else {
			if (result.firstChild)
	        		return result.firstChild.nodeValue;
			else
			        return "n/a";
		}
	} else {
		return "n/a";
	}
}

function BSGetTextContent( element ) {
	if ( element.textContent ) {
		return element.textContent;
	} else {
		return element.innerText;
	}
}

function BSReplaceOptions( element, newtext ) {
	if ( element.outerHTML ) {
		var oldtext = element.outerHTML;
		var n = oldtext.search(/<option/i);
		if (-1 == n) 
			element.outerHTML = oldtext.replace(/<\/select>/i, newtext + "</select>");
		else 
			element.outerHTML = oldtext.substr(0, n) + newtext + "</select>";
	} else {
		element.innerHTML = newtext; 
	}
}


function BSBookmark( obj, title, url ){
	if (window.sidebar) { // firefox
		window.sidebar.addPanel(title, url, "");
	} else if(window.opera){ // opera
		obj.setAttribute('href',url);
		obj.setAttribute('title',title);
		obj.setAttribute('rel','sidebar');
		obj.click();
	} else if(document.all) { // ie
		window.external.AddFavorite(url, title);
	}
}

function BSBookmarkThis( aElem ){
	 BSBookmark( aElem, document.title, location.href );
}

function BSGetMaxWidthProperty() {
	return document.all ? "width":"max-width";
}

function BSAddSelectOption( s, id, txt ) {
	var opt = document.createElement('option');
	opt.text = txt;
	opt.value = id;
	if ( window.ActiveXObject ) {
		s.add( opt );
	} else {
		s.add( opt, null );
	}
}

function trim(str) {
	str = str.replace(/^\s+/, '');
	for (var i = str.length - 1; i >= 0; i--) {
		if (/\S/.test(str.charAt(i))) {
			str = str.substring(0, i + 1);
			break;
		}
	}
	return str;
}



function leftpad( s, ch, len ) {
	var res = new String(s);
	while( res.length<len ) {
		res = ch + res;	
	}
	return res;
}

function String2Date( s ) {
	var d = new Date( );
	if ( typeof(s)=='string' ) {
		ret = TryString2Date( s );
		if (ret instanceof Date) {
			return ret;
		}
	} else {
		d = new Date( s );
	}
	return d;
}

function TryString2Date( str ) {
	var re = /^(\d{4})-(\d{2})-(\d{2}) (\d{2}):(\d{2}):(\d{2})( BC$|$)/i;
	var s = trim(str);
	var arr = s.match(re);
	if ( arr ) {
		var d = new Date( Number(arr[1]),Number(arr[2])-1,arr[3],arr[4],arr[5],arr[6] );
		if ( arr[7]==" BC" ) {
			d.setFullYear( 1-Number(arr[1]) );
		} else {
			d.setFullYear( arr[1] );
		}
		return d;
	}
	return s;
}


function Date2String( v ) {
	var y = v.getFullYear();
	var bc = y<=0?' BC':'';
	if ( y<=0 ) y = 1-y;
	return  leftpad(y,'0',4) +'-' + leftpad((v.getMonth()+1),'0',2) + '-' + leftpad(v.getDate(),'0',2) + ' ' + leftpad(v.getHours(),'0',2) + ':' + leftpad(v.getMinutes(),'0',2)+ ':' + leftpad(v.getSeconds(),'0',2) + bc;
}

function BSDateParse( s ) {
	return String2Date( s );
}

function BSInsertFlash(width, height, destination)
{
	if ( document.all ) //IE
		return "<object classid=\"clsid:d27cdb6e-ae6d-11cf-96b8-444553540000\" codebase=\"http://fpdownload.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=8,0,0,0\" width=\"" + width + "\" height=\"" + height + "\" id=\"" + destination + "_chart\" align=\"middle\"><param name=\"allowScriptAccess\" value=\"sameDomain\" /><param name=\"wmode\" value=\"opaque\"/><param name=\"movie\" value=\"/open-flash-chart.swf\" /><param name=\"quality\" value=\"high\" /></object>";
	else
		return "<embed src=\"/open-flash-chart.swf\" quality=\"high\" bgcolor=\"#FFFFFF\" width=\"" + width + "\" height=\"" + height + "\" name=\"open-flash-chart\" align=\"middle\" allowScriptAccess=\"sameDomain\" type=\"application/x-shockwave-flash\" pluginspage=\"http://www.macromedia.com/go/getflashplayer\" wmode=\"opaque\"/>";
}


function BSIsSystemKey( pressedKey ) {
	return pressedKey.charCode==120 || pressedKey.charCode==99 || pressedKey.charCode==118; //copy&paste in FF
}