var openClose = $('.openClose');
openClose.on('click', function() {
var cook = ReadCookie('slideHide'),
miniParent = $(this).parent().parent().parent().children('.main-content'),
miniDisp = miniParent.css('display');
if (miniDisp ==="block") {
KillCookie('slideHide');
$(this).parent().parent().parent().children('.main-content').slideUp();
var slide = cook + "," + "#"+$(this)
.parent()
.parent()
.parent()
.parent().attr("id") +
" #"+$(this).parent()
.parent().parent().attr("id");
SetCookie('slideHide', slide, 100);
}
else
{
$(this).parent().parent().parent().children('.main-content').slideDown();
var newCookie=[];
var a= $('.module').children('.main-content').filter(":hidden");
for(var i=0;i<a.length;i++){
var d = $(a[i++]);
var c = "#"+d.parent('.module').attr('id');
}
newCookie= c;
console.log(newCookie);
KillCookie('slideHide');
SetCookie('slideHide',d, 100);
}
});
These are my cookie functions:
function SetCookie(cookieName,cookieValue,nDays) {
var today = new Date();
var expire = new Date();
if (nDays==null || nDays==0) nDays=1;
expire.setTime(today.getTime() + 3600000*24*nDays);
document.cookie = cookieName+"="+escape(cookieValue)
+ ";expires="+expire.toGMTString(),';path = /';
}
function KillCookie(cookieName) {
SetCookie(cookieName,"", - 1);
}
function ReadCookie(cookieName) {
var theCookie=""+document.cookie;
var ind=theCookie.indexOf(cookieName+"=");
if (ind==-1 || cookieName=="") return "";
var ind1=theCookie.indexOf(";",ind);
if (ind1==-1) ind1=theCookie.length;
return unescape(theCookie.substring(ind+cookieName.length+1,ind1));
}
Setting the cookie to make it slideUp and stay hidden works, but when I try to open it, it slidesDown, then I refresh the page it doesn't stay open like it should.
To sort of get the picture - http://jsfiddle.net/zRT9u/
If you need to know more please ask me I am willing to provide more!
I edited the javascript it almost works but I am not getting all the objects that I need
NEW EDIT- Tried the $.map() function but when I open one, and refresh all of them are now open?
else {
$(this).parent().parent().parent().children('.main-content').slideDown();
KillCookie('slideHide');
var newCookie=[];
var a= $('.module').children('.main-content').filter(":hidden");
var c = $.map(a,function(n,i){
return $(n).parent().attr('id');
});
newCookie= c;
SetCookie('slideHide',newCookie, 100);
}
Fixed it by using $.map and .join()
var openClose = $('.openClose');
openClose.on('click', function() {
var cook = ReadCookie('slideHide'),
miniParent = $(this).parent().parent().parent().children('.main-content'),
miniDisp = miniParent.css('display');
if (miniDisp ==="block") {
KillCookie('slideHide');
$(this).parent().parent().parent().children('.main-content').slideUp();
var slide = cook+","+ "#"+$(this).parent().parent().parent().attr("id");
SetCookie('slideHide', slide, 100);
} else {
$(this).parent().parent().parent().children('.main-content').slideDown();
KillCookie('slideHide');
var newCookie=[],
a= $('.module').children('.main-content').filter(":hidden"),
c = $.map(a,function(n,i){
return "#"+$(n).parent().attr('id');
});
newCookie= c.join(',');
SetCookie('slideHide',newCookie, 100);
}
});
By creating a "global" array and then using the $.map function as well as adding "#"+ to the map function I was able to get the actual ID names. Then I set newCookie to c.join(',') and everything works perfectly after that!
Related
I'm programming an experiment in Qualtrics and I basically need to create, with Javascript, a variable that tells me how long (total) participants held down any button. Pressing a button will display text to the participants and releasing it will make the text disappear, so basically it tells me how much time they had to read the text. So let's say they press the button three times, first for 30 seconds, second for 10 seconds and third for 2 seconds, this code should store the value 42.
What I have so far is this:
addEventListener("keydown", function(event) {
if (event.keyCode == 86)
document.getElementById("text").innerHTML = "Text to show";
var d1 = new Date();
document.getElementById("div1").innerHTML = d1.getTime();
});
addEventListener("keyup", function(event) {
if (event.keyCode == 86)
document.getElementById("text").innerHTML = "";
var d2 = new Data();
var d1 = parseFloat(document.getElementById("div1"));
var diff = d2 - d1.getTime();
var old = parseFloat(document.getElementById("div2"));
var old = old + diff;
document.getElementById("div2").innerHTML = old;
Qualtrics.SurveyEngine.setEmbeddedData("readingtime", totalTime);
});
I store the values in divs because I can't seem to reuse values from one event listener to the other (this is probably because I don't know enough about javascript and scopes). Oh, and the last function is just a Qualtrics-specific function to store the value in the database. Anyway, I can't get it to work, when I check the variable in the database it is simply empty. Anyone can spot what I'm doing wrong?
I did a few changes to your code:
Added global variables
Added few missing brackets
Attached listeners to window
Removed multiple calls to DOM elements
Created a function for each event listener
Rounded the elapsed time to seconds
var d0;
var d1;
var subtotal = 0;
var total = 0;
var div1 = document.getElementById("div1");
var text = document.getElementById("text");
window.addEventListener("keydown", dealWithKeyDown, false);
window.addEventListener("keyup", dealWithKeyUp, false);
function dealWithKeyDown(event) {
if (event.keyCode == 86) {
if (typeof d0 === 'undefined') {
d0 = new Date();
}
d1 = new Date();
subtotal = Math.round((d1.getTime() - d0.getTime()) / 1000);
div1.innerHTML = subtotal;
text.innerHTML = "Text to show";
}
}
function dealWithKeyUp(event) {
if (event.keyCode == 86) {
total = total + subtotal;
text.innerHTML = "";
d0 = undefined;
Qualtrics.SurveyEngine.setEmbeddedData("readingtime", total);
}
}
Okey dokey, since none of the posted answers seem to have been accepted, I'm gonna post my own.
There's really not that much to say about this solution, it's as easy as it gets, nicely put into objects, so that we know what's going on, and I am even giving you a fiddle for it!
There's one problem I don't know if I solved or not, but sometimes the button will show that it has been pressed for millions of seconds, I think that's because Key is not being initialized properly, which is pretty weird, but it happens rarely enough for me to put the burden of fixing it on you.
The code is here:
https://jsfiddle.net/vo2n1jw1/
Pasted over:
var Key = function(code)
{
this.code = code;
};
Key.prototype.time = 0;
Key.prototype.pressedAt = 0;
Key.prototype.getTimeInSeconds = function()
{
return this.time / 1000;
};
var Keyboard = function()
{
this.keys = [];
};
Keyboard.prototype.addOrGetKey = function(code)
{
var key = this.getKey(code);
if(!key)
{
key = new Key(code);
this.addKey(key);
}
return key;
};
Keyboard.prototype.addKey = function(key)
{
this.getKeys()[key.code] = key;
};
Keyboard.prototype.getKey = function(code)
{
return this.getKeys()[code];
};
Keyboard.prototype.getKeys = function()
{
return this.keys;
};
Keyboard.prototype.printAllKeysIntoElement = function(element)
{
var keys = this.getKeys();
var length = keys.length;
element.innerHTML = "";
for(var i = 0; i < length; i++)
{
var key = keys[i];
if(!key)
{
continue;
}
var keyElement = document.createElement("div");
keyElement.innerHTML = "Button: " + key.code + " has been pressed for " + key.getTimeInSeconds() + " seconds";
element.appendChild(keyElement);
}
};
var KeyboardListener = function(keyboard, element)
{
this.keyboard = keyboard;
this.container = element;
this.onKeyDownThis = this.onKeyDown.bind(this);
document.addEventListener("keydown", this.onKeyDownThis, false);
document.addEventListener("keyup", this.onKeyUp.bind(this), false);
};
KeyboardListener.prototype.onKeyDown = function(event)
{
console.log("press");
var keyboard = this.getKeyboard();
var code = event.keyCode;
var key = keyboard.addOrGetKey(code);
key.pressedAt = Date.now();
document.removeEventListener("keydown", this.onKeyDownThis, false);
return false;
};
KeyboardListener.prototype.onKeyUp = function(event)
{
console.log("release");
var keyboard = this.getKeyboard();
var code = event.keyCode;
var key = keyboard.addOrGetKey(code);
if(key.pressedAt)
{
key.time += Date.now() - key.pressedAt;
keyboard.printAllKeysIntoElement(this.container);
}
document.addEventListener("keydown", this.onKeyDownThis, false);
return false;
};
KeyboardListener.prototype.getKeyboard = function()
{
return this.keyboard;
};
var resultsElement = document.getElementById("results");
var keyboard = new Keyboard();
var listener = new KeyboardListener(keyboard, resultsElement);
There's 3 objects:
Key
Keyboard
KeyboardListener
They really do what they sound like.
Tell me, if you want anything explained.
Oh, one thing, I know you're not supposed to use arrays like this, but I was lazy.
You can try to create a variable outside both listeners, and outside functions, so you can use it anywhere.
And I think you are doing well by getting the times of Dates.
var firstTime = new Date();
var totalTime = 0;
addEventListener("keydown", function(event) {
if (event.keyCode == 86) {
document.getElementById("text").innerHTML = "Text to show";
firstTime = new Date();
}
});
addEventListener("keyup", function(event) {
if (event.keyCode == 86) {
document.getElementById("text").innerHTML = "";
var d2 = new Date();
var diff = d2.getTime() - firstTime.getTime();
totalTime += diff;
Qualtrics.SurveyEngine.setEmbeddedData("readingtime", totalTime);
}
});
It's better to declare d1 & d2 variables global instead of using html elements as storage.
var d1, d2;
var total_time = 0;
var key_pressed = false;
addEventListener("keydown", function(event) {
if (event.keyCode == 86) {
if (!key_pressed)
d1 = new Date();
key_pressed = true;
}
});
addEventListener("keyup", function(event) {
if (event.keyCode == 86) {
key_pressed = false;
d2 = new Date();
total_time += d2.getTime() - d1.getTime();
Qualtrics.SurveyEngine.setEmbeddedData("readingtime", total_time);
}
});
When the 'v' key is pressed and hold, keydown listener is called repeatedly. That's why there is boolean variable i.e. "key_pressed" to detect hold key first time.
Where does the "totalTime" get assigned?
Is your totalTime has any value?
Did you try to debug the javascript using the browser console?
If you don't want to store data to divs, u can store it within global vars.
var times = {
start: 0,
total: 0
}
addEventListener("keydown", function(event) {
if (event.keyCode == 86) {
// i think your hole code should be executed only on releasing this one button
document.getElementById("text").innerHTML = "Text to show";
times.start = new Date();
}
});
addEventListener("keyup", function(event) {
if (event.keyCode == 86) {
// i think your hole code should be executed only on releasing this one button
document.getElementById("text").innerHTML = "";
var diff = new Date().getTime() - times.start.getTime();
times.total = times.total + diff;
Qualtrics.SurveyEngine.setEmbeddedData("readingtime", times.total);
}
});
So you can use the var times outside of the event listener function to declare it global.
I noticed that you used the if ().. without { and }, so only the next line is affected, im dont shure if you want that.
*For reference I'm using iron router.
Instead of a sign in page I have this global sign in form embedded in an nav (aka on every page).
Right now I'm doing a really hacky refresh to reload the page once a user logs in.
I would like to just reload to the template aka not refresh the whole page.
Basically just want the templates rendered function to rerun on login.
Here's my current login code:
'submit #login': function(event, template){
event.preventDefault();
var handle = template.find('#usernameLogin').value;
var secretKey = template.find('#passwordLogin').value;
Meteor.loginWithPassword(handle, secretKey, function(err){
if (err) {
alert(err);
}else{
$('#close').click();
/* replace this with reactive ajax or whatever when you can! */
Meteor._reload.reload();
}
});
},
My render function which I think may be the real issue now:
Template.tournament.rendered = function () {
thisCampaign = this.data;
var self = this;
if (this.data.tournament.live) {
/* if theres a registered user */
if (Meteor.userId()) {
/* Select a winner box */
var participants = $('.participant-id');
var currentParticipant;
var nextRound;
var thisMatch;
var nextMatch;
var bracket;
participants.map(function(index, value){
if ($(value).text() === Meteor.userId()) {
if ($(value).parent().find('.participant-status').text() === 'undetermined') {
nextRound = $(value).parent().find('.participant-round').text();
thisMatch = $(value).parent().find('.participant-match').text();
bracket = $(value).parent().parent().parent().find('.participant');
};
};
});
nextRound = parseInt(nextRound) + 1;
nextMatch = Math.round(parseInt(thisMatch)/2) - 1;
if (parseInt(thisMatch) % 2 != 0) {
currentParticipant = 0;
}else{
currentParticipant = 1;
}
var winnerOptions = '';
var winnerBox = $('<div class="select-winner">');
if (bracket) {
bracket.map(function(index, value) {
winnerOptions += '<span class="winner-option"> '+$(value).find('.participant-title').text()+' <div class="winner-info"> '+$(value).find('a').html()+' </div> </span>'
});
winnerBox.append(winnerOptions);
$($($('.round'+nextRound).find('li')[nextMatch]).find('.participant')[currentParticipant]).removeClass('loser').addClass('undetermined');
$($($('.round'+nextRound).find('li')[nextMatch]).find('.participant')[currentParticipant]).find('a').addClass('tooltip').html(winnerBox);
};
}else{
}
}else{
/* Tournament Start Time */
var tournamentStartTime = function(){
var d = new Date();
var n = d.getTime();
var currentTime = TimeSync.serverTime(n);
var startTime = self.data.card.startTime;
var difference = startTime - currentTime;
var hoursDifference = Math.floor(difference/1000/60/60);
difference -= hoursDifference*1000*60*60
var minutesDifference = Math.floor(difference/1000/60);
difference -= minutesDifference*1000*60
var secondsDifference = Math.floor(difference/1000);
/* if ends (make tournament live server side?) */
if (hoursDifference < 0 || minutesDifference < 0 || secondsDifference < 0) {
Meteor.clearInterval(tStartTime);
Session.set("tournamentStartTime", false);
}else{
if (hoursDifference < 10) {hoursDifference = "0"+hoursDifference;}
if (minutesDifference < 10) {minutesDifference = "0"+minutesDifference;}
if (secondsDifference < 10) {secondsDifference = "0"+secondsDifference;}
var formattedTime = hoursDifference + ':' + minutesDifference + ':' + secondsDifference;
Session.set("tournamentStartTime", formattedTime);
}
};
Session.set("tournamentStartTime", '00:00:00');
tournamentStartTime();
var tStartTime = Meteor.setInterval(tournamentStartTime, 1000);
/* Allow new user sign up */
var alreadySignedUp = false;
var usersSignedUp = $('.participant-id')
usersSignedUp.map(function (index, user) {
if ($(user).text().trim() === Meteor.userId()) {
alreadySignedUp = true;
}
});
if (this.data.card.host != Meteor.user().username && !(alreadySignedUp)) {
var openSlots = [];
var allSlots = $('.participant');
allSlots.map(function (index, participant) {
if ($(participant).find('.participant-title').text().trim() === '' && !($(participant).hasClass('loser'))) {
openSlots.push(participant);
}
});
openSlots.map(function (openSlot, index) {
$(openSlot).removeClass('winner').addClass('undetermined');
});
}
/* if theres a registered user */
if (Meteor.userId()) {
}else{
}
}
};
From what i can see there, your rendered function would not work as you expect as the template may render while the loggingIn state is still occuring...
My suggestion would be to use something along the lines of {{#if currentUser}} page here{{/if}} and then put the code you are trying to run in the rendered in a helper inside that currentUser block that way it would only display and be called if there is a logged in user, otherwise it would not show up and you would not need to re-render the page to perform any of that.
Basically once the user has logged in, any helper (other than rendered) that has the Meteor.userId() or Meteor.user() functions being called would re-run automatically, otherwise you could perform login actions inside a Tracker.autorun function if they are global to your app per client.
I am trying to hide random multiple elements, so what I have done was given each a unique ID.
$(function() {
var left= $('#left'),
right = $('#right'),
heads = $('.maintitle'),
i,
leftHead = $(left).find(heads),
rightHead = $(right).find(heads);
$(leftHead).prepend('<div class="close"></div>');
$(rightHead).prepend('<div class="close"></div>');
var close = $('.close'),
Lnumber = $('#left .module'),
Rnumber =$('#right .module');
for (i=0;i<Lnumber.length;i++) {
$(Lnumber)[i].id='widg'+i;
}
close.click(function() {
var id = $(this).parent().parent().attr('id');
$(this).parent().parent().slideUp().addClass('hidden');
SetCookie('hidden'+id,"true",100);
});
var cookieId = $('#left .module');
for (i=0;i<cookieId.length;i++) {
var newArray = [cookieId[i].id];
if (ReadCookie(newArray) == 'true') {
var cName = newArray.replace('hidden','');
alert(cName);
}
}
});
As you can see in the ReadCookie function I have it alerting the ID's that are hidden, though this doesn't work either yet. I am brand new to Cookies and just having a hard time getting this to work correctly.
Here are the functions for the cookies...
function SetCookie(cookieName,cookieValue,nDays) {
var today = new Date();
var expire = new Date();
if (nDays==null || nDays==0) nDays=1;
expire.setTime(today.getTime() + 3600000*24*nDays);
document.cookie = cookieName+"="+escape(cookieValue)
+ ";expires="+expire.toGMTString(),';path = /';
}
function KillCookie(cookieName) {
SetCookie(cookieName,"", - 1);
}
function ReadCookie(cookieName) {
var theCookie=""+document.cookie;
var ind=theCookie.indexOf(cookieName+"=");
if (ind==-1 || cookieName=="") return "";
var ind1=theCookie.indexOf(";",ind);
if (ind1==-1) ind1=theCookie.length;
return unescape(theCookie.substring(ind+cookieName.length+1,ind1));
}
If anyone sees any other way to do this that is fine, just need to get the specific ID's to make sure they stay hidden when clicked and changing pages.
Have you tried the jQuery Cookie plugin?
https://github.com/carhartl/jquery-cookie
Then create expiring cookie, valid across entire site:
$.cookie('the_cookie', 'the_value', { expires: 7, path: '/' });
Then to read the cookie:
$.cookie('the_cookie'); // => "the_value"
I'm trying to write this tool, to animate a game map from a range of dates. The flow is like this:
1st: choose game world
2nd: set map display parameters (date range, map type and animation speed)
3rd: the js code grab png file according to the dates and display them one by one according to the animation speed
The problem I'm having is this:
if you just click on one world, and click animate, everything is fine, the animation displays correctly. Then if you choose another world (without refreshing the page), the animation either flickers or somehow displaying image from other worlds. and I can't figure out what's causing this (I'm totally n00b at js)
$(function(){
$("#image_area").hide();
$("#tw_image").hide();
$('#W40').click(function(){
$("#tw_image").hide();
show_image_area('40');
});
$('#W42').click(function(){
$("#tw_image").hide();
show_image_area('42');
});
$('#W56').click(function(){
$("#tw_image").hide();
show_image_area('56');
});
});
function show_image_area(world){
$("#tw_image").hide();
if(world == "40" || world == "42" || world == "56"){
$("#map_notice").remove();
$("#image_area").prepend('<div id="map_notice">Map for W'+world+' available from <span id="date_highlight">April 7th 2011</span>, all previous dates invalid and will not have map available</div>');
}
$("#date_from").datepicker({ showAnim: 'blind' });
$("#date_to").datepicker({ showAnim: 'blind' });
$('#image_area').show();
$("#animate").click(function(){
$("#tw_image").hide();
var date_from = $("#date_from").val();
var date_to = $("#date_to").val();
if(!(date_from && date_to)){
alert("From and To dates required.")
return false;
}
var map_type = $("#map_type").val();
var speed = $("#speed").val();
var days = daydiff(parseDate(date_from), parseDate(date_to));
var date_one = new Date(Date.parse(date_from));
var b = date_one.toISOString().split("T")[0].split("-");
var c = get_map_type(map_type) + b[0] + b[1] + b[2];
var width = get_map_type_width(map_type);
var img_load = "" + world + "/" + c + ".png";
$('#image_area').load(img_load, function(){
$("#tw_image").attr("width", width);
$("#tw_image").attr("src", img_load);
$("#tw_image").show();
$("#debug").html("world = "+world);
});
var i = 0;
var interval = setInterval(
function(){
date_one.setDate(date_one.getDate() + 1);
b = date_one.toISOString().split("T")[0].split("-");
c = get_map_type(map_type) + b[0] + b[1] + b[2];
var src_one = "" + world + "/"+c+".png";
var img = new Image();
img.src = src_one;
img.onload = function(){
$("#tw_image").attr("src", img.src);
$("#debug").html("world = "+world);
}
i++;
if(i >= days) clearInterval(interval);
},speed);
});
}
function get_map_type(map_type){
if(map_type == "topk"){
return "topktribes";
}
if(map_type == "toptribe"){
return "toptribes";
}
if(map_type == "topnoble"){
return "topnoblers";
}
}
function get_map_type_width(map_type){
if(map_type == "topk"){
return 1000;
}
if(map_type == "toptribe"){
return 1300;
}
if(map_type == "topnoble"){
return 1300;
}
}
function parseDate(str) {
var mdy = str.split('/');
return new Date(mdy[2], mdy[0]-1, mdy[1]);
}
function daydiff(first, second) {
return (second-first)/(1000*60*60*24)
}
Ok I think I have a solution here although its not what I thought it was going to be. Basically every time you are calling image_area_world you are creating a new click handler on the animate button. Due to the way JavaScript scope works the World variable is kept the same for that click handler at the point of creation.
Anyway to solve this problem what you can try is this just before you define your click handler.
$("#animate").unbind("click");
$("#animate").click(function () { *code* }
A couple of tools to help you out.
Visual Event
Firebug
Also a bit explaining how JavaScript Scope and Closures work
I have hacked this tab system together.
I need to reduce the spacing(padding) between each tab. When viewed in firebug, you can see the javascript function is adding various left pixels between each, but instead of random padding-left pixels I need padding-left: 100px between each tab. Any idea how I can do that?
Below is the javascript.
<script type="text/javascript">
var menuAlignment = 'left'; // Align menu to the left or right?
var topMenuSpacer = 0; // Horizontal space(pixels) between the main menu items
var activateSubOnClick = false; // if true-> Show sub menu items on click, if false, show submenu items onmouseover
var leftAlignSubItems = true; // left align sub items t
var activeMenuItem = false; // Don't change this option. It should initially be false
var activeTabIndex = 0; // Index of initial active tab (0 = first tab) - If the value below is set to true, it will override this one.
var rememberActiveTabByCookie = true; // Set it to true if you want to be able to save active tab as cookie
var MSIE = navigator.userAgent.indexOf('MSIE')>=0?true:false;
var Opera = navigator.userAgent.indexOf('Opera')>=0?true:false;
var navigatorVersion = navigator.appVersion.replace(/.*?MSIE ([0-9]\.[0-9]).*/g,'$1')/1;
/*
These cookie functions are downloaded from
http://www.mach5.com/support/analyzer/manual/html/General/CookiesJavaScript.htm
*/
function Get_Cookie(name) {
var start = document.cookie.indexOf(name+"=");
var len = start+name.length+1;
if ((!start) && (name != document.cookie.substring(0,name.length))) return null;
if (start == -1) return null;
var end = document.cookie.indexOf(";",len);
if (end == -1) end = document.cookie.length;
return unescape(document.cookie.substring(len,end));
}
// This function has been slightly modified
function Set_Cookie(name,value,expires,path,domain,secure) {
expires = expires * 60*60*24*1000;
var today = new Date();
var expires_date = new Date( today.getTime() + (expires) );
var cookieString = name + "=" +escape(value) +
( (expires) ? ";expires=" + expires_date.toGMTString() : "") +
( (path) ? ";path=" + path : "") +
( (domain) ? ";domain=" + domain : "") +
( (secure) ? ";secure" : "");
document.cookie = cookieString;
}
function showHide()
{
if(activeMenuItem){
activeMenuItem.className = 'inactiveMenuItem';
var theId = activeMenuItem.id.replace(/[^0-9]/g,'');
document.getElementById('submenu_'+theId).style.display='none';
var img = activeMenuItem.getElementsByTagName('IMG');
if(img.length>0)img[0].style.display='none';
}
var img = this.getElementsByTagName('IMG');
if(img.length>0)img[0].style.display='inline';
activeMenuItem = this;
this.className = 'activeMenuItem';
var theId = this.id.replace(/[^0-9]/g,'');
document.getElementById('submenu_'+theId).style.display='block';
if(rememberActiveTabByCookie){
Set_Cookie('dhtmlgoodies_tab_menu_tabIndex','index: ' + (theId-1),100);
}
}
function initMenu()
{
var mainMenuObj = document.getElementById('mainMenu');
var menuItems = mainMenuObj.getElementsByTagName('A');
if(document.all){
mainMenuObj.style.visibility = 'hidden';
document.getElementById('submenu').style.visibility='hidden';
}
if(rememberActiveTabByCookie){
var cookieValue = Get_Cookie('dhtmlgoodies_tab_menu_tabIndex') + '';
cookieValue = cookieValue.replace(/[^0-9]/g,'');
if(cookieValue.length>0 && cookieValue<menuItems.length){
activeTabIndex = cookieValue/1;
}
}
var currentLeftPos = 1;
for(var no=0;no<menuItems.length;no++){
if(activateSubOnClick)menuItems[no].onclick = showHide; else menuItems[no].onmouseover = showHide;
menuItems[no].id = 'mainMenuItem' + (no+1);
if(menuAlignment=='left')
menuItems[no].style.left = currentLeftPos + 'px';
else
menuItems[no].style.right = currentLeftPos + 'px';
currentLeftPos = currentLeftPos + menuItems[no].offsetWidth + topMenuSpacer;
var img = menuItems[no].getElementsByTagName('IMG');
if(img.length>0){
img[0].style.display='none';
if(MSIE && !Opera && navigatorVersion<7){
img[0].style.bottom = '-1px';
img[0].style.right = '-1px';
}
}
if(no==activeTabIndex){
menuItems[no].className='activeMenuItem';
activeMenuItem = menuItems[no];
var img = activeMenuItem.getElementsByTagName('IMG');
if(img.length>0)img[0].style.display='inline';
}else menuItems[no].className='inactiveMenuItem';
if(!document.all)menuItems[no].style.bottom = '-1px';
if(MSIE && navigatorVersion < 6)menuItems[no].style.bottom = '-2px';
}
var mainMenuLinks = mainMenuObj.getElementsByTagName('A');
var subCounter = 1;
var parentWidth = mainMenuObj.offsetWidth;
while(document.getElementById('submenu_' + subCounter)){
var subItem = document.getElementById('submenu_' + subCounter);
if(leftAlignSubItems){
// No action
}else{
var leftPos = mainMenuLinks[subCounter-1].offsetLeft;
document.getElementById('submenu_'+subCounter).style.paddingLeft = LeftPos + 'px';
subItem.style.position ='absolute';
if(subItem.offsetWidth > parentWidth){
leftPos = leftPos - Math.max(0,subItem.offsetWidth-parentWidth);
}
subItem.style.paddingLeft = leftPos + 'px';
subItem.style.position ='static';
}
if(subCounter==(activeTabIndex+1)){
subItem.style.display='block';
}else{
subItem.style.display='none';
}
subCounter++;
}
if(document.all){
mainMenuObj.style.visibility = 'visible';
document.getElementById('submenu').style.visibility='visible';
}
document.getElementById('submenu').style.display='block';
}
window.onload = initMenu;
</script>
I don't want to put down your effort, but your solution looks very complicated, feels slow on a 3Ghz dual-core workstation, throws a lot of Javascript errors and, as your question illustrates, makes customization very difficult. I'm not sure this is the way to go - I find it hard to dig into the script to even find the place to make the change you want to make.
Why not, for example, use something pre-built and small like the old but mostly reliable framework-agnostic DOMTab?
There is a great number of tab scripts based on the popular frameworks as well, see e.g. here.