﻿/**********************************************************************
 *           G2 Cross-platform Javascript library                     *
 **********************************************************************/
Array.prototype.dequeue = function() {var r = this[0]; this.splice(0,1); return r;};
Array.prototype.FirstOrDefault = function(predicate)
{
	for(var i=0;i<this.length;i++)
	{
		var item = this[i];
		if(predicate(item))
			return item;
	}
	return null;
}
Array.prototype.ForEach = function(action)
{
	for(var i=0;i<this.length;i++)
	{
		var item = this[i];
		action(item);
	}
}
Array.prototype.RemoveItem = function(itemToRemove)
{
    for(var i=0;i<this.length;i++)
	{
		if (this[i] == itemToRemove)
		{
		    this.splice(i,1);
		    break;
		}
	}
}

var G2DOM = 
{
	GetChildElementById : function(element, id)
	{
		if(isIE)
		{
			var child = element.all[id];
			if(child==null)
				return null;
			if(child.length!=null)
				return child[0];
			return child;
		}
		else if(isMoz)
		{
			return this._GetChildElementById(element, id);
		}
		else
			throw new Error("not supported");
	},
	_GetChildElementById : function(element, id)
	{
		var child = element.firstChild;
		while(child!=null)
		{
			if(child.id==id)
				return child;
			var grandChild = this._GetChildElementById(child, id);
			if(grandChild!=null)
				return grandChild;
			child = child.nextSibling;
		}
		return null;
	},
	
	// This method gets a root element and a progid value and find the first child element with the progid specified
	// In case you got the whole progId path it is preffered to use the method 'findControl' below. It is much faster.
	// This method uses Depth-First-Search(DFS) recursively.
	GetChildByProgid_dfs : function(root, childProgid)
	{
		if (! root)
			return null;

		if (root.progid == childProgid)
			return root;

		var child = root.firstChild;
		while (child)
		{
			var res = this.GetChildByProgid(child, childProgid);
			if (res != null)
				return res;
			child = child.nextSibling;
		}
		
		return null;
	},
	

	// This method gets a root element and a progid value and find the first child element with the progid specified
	// This method uses Breadth-First-Search (BFS) instead of Depth-First-Search(DFS). It is therefore non-recursive.
	GetChildByProgid : function(root, childProgid)
	{
		if (! root)
			return null;
			
		if (root.progid == childProgid)
			return root;
			
		var queue = [root];		
		while (queue.length>0)
		{
			root = queue.dequeue();
			if (root.progid == childProgid)
				return root;
			var children = root.children;
			for (var i=0,j=children.length;i<j;i++)
				queue.push(children[i]);
		}	
				
		return null;
	},
	
	// This method gets a root element and a progid value and find the first parent element with the progid specified
	GetParentByProgid : function(root, childProgid)
	{
		while(root && root.progid != childProgid)
		{
			root = root.parentElement;
		}
		
		return root;
	},

	// gets the given object position	
	findPos : function(obj)
	{
		var curleft = 0;
		var curtop = 0;
		if (obj.offsetParent)
		{
			curleft = obj.offsetLeft;
			curtop = obj.offsetTop;
			while (obj = obj.offsetParent)
			{
				curleft += obj.offsetLeft;
				curtop += obj.offsetTop;
					
		    // taking into account scrooling with in overflow scroll elements
		    if(obj.tagName != 'HTML' && obj.scrollTop != null)
			    curtop -= obj.scrollTop;
			}
		}
		return [curleft,curtop];
	},
		
	// Create a covering DIV for a modal effect.
	// The input parameters:
	// side - left, top, right or bottom
	// tableId - the modal element or its id
	// errorMsg - message to shown when clicking on the div. optional
	CreateCoverDiv : function(side,tableId,errorMsg)
	{
		// validate modal element
		if(tableId == null)
			return;

		var tbl = tableId;
		if(typeof(tableId) == "string")
			tbl = $(tableId);

		var arr = this.findPos(tbl)	
		var docHeight,docWidth;
		var coverDiv = document.createElement('DIV');
		var div;
		if (side == "left")
		{
				div = $('leftCoverDiv');
			if (div!=null)
				return div;
			docHeight = document.documentElement.scrollHeight;		
			docWidth = arr[0];
			coverDiv.id = "leftCoverDiv";
		}
		else if (side == "top")
		{
				div = $('topCoverDiv');
			if (div!=null)
				return div;
			docWidth = document.documentElement.scrollWidth;
			docHeight = arr[1];	
			coverDiv.id = "topCoverDiv";
		}			
		else if (side == "right")
		{
				div = $('rightCoverDiv');
			if (div!=null)
				return div;
			docWidth = document.documentElement.scrollWidth-tbl.offsetWidth;
			docHeight = tbl.offsetHeight;
			coverDiv.id = "rightCoverDiv";
		}			
		else if(side == "bottom")
		{
				div = $('bottomCoverDiv');
			if (div!=null)
				return div;
			docWidth = document.documentElement.scrollWidth;
			docHeight = window.document.documentElement.scrollHeight-(arr[1]+tbl.offsetHeight);
			coverDiv.id = "bottomCoverDiv";
		}			
		coverDiv.className = "CoverDiv";
		if (side == "left" || side == "top")
		{
				coverDiv.style.left = "0px";
				coverDiv.style.top = "0px";
		}
		else if (side == "right")
		{
				coverDiv.style.left = arr[0]+tbl.offsetWidth+"px";
				coverDiv.style.top = arr[1]+"px";
		}
		else if (side == "bottom")
		{
				coverDiv.style.left = "0px";
				coverDiv.style.top = arr[1]+tbl.offsetHeight+2+"px";
		}
		coverDiv.style.height = docHeight+"px";
		coverDiv.style.width = docWidth+"px";	
		coverDiv.style.position="absolute";			
		coverDiv.onclick = function()
		{
			if(errorMsg)
				alert(errorMsg);
			else
				alert("You are in Edit Mode, Click Done to save or Cancel to exit");
		};
		return coverDiv;
	},

	//Transfers the custom attributes from the element to its properties (they are the same in IE, not in FF)
	G2TransferAttributes : function(elem)
	{
		if (isIE || elem==null || elem.attributesTransferred) //IE is nice enough
			return;
		elem.attributesTransferred = true;
		for (var atnum in elem.attributes)
		{
			var atNode = elem.attributes[atnum];
			var atname = atNode.nodeName;
			var atvalue = atNode.nodeValue;
			if (typeof(elem[atname])=="undefined")
				elem[atname] = atvalue;
		}	
	},

	G2GetSelection : function()
	{
		return (window.getSelection || (document.getSelection && document.getSelection()) || document.selection);
	},

	G2GetNextChild : function ( n )
	{
		if (isIE)
			return n.nextSibling;

		do
		{
			n	 = n.nextSibling;
		} 
		while (n!=null && n.nodeType == Node.TEXT_NODE);

		return n;
	},
	G2CreateElementFromHtml : function(html, doc)
	{
	  if(doc==null)
	    doc = document;
		var tagName = html.substr(html.search("<")+1, 2).toUpperCase();
		var div = doc.createElement('div');
		if(tagName=="TR")		
		{
			div.innerHTML = "<table><tbody>"+html+"</tbody></table>";
			var newRow = div.firstChild.firstChild.firstChild;
			newRow.parentElement.removeChild(newRow);
			return newRow;
		}
		else if(tagName=="TD")
		{
			var div = doc.createElement("div");
			div.innerHTML = "<table><tr>"+outerHTML+"</tr></table>";
			var cell = div.firstChild.firstChild.firstChild.firstChild;
			return cell;
		}
		else
		{
			div.innerHTML = html;
			return div.children[0]; //FF
		}
	},

	//Replaces a node's outerHTML (Already Implemented in IE, not in FF)
	//TODO: Check if this is needed or if the outerHTML setter works in FF 2.0
	G2ReplaceOuterHTML : function(obj,outerHTML)
	{
		if(isIE)
		{
			//added by dan-el - the simple method doesn't work for TR's.
			if(obj.tagName=="TR")
			{
				var tempDiv = document.createElement('div');
				tempDiv.innerHTML = "<table>"+outerHTML+"</table>";
				var newRow = tempDiv.firstChild.firstChild.firstChild;
				var row = obj;
				var table = obj.parentNode;
				table.replaceChild(newRow, row);
			}
			else if(obj.tagName=="TD")
			{
				var div = document.createElement("div");
				div.innerHTML = "<table><tr>"+outerHTML+"</tr></table>";
				var cell = div.firstChild.firstChild.firstChild.firstChild;
				obj.replaceNode(cell);
			}
			else
			{
				obj.outerHTML = outerHTML;
//				var div = document.createElement("div");
//				div.innerHTML = outerHTML;
//				if (div.firstChild)
//					obj.replaceNode(div.firstChild);
			}
		}
		else //this method caused problems with image caching in Explorer
		{
			obj.outerHTML = outerHTML; //Changed by Alon
			/*var tempDiv = document.createElement('div');
			tempDiv.innerHTML = outerHTML;
			obj.replaceNode(tempDiv.firstChild);*/
		}
	},

	//Firefox stores attributes in a different manner than IE
	G2GetAttribute : function (obj,attributeName)
	{	
		if (isIE)
			return obj[attributeName];
		else if (obj!=null && obj.hasAttribute!=null && obj.hasAttribute(attributeName.toLowerCase()))
			return obj.attributes[attributeName.toLowerCase()].nodeValue;
		else 
		{
			var t = obj.attributes[attributeName.toLowerCase()];
			if (t!=null)
				return t.nodeValue;				
			else
			t = obj[attributeName.toLowerCase()] || obj[attributeName];
			return t;
		}
	},

	G2SetAttribute : function (obj,attributeName,val)
	{
		if (isIE)
			obj[attributeName] = val;
		else
			obj.attributes[attributeName.toLowerCase()].nodeValue = val;
	},

	G2CreateElement : function(t)
	{
		if (isIE || t.charAt(0)!="<")
			return document.createElement(t); //  e.g. document.createElement("DIV")
			
		var tempDiv = document.createElement("DIV");
		tempDiv.innerHTML = t;
		return tempDiv.childNodes[0];
	},

	// This method return row.rowIndex
	GetRowIndex : function(row)
	{
		var body = row.parentElement;
		if (!body)
			return -1;
		var currRow = body.firstChild;
		var index = 0;
		while(currRow)
		{
			if (currRow == row)
				return index;
			index++;
			currRow = currRow.nextSibling;
		}
		return -1;
	},

	// This methods returns a row by its index by going throw the table rowafter row 
	// instead of using the table indexing
	GetRowByIndex : function(table, rowIndex)
	{	
		var row = table.firstChild;
		if (! row)
			return null;
			
		while (row && row.tagName != "TR")
			row = row.firstChild;
			
		if (! row)
			return null;
		
		if (rowIndex == 0)
			return row;
		
		for(var i = 0; i < rowIndex; i++)
		{
			row = row.nextSibling;
			if (!row)
				return null;
		}
		return row;
	},

	// Gets a table and return the number of rows
	GetRowsLength : function(table)
	{
		var row = table.firstChild;
		if (! row)
			return 0;
			
		while (row && row.tagName != "TR")
			row = row.firstChild;
		if (! row)
			return 0;
			
		var count = 0;
		while(row)
		{
			row = row.nextSibling;
			count++;
		}
		return count;
	},
	
	GetCellByIndex : function(row, cellIndex)
	{	
		var cell = row.firstChild;
		if (! cell)
			return null;
		
		if (cellIndex == 0)
			return cell;
		
		for(var i = 0; i < cellIndex; i++)
		{
			cell = cell.nextSibling;
			if (!cell)
				return null;
		}
		return cell;
	},
	
	// Gets a row and return the number of cells
	GetCellsLength : function(row)
	{
		var cell = row.firstChild;
		if (! cell)
			return 0;
			
		var count = 0;
		while(cell)
		{
			cell = cell.nextSibling;
			count++;
		}
		return count;
	},
    G2DisableSelects : function()
    {
         if (!IE6)
            return;
            
        selects = document.getElementsByTagName('SELECT');
        for (var i = 0; i < selects.length; i++)
        {
            sel = selects[i];
            if (sel.isDisabled == false)
            {
              sel.disabled = true;
              sel.wasGenerallyDisabled  = true; 
            }
         }
          
    },
    G2EnableSelects : function()
    {
       if (!IE6)
            return;
            
        selects = document.getElementsByTagName('SELECT');
        for (var i = 0; i < selects.length; i++)
        {
            sel = selects[i];
            if (sel.isDisabled && sel.wasGenerallyDisabled)
            {
                sel.disabled = false;
                sel.wasGenerallyDisabled = false;
             }
         }
    },
    G2InsertRowToTable : function(table, index)
    {
        if (index == null)
            index = table.rows.length;
        return table.insertRow(index);
    },
    
    G2InsertCellToRow : function (row, index)
    {
        if (index == null)
            index = row.cells.length;
        return row.insertCell(index);
    },
    
    G2RemoveNode : function (elem)
    {
        elem.parentNode.removeChild(elem);
    },
    
    G2Focus : function (elem)
    {
			try{
				elem.focus();
			}
			catch(e){
				//do nothing- error when pressing the widget of combo is unclear but cause no problem. 
				// the menu is displayed as usual.
			}
    },
    
    G2HTMLEncode : function (text)
    {
	    if ( !text )
		    return '' ;

	    text = text.replace( /&/g, '&amp;' ) ;
	    text = text.replace( /</g, '&lt;' ) ;
	    text = text.replace( />/g, '&gt;' ) ;
	    return text ;
    }
  
}

G2_DeclareUtilInstance(G2DOM);

//the following script adds document.getElementById if it is not present
if(document.all && !document.getElementById) 
{
	document.getElementById = function(id) 
	{
		return document.all[id];
	}
}


/**********************************************************************
 *           G2 Event handling                                        *
 *     portions taken from the Prototype library version 1.4.0        *
 **********************************************************************/

G2_DeclareFunctions(
{
	G2_AttachEventWithCaller : function(element, eventName, handler, caller)
	{
		element.attachEvent(eventName, G2.GetDelegate(caller, handler));
	},
	G2_DetachEventWithCaller : function(element, eventName, handler, caller)
	{
		element.detachEvent(eventName, G2.GetDelegate(caller, handler));
	},


	G2_FireEvent : function(target, eventName, eventArgs)
	{
		if(isIE)
		{
			return target.fireEvent(eventName, eventArgs);
		}
		else
		{
			var handler = target[eventName];
			if (handler!=null)
			{
				if (typeof(handler)=="function")
					handler();
				else eval(handler);
			}
			else
				throw new Error("not supported");
		}
	},

	// This method wraps an event handler, to achieve two goals:
	// 1. When the method executes, its 'this' context will be the actual object (who 'owns' the function)
	// 2. Cross-platform event handling:
	//    In IE, the current event that is being process is stored in window.event
	//    In Mozilla (and FireFox), the event object is passed as an argument to the event handler
	G2_PrepareEvent : function(newContext,method)
	{
		if (method.preparedEvent && method.preparedEvent!=null)
		{
			return method.preparedEvent;
		}
		method.preparedEvent = function(event)
		{
			if (event==null)
				event = window.event;
			return method.call(newContext,event);
		}
		
		return method.preparedEvent;
	},

	// Attaches an event handler to the target, as a response to that event
	// The handler should be a function that receives a single argument, named 'event'.
	// It should NOT use window.event, only the supplied event.
	G2_AttachEvent : function(target, eventName, handler, capture)
	{
		if (eventName.substr(0,2)=="on")
			eventName = eventName.substring(2);
		
		//Note: Capture is only supported in FireFox
		if (!capture)
			capture = false;
		
		if(isIE)
		{
			target.attachEvent('on'+eventName, G2_PrepareEvent(target,handler));
		}
		else if (target.addEventListener!=null)
		{		
				target.addEventListener(eventName,G2_PrepareEvent(target,handler),capture);
		} 
		else
			throw new Error("not supported");
	},


	G2_DetachEvent : function(target,eventName, handler, capture)
	{
		if (eventName.substr(0,2)=="on")
			eventName = eventName.substring(2);
		
		//Note: Capture is only supported in FireFox
		if (!capture)
			capture = false;
		
		if (isIE) 
		{
				target.detachEvent('on' + eventName, G2_PrepareEvent(target,handler));
		}
		else if (target.removeEventListener!=null)
		{
				target.removeEventListener(eventName, G2_PrepareEvent(target,handler), capture);
		} 
		else 
			throw new Error("not supported");
	},
	G2StopEvent : function(event)
	{
		G2Event.stop(event);
	},
		
	// Get child element in a given element by its id
	G2_FindChildControlById : function(element, id)
	{
		if(String.EndsWith(element.id, id))
			return element;
		var child = element.firstChild;
		while(child!=null)
		{
			var found = G2_FindChildControlById(child, id);
			if(found!=null)
				return found;
			child=child.nextSibling;
		}
		return null;
	},
	
	// Get the first child element in a given element with a specified tagName
	G2_FindChildControlByTagName : function(element, tagName)
	{
		if(! element)
			return null;
		if (element.tagName)
			if(element.tagName.toLowerCase() == tagName.toLowerCase())
				return element;
		var child = element.firstChild;
		while(child!=null)
		{
			var found = G2_FindChildControlByTagName(child, tagName);
			if(found!=null)
				return found;
			child=child.nextSibling;
		}
		return null;
	},

	///
	///Recursivly searches an element from the current control and up that has a certain tag name
	///
	G2_GetParentElementByTagName : function(control, tagName)
	{	
		tagName = tagName.toUpperCase();
		return _G2_GetParentElementByTagName(control, tagName);
	},
	_G2_GetParentElementByTagName : function(control, tagName)
	{	
		if(control==null)
			return null;
		if(control.tagName==tagName) //TODO: Compare case insensitive
			return control;
		control = control.parentElement;
		return _G2_GetParentElementByTagName(control, tagName);
	},

	//returns an array of all the nodes under node with progid=parentProgId that have the 
	//specified attribute name and value 
	findControlsByAttribute : function(node, parentProgId, attributeName, attributeValue)
	{
		
		var pred = function(el)
		{
			if(G2DOM.G2GetAttribute(el, "progid")==parentProgId)
					return el;
		}
		var testAttribute = function(node)
		{
			if(G2DOM.G2GetAttribute(node, attributeName)==attributeValue)
					return node;
		}
		var curNode = searchUp(node, pred);
		if(curNode == null)
			return null;

		var childrenArray = new Array();
		
		collectChildrenByAttribute(curNode, testAttribute, childrenArray);
		return childrenArray; 
	},
	
	collectChildrenByAttribute : function (obj, predicate, childrenArray)
	{
		if (obj==null)
			obj = this;
			
		if (obj.childNodes.length==0)
			return childrenArray;
			
		var c = obj.firstChild;
		
		while(c!=null)
		{
			collectChildrenByAttribute(c,predicate, childrenArray);
			if (c.nodeType == 1 && predicate(c))
				childrenArray.push(c);
			c = c.nextSibling;
		}
	},
	
		
	//Finds an element by progid
	//Usage: provide a start node and a path seperated by dots, i.e. findControl(el, 'div1.panel2.button3');
	//       in this example, a node with progid div will be searched UPWARDS from el
	//       Then a div1 child element with progid 'panel2'will be searched DOWN.
	//       Then a panel2 child element with progid 'button3'will be searched DOWN. 
	//Returns: the first element with the last progid in the path that matches
	findControl : function(node, progIdpath)
	{
		var tokens = progIdpath.split('.');
		if(tokens.length==0)
			return null;
		var progid=tokens[0];
		tokens.splice(0,1);//Remove first token
	  
		var pred = function(el)
		{
			if(G2DOM.G2GetAttribute(el, "progid")==progid)
					return el;
		}
		var curNode = searchUp(node, pred);
		if(curNode == null)
			return null;
		if(tokens.length==0)
			return curNode;
		var newPath = tokens.join('.');
		return _findChildControl(curNode, newPath); 
	},

	_findChildControl : function(node, progIdpath)
	{
		var curNode = node;
		var tokens = progIdpath.split('.');
		if(tokens.length==0)
			return curNode;
		
		var tokensLength = tokens.length;
		for(var i=0; i<tokensLength; i++)
		{
			var progid=tokens[i];
			var pred = function(el)
			{
				if(G2DOM.G2GetAttribute(el, "progid")==progid)
					return el;
			}
			curNode = searchDown(curNode, pred);  
			if(curNode==null)
				return null;
		}
		return curNode;
	},

	searchUp : function(node, predicate)
	{
		while(node!=null)
		{
			if(predicate(node))
				return node;
			node = node.parentElement;
		}  
		return null;
	},
	searchDown : function(node, predicate)
	{
		return _searchDown(node, predicate);
	},
	_searchDown : function(node, predicate)
	{
		if(predicate(node))
				return node;
		node = node.firstChild; 
		if (node!=null && node.nodeType != 1)
			node = G2DOM.G2GetNextChild(node);
		while(node!=null)
		{
			var n = _searchDown(node, predicate);
			if(n!=null)
				return n;
			node = G2DOM.G2GetNextChild(node);
		}  
		return null;
	}
	
});

var G2Event = {
  KEY_BACKSPACE: 8,
  KEY_TAB:       9,  
  KEY_RETURN:   13,
  KEY_ESC:      27,
  KEY_LEFT:     37,
  KEY_UP:       38,
  KEY_RIGHT:    39,
  KEY_DOWN:     40,
  KEY_DELETE:   46,
  KEY_SPECIAL_COPY: 17,

	//Returns the target(FF)/source(IE) element - which is the event's context
	//Usage:  Event.element( e )
  element: function(event) {
		if (event==null)
			event = window.event;
    return event.target || event.srcElement;
  },

	//Returns true if the click was a left mouse click
	//Usage:  Event.isLeftClick( e )
  isLeftClick: function(event) {
		if (event==null)
			event = window.event;
    return (((event.which) && (event.which == 1)) ||
            ((event.button) && (event.button == 1)));
  },
	
	//Returns the cursor X coordinate (relative to the page)
	//Usage:  Event.pointerX( e )
  pointerX: function(event) {
		if (event==null)
			event = window.event;
    return event.pageX || (event.clientX +
      (document.documentElement.scrollLeft || document.body.scrollLeft));
  },

	//Returns the cursor Y coordinate (relative to the page)
	//Usage:  Event.pointerY( e )
  pointerY: function(event) {
		if (event==null)
			event = window.event;
    return event.pageY || (event.clientY +
      (document.documentElement.scrollTop || document.body.scrollTop));
  },

	//Stops the event propagation
	//Usage:  Event.stop( e )
  stop: function(event) {
		if (event==null)
			event = window.event;
    if (event.preventDefault) {
      event.preventDefault();
      event.stopPropagation();
    } else {
      event.returnValue = false;
      event.cancelBubble = true;
    }
  },

  // Finds the first node with the given tagName, starting from the
  // node the event was triggered on; traverses the DOM upwards
  findElement: function(event, tagName) {
		if (event==null)
			event = window.event;
    var element = Event.element(event);
    while (element.parentNode && (!element.tagName ||
        (element.tagName.toUpperCase() != tagName.toUpperCase())))
      element = element.parentNode;
    return element;
  }/*,

  observers: false,

  _observeAndCache: function(element, name, observer, useCapture) {
    if (!this.observers) this.observers = [];
    if (element.addEventListener) {
      this.observers.push([element, name, observer, useCapture]);
      element.addEventListener(name, observer, useCapture);
    } else if (element.attachEvent) {
      this.observers.push([element, name, observer, useCapture]);
      element.attachEvent('on' + name, observer);
    }
  },

  unloadCache: function() {
    if (!Event.observers) return;
    for (var i = 0; i < Event.observers.length; i++) {
      Event.stopObserving.apply(this, Event.observers[i]);
      Event.observers[i][0] = null;
    }
    Event.observers = false;
  },

  observe: function(element, name, observer, useCapture) {
    var element = $(element);
    useCapture = useCapture || false;

    if (name == 'keypress' &&
        (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
        || element.attachEvent))
      name = 'keydown';

    this._observeAndCache(element, name, observer, useCapture);
  },

  stopObserving: function(element, name, observer, useCapture) {
    var element = $(element);
    useCapture = useCapture || false;

    if (name == 'keypress' &&
        (navigator.appVersion.match(/Konqueror|Safari|KHTML/)
        || element.detachEvent))
      name = 'keydown';

    if (element.removeEventListener) {
      element.removeEventListener(name, observer, useCapture);
    } else if (element.detachEvent) {
      element.detachEvent('on' + name, observer);
    }
  }*/
};




//Add Debug.writeln support for Firefox
//In order to enable logging:
// 1. open firefox
// 2. open about:config
// 3. right-click and New->String
// 4. Name the new entry "browser.dom.window.dump.enabled"
// 5. Set its value to true
// 6. Open firefox with the -console parameter (it might complain, but it works).
// For additional information, contact Alon.
// 
// Note: Console is disabled by default. On production systems no change needs to be done.
if (typeof(Debug)=="undefined")
	Debug = {writeln:function(txt){window.dump(txt+"\n");}};
	


/**********************************************************************
 *           G2 Firefox HTMLElement extension                         *
 **********************************************************************/

if(!document.documentElement.outerHTML)
{

    HTMLElement.prototype.getAttributes = function(){
       var attStr = "";
       if(this && this.attributes.length > 0){
          for(a = 0; a < this.attributes.length; a ++){
             attStr += " " + this.attributes.item(a).nodeName + "=\"";
             attStr += this.attributes.item(a).nodeValue + "\"";
          }
       }
       return attStr;
    }

    HTMLElement.prototype.getInsideNodes = function(){
       if(this){
          var cNodesStr = "", i = 0;
          var iEmpty = /^(img|embed|input|br|hr|bgsound)$/i;
          var cNodes = this.childNodes;
          for(i = 0; i < cNodes.length; i ++){
             switch(cNodes.item(i).nodeType){
                 case 1 :
                    cNodesStr += "<" + cNodes.item(i).nodeName.toLowerCase();
                    if(cNodes.item(i).attributes.length > 0){
                       cNodesStr += cNodes.item(i).getAttributes();
                    }
                    cNodesStr += (cNodes.item(i).nodeName.match(iEmpty))? "" : ">";
                    if(cNodes.item(i).childNodes.length > 0){
                       cNodesStr += cNodes.item(i).getInsideNodes();
                    }
                    if(cNodes.item(i).nodeName.match(iEmpty)){
                       cNodesStr += " />";
                    } else {
                       cNodesStr += "</" + cNodes.item(i).nodeName.toLowerCase() + ">";
                    }
                    break;
                 case 3 :
                    cNodesStr += cNodes.item(i).nodeValue;
                    break;
                 case 8 :
                    cNodesStr += "<!--" + cNodes.item(i).nodeValue + "-->";
                    break;
             }
          }
          return cNodesStr;
       }
    }

    G2MozGetOuterHTML = function(){
       var strOuter = "";
       var iEmpty = /^(img|embed|input|br|hr|bgsound)$/i;
       switch(this.nodeType){
          case 1 :
             strOuter += "<" + this.nodeName.toLowerCase();
             strOuter += this.getAttributes();
             if(this.nodeName.match(iEmpty)){
                 strOuter += " />";
             } else {
                 strOuter += ">" + this.getInsideNodes();
                 strOuter += "</" + this.nodeName.toLowerCase() + ">";
             }
             break;
          case 3 :
             strOuter += this.nodeValue;
             break;
          case 8 :
             cNodesStr += "<!--" + this.nodeValue + "-->";
             break;
       }
       return strOuter;
    }

    G2MozSetOuterHTML = function(str){
       var iRange = document.createRange();
       iRange.setStartBefore(this);
       var strFragment = iRange.createContextualFragment(str);
       var sRangeNode = iRange.startContainer;
       iRange.insertNode(strFragment);
       sRangeNode.removeChild(this);
    }
    
    //Returns the object's document
		G2GetDocument = function (obj)
		{
			if (obj == null)
				obj = this;
			return obj.ownerDocument;
		}

		// Artificially get the 'Children' array for the given node.
		// Added as a getter to the Node class in FF
		G2GetChildren = function (obj)
		{
			if (obj==null)
				obj = this;
				
			var childrenArray = new Array();
			if (obj.childNodes.length==0)
				return childrenArray;
				
			var c = obj.firstChild;
			while(c!=null)
			{
				if (c.nodeType != Node.TEXT_NODE)
					childrenArray.push(c);
				c = c.nextSibling;
			}
			
			childrenArray.namedItem = function(name)
			{
				for (var i=0;i<this.length;i++)
				{
					var node = this[i];
					if (node.id == name)
						return node;
				}
				return null;
			}
			
			return childrenArray;
		}
		
		G2GetTagName = function(obj)
		{
			if (obj==null)
				obj = this;
			return obj.nodeName;
		}

		function G2GetParent(obj)
		{	
			if (obj==null)
				obj = this;
			return obj.parentNode;
		}
		
		function G2GetCurrentStyle(obj)
		{
			if (obj==null)
				obj = this;
			return window.getComputedStyle(obj,null);
		}
		
		function G2GetInnerText(obj)
		{
			if (obj==null)
					obj = this;
			return obj.textContent;
		}
		
		function G2SetInnerText(txt)
		{
			this.innerHTML = txt;
		}
		
		function G2ContainsChild(c)
		{
			var chlrn = this.children;
			for (var i=0,j=chlrn.length;i<j;i++)
				if (chlrn[i]==c)
					return true;
			return false;
		}
		
		function G2GetContentDocument()
		{
			return this.contentDocument;
		}
		
		function G2MozGetParentWindow()
		{
			return this.defaultView;
		}
		
		HTMLElement.prototype.contains = G2ContainsChild;
		
		//Implement insertAdjacentElement, insertAdjacentText and insertAdjacentHTML
		HTMLElement.prototype.insertAdjacentElement = function(where,parsedNode)
		{
			switch (where)
			{
				case "beforeBegin":
					this.parentNode.insertBefore(parsedNode,this)
					break;
				case "afterBegin":
					this.insertBefore(parsedNode,this.firstChild);
					break;
				case "beforeEnd":
					this.appendChild(parsedNode);
					break;
				case "afterEnd":
					if (this.nextSibling)
						this.parentNode.insertBefore(parsedNode,this.nextSibling);
					else 
						this.parentNode.appendChild(parsedNode);
					break;
			}
		}
		
		HTMLElement.prototype.insertAdjacentHTML = function(where,htmlStr)
		{
			var r = this.ownerDocument.createRange();
			r.setStartBefore(this);
			var parsedHTML = r.createContextualFragment(htmlStr);
			this.insertAdjacentElement(where,parsedHTML)
		}
		
		HTMLElement.prototype.insertAdjacentText = function(where,txtStr)
		{
			var parsedText = document.createTextNode(txtStr)
			this.insertAdjacentElement(where,parsedText)
		}
		var lastGivenID = 1000;			
		function G2GetElementUniqueID ()
		{
			if (this._uniqueID) //already defined
				return this._uniqueID;
			//Generate using counter
			this._uniqueID = lastGivenID;
			lastGivenID++;
			return this._uniqueID;
		}	
		
		function G2GetEventSourceElement() 
		{
			var node = this.target;
			while (node.nodeType != 1) node = node.parentNode;
			return node;
		}
		
		function G2GetProgId()
		{
			if (this.hasAttribute("progid"))
				return this.attributes["progid"].nodeValue;
		}
		
		HTMLElement.prototype.attachEvent = function(eventName, handler, capture) //Simulate AttachEvent on Mozilla
	  {
	    if (eventName.substr(0,2)=="on")
		  	eventName = eventName.substring(2);		  
		  if (!capture)
		    capture = false;
	    this.addEventListener(eventName,handler,capture);
	  }
	  
	  HTMLElement.prototype.detachEvent = function(eventName, handler, capture) //Simulate DetachEvent on Mozilla
	  {
	    if (eventName.substr(0,2)=="on")
		  	eventName = eventName.substring(2);		  
		  if (!capture)
		    capture = false;
	    this.removeEventListener(eventName,handler,capture);
	  }
		
		function defineStyleProperties(names)
		{
			for(var i=0;i<names.length;i++)
			{
				var shortName = names[i];
				var pixelName = "pixel"+shortName.substring(0,1).toUpperCase()+shortName.substring(1);
				defineStyleProperty(shortName,pixelName);
			}
		}

		function defineStyleProperty(shortName,pixelName)
		{
			CSSStyleDeclaration.prototype.__defineGetter__(pixelName,function(){return parseInt(this[shortName])});
			CSSStyleDeclaration.prototype.__defineSetter__(pixelName,function(v){this[shortName]=v+"px";});
		}
		
		
		defineStyleProperties(["width","height","left","top"]);
		
		/*function Selection(doc)
		{		
		  this._doc = doc;
		}
		Selection.prototype.createRange = function(element)
		{
		  debugger;
		  var sel = window.getSelection();		  
		  var range = null;
		  if (sel.rangeCount==0)
		  {
		    if (element!=null)
		    {
 		      range = document.createRange();
 		      range.selectNodeContents(element);
 		      //range.setStart(element, 0);
 		      //var len = (element.nodeType==1 && element.tagName=="INPUT") ? element.value.length : element.innerText.length;
          //range.setEnd(element,0);
          //range.expand
		      sel.addRange(range);
		    }
		  }
		  else range = sel.getRangeAt(0);
		  var rng = new G2MozRange(range);
		  return rng;
		}
    function G2GetDocumentSelection()
		{
		  if (this._emulatedSelectionObject==null)
		    this._emulatedSelectionObject = new Selection(this);
		  return this._emulatedSelectionObject;
		}
		
		function G2MozRange(rng)
		{
		  this._range = rng;
		}
		function G2MozRange_GetText()
		{
		  return this._range.toString();
		}
		function G2MozRange_SetText(value)
		{
		  //this.commonAncestorContainer.innerText = value;
		  debugger;
		  var lastElement = this._range.endContainer;
		  if (lastElement==null)
		    debugger;
		  if (lastElement.nodeType==1)
		  {
		    if (lastElement.tagName=="INPUT")
		    {
		      lastElement.value += value;
		    }
		    else
		      lastElement.innerText += value;
		  }
		  else if (lastElement.nodeType==3)
		  {
		    lastElement.nodeValue += value;
		  }
		    
		}
		G2MozRange.prototype.__defineGetter__("text",G2MozRange_GetText);
		G2MozRange.prototype.__defineSetter__("text",G2MozRange_SetText);
		*/
		//Fix for firefox BACK
		window.addEventListener("pageshow",function(e){if(e.persisted) {window.location.href = window.location.href;}},false);
    
    HTMLDocument.prototype.__defineGetter__("parentWindow",G2MozGetParentWindow);
    //HTMLDocument.prototype.__defineGetter__("selection",G2GetDocumentSelection);
    HTMLElement.prototype.__defineGetter__("progid",G2GetProgId);
    HTMLElement.prototype.__defineGetter__("outerHTML",G2MozGetOuterHTML);
		HTMLElement.prototype.__defineSetter__("outerHTML",G2MozSetOuterHTML);
		HTMLElement.prototype.__defineGetter__("innerText",G2GetInnerText);
		HTMLElement.prototype.__defineSetter__("innerText",G2SetInnerText);
		HTMLElement.prototype.__defineGetter__("children",G2GetChildren);
		HTMLElement.prototype.__defineGetter__("document",G2GetDocument);
		HTMLElement.prototype.__defineGetter__("tagName",G2GetTagName);
		HTMLElement.prototype.__defineGetter__("parentElement",G2GetParent);
		HTMLElement.prototype.__defineGetter__("currentStyle",G2GetCurrentStyle);
		HTMLElement.prototype.__defineGetter__("uniqueID",G2GetElementUniqueID);
		HTMLIFrameElement.prototype.__defineGetter__("Document",G2GetContentDocument);
		Event.prototype.__defineGetter__("srcElement", G2GetEventSourceElement);
		
		
}
// returns true if the string 's' ends with the string 'endsWith'
String.EndsWith = function(s, endsWith)
{
	if(s==null)
		return endsWith==null;
	return s.substr(s.length-endsWith.length, endsWith.length)==endsWith;
}


