/* base class */
var SCRibbon = function(str_scribbon_div, bit_vertical, int_max_num_rows, int_flyout_type, str_item_class) {

	this.int_line_num		= 1;					//counter for the line number we are on
	this.int_item_num		= 0;					//counter for how many items are in the menu
	
	this.str_scribbon_div	= str_scribbon_div;		//the id of the div that will become our scribbon
	this.bit_vertical		= bit_vertical;			//whether this is a vertical or horizontal menu
	this.int_max_num_rows	= int_max_num_rows;		//maximum number of rows allowed in the menu, only applies to horizontal menus
	this.int_flyout_type	= int_flyout_type;	//if true, the flyouts will not scroll with the page
	this.str_item_class		= str_item_class;		//extra css class for the outer divs that container the items

	this.bit_loaded	= 0;						//whether the scribbon contains any data

	/* draws the scribbon with the given options */
	this.drawSCRibbon = function(obj_scribbon_data) {/* {{{ */
		/* 
		 *	params
		 *
		 *	obj_scribbon_data	this is a javascript object containing the options we are going to show. 
		 *						see obj_itemedit_menu_page in itemedit.menu.data.js
		 */

		this.preDraw();

		var obj_scribbon_div = $(this.str_scribbon_div);
		var int_num_items = 0;	//counter for how many items there are total
		var int_items_displayed = 0; //number of items from the definition that have been displayed

		//find out how many items there are
		for (y in obj_scribbon_data.links) {
			var arr_item = obj_scribbon_data.links[y];
			if (arr_item != null) {
				if (arr_item['type'] == "link") {
					int_num_items++;
				}
			}
		}

		
		for (x in obj_scribbon_data.links) {
			
			var arr_item = obj_scribbon_data.links[x];

			if (arr_item != null && arr_item['type'] != "hiddenlink" && arr_item['element'] != null) {

				//skip this item if it is a line break and we are on the last row allowed (only applies to horizonal menus)
				if (arr_item['element'] == 'br' && this.int_line_num == this.int_max_num_rows && !this.bit_vertical) {
					continue;
				}
					
				var obj_item_div = this.buildSCRibbonItem(arr_item, x + '_div');
				obj_scribbon_div.appendChild(obj_item_div);
				int_items_displayed++;

				if (arr_item['flyout']) {
					this.attachFlyout(obj_item_div, arr_item.flyout.scribbon, this.int_flyout_type, null, arr_item.flyout.bit_vertical, arr_item.flyout.classname, arr_item.flyout.item_class);
				}
			
				if ((this.bit_vertical == 1) && (int_items_displayed != int_num_items)) {
					var arr_item = {  
						type        : 'link',
					    element     : 'br',
						attributes  : {  
					        name    : 'hr_spacer'
						}    
					}
					
					var obj_item_div = this.buildSCRibbonItem(arr_item, x + '_div');
					obj_scribbon_div.appendChild(obj_item_div);

				}
				

			}//end if

		}//end for
		
		this.bit_loaded = 1;
		this.postDraw();
	
	}/* }}} */

	/* unloads and hides the scribbon */
	this.removeSCRibbon = function() { /* {{{ */
		$(this.str_scribbon_div).innerHTML = "";
		$(this.str_scribbon_div).style.display = "none";
		$J(".skin-scribbon-flyout").css("display", "none");
		this.int_line_num = 1;
		this.int_item_num = 0;
		this.bit_loaded = 0;
		this.postRemove();
	}/* }}} */
	
	/* clears existing scribbon display and replaces it with new data */
	this.replaceSCRibbon = function(obj_scribbon_data) {/* {{{ */
		this.removeSCRibbon();
		this.drawSCRibbon(obj_scribbon_data);
	}/* }}} */

	/* adds an item to the scribbon */
	this.buildSCRibbonItem = function(arr_item, str_div_name) {/* {{{ */

		//this stuff is the same for all types of scribbon items
		var obj_item_div = document.createElement('div');
		obj_item_div.setAttribute("id", str_div_name);

		if (arr_item['element'] == 'br') {
			obj_item_div.className = "skin-scribbon-item-break";
			this.int_line_num++;
		} else if (this.bit_vertical == 1) {
			obj_item_div.className = "skin-scribbon-item-vert ";
			if (typeof(this.str_item_class) != "undefined") {
				$J(obj_item_div).addClass(this.str_item_class);
			}
		} else {
			obj_item_div.className = "skin-scribbon-item ";
			if (typeof(this.str_item_class) != "undefined") {
				$J(obj_item_div).addClass(this.str_item_class);
			}
		}
	
		var obj_item = document.createElement(arr_item['element']);

		//set the item's id and classname. if they are defined in arr_item.attributes, it will override this
		obj_item.id			= "scribbon_item" + this.int_item_num;
		obj_item.className	= "skin-scribbon-item";

		//set this item's attributes
		for (y in arr_item.attributes) {
		
			//you have to set event attributes differently than others because of how IE7 handles them
			if (y.substr(0,2) == 'on') {
				if (typeof(arr_item.attributes[y]) == "string") {
					eval('obj_item.' + y.toLowerCase() + ' = function(e){ ' + arr_item.attributes[y] + '}');
				} else {
					eval('obj_item.' + y.toLowerCase() + ' = ' + arr_item.attributes[y]);
				}
			} else if (y == 'classname') {
				obj_item.className = arr_item.attributes[y];
			} else if (y == 'innerHTML') {
				obj_item.innerHTML = arr_item.attributes[y];
			} else {
				obj_item.setAttribute(y, arr_item.attributes[y]);
			}//end if

		}//end for each attribute
		
		//create the height forcer element (transparent image)
		var obj_height_forcer = document.createElement('img');	
		obj_height_forcer.setAttribute('src', '/education/graphics/trans.gif');
		obj_height_forcer.className = 'skin-scribbon-height-forcer ' + this.str_item_class;

		//create the icon if needed
		if (arr_item['icon']) {
			var obj_item_icon = document.createElement('img');
			obj_item_icon.src = arr_item['icon'];
			obj_item_icon.className = "skin-scribbon-icon";
		}

		//some things like icons and labels are handled differently depending on element type
		switch (arr_item['element']) {

			case 'a':
		
				obj_item.appendChild(obj_height_forcer);
				
				//in an anchor tag, the icon and label are inside the anchor
				if (arr_item['icon']) {
					obj_item.appendChild(obj_item_icon);
				}

				//the label will be after the icon
				if (arr_item['label']) {
					var obj_item_label = document.createElement('span');
					obj_item_label.className = 'skin-scribbon-label';
					obj_item_label.innerHTML = arr_item['label'];
					obj_item.appendChild(obj_item_label);
				}

				
				obj_item_div.appendChild(obj_item);
				
				break;

			case 'select':

				//set this item's attributes
				for (z in arr_item.options) {
						
					var arr_option_details = arr_item.options[z];
					var obj_item_option = document.createElement('option');
					
					for (a in arr_option_details) {
						
						//you have to set event attributes differently than others because of how IE7 handles them
						if (a == 'label' || a == 'innerHTML') {
							obj_item_option.innerHTML = arr_option_details[a];
						} else if (a.substr(0,2) == 'on') {

							if (typeof(arr_item.attributes[y]) == "string") {
								eval('obj_item_option.' + a.toLowerCase() + ' = function(e){ ' + arr_option_details[a] + '}');
							} else {
								eval('obj_item_option.' + a.toLowerCase() + ' = ' + arr_option_details[a] + ';');
							}
						} else if (y == 'classname') {
							obj_item_option.className = arr_option_details[a];
						} else {
							obj_item_option.setAttribute(a, arr_option_details[a]);
						}//end if

					}
					
					obj_item.appendChild(obj_item_option);

				}//end for each attribute
				
				//fall through

			case 'input': 
			
				var obj_item_div_inner = document.createElement('div');
				obj_item_div_inner.className = "skin-scribbon-item-inner";
				obj_item_div_inner.appendChild(obj_height_forcer);
	
				//in an input the icon will be inside the item container
				if (arr_item['icon']) {
					var obj_item_icon = document.createElement('img');
					obj_item_div_inner.appendChild(obj_item_icon);
					
					obj_item_icon.src = arr_item['icon'];
					obj_item_icon.className = "skin-scribbon-icon";
				}
				
				//input elements have label tags that are associated with them. build it
				if (arr_item['label']) {
					var obj_item_label = document.createElement('label');
					obj_item_label.className = 'skin-scribbon-label';
					obj_item_label.innerHTML = arr_item['label'];
					obj_item_label.setAttribute("for", obj_item.id);
				}

				//checkboxes have the label after the input, all others label first
				if (arr_item.attributes['type'] == 'checkbox' || arr_item.attributes['type'] == 'radio') {
				
					//radio buttons need special padding to display in line with everything else
					obj_item.className = "skin-scribbon-item-radio";

					obj_item_div_inner.appendChild(obj_item);

					if (arr_item['label']) {
						obj_item_div_inner.appendChild(obj_item_label);
					}

				} else {
					
					if (arr_item['label']) {
						obj_item_div_inner.appendChild(obj_item_label);
					}

					obj_item_div_inner.appendChild(obj_item);
				}

				obj_item_div.appendChild(obj_item_div_inner);				

				break;
			
			case 'br':
									
				obj_divider_start = document.createElement('div');
				obj_divider_end = document.createElement('div');
				obj_divider_start.className = 'skin-scribbon-divider-start';
				obj_divider_end.className = 'skin-scribbon-divider-end';

				obj_item_div.appendChild(obj_divider_start);			
				obj_item_div.appendChild(obj_item);			
				obj_item_div.appendChild(obj_divider_end);			
				
				break;	
			
			default:
				
				//we don't need to do anything special, just append it	
				var obj_item_div_inner = document.createElement('div');
				obj_item_div_inner.className = "skin-scribbon-item-inner";
				obj_item_div_inner.appendChild(obj_height_forcer);
				obj_item_div_inner.appendChild(obj_item);
				obj_item_div.appendChild(obj_item_div_inner);				

				break;

		} //end switch

		this.int_item_num++;

		return obj_item_div;

	}/* }}} */

	/* additional tasks to perform before drawing */
	this.preDraw = function() { /* {{{ */
		//the base class does nothing here. child classes can redefine this.
	}/* }}} */

	/* additional tasks to perform after drawing */
	this.postDraw = function() { /* {{{ */
		//the base class does nothing here. child classes can redefine this.
	}/* }}} */

	/* additional tasks to perform after removing */
	this.postRemove = function() { /* {{{ */
		//the base class does nothing here. child classes can redefine this.
	}/* }}} */

	/* unhides the scribbon div and shows it underneath the specified parent div (for flyouts etc) */
    this.show = function(str_parent_id, str_align, callbackFn) {/* {{{ */
		
		/*
		 * params
		 *
		 * str_parent_id		id of the div this will display under
		 * str_location			left or right, which bottom corners will line up, 
		 *						this will be forced to a different value if the menu would have displayed off the page.
		 * callbackFn			function to call upon completion
		 *
		 */


		if (callbackFn == null) {
			callbackFn = function() {};
		}

		if (str_align == null) {
			str_align = "left";
		}
	
		obj_scribbon_div = $J("#" + this.str_scribbon_div);		

		if (obj_scribbon_div.css("display") == "none") {
			
			//kittens will die....
			$J(".skin-scribbon-flyout").css("display", "none");

			obj_scribbon_div.show();

			obj_scribbon_div.position({ 
				my          :   str_align + " top",
				at          :   str_align + " bottom",
				of          :   $J("#" + str_parent_id),
				collision   :   "none"
			});
		
			obj_scribbon_div.hide();
			
			obj_scribbon_div.toggle('blind', {}, 400, function() {
				callbackFn();
			});
		}	
		
    }/* }}} */
     
	/* hides the scribbon div */
    this.hide = function(callbackFn) {/* {{{ */
		
		if (callbackFn == null) {
			callbackFn = function() {};
		}
		
		obj_scribbon_div = $J("#" + this.str_scribbon_div);

		if (obj_scribbon_div.css("display") != "none") {

			$J("#" + this.str_scribbon_div).toggle('blind', {}, 400, function() {
				callbackFn();
			});
		}

	}/* }}} */

	/* attaches a new scribbon flyout to an element. */
	this.attachFlyout = function(obj_item, arr_scrib_def, int_flyout_type, str_align, bit_vertical, str_classname, str_item_class) {/* {{{ */	
		/* 
		 * params
		 *
		 * obj_item				item that the click event will be bound to and where the flyout will come from
		 * arr_scribbon_def		scribbon definition of items that will be in the flyout
		 * int_flyout_type		0: the flyout will scroll with the page (default), appened to the dom at body
		 *						1: the flyout will not scroll with the page, appended to a fixed reference point
		 *						2: the flyout will scroll with the page, appended to the dom at obj_item
		 * str_align			left or right
		 * bit_vertical			if the scribbon in the flyout should be displayed vertically or horizontally, vert by default.
		 * str_classname		addtional css class for the flyout menu itself
		 * str_item_class		additonal css class for the items in the scribbon (container divs)
		 * bit_inline			attach to the dom at obj_item. int_flyout_type cannot be set with this.
		 *
		 * */

		if (typeof(int_flyout_type) == "undefined") {
			int_flyout_type = 0;
		}
		
		if (typeof(bit_vertical) == "undefined") {
			bit_vertical = 1;
		}

		//get the point where this flyout will be attached to the dom
		if (int_flyout_type == 1) {
			var obj_reference_point = $('scribbon-flyout-reference-point');
		
			if (obj_reference_point == null) {
				obj_reference_point = document.createElement('div');
				obj_reference_point.setAttribute("id", "scribbon-flyout-reference-point");
				obj_reference_point.style.zIndex = '5010';
				obj_reference_point.style.width = '1px';
				obj_reference_point.style.height = '1px';
				obj_reference_point.style.position = 'fixed';
				obj_reference_point.style.top = '0';
				obj_reference_point.style.left = '0';
				$$("body")[0].appendChild(obj_reference_point);
			}
		} else if (int_flyout_type == 2) {
			var obj_reference_point = obj_item;
		} else {
			var obj_reference_point = $$('body')[0];
		}

		var obj_flyout_div = document.createElement('div');
		var obj_scribbon_div = $$("body")[0];
		obj_flyout_div.className = 'skin-scribbon-flyout ' + str_classname;
		obj_flyout_div.setAttribute('id', obj_item.id + '_flyout');
		obj_reference_point.appendChild(obj_flyout_div);
				
		var obj_scribbon_flyout = new SCRibbon(obj_flyout_div.id, bit_vertical, 0, int_flyout_type, str_item_class);
		obj_scribbon_flyout.replaceSCRibbon(arr_scrib_def);
					
		$J(obj_item).bind("click", function() {
			obj_scribbon_flyout.show(obj_item.id, str_align);
		});

		$J(obj_flyout_div).bind("mouseout", function(e) { 
			if (!eventContains(this, e.relatedTarget || window.event.srcElement)) {
				obj_scribbon_flyout.hide();
			}
		});

	}/* }}} */

	/* for use with the mouseout events, returns true if the element mouseoutted to is a child of the event that fired it */
	function eventContains(e, c) {/* {{{ */
		return (e == c) ? true : (c.parentNode) ? eventContains(e, c.parentNode) : false;
	}/* }}} */

}

/* this is a derived class that inherits from the base scribbon class. it has some differing post/pre draw/remove events */
var ToolbarSCRibbon = function(str_scribbon_div, bit_vertical, int_max_num_rows) {

	this.inheritFrom = SCRibbon;
	this.inheritFrom(str_scribbon_div, bit_vertical, int_max_num_rows, 1);

	/* pushes the page down so that the page starts after the toolbar */
	this.adjustPage = function() {/* {{{ */
		
		try {
			var int_toolbar_offset  = $("skin-toolbar").offsetHeight;
			var int_squiggle_offset = 16;
			var obj_body			= $J("body");
			var obj_scbody			= $("scBody");
			var obj_debug			= $("sc-debug-messages");
			var obj_offset_div	= $("skin-toolbar-offset-div");
			var str_curr_background_pos = obj_body.css('background-position');
		
			//ie hack... and you thought we didn't need these with jQuery...	
			if (typeof(str_curr_background_pos) == "undefined") {
				str_curr_background_pos = obj_body.css('background-position-x');		
			}

			if (typeof(str_curr_background_pos) == "undefined") {
				str_curr_background_pos = "";
			}

			//if this is a non-admin page with no debug information on it and the scribbon is not loaded, shift page down only to the top of the squiggle.
			if (obj_scbody != null && obj_debug == null && this.bit_loaded == 0) {
				int_toolbar_offset = int_toolbar_offset - int_squiggle_offset;
			}

			//make sure we can see the debug container
			if (obj_debug != null) {
				obj_debug.style.marginTop = int_toolbar_offset + "px";
			}
			
			//adjust the background if we are not on an admin page
			if (obj_scbody != null) {	
				if (str_curr_background_pos.indexOf("50%") != -1) {
					obj_body.css("backgroundPosition", "50% " + int_toolbar_offset + "px");
				} else if (str_curr_background_pos != "") {
					obj_body.css("backgroundPosition", str_curr_background_pos + " " + int_toolbar_offset + "px");
				} else {
					obj_body.css("backgroundPosition", "0% " + int_toolbar_offset + "px");
				}
			}

			obj_offset_div.style.marginTop		= (int_toolbar_offset - int_squiggle_offset) + 'px';
			
		} catch(e) {}

	}/* }}} */

	/* makes the slide out panel for the scribbon visible if it is not already */
	this.showPanel = function () {/* {{{ */

		//this is for the part of the panel under the superbutton
		try {
			$('skin-superbutton-noscribbon').id = 'skin-superbutton';
		} catch(e) {}

		//this is for the part of the panel under the main menu
		try {
			$('skin-menu-container-noscribbon').id = 'skin-menu-container';
		} catch(e) {}
	}/* }}} */

	/* makes the slide out panel for the scribbon invisible if it is not already */
	this.hidePanel = function () {/* {{{ */

		//this is for the part of the panel under the superbutton
		try {
			$('skin-superbutton').id = 'skin-superbutton-noscribbon';
		} catch(e) {}

		//this is for the part of the panel under the main menu
		try {
			$('skin-menu-container').id = 'skin-menu-container-noscribbon';
		} catch(e) {}
	}/* }}} */

	/* additional tasks to perform before drawing */
	this.preDraw = function() {/* {{{ */
		this.showPanel();
	}/* }}} */

	/* additional tasks to perform after drawing */
	this.postDraw = function() { /* {{{ */
		
		$(this.str_scribbon_div).style.display = "";
		this.adjustPage();
	
	}/* }}} */

	/* additional tasks to perform after removing */
	this.postRemove = function() {/* {{{ */
		this.hidePanel();
	}/* }}} */

}
