
/**
 * Script de menus déroulants
 * 
 * @author Roland Dufour <roland@rentashop.fr> pour Rentashop eCommerce
 */

var RSPlug_Menu_InstanceId = 0;

var RSPlug_Menu = function (element, options){
	if (null === options || undefined === options){
		options = {};
	}
	this.instanceId = ++RSPlug_Menu_InstanceId;
	this._config = { 
		isHoverMenu: false,
		isWideMenu: false,
		doNothingOnClick: false,
		closeOnClickInside: true,
		clickOutsideToClose: true,
		moveOutsideToClose: false,
		removeTooltips: true,
		showIfOverFor: 0,
		closeIfOutsideFor: 0,
		onShowCallback: null,
		onCloseCallback: null,
		ssmenuClassName: 'rspm_ssmenu',
		ssmenuId: 'rspm_ssmenu_[instanceId]_[ssmenuId]',
		ssmenuIsDirectChild: false,
		activeSsMenuUlClassName: '',
		activeSsMenuLinkClassName: 'rspm_active_ssmenu',
		firstSsMenuElementClassName: 'rspm_first',
		multipleMenus: false,
		multipleMenusClassName: 'rspm_convert_menu',
		
		wideMenuConfig: {
			wideMenuCols: 0,
			wideMenuAllowCutBlock: false,
			wideMenuReinsertNiv2IfCutBlock: false,
			wideMenuReinsertNiv2IfCutBlockText: '[html]',
			wideMenuAllowCutFirstLineNiv2: false,
			wideMenuAllowCutFirstLineNiv3: false,
			wideMenuOptimizeCutting: false,
			wideMenuLineHeightNiv2: 1.5,
			wideMenuLineHeightNiv3: 1,
			wideMenuDontCutIfNumberOfRemainingLinesIs: 1,
			wideMenuNiv2Element: 'h3',
			wideMenuNiv2ClassName: 'niv2',
			wideMenuNiv3ClassName: 'niv3',
			wideMenuColClassName: 'col',
			wideMenuColClassNameNumber: 'col-num[col_index]',
			wideMenuPrepend: '',
			wideMenuAppend: '',
			wideMenuSetColHeight: false
		}
	};
	for (var optName in options){
		if (optName.substring(0, 14) == 'wideMenuConfig'){
			if (optName != 'wideMenuConfig' && !this._config[optName]){
				this._config[optName] = {};
				for (var subOptName in this._config.wideMenuConfig){
					this._config[optName][subOptName] = this._config.wideMenuConfig[subOptName];
				}
			}
			for (var subOptName in options[optName]){
				if ((undefined !== this._config[optName] && undefined !== this._config[optName][subOptName] && null !== this._config[optName][subOptName]) || subOptName == 'json'){
					this._config[optName][subOptName] = options[optName][subOptName];
				}
			}
		}
		else if ((null !== this._config[optName] && undefined !== this._config[optName]) || (optName == 'onShowCallback' || optName == 'onCloseCallback')){
			this._config[optName] = options[optName];
		}
	}
	
	this.init(element);
};

RSPlug_Menu.prototype.init = function (element){
	this.menuOpened = null;
	this.linkMenuOpened = null;
	this.linkMenuOpening = null;
	this.closeOutsideForTimer = null;
	this.showIfOverForTimer = null;
	this.nb_ssmenu = 0;
	var menuContainer = null;
	
	if (typeof element == 'string'){
		element = document.getElementById(element);
	}
	if (element){
		if (element.nodeName.toLowerCase() == 'ul'){
			this._init(element);
		} else if (this._config.multipleMenus) {
			var uls = element.getElementsByTagName('ul');
			for (var i=0; i<uls.length; i++){
				if (this.css.hasClassName(uls[i], this._config.multipleMenusClassName)){
					this._init(uls[i]);
				}
			}
		} else {
			var uls = element.getElementsByTagName('ul');
			if (uls[0]){
				var theUls = uls[0].parentNode.childNodes;
				for (var i=0; i<theUls.length; i++){
					if (theUls[i].nodeType == 1 && theUls[i].nodeName.toLowerCase() == 'ul'){
						this._init(theUls[i]);
					}
				}
			}
		} 
	}
};

RSPlug_Menu.prototype._init = function (menuContainer){
	if (null !== menuContainer){
		var lis = menuContainer.childNodes;
		var inst = this;
		for (var i=0; i<lis.length; i++){
			if (lis[i].nodeType == '1' && lis[i].nodeName.toLowerCase() == 'li'){
				var linksMenu = lis[i].getElementsByTagName('a');
				if (linksMenu.length > 0){
					var linkMenu = linksMenu[0];
					this.nb_ssmenu++;
					if (this._config.isWideMenu){
						var sslis = lis[i].getElementsByTagName('div');
					} else if (this._config.ssmenuIsDirectChild){
						var sslis = linkMenu.nextSibling;
						while (sslis !== null && sslis.nodeType != 1){
							sslis = sslis.nextSibling;
						}
						var sslis = (sslis !== null ? [sslis] : []);
					} else {
						var sslis = lis[i].getElementsByTagName('li');
					}
					if (sslis.length > 0){
						(function(menu){
							if (!inst._config.isHoverMenu){
								linkMenu.onclick = function(){
									if (inst._config.isWideMenu){
										var ssmenu = sslis;
									} else if (inst._config.ssmenuIsDirectChild){
										var ssmenu = sslis;
									} else {
										var ssmenu = menu.getElementsByTagName('ul');
									}
									if (ssmenu[0]){ 
										if (inst.menuOpened == ssmenu[0]){
											if (inst._config.closeOnClickInside){
												inst.closeMenu(ssmenu[0], this);
											}
										} else {
											inst.showMenu(ssmenu[0], this);
										}
									} 
									return false; 
								};
								if (inst._config.showIfOverFor > 0){
									linkMenu.onmouseover = function(){
										if (inst._config.isWideMenu && sslis[0]){
											inst.initShowMenu(sslis[0], this);
										} else if (inst._config.ssmenuIsDirectChild && sslis[0]){
											inst.initShowMenu(sslis[0], this);
										} else if (!inst._config.isWideMenu) {
											var ssmenu = menu.getElementsByTagName('ul');
											if (ssmenu[0]){ 
												inst.initShowMenu(ssmenu[0], this);
											}
										}
									};
									linkMenu.onmouseout = function(){
										if (null !== inst.showIfOverForTimer){
											clearTimeout(inst.showIfOverForTimer);
											inst.showIfOverForTimer = null;
											inst.linkMenuOpening = null;
										}
									};
								}
							} else {
								linkMenu.onmouseover = function(){ 
									if (inst._config.isWideMenu){
										var ssmenu = this.parentNode.getElementsByTagName('div');
									} else if (inst._config.ssmenuIsDirectChild){
										var ssmenu = this.nextSibling;
										while (ssmenu !== null && ssmenu.nodeType != 1){
											ssmenu = ssmenu.nextSibling;
										}
										ssmenu = [ssmenu];
									} else {
										var ssmenu = menu.getElementsByTagName('ul');
									}
									if (ssmenu[0]){ 
										inst.initShowMenu(ssmenu[0], this);
									} 
								};
								if (inst._config.doNothingOnClick){
									linkMenu.onclick = function(){ return false; }
								}
							}
						})(lis[i]);
						
						if (this._config.isWideMenu){
							var ssmenuObj = sslis[0];
							
							/** Remise en forme du grand sous-menu **/
							var divs = ssmenuObj.getElementsByTagName('div');
							var json = null;
							var gsm_ssmenu = null;
							for (var k=0; k<divs.length; k++){
								if (this.css.hasClassName(divs[k], 'gsm_json')){
									json = divs[k].innerHTML;
									divs[k].parentNode.removeChild(divs[k]);
									if (null !== gsm_ssmenu){
										break;
									}
									continue;
								}
								if (this.css.hasClassName(divs[k], 'gsm_ssmenu')){
									gsm_ssmenu = divs[k];
									if (null !== json){
										break;
									}
									continue;
								}
							}
							if (null !== gsm_ssmenu){
								var configName = 'wideMenuConfig';
								if (undefined !== this._config[configName + this.nb_ssmenu]){
									configName = configName + this.nb_ssmenu;
								}
								if (null !== json){
									json = eval('(' + json + ')');
								} else if (this._config[configName].json){
									json = this._config[configName].json;
								}
								if (null !== json){
									this.generateBigSubMenu(gsm_ssmenu, json, this._config[configName]);
								}
							}
						} 
						else if (this._config.ssmenuIsDirectChild && sslis[0]){
							var ssmenuObj = sslis[0];
						}
						else {
							var ssmenuObj = sslis[0].parentNode;
						}
						this.css.hide(ssmenuObj);
						this.css.addClassName(ssmenuObj, this._config.ssmenuClassName);
						ssmenuObj.id = this._config.ssmenuId.replace('[instanceId]', this.instanceId).replace('[ssmenuId]', this.nb_ssmenu);
						if (this._config.firstSsMenuElementClassName != ''){
							this.css.addClassName(sslis[0], this._config.firstSsMenuElementClassName);
						}
					}
					
					// Pour liens sans ss-menus
					else {
						if (!this._config.isHoverMenu){
							linkMenu.onclick = function(){ 
								inst.closeOpenedMenu();
							};
						} else {
							linkMenu.onmouseover = function(){ 
								inst.closeOpenedMenu();
							};
						}
					}
					
					if (this._config.removeTooltips){
						var links = lis[i].getElementsByTagName('a');
						for (var j=0; j<links.length; j++){
							if (links[j].hasAttribute && links[j].hasAttribute('title') && links[j].removeAttribute){
								links[j].removeAttribute('title');
							} else if (links[j].title) {
								links[j].title = '';
							}
						}
					}
				}
			}
		}
		if (this.nb_ssmenu > 0){
			if (this._config.moveOutsideToClose || this._config.closeIfOutsideFor > 0){				
				this.addEvent('mousemove', function (e){ inst.checkIfIsOutside(e, false); });
			}
			if (this._config.clickOutsideToClose && !this._config.moveOutsideToClose){			
				this.addEvent('click', function (e){ inst.checkIfIsOutside(e, true); });
			}
		}
	}
};

RSPlug_Menu.prototype.generateBigSubMenu = function (bigSubMenu, links, config){
	bigSubMenu.innerHTML = config.wideMenuPrepend;
	var nbLinks = 0;
	var nbLinksNiv2 = 0;
	for (var i=0; i<links.length; i++){
		nbLinksNiv2++;
		nbLinks += links[i].linkChilds.length;
	}
	
	var remaining = ((nbLinksNiv2 * config.wideMenuLineHeightNiv2) + (nbLinks * config.wideMenuLineHeightNiv3));
	var cutAfter = null;
	if (config.wideMenuCols > 0){
		cutAfter = Math.ceil(remaining / config.wideMenuCols);
	}
	
	var cols = 1;
	var colsArray = [];
	var col = document.createElement('div');
	colsArray.push(col);
	col.className = config.wideMenuColClassName + ' ' + config.wideMenuColClassNameNumber.replace('[col_index]', cols);
	var counter = 0;
	var maxCounter = 0, maxColHeight = 0;
	for (var i=0; i<links.length; i++){
		var nbLinkChilds = links[i].linkChilds.length;
		if (null !== cutAfter && counter > 0 && cols < config.wideMenuCols && (config.wideMenuAllowCutFirstLineNiv2 || counter >= cutAfter || (config.wideMenuOptimizeCutting && nbLinkChilds > 0 && (remaining <= maxCounter || (counter + config.wideMenuLineHeightNiv2 + config.wideMenuLineHeightNiv3) > (maxCounter > cutAfter ? maxCounter : cutAfter))))){
			bigSubMenu.appendChild(col);
			cols++;
			if (col.offsetHeight && col.offsetHeight > maxColHeight){
				maxColHeight = col.offsetHeight;
			}
			var col = document.createElement('div');
			colsArray.push(col);
			col.className = config.wideMenuColClassName + ' ' + config.wideMenuColClassNameNumber.replace('[col_index]', cols);
			if (counter > maxCounter){
				maxCounter = counter;
			}
			counter = 0;
		}
		
		var linkContainer = document.createElement(config.wideMenuNiv2Element);
		linkContainer.className = config.wideMenuNiv2ClassName;
		var link = document.createElement('a');
		link.href = links[i].linkUrl;
		link.innerHTML = links[i].linkName;
		if (null !== links[i].linkClass && undefined !== links[i].linkClass && '' != links[i].linkClass){
			linkContainer.className = links[i].linkClass;
		}
		linkContainer.appendChild(link);
		col.appendChild(linkContainer);
		counter += config.wideMenuLineHeightNiv2;
		remaining -= config.wideMenuLineHeightNiv2;
		
		if (nbLinkChilds > 0){
			var subLinks = document.createElement('ul');
			subLinks.className = config.wideMenuNiv3ClassName;
			for (var j=0; j<nbLinkChilds; j++){
				if (config.wideMenuAllowCutBlock &&  counter > cutAfter && (config.wideMenuAllowCutFirstLineNiv3 || (!config.wideMenuAllowCutFirstLineNiv3 && j > 0)) && cols < config.wideMenuCols){
					if (!config.wideMenuOptimizeCutting || ((nbLinkChilds -j) > config.wideMenuDontCutIfNumberOfRemainingLinesIs && (nbLinkChilds -j <= config.wideMenuDontCutIfNumberOfRemainingLinesIs || counter >= maxCounter))){
						col.appendChild(subLinks);
						bigSubMenu.appendChild(col);
						cols++;
						if (col.offsetHeight && col.offsetHeight > maxColHeight){
							maxColHeight = col.offsetHeight;
						}
						var col = document.createElement('div');
						colsArray.push(col);
						col.className = config.wideMenuColClassName + ' ' + config.wideMenuColClassNameNumber.replace('[col_index]', cols);;
						if (config.wideMenuReinsertNiv2IfCutBlock){
							var linkContainer = document.createElement(config.wideMenuNiv2Element);
							linkContainer.className = config.wideMenuNiv2ClassName;
							var link = document.createElement('a');
							link.href = links[i].linkUrl;
							link.innerHTML = config.wideMenuReinsertNiv2IfCutBlockText.replace('[html]', links[i].linkName);
							if (null !== links[i].linkClass && undefined !== links[i].linkClass && '' != links[i].linkClass){
								linkContainer.className = links[i].linkClass;
							}
							linkContainer.appendChild(link);
							col.appendChild(linkContainer);
						}
						var subLinks = document.createElement('ul');
						subLinks.className = config.wideMenuNiv3ClassName;
						if (counter > maxCounter){
							maxCounter = counter;
						}
						counter = 0;
					}
				}
				
				var liLink = document.createElement('li');
				var subLink = document.createElement('a');
				subLink.href = links[i].linkChilds[j].linkUrl;
				subLink.innerHTML = links[i].linkChilds[j].linkName;
				if (null !== links[i].linkChilds[j].linkClass && undefined !== links[i].linkChilds[j].linkClass && '' != links[i].linkChilds[j].linkClass){
					liLink.className = links[i].linkChilds[j].linkClass;
				}
				liLink.appendChild(subLink);
				subLinks.appendChild(liLink);
				counter += config.wideMenuLineHeightNiv3;
				remaining -= config.wideMenuLineHeightNiv3;
			}
			col.appendChild(subLinks);
		}
	}
	bigSubMenu.appendChild(col);
	if (col.offsetHeight && col.offsetHeight > maxColHeight){
		maxColHeight = col.offsetHeight;
	}
	
	if (config.wideMenuSetColHeight){
		for (var i=0; i<colsArray.length; i++){
			colsArray[i].style.height = maxColHeight +'px';
		}
	}
	
	if (config.wideMenuAppend != ''){
		bigSubMenu.innerHTML += config.wideMenuAppend;
	}
};

RSPlug_Menu.prototype.addEvent = function (eventName, callback){
	if (document.addEventListener){
		document.addEventListener(eventName, callback, false);
	} else if (document.attachEvent){
		document.attachEvent('on' + eventName, callback);
	}
};

RSPlug_Menu.prototype.closeOpenedMenu = function (){
	if (null !== this.menuOpened){
		this.closeMenu(this.menuOpened, this.linkMenuOpened);
	}
};

RSPlug_Menu.prototype.checkIfIsOutside = function (event, immediatly){
	if (null !== this.menuOpened){
		var el = event.target ? event.target : event.srcElement;
		while (true){
			if (!el || (el.nodeType == 1 && (el.nodeName.toLowerCase() == 'body' || el.nodeName.toLowerCase() == 'html'))){
				if (!immediatly && this._config.closeIfOutsideFor > 0){
					this.initCloseMenu(this.menuOpened, this.linkMenuOpened);
				} else {
					this.closeMenu(this.menuOpened, this.linkMenuOpened);
				}
				return false;
			}
			if (el.nodeType == 1 && (el == this.menuOpened || el == this.linkMenuOpened)){
				if (null !== this.showIfOverForTimer){
					clearTimeout(this.showIfOverForTimer);
					this.showIfOverForTimer = null;
					this.linkMenuOpening = null;
				}
		    	if (null !== this.closeOutsideForTimer){
		    		clearTimeout(this.closeOutsideForTimer);
		    		this.closeOutsideForTimer = null;
		    	}
			    return true;
		    }
			el = el.parentNode;
	    }
	} 
	else if (null !== this.showIfOverForTimer && null !== this.linkMenuOpening) {
		var el = event.target ? event.target : event.srcElement;
		while (true){
			if (!el || (el.nodeType == 1 && (el.nodeName.toLowerCase() == 'body' || el.nodeName.toLowerCase() == 'html'))){
				if (null !== this.showIfOverForTimer){
					clearTimeout(this.showIfOverForTimer);
					this.showIfOverForTimer = null;
					this.linkMenuOpening = null;
				}
				return false;
			}
			if (el.nodeType == 1 && (el == this.linkMenuOpening)){
			    return true;
		    }
			el = el.parentNode;
	    }
	}
	return false;
};

RSPlug_Menu.prototype.initShowMenu = function (menu, link){
	if (menu !== this.menuOpened){
		if (this._config.showIfOverFor > 0 && null === this.menuOpened){
			if (null === this.showIfOverForTimer || this.linkMenuOpening !== link){				
				if (null !== this.showIfOverForTimer){
					clearTimeout(this.showIfOverForTimer);
					this.showIfOverForTimer = null;
				}
				if (null !== this.closeOutsideForTimer){
					clearTimeout(this.closeOutsideForTimer);
					this.closeOutsideForTimer = null;
				}
				var inst = this;
				this.showIfOverForTimer = setTimeout(function (){ inst.showMenu(menu, link); }, this._config.showIfOverFor);
				this.linkMenuOpening = link;
			}													
		}
		else {
			if (null !== this.closeOutsideForTimer){
				clearTimeout(this.closeOutsideForTimer);
				this.closeOutsideForTimer = null;
			}
			this.showMenu(menu, link);
		}
	}
};

RSPlug_Menu.prototype._onShowMenu = function (menu, link){
	if (null !== this._config.onShowCallback){
		return this._config.onShowCallback(this, menu, link);
	}
	return true;
};

RSPlug_Menu.prototype.showMenu = function (menu, link){
	if (!this._onShowMenu(menu, link)){
		return false;
	}
	if (null !== this.closeOutsideForTimer){
		clearTimeout(this.closeOutsideForTimer);
		this.closeOutsideForTimer = null;
	}
	if (null !== this.showIfOverForTimer){
		clearTimeout(this.showIfOverForTimer);
		this.showIfOverForTimer = null;
		this.linkMenuOpening = null;
	}
	if (null !== this.menuOpened){
		if (!this.closeMenu(this.menuOpened, this.linkMenuOpened)){
			return false;
		}
		this.menuOpened = null;
		this.linkMenuOpened = null;
	}
	if (this.css.show(menu)){
		this.css.addClassName(link, this._config.activeSsMenuLinkClassName);
		this.menuOpened = menu;
		this.linkMenuOpened = link;
		if (this._config.activeSsMenuUlClassName != ''){
			this.css.addClassName(link.parentNode.parentNode, this._config.activeSsMenuUlClassName); // Class du UL parent
		}
	}
	return true;
};

RSPlug_Menu.prototype.initCloseMenu = function (menu, link){
	if (this._config.closeIfOutsideFor > 0){
		if (null === this.closeOutsideForTimer){
			var inst = this;
			this.closeOutsideForTimer = setTimeout(function (){ inst.closeMenu(menu, link); }, this._config.closeIfOutsideFor);
		}
	}
	else {
		this.closeMenu(menu, link);
	}
};

RSPlug_Menu.prototype._onCloseMenu = function (menu, link){
	if (null !== this._config.onCloseCallback){
		return this._config.onCloseCallback(this, menu, link);
	}
	return true;
};

RSPlug_Menu.prototype.closeMenu = function (menu, link){
	if (!this._onCloseMenu(menu, link)){
		return false;
	}
	if (null !== this.closeOutsideForTimer){
		clearTimeout(this.closeOutsideForTimer);
		this.closeOutsideForTimer = null;
	}
	if (this.css.hide(menu)){
		this.css.removeClassName(link, this._config.activeSsMenuLinkClassName);
		if (this.menuOpened == menu){
			this.menuOpened = null;
			this.linkMenuOpened = null;
		}
		if (this._config.activeSsMenuUlClassName != ''){
			this.css.removeClassName(link.parentNode.parentNode, this._config.activeSsMenuUlClassName); // Class du UL parent
		}
	}
	return true;
};



RSPlug_Menu.prototype.css = {};

RSPlug_Menu.prototype.css.show = function (element){
	if (element){
		element.style.display = '';
		return true;
	}
	return false;
};

RSPlug_Menu.prototype.css.hide = function (element){
	if (element){
		element.style.display = 'none';
		return true;
	}
	return false;
};

RSPlug_Menu.prototype.css.hasClassName = function (obj, className){
	var classes = obj.className.split(/\s+/);
	for (var i=0; i<classes.length; i++){
		if (classes[i] == className){
			return true;
		}
	}
	return false;
}

RSPlug_Menu.prototype.css.removeClassName = function (obj, className){
	if (obj){
		var classes = obj.className.split(/\s+/);
		obj.className = '';
		for (var i=0; i<classes.length; i++){
			if (classes[i] != className){
				obj.className += (obj.className == '' ? '' : ' ') + classes[i];
			}
		}
	}
}

RSPlug_Menu.prototype.css.addClassName = function (obj, className){
	if (obj && !this.hasClassName(obj, className)){
		obj.className += (obj.className == '' ? '' : ' ') + className;
	}
}


