Fortis Demo
');
\n';
this.cursor += mw;
if(i != (this.submenus.length - 1))
{
var sepw = this.separator.getFMSLen();
html += '\n this.bgcolor + '; color: ' + this.fgcolor + '; padding 3px; width:' + sepw + 'pt; left:' + this.cursor + 'pt">\n' +
this.separator + '
\n';
this.cursor += sepw;
}
if(this.submenus[i].closestr) thecloser += this.submenus[i].closestr;
}
var disable = "function window.FMS_disable(menu, entry)\n{\n\tvar sid = window.FMS_menuIds[menu] + '_' + (entry - 1); \n\tif(eval('document.all.' + sid))\n\t{\n\t\teval('window.FMS_disabledMenus[\\'' + sid + '\\'] = 1');\n\t\teval('document.all.' + sid + '.style.color = \\'' + window.FMS_menuColsD[menu] + '\\';');\n\t}\n}\n\n";
var enable = "function window.FMS_enable(menu, entry)\n{\n\tvar sid = window.FMS_menuIds[menu] + '_' + (entry - 1); \n\tif(eval('document.all.' + sid))\n\t{\n\t\teval('window.FMS_disabledMenus[\\'' + sid + '\\'] = 0');\n\t\teval('document.all.' + sid + '.style.color = \\'' + window.FMS_menuColsE[menu] + '\\';');\n\t}\n}\n\n";
var close = "\nfunction window.FMS_closeMenus()\n{\n\twindow.FMS_lockedMenus = new Array();\n\tfor(m in window.FMS_closerArray)\n\t\teval(window.FMS_closerArray[m]);\n}\n";
var globals = "if(!window.FMS_disabledMenus)\n\twindow.FMS_disabledMenus = new Array();\n\nif(!window.FMS_menuIds)\n\twindow.FMS_menuIds = new Array();\n\nif(!window.FMS_menuColsD)\n\twindow.FMS_menuColsD = new Array();\n\nif(!window.FMS_menuColsE)\n\twindow.FMS_menuColsE = new Array();\n\nif(!window.FMS_closerArray)\n\twindow.FMS_closerArray = new Array();\n\nwindow.FMS_lockedMenus = new Array();\n" + close + enable + disable;
var closeme = "\nwindow.FMS_closerArray['" +
this.id + "'] =\n'" + thecloser + "';";
eval(closeme); // For compatibility with dynamic environments
var prehtml = ' '--> \n<'+'SCRIPT>\n' + globals + closeme + '\n<'+'/SCRIPT>\n';
prehtml += '\n '" STYLE="' + this.style + ' width: ' + this.width + 'px;">\n';
return prehtml + html + '\n';
}
// END OF FMS_Menu
/* -- FMS_SubMenu --
Use this constructor to generate submenus at any level under the main menu.
SubMenus can be nested, just like in normal windowing systems.
Parameters (all optional):
title: the HTML to display in the menu. If you do not supply a plain string,
make sure you specify a width value for nicer output.
Default: the object id.
width: the width (in points) of the item in the menu bar. It does not apply
for submenus of lower levels, where the innerWidth of the parent menu
is used instead.
Default: an automatically calculated value based on an average font and size
calculated by analazing the characters in the string. This includes any tag,
so make sure you specify the width for strange fonts or titles.
innerWidth: the width (in points) of the collapsable submenu that opens on mouseover.
Default: an automatically calculated value based on an average font and size
calculated by analazing the characters in the title of the longest title string
of the elements of the submenus. This includes any tag, so make sure you specify
your value for strange fonts or entry titles.
ownFont: the font face name (or list thereof) of this submenu. You can specify a
list of fonts that are tried in order like in HTML or CSS.
Default: the normal menu font
caption: a message that appears when the mouse stays on the submenu title for a couple
of seconds. Useful for giving explanations or instructions. This is implemented
with the TITLE property in HTML and therefore handled by the browser (it's like
an ALT property for an IMG tag).
Default: no caption.
Properties for public use: none.
Methods:
add: use it to add an entry to the submenu.
addSub: use it to nest submenus.
addHTML: use it to add an HTML component that resides in its own submenu and
stays locked open on mouseover until you call FSM_CloseMenus();
toString: called automatically when evaluating the object itself as a string.
It's used bu FMS_Menu.toString and it's not useful when called manually.
*/
function FMS_SubMenu(title, width, innerWidth, ownFont, caption)
{
this.id = 'FMS_' + window.FMS_menuCount++;
this.title = title?title:this.id;
this.width = width;
this.innerWidth = innerWidth;
this.ownFont = ownFont;
this.caption = caption?caption:'';
this.action = ';';
this.SubItem = function(name, content, isSub, icon, elh, caption, isHtml)
{
this.name = name;
this.content = content;
this.isSub = isSub;
this.icon = icon;
this.elh = elh;
this.caption = caption?caption:'';
this.isHtml = isHtml;
}
this.items = new Array();
this.sub = new Array();
this.subchain = new Array();
}
/* - FMS_SubMenu.add
Adds an entry to the submenu.
Parameters (all optional):
title: the HTML to display in the menu. If you do not supply a plain string,
make sure you specify a width value for nicer output. If you specify
'DIVIDER', or nothing at all, as the name, you will get a menu divider.
Default: 'DIVIDER';
action: the JavaScript to execute when the item is clicked.
Default: ';' (no action, useful for self-behaving elements like links).
icon: the icon to place to the left of the entry. Its size is automatically
calculated making the image a square with the side equal to the
entry's height. The paramenters contains the URL of the image. All
the other elements are indented to the size of the largest
icon. If you specify the character '*' the icon is not placed, the
space to the left zeroed, and the item does not highlight or respond to
clicks. Useful if you want to place some raw HTML in the menu. Check also
the addHTML method to see which one fits your needs.
Default: no icon.
elh: overrides the automatic size mesurment and allows you to set an arbitraty
item hight (and consequently icon size and indentation). In conjunction
with the '*' icon and the innerWidth property, allows you to reserve an
arbitrary space for any HTML you want to display.
Default: normal item height,
caption: a message that appears when the mouse stays on the element for a couple
of seconds. Useful for giving explanations or instructions. This is implemented
with the TITLE property in HTML and therefore handled by the browser (it's like
an ALT property for an IMG tag).
Default: no caption
*/
function FMS_SubMenu.prototype.add(name, action, icon, elh, caption)
{
var pos = this.items.length;
name = name?name:'DIVIDER';
action = action?action:';';
this.items[pos] = new this.SubItem(name, action, 0, icon, elh, caption);
}
/* - FMS_SubMenu.addSub
Adds a submenu to the submenu.
Parameters:
sub: reference to an FMS_SubMenu object.
icon: the icon to place to the left of the entry. Its size is automatically
calculated making the image a square with the side equal to the
entry's height. All the other elements are indented to the size of the largest
icon. The paramenters contains the URL of the image.
Default: no icon.
elh: overrides the automatic size mesurment and allows you to set an arbitraty
item hight (and consequently icon size and indentation).
Default: normal item height,
*/
function FMS_SubMenu.prototype.addSub(sub, icon, elh)
{
var pos = this.items.length;
this.items[pos] = new this.SubItem(sub.title, sub, 1, icon, elh);
this.sub[sub.title] = sub;
}
/* - FMS_SubMenu.addHTML
Adds an HTML component that opens like a submenu of the submenu.
This submenu has the special property that once the user goes over
it with the mouse, it stays open togheter with the whole menu
structure that preceded it until the function FMS_closeMenus() is called.
This allows to use forms and other interactive components. If you do
not desire this behavior, use a normal submenu entry with a '*' icon
instead.
WARNING: One side-effect of the submenu behavior is that, while other
submenus (from the root) work normally, the submenus from the same root
that are open while the menu is locked, stay open as well. If this really
bothers you, you can disable such entries and then enable then back later.
Such submenus always stay behind the HTML menus to avoid input problems.
Parameters (all optional):
name: the HTML to display as the title of the submenu that contains the HTML.
Default: the id of the submenu created to allocate the HTML
html: the HTML to render.
Default: no HTML;
width: the width in points of the submenu that contains the HTML.
Default: a width equal to the normal item height.
height: the height in points of the submenu that contains the HTML.
Default: the heigth of a normal menu entry.
icon: the icon to place to the left of the entry. Its size is automatically
calculated making the image a square with the side equal to the
entry's height. The paramenters contains the URL of the image. All
the other elements are indented to the size of the largest icon.
The paramenters contains the URL of the image.
Default: no icon.
elh: overrides the automatic size mesurment and allows you to set an arbitraty
item hight (and consequently icon size and indentation).
Default: normal item height,
caption: a message that appears when the mouse stays on the element for a couple
of seconds. Useful for giving explanations or instructions. This is implemented
with the TITLE property in HTML and therefore handled by the browser (it's like
an ALT property for an IMG tag).
Default: no caption
*/
function FMS_SubMenu.prototype.addHTML(name, html, width, height, icon, elh, caption)
{
var pos = this.items.length;
html = html?html:'';
width = width?width:1;
var thesub = new FMS_SubMenu(name, 0, width, '', caption);
thesub.add(html, '', '*', height);
this.items[pos] = new this.SubItem(thesub.title, thesub, 0, icon, elh, '', 1);
}
//- FMS_SubMenu.toString
// Returns the submenu HTML. It's supposed to be called by FMS_Menu.toString.
//
// Parameters: none
function FMS_SubMenu.prototype.toString()
{
var selfref = 'document.all.' + this.id;
this.cursor = 0;
var elh = this.fontSize * 1.4;
var closeparents = 'FMS_closeMenus();';
this.closestr = "document.all." +
this.id +
".style.visibility = \\'hidden\\'; ";
if(!this.innerWidth)
{
var maxlen = 0;
for(var i = 0; i < this.items.length; i++)
maxlen = Math.max(maxlen, (this.items[i].name.getFMSLen()));
maxlen += elh;
}
else
var maxlen = this.innerWidth
if(!this.menuH)
var mh = (this.fontSize * 1.4);
else
var mh = (this.fontSize * 1.4) - this.menuH;
maxlen += 6;
var indent = elh;
var menuh = 6;
for(var i = 0; i < this.items.length; i++)
{
if(this.items[i].elh)
if(this.items[i].icon != '*')
indent = Math.max(this.items[i].elh, indent);
if(this.items[i].name == 'DIVIDER')
menuh += elh / 2;
else
menuh += elh;
if(this.items[i].elh)
menuh += this.items[i].elh - elh;
}
maxlen += indent;
// For compatibility with dynamic environments
window.FMS_menuIds[this.title] = this.id;
window.FMS_menuColsE[this.title] = this.fgcolor;
window.FMS_menuColsD[this.title] = this.disColor;
var disreg = "window.FMS_menuIds['" + this.title + "'] = '" + this.id +
"'; window.FMS_menuColsE['" + this.title + "'] = '" + this.fgcolor +
"'; window.FMS_menuColsD['" + this.title + "'] = '" + this.disColor +
"'; ";
var html = '\n<'+'SCRIPT>\n'+disreg+'\n\n\n '" STYLE="position: absolute; overflow:visible; visibility:hidden; background-color: ' +
this.bgcolor + '; color: ' + this.fgcolor + '; height:' +
menuh + 'pt; width:' + maxlen + 'pt; top:' +
+ mh + 'pt; left: 2px; border: 1px ' + this.bgcolor + ' outset">\n';
this.cursor = 2;
maxlen -= 2;
for(var i = 0; i < this.items.length; i++)
{
var elh = this.fontSize * 1.4;
var item = this.items[i].name;
var sid = this.id + '_' + i;
var hilite = "style.backgroundColor = '" +
this.fgcolor + "'; if(!window.FMS_disabledMenus['" +
sid + "']) style.color = '" +
this.bgcolor + "';";
var normal = "style.backgroundColor = '" +
this.bgcolor + "'; if(!window.FMS_disabledMenus['" +
sid + "']) style.color = '" +
this.fgcolor + "'; else style.color = '" + this.disColor + "';";
if(this.items[i].elh)
elh = this.items[i].elh;
var themiddle = elh/2 - (this.fontSize*1.4)/2;
var arrow = '\n 'pt; top:' + themiddle + 'pt; width:' + 30 + 'pt; text-indent:' +
indent + 'pt; left:'+ (maxlen - indent - 14) + 'pt">\n' + this.subind + '\n';
if(this.items[i].icon)
{
if(this.items[i].icon == '*')
{
var icon = '';
themiddle = 0;
hilite = '';
normal = '';
closeparents = '';
}
else
{
var icon = '\n 'pt; top:1pt; width:' + elh + 'pt; text-indent:0pt; left:1pt">' +
'\n' +
'\n';
}
}
else
var icon = '';
var entry = '\n 'pt; top:' + themiddle + 'pt; width:' + maxlen + 'pt; text-indent:' +
indent + 'pt; left:1pt">\n' + item + '\n';
if(item == 'DIVIDER')
{
var bdrcolor = this.disColor;
html += '\n this.bgcolor + '; color: ' + this.fgcolor + '; height:2px; top:' +
(this.cursor + elh/4) + 'pt; border-top-style: inset; height:' +
elh/2 + 'pt; border-top-width: 2px; border-top-color: ' +
bdrcolor + '; width:' + (maxlen - 4) + 'pt; text-indent:0px; left:2pt">\n';
this.cursor += elh/2;
}
else if(this.items[i].isSub)
{
this.idx = i;
var subref = 'document.all.' + this.items[i].content.id;
var open = "if(!window.FMS_disabledMenus['" + sid + "'] && !window.FMS_menuLock) {" +
subref + ".style.visibility = 'visible';" +
subref + ".style.left = '" + (maxlen-1) + "pt';" +
subref + ".style.pixelTop = 0;}";
var close = "if(!window.FMS_lockedMenus['" + this.rootId + "']) " + subref + ".style.visibility = 'hidden';";
this.items[i].content.bgcolor = this.bgcolor;
this.items[i].content.fgcolor = this.fgcolor;
this.items[i].content.parentMenu = this;
this.items[i].content.font = this.font;
this.items[i].content.fontSize = this.fontSize;
this.items[i].content.subind = this.subind;
this.items[i].content.disColor = this.disColor;
this.items[i].content.rootId = this.rootId;
html += '\n '"; onmouseover="' + hilite + open +
'" onmouseout="' + normal + close +
'" STYLE="position: absolute; overflow:visible; height:' + elh + 'pt; top:' +
this.cursor + 'pt; z-index: 0; width:' + maxlen + 'pt; text-indent:' + indent + 'pt; left:0pt">\n' +
icon + entry + arrow + this.items[i].content + '\n' ;
this.cursor += elh;
if(this.items[i].content.closestr) this.closestr += this.items[i].content.closestr;
}
else if(this.items[i].isHtml)
{
this.idx = i;
var subref = 'document.all.' + this.items[i].content.id;
var open = "if(!window.FMS_disabledMenus['" + sid + "'] && !window.FMS_menuLock) {" +
subref + ".style.visibility = 'visible';" +
subref + ".style.left = '" + (maxlen-1) + "pt';" +
subref + ".style.pixelTop = 0;}";
var close = "if(!window.FMS_lockedMenus['" + this.rootId + "']) " + subref + ".style.visibility = 'hidden';";
this.items[i].content.bgcolor = this.bgcolor;
this.items[i].content.fgcolor = this.fgcolor;
this.items[i].content.parentMenu = this;
this.items[i].content.font = this.font;
this.items[i].content.fontSize = this.fontSize;
this.items[i].content.isHtml = true;
this.items[i].content.rootId = this.rootId;
html += '\n '"; onmouseover="' + hilite + open +
'" onmouseout="' + normal + close +
'" STYLE="position: absolute; overflow:visible; height:' + elh + 'pt; top:' +
this.cursor + 'pt; z-index: 1; width:' + maxlen + 'pt; text-indent:' + indent + 'pt; left:0pt">\n' +
icon + entry + arrow + this.items[i].content + '\n' ;
this.cursor += elh;
if(this.items[i].content.closestr) this.closestr += this.items[i].content.closestr;
}
else
{
if(!this.isHtml)
{
var actioner = "if(!window.FMS_disabledMenus['" + sid + "'] && !window.FMS_menuLock) " +
this.items[i].content;
html += '\n '" onclick="' + normal + closeparents + actioner +
'"; onmouseover="' + hilite +
'" onmouseout="' + normal +
'" STYLE="position: absolute; height:' + elh + 'pt; top:' +
this.cursor + 'pt; width:' + maxlen + 'pt; text-indent:' + indent + 'pt; left:0pt">\n' +
icon + entry + '\n';
this.cursor += elh;
}
else
{
var lock = "window.FMS_lockedMenus['" + this.rootId + "'] = 1;";
html += '\n '"; onmouseover="' + lock +
'" STYLE="position: absolute; height:' + elh + 'pt; top:' +
this.cursor + 'pt; width:' + maxlen + 'pt; text-indent:' + indent + 'pt; left:0pt">\n' +
icon + entry + '\n';
this.cursor += elh;
}
}
}
return html += '\n';
}
// END OF FMS_SubMenu
/* -- FMS_MenuEntry --
Use this constructor to generate menu entries that reside on the menu bar, and
not in a submenu, but can be clicked to generate behavior instead of opening
a submenu. It's essentially a FMS_SubMenu with no content an action property,
so it cannot be disabled.
Parameters (all optional):
title: the HTML to display in the menu. If you do not supply a plain string,
make sure you specify a width value for nicer output.
Default: the object id.
action: the JavaScript to execute when the item is clicked.
Default: ';' (no action, useful for self-behaving elements).
width: the width (in points) of the item in the menu bar.
Default: an automatically calculated value based on an average font and size
calculated by analazing the characters in the string. This includes any tag,
so make sure you specify the width for strange fonts or titles.
ownFont: the font face name (or list thereof) this entry. You can specify a
list of fonts that are tried in order like in HTML or CSS.
Default: the normal menu font
caption: a message that appears when the mouse stays on the element for a couple
of seconds. Useful for giving explanations or instructions. This is implemented
with the TITLE property in HTML and therefore handled by the browser (it's like
an ALT property for an IMG tag).
Default: no caption.
Properties for public use: none.
Methods:
toString: called automatically when evaluating the object itself as a string.
It's used bu FMS_Menu.toString and it's not useful when called manually.
*/
function FMS_MenuEntry(title, action, width, ownFont, caption)
{
this.id = 'FMS_' + window.FMS_menuCount++;
this.title = title?title:this.id;
this.action = action?('if(!FMS_menuLock) {' + action + '}'):';';
this.width = width;
this.ownFont = ownFont;
this.caption = caption?caption:'';
}
//- FMS_MenuEntry.toString
// Returns the submenu HTML. It's supposed to be called by FMS_Menu.toString
//
// Parameters: none
function FMS_MenuEntry.prototype.toString()
{
var html = ' '" STYLE="position: absolute; height:0px; width:0px;">';
return html;
}
// END OF FMS_MenuEntry
// -- String.prototype.getFMSLen --
// This function is used to estimate the length of a string as it's
// displayed with a variable width font. It's quite crude, since it
// does not not take into consideration font family or size, but it works
// well enough on normal fonts size 9 to 12 points. You can specify
// every width you need, so you don't even have to use it if you don't want
// to (except for the width of the separator). You can easily modify 'amt'
// for a higher or lower staring value, and 'r' to change the multiplication
// factor and make it work for smaller or larger fonts, or provide your own,
// improved, version. The result is interpreted in points.
function String.prototype.getFMSLen()
{
var amt = 0;
var r = 1;
for(var i = 0; i < this.length; i++)
{
switch(this.charAt(i))
{
case ' ' : amt += 2*r;
case 'i' :
case 'l' : amt += 4*r;
break;
case 'j' :
case 'f' :
case '.' :
case ',' : amt += 5*r;
break;
case '|' :
case 'I' :
case 'J' : amt += 6*r;
break;
case 'c' :
case 'k' :
case 'r' :
case 's' :
case 't' :
case 'v' :
case 'x' :
case 'y' :
case 'z' : amt += 8*r;
break;
case 'A' :
case 'D' :
case 'G' :
case 'H' :
case 'N' :
case 'U' :
case 'V' : amt += 10*r;
break;
case 'M' :
case 'O' :
case 'Q' : amt += 11*r;
break;
case 'm' :
case 'w' : amt += 12*r;
break;
case 'W' :
case '@' : amt += 14*r;
break;
default : amt += 9*r;
}
}
return amt;
}
//EOF: fms.js