function GEOTabGridObject(container,options){
	var self = this;
	this.options = {
		//Level 1
		Elements : [], // Full list can be: ["selector","path","filter","grid", "buttons"]	
		onFilter:null,
		onRowClick:null,
		onAdd:null,
		onDelete:null,
		onEdit:null,
		onSelectorChange:null,
		blCheckboxes:false,
		//Level 2
		rootPId : 9998, // the root pId of the nodes
		filterEmptyText : "Type here to search for item",
		checkboxesLabel : "Select All/None",
		rootLabel : "Back to Top",
		iptDisabledClass : "geo_iptFilterDisabled",
		iptEnabledClass : "geo_iptFilterEnabled",
		iconGroup: "/gfx/groupIcon.gif",
		iconLevelUp : "/gfx/iconLevelUp.gif",
		iconDevice : "/gfx/iconDevice.gif",
		iconDriver : "/gfx/iconDriver.gif",
		trNormalClass: "geo_normalRow",
		trSelectedClass: "geo_selectedRow",
		elementID : {
			"grid" : "geo_groups_grid",
			"selector" : "geo_groups_selector",
			"filter" : "geo_filter",
			"path" : "geo_groupPath",
			"buttons" : "geo_buttonArea"
		},
		dialogWindowClass: "dialogWindow",
		dialogWindowIptClass: "geo_ipt",
		btnClass: "btn",
		addBtnLbl:"Add",
		delBtnLbl:"Remove",
		editBtnLbl:"Edit"
	}
	
	// debug (paddings)
	this._extHeightSubst = 40;
	//container of object
	this.container = null;
	// container of table
	this.table = null;
	// filter (input)
	this.filter = null;
	//path container
	this.path = null;
	// buttons Area
	this.buttons = null;
	// Selector area
	this.selector = null;
	//the tree: struct with all the possible nodes. {pId,name}
	this.pathTree = {};
	//current html tr row.
	this.currentRow = null;
	//data of the rows
	this.currentRowData = {};
	// the cutrrent pId of the nodes
	this.current_pId = this.options.rootPId;
	
	
	// Init options
	this.initOptions = function(options){
		for (var i in options){
			this.options[i] = options[i];	
		}
	}
	//init all the contaniers.
	this.init = function(container){
		this.current_pId = this.options.rootPId;	
		this.container = document.getElementById(container)||null;
		for (var i=0; i<this.options.Elements.length; i++){
			switch(this.options.Elements[i]){
				case "grid":
					if (this.options.blCheckboxes) this.initCheckboxes();
					this.initTable();
					break;
				case "filter":
					this.initFilter();
					break;
				case "buttons":
					this.initButtons();
					break;	
				case "selector":
					this.initSelector();
					break;
				case "path":
					this.initPath();
					break;	
			}
		}
		var filterString = self.getFilter();
		var selectorValue = self.getSelector();	
		self.options.onRowClick(this.current_pId,filterString,selectorValue,self.fillWithData);
		this.fixHeight();
	}
	// make the html text correct for display as normal text on the page
	this.htmlFormat = function(str){
		str = str||"";
		str = str.replace(/>/gi,"&gt;");
		str = str.replace(/</gi,"&lt;");
		return str;
	}
	
	this.getComponentsHeights = function(){
		return (this.path?this.path.scrollHeight:0)+(this.filter?this.filter.scrollHeight:0)+(this.buttons?this.buttons.scrollHeight:0)+(this.selector?this.selector.scrollHeight:0);
	}
	this.fixHeight = function(){
		this.container.style.height = Math.max(this.options.dataTableHeight,150)+"px";
		var h = Math.max(this.options.dataTableHeight,150) - this.getComponentsHeights()-32;
		this.table.parentNode.style.height=h+"px";
	}
	this._find = function(ar,v){
		for (var i=0; i<ar.length; i++)
			if (ar[i]==v) return true;
		return false;
	}
	
	/////////////////////////////////////////////////
	// Init Selector Line
	this.initSelector = function(){
		var div = this.container.appendChild(document.createElement("DIV"));
		div.id = this.options.elementID["selector"];
		div.appendChild(document.createElement("SELECT"));
		div.firstChild.options[0] = new Option("Device","device");
		div.firstChild.options[1] = new Option("Drvier","driver");
		div.firstChild.onchange = function(){
			var filterString = self.getFilter();
			var selectorValue = self.getSelector();	
			if (self.options.onSelectorChange) {
				self.options.onSelectorChange(self.current_pId,filterString,selectorValue,self.fillWithData);
			}
		}
		this.selector = div;
	}
	this.getSelector = function(){
		var str = (!this.selector)?"":this.selector.firstChild.value;	
		return str;
	}
	
	/////////////////////////////////////////////////
	// Init Checkboxes line
	this.initCheckboxes = function(){
		var div = this.container.appendChild(document.createElement("DIV"));
		div.className="geo_checkBoxesDiv";
		div.innerHTML = '<input type="checkbox"/> '+this.options.checkboxesLabel;
		div.firstChild.onclick = function(){
			self.checkAll(this.checked);	
		}
	}
	this.checkAll = function(mode){
		for (var i=0; i<this.table.rows.length; i++){
			var c = this.table.rows[i].cells[0];
			if (c.firstChild&&c.firstChild.type=='checkbox')
				c.firstChild.checked = mode;
		}
	}
	this._getAllchecked = function(){
		var res = [];
		for (var i=0; i<this.table.rows.length; i++){
			var c = this.table.rows[i].cells[0];
			if (c.firstChild&&c.firstChild.type=='checkbox'&&c.firstChild.checked)
				res[res.length] = c.firstChild.value;
		}
		return res;
	}
	this.getChecked = function(types){
		var res = {};
		for (var i=0; i<types.length; i++)
			res[types[i]] = [];	
		var values = this._getAllchecked();
		for (var i=0; i<values.length;i++){
			var type = values[i].split("_")[0];	
			if (!res[type]) res[type] = [];
			res[type][res[type].length] = values[i].split("_")[1];	
		}
		var result = [];
		for (var i=0; i<types.length; i++)
			result[i] = res[types[i]];
		return result;
	}
	
	/////////////////////////////////////////////////
	// Init filter
	this.initFilter = function(){
		var div = this.container.appendChild(document.createElement("DIV"));
		div.id=this.options.elementID["filter"];
		div.innerHTML = '<input type="text" class="'+this.options.iptDisabledClass+'" value="'+this.options.filterEmptyText+'"/>';
		this.filter = div.firstChild;
		this.filter.onfocus = function(){
			if (self.filter.className == self.options.iptDisabledClass){
				self.filter.className = self.options.iptEnabledClass;
				self.filter.value="";
			}
		}
		this.filter.onblur = function(){
			if (self.filter.value == ""){
				self.filter.className = self.options.iptDisabledClass;
				self.filter.value=self.options.filterEmptyText;
			}
		}
		this.filter.onkeypress = function(e){
			e = e||window.event;
			if (e.keyCode==13)
				self.applyFilter();
		}
	}
	this.getFilter = function(){
		var str = (!this.filter || this.filter.className==this.options.iptDisabledClass||this.filter.value=="")?"%":this.filter.value.replace(/\*/gi,"%");
		return str;
	}
	this.cleanFilter = function(){
		this.filter.className = this.options.iptDisabledClass;
		this.filter.value=this.options.filterEmptyText;
		window.focus();
	}
	//apply filter to the content in the container 
	this.applyFilter = function(){
		var filterString = this.getFilter();
		var selectorValue = this.getSelector();	
		if (this.options.onFilter) {
			this.options.onFilter(this.current_pId,filterString,selectorValue,this.fillWithData);
		}
	}
	/////////////////////////////////////////////////
	
	
	
	/////////////////////////////////////////////////
	//container
	this.initTable = function(){
		var div = this.container.appendChild(document.createElement("DIV"));
		div.id = this.options.elementID["grid"];
		tbl = document.createElement("TABLE");
		tbl.cellPadding="0";
		tbl.cellSpacing="0";
		tbl.appendChild(document.createElement("TBODY"));
		this.table = div.appendChild(tbl);	
	}
	this.getSelectedItem = function(){
		return (this.currentRow?{id:this.currentRowData[this.currentRow.id],name:this.currentRowData[this.currentRow.id].name,pId:this.current_pId}:{id:0,name:"",pId:this.current_pId});
	}
	this._addRow = function(id,lbl,type){
		// Path is alerady exists so we have to add this value manually
		self.addToPath(id,lbl);					   	
		self.addRow(id,lbl,type);
	}
	this.addRow = function(id,lbl,type){
		type = type||"group";
		var icon = "";
		switch(type){
			case "group": icon = this.options.iconGroup;break;
			case "levelUp": icon = this.options.iconLevelUp;break;
			case "device": icon = this.options.iconDevice;break;
			case "driver": icon = this.options.iconDriver;break;
		}
		this.currentRowData[id] = {id:id,name:lbl};
		var tr = this.table.insertRow(id==0?0:-1);
		tr.id = id;
		tr.onselectstart=function(){return false}
		tr.appendChild(document.createElement("TD"));
		tr.appendChild(document.createElement("TD"));
		tr.childNodes[0].style.width=this.options.blCheckboxes?'40px':"22px";
		tr.childNodes[0].innerHTML=(this.options.blCheckboxes?'<input value="'+type+"_"+id+'" type="checkbox" />':"")+'<img src="'+icon+'" align="top"/>';
		tr.childNodes[1].innerHTML=this.htmlFormat(lbl)+"&nbsp;";
		tr.title = lbl;
		tr.className = this.options.trNormalClass;
		tr.onclick = function(){
			if (self.currentRow) self.currentRow.className=self.options.trNormalClass;
			self.currentRow = this;
			self.currentRow.className = self.options.trSelectedClass;
		}
		if (this._find(["group","levelUp"],type))
			if (this.options.onRowClick) tr.ondblclick = function(){
				var filterString = self.getFilter();
				var selectorValue = self.getSelector();	
				var id = this.id;
				if (id==0) id=self.pathTree[self.current_pId].pId; 
				self.options.onRowClick(id,filterString,selectorValue,self.fillWithData);
			};		
	};
	
	this._setRowName = function(id,name){
		self.setRowName(id,name); 
	}
	this.setRowName = function(id,name){
		for (var i=this.table.rows.length-1; i>=0; i--)
			if (this.table.rows[i].id==id){
				this.table.rows[i].cells[1].innerHTML = this.htmlFormat(name);
				break;
			}
		this.pathTree[id].name = name;
	}
	this._deleteRow = function(id){
		self.deleteRow(id);	
	}
	this.deleteRow = function(id){
		for (var i=this.table.rows.length-1; i>=0; i--)
			if (this.table.rows[i].id==id){
				this.table.deleteRow(i);
				break;
			}
		for (var i in this.pathTree)
			if (this.pathTree[i].pId == id)
				this.pathTree[i].pId = this.pathTree[id].pId;
		this.pathTree[id] = null;
	}
	this.cleanTable = function(){
		for (var i=this.table.rows.length-1; i>=0; i--)
			this.table.deleteRow(i);
	}
	/////////////////////////////////////////////////
	
	
	/////////////////////////////////////////////////
	// Init Path
	this.initPath = function(){
		this.path = this.container.appendChild(document.createElement("DIV"));
		this.path.id =this.options.elementID["path"];
		this.pathTree[this.options.rootPId] = {pId:0,name:this.options.rootLabel};
	}
	// add the element to the path tree
	this.addToPath = function(id,name){
		if (this.current_pId==0) name=this.options.rootLabel;
		this.pathTree[id] = {pId:this.current_pId,name:name}
	}
	// draw the path according to the parentId.
	this.drawPath = function(id,avoidClean){
		if (!this.path) return;
		// first call	
		if (!avoidClean) {
			this.path.innerHTML="<nobr />";
			if (id!=this.options.rootPId){
				this.addRow(0,"..","levelUp");
			}
		}
	
		if (!this.pathTree[id] || (!avoidClean && id==this.options.rootPId)) return;
		var a = document.createElement("A");
		a.href="javascript:void(0);";
		a.onclick=function(){
			if (self.options.onRowClick) {
				var filterString = self.getFilter();
				var selectorValue = self.getSelector();	
				self.options.onRowClick(id,filterString,selectorValue,self.fillWithData);
			}
			return false;	
		}
		a.innerHTML=this.pathTree[id].name;
		if (this.path.firstChild.firstChild){
			this.path.firstChild.insertBefore(a,this.path.firstChild.firstChild)
		}else{
			this.path.firstChild.appendChild(a);
		}
		this.drawPath(this.pathTree[id].pId,true);	

		
		var m = this.path.offsetWidth - this.path.scrollWidth;
		if (m>0) m=0;
		this.path.firstChild.style.left = m+"px";
			
	}
	
	
	this.getOrganizationNode = function() {
        return this.options.rootPId;
    };
	this.fillWithData = function(id,data,selector){
		if (!selector) {
			self.current_pId = id;
			self.cleanTable();
		}
		for (i=0; i<data[0].children.length; i++){
			self.addToPath(data[0].children[i].id,data[0].children[i].name);	
			self.addRow(data[0].children[i].id,data[0].children[i].name,selector);
		}
		
		if (!selector){
			self.drawPath(id);	
		}
	}
	
	
	///////////////////////////////////////////////////////////////////
	// Init Buttons:
	this.initButtons = function(){
		this.buttons = this.container.appendChild(document.createElement("DIV"));
		this.buttons.id = this.options.elementID["buttons"];
		
		<!--- The Dialog for the grid --->
		var div = document.body.appendChild(document.createElement("DIV"));
		div.className = this.options.dialogWindowClass;
		div.innerHTML = '<input class="'+this.options.dialogWindowIptClass+'" />';
		this._dialogIpt = div.firstChild;
		this._dialog = $(div).dialog(GeotabConfig.datatable.dialog);
		
		
		var btn = document.createElement("INPUT");
		btn.className = this.options.btnClass;
		btn.value = this.options.addBtnLbl;
		btn.type="button";
		if (this.options.onAdd) btn.onclick = function(){
			self._dialogIpt.value="";	
			self._dialog.data('title.dialog', GeotabConfig.datatable.dialog_add.title); 
			var b = {};
			b[GeotabConfig.datatable.dialog_add.buttons[0]] = function(){
				var node = self.getSelectedItem();
				var selectorValue = self.getSelector();	
				self.options.onAdd(0,self.current_pId,self._dialogIpt.value,selectorValue,self._addRow);	
				self._dialog.dialog("close");		
			}
			b[GeotabConfig.datatable.dialog_add.buttons[1]] = function(){$(this).dialog("close");}
			self._dialog.data("buttons.dialog",b);
			self._dialog.dialog("open");	
		}
		this.buttons.appendChild(btn);
		
		var btn = document.createElement("INPUT");
		btn.className = this.options.btnClass;
		btn.value = this.options.editBtnLbl;
		btn.type="button";
		if (this.options.onEdit) btn.onclick = function(){
			var node = self.getSelectedItem();	
			if (!node.id){
				alert("No nodes were selected.");	
			} else {
				self._dialogIpt.value=node.name;	
				self._dialog.data('title.dialog', GeotabConfig.datatable.dialog_edit.title); 
				var b = {};
				b[GeotabConfig.datatable.dialog_edit.buttons[0]] = function(){
					var node = self.getSelectedItem();
					if (confirm("The node '"+ node.name +"' will be renamed. Click Ok to Continue."))
					self.options.onEdit(node.id,self.current_pId,self._dialogIpt.value,self.setRowName);	
				}
				b[GeotabConfig.datatable.dialog_add.buttons[1]] = function(){$(this).dialog("close");}
				self._dialog.data("buttons.dialog",b);
				self._dialog.dialog("open");	
			}
		}
		this.buttons.appendChild(btn);
		
		
		var btn = document.createElement("INPUT");
		btn.className = this.options.btnClass;
		btn.value = this.options.delBtnLbl;
		btn.type="button";
		if (this.options.onDelete) btn.onclick = function(){
			var node = self.getSelectedItem();
			if (!node.id){
				alert("No nodes were selected.");	
			} else {
				if (confirm("The node '"+ node.name +"' will be removed. Click Ok to Continue."))
					self.options.onDelete(node.id,self.current_pId,node.name,self._deleteRow);	
			}
		}
		this.buttons.appendChild(btn);
	}
	
	options = options||{};
	if (options.length){
		for (var i=0; i<options.length; i++)
			this.initOptions(options[i]);	
	} else {
		this.initOptions(options);		
	}
	this.init(container);	
}