//this function gets a control
//and disables/enables it and all its children recursively
SetControlDisability = function(control, disable)
{
	if(control == null)
		return;
	if (control.supportdisabledcss == "true")
	{
		control.disabled = disable;
		//we want the main css class to be standing alone
		//so when disabling, replace css class by disabled css class
		//when enabling if there are other classes, just remove disabled
		if (disable || control.className == control.disabledcssclass)
			G2_ReplaceCssClass(control, control.cssclass, control.disabledcssclass, disable);
		else
			G2_RemoveCssClass(control, control.disabledcssclass);
	}
	//we don't want to replace the initial css class but to add the disable css class
	else if (control.supportdefauldisabledtcss == "true") 
	{
		control.disabled = disable;
		if (disable)
			G2_AddCssClass(control, control.disabledcssclass);
		else
			G2_RemoveCssClass(control, control.disabledcssclass);
	}
	G2_VerifyControlInitialized(control);
	if(typeof(control.setEnabled)=="function")
		control.setEnabled(!disable);
	else
	{
		control.disabled = disable;
		SetControlChildrenDisability(control, disable);
	}
}

SetControlChildrenDisability = function(control, disable)
{
		if(control.children.length > 0)
		{
			var child = control.children[0];
			//lets be sure we are talking about html tag
			while(child != null)
			{
				if(child.nodeType == 1)
				{
					child.disabled = disable;
					SetControlDisability(child, disable);
				}
	
				child = child.nextSibling;
			}
		}
	}
