...

View Full Version : OO Menu, First Function Never Entered



Jesdisciple
08-17-2007, 08:05 PM
menus.html

<html>
<head>
<title>Untitled Document</title>
<script type="text/javascript" src="menus.js"></script>
</head>
<body onLoad="new MenuBar(this, false).setVisible(true);">

</body>
</html>

menus.js

// JavaScript Document

var menuBarCount = 0;
var menuBars[] = new Array();

//begin class MenuItem
function MenuItem(label, url, target){
this.type = 'MenuItem';
label = label.replace(/ /, '&nbsp;');
this.text = '<a href="' + url + '" target="' + target + '">' + label + '</a>';
}
//end class MenuItem

//begin class Menu
function Menu(label, url, target){
this.type = 'Menu';
this.label = label.replace(/ /, '&nbsp;');
this.url = url;
this.target = target;
this.items = new Array();
this.length = 0;
this.width = null;
this.isVisible = false;
this.hasShown = false;
this.table = document.createElement('table');
this.table.style.visibility = 'hidden';
this.table.style.position = 'absolute';
}
Menu.prototype = MenuItem;
function Menu.prototype.add(menuItem){
if(!menuItem || !menuItem.type || (menuItem.type != 'MenuItem' && menuItem.type != 'Menu'))
throw 'A non-null MenuItem or Menu must be supplied for addition to any Menu.';
menuItem.index = this.length++;
menuItem.id = this.id + '.items[' + menuItem.index + ']';
menuItem.text = '<a href="' + menuItem.url + '" target="' + menuItem.target + '" onMouseover="cancel(event); ' + menuItem.id +
'.setVisible(true)" onMouseout="cancel(event); ' + menuItem.id + '.setVisible(false)">' + menuItem.label +
'&nbsp;<img src="pointer.gif" border="0"></a>';
this.items[menuItem.index] = menuItem;
this.table.insertRow(index);
this.table.rows[index].insertCell(0);
this.table.rows[index].cells[0].innerHTML = menuItem.text;
}
function Menu.prototype.setVisible(boolean){
this.isVisible = boolean;
if(this.isVisible){
this.table.style.visibility = 'visible';
if(!this.hasShown){
this.hasShown = true;
this.handle = findPos(this.parent.table.cells[this.index]);
this.handle[0] += this.parent.width;

this.table.style.left = this.handle[0];
this.table.style.top = this.handle[1];

this.width = this.table.width;
alert(this.width);
}
}else this.table.style.visibility = 'hidden';
}
//end class Menu

//begin class MenuBar
function MenuBar(parent, isHorizontal){
alert(0);
this.type = 'MenuBar';
this.index = menuBarCount++;
menuBars[this.index] = this;
this.id = 'menuBars[' + this.index + ']';
if(!parent) throw 'The first argument of the MenuBar constructor, "parent", must be non-null.';
this.menus = new Array();
this.length = 0;
this.parent = parent;
this.isHorizontal = isHorizontal;
this.table = document.createElement('table');
if(isHorizontal) this.table.insertRow(0);
this.width = null;
}
function MenuBar.prototype.add(menu){
if(!menu || !menu.type || menu.type != 'Menu') throw 'A non-null Menu must be supplied for addition to any MenuBar.';
menu.index = this.length++;
this.menus[menu.index] = menu;
menu.parent = this;
menu.id = this.id + '.menus[' + menu.index + ']';
menu.text = '<a href="' + menu.url + '" target="' + menu.target + '" onMouseover="cancel(event); ' + menu.id +
'.setVisible(true)" onMouseout="cancel(event); ' + menu.id + '.setVisible(false)">' + menu.label +
'&nbsp;<img src="pointer.gif" border="0"></a>';
if(this.isHorizontal){
this.table.rows[0].insertCell(menu.index);
this.table.rows[0].cells[menu.index].innerHTML = menu.text;
}else{
this.table.insertRow(menu.index);
this.table.rows[menu.index].insertCell(0);
this.table.rows[menu.index].cells[0].innerHTML = menu.text;
}
}
function MenuBar.prototype.remove(index){
if(index < 0 || index >= this.length) throw 'To remove a Menu from this MenuBar, you must supply an index > -1 and < ' +
this.length + '.';
for(var i = index; i < this.length; i++) this.menus[i] = this.menus[i + 1];
}
function MenuBar.prototype.setVisible(boolean){
this.isVisible = boolean;
if(this.isVisible){
this.table.style.visibility = 'visible';
this.parent.appendChild(this.table);

this.width = this.table.width;
alert(this.width);
}else this.table.style.visibility = 'hidden';
}
//end class MenuBar

function cancel(evnt){
if(window.event) event.cancelBubble = true;
else if(evnt.stopPropagation) evnt.stopPropagation();
}

function findPos(obj) {
var left = 0;
var top = 0;
if (obj.offsetParent) {
left = obj.offsetLeft
top = obj.offsetTop
while (obj = obj.offsetParent) {
left += obj.offsetLeft
top += obj.offsetTop
}
}
return new Array(left, top);
}

JSLint's response

Error:

Problem at line 4 character 13: Missing semicolon.

var menuBars[] = new Array();

Problem at line 4 character 13: Expected '[' to have an indentation of 0 instead of 12.

var menuBars[] = new Array();

Problem at line 4 character 16: Bad assignment.

var menuBars[] = new Array();

Problem at line 4 character 16: Stopping, unable to continue. (2% scanned).

Opera's response

JavaScript - http://localhost/menus.html
Inline script compilation
Syntax error while loading: line 4 of linked script at http://localhost/menus.js :
var menuBars[] = new Array();
--------------^
JavaScript - http://localhost/menus.html
Event thread: load
Error:
name: ReferenceError
message: Statement on line 1: Reference to undefined variable: MenuBar
Backtrace:
Line 1 of script
new MenuBar(this, false).setVisible(true);
At unknown location
[statement source code not available]

I fail to understand JSLint's and Opera's errors. Firefox and IE6 give none. I know that the MenuBar constructor is never entered because I never receive an alert.

function MenuBar(parent, isHorizontal){
alert(0);

What have I not checked?

GJay
08-17-2007, 09:07 PM
the problem with both is this line:


var menuBars[] = new Array();

lose the []s and it should work, the aren't necessary to indicate an array- Opera won't know about your MenuBar function because it's failing to parse past the [] in the variable name

Jesdisciple
08-18-2007, 12:02 AM
It's odd that you should say that; that was the only change which I understood JSLint to demand. Without that, JSLint responds:


Error:

Implied global: add, document, menuItem

Problem at line 4 character 20: Use the array literal notation [].

var menuBars = new Array();

Problem at line 7 character 2: Expected 'function' to have an indentation of 0 instead of 1.

function MenuItem(label, url, target){

Problem at line 7 character 39: Missing space after ')'.

function MenuItem(label, url, target){

Problem at line 8 character 3: Expected 'this' to have an indentation of 4 instead of 2.

this.type = 'MenuItem';

Problem at line 9 character 3: Expected 'label' to have an indentation of 4 instead of 2.

label = label.replace(/ /, '&nbsp;');

Problem at line 10 character 3: Expected 'this' to have an indentation of 4 instead of 2.

this.text = '<a href="' + url + '" target="' + target + '">' + label + '</a>';

Problem at line 11 character 2: Expected '}' to have an indentation of 0 instead of 1.

}

Problem at line 15 character 2: Expected 'function' to have an indentation of 0 instead of 1.

function Menu(label, url, target){

Problem at line 15 character 35: Missing space after ')'.

function Menu(label, url, target){

Problem at line 16 character 3: Expected 'this' to have an indentation of 4 instead of 2.

this.type = 'Menu';

Problem at line 17 character 3: Expected 'this' to have an indentation of 4 instead of 2.

this.label = label.replace(/ /, '&nbsp;');

Problem at line 18 character 3: Expected 'this' to have an indentation of 4 instead of 2.

this.url = url;

Problem at line 19 character 3: Expected 'this' to have an indentation of 4 instead of 2.

this.target = target;

Problem at line 20 character 3: Expected 'this' to have an indentation of 4 instead of 2.

this.items = new Array();

Problem at line 20 character 20: Use the array literal notation [].

this.items = new Array();

Problem at line 21 character 3: Expected 'this' to have an indentation of 4 instead of 2.

this.length = 0;

Problem at line 22 character 3: Expected 'this' to have an indentation of 4 instead of 2.

this.width = null;

Problem at line 23 character 3: Expected 'this' to have an indentation of 4 instead of 2.

this.isVisible = false;

Problem at line 24 character 3: Expected 'this' to have an indentation of 4 instead of 2.

this.hasShown = false;

Problem at line 25 character 3: Expected 'this' to have an indentation of 4 instead of 2.

this.table = document.createElement('table');

Problem at line 26 character 4: Expected 'this' to have an indentation of 4 instead of 3.

this.table.style.visibility = 'hidden';

Problem at line 27 character 4: Expected 'this' to have an indentation of 4 instead of 3.

this.table.style.position = 'absolute';

Problem at line 28 character 2: Expected '}' to have an indentation of 0 instead of 1.

}

Problem at line 29 character 2: Expected 'Menu' to have an indentation of 0 instead of 1.

Menu.prototype = MenuItem;

Problem at line 30 character 2: Expected 'function' to have an indentation of 0 instead of 1.

function Menu.prototype.add(menuItem){

Problem at line 30 character 15: Expected '(' and instead saw '.'.

function Menu.prototype.add(menuItem){

Problem at line 30 character 25: Expected ')' to match '.' from line 30 and instead saw '.'.

function Menu.prototype.add(menuItem){

Problem at line 30 character 26: Missing space after '.'.

function Menu.prototype.add(menuItem){

Problem at line 30 character 26: Expected '{' and instead saw 'add'.

function Menu.prototype.add(menuItem){

Problem at line 30 character 39: Missing semicolon.

function Menu.prototype.add(menuItem){

Problem at line 30 character 39: Expected '{' to have an indentation of 0 instead of 38.

function Menu.prototype.add(menuItem){

Problem at line 31 character 3: Expected to see a statement and instead saw a block.

if(!menuItem || !menuItem.type || (menuItem.type != 'MenuItem' && menuItem....

Problem at line 31 character 3: Stopping, unable to continue. (23% scanned).

GJay
08-18-2007, 01:01 AM
array literal notation would be:


var menuBars = [];

Jesdisciple
08-18-2007, 02:54 AM
Ah! After I complied with all of JSLint's demands (except one: that I not assign in a while-loop header), it alerts in Firefox and IE6, but not Opera. Does Opera not do alerts?

EDIT: Opera now alerts as well. Thanks!

EDIT: The alert was coming from <body onload="alert(0)">. The first function is still never entered.


// JavaScript Document

var menuBarCount = 0;
var menuBars = [];

//begin class MenuItem
function MenuItem(label, url, target) {
this.type = 'MenuItem';
label = label.replace(/ /, '&nbsp;');
this.text = '<a href="' + url + '" target="' + target + '">' + label + '</a>';
}
//end class MenuItem

//begin class Menu
function Menu(label, url, target) {
this.type = 'Menu';
this.label = label.replace(/ /, '&nbsp;');
this.url = url;
this.target = target;
this.items = [];
this.length = 0;
this.width = null;
this.isVisible = false;
this.hasShown = false;
this.table = document.createElement('table');
this.table.style.visibility = 'hidden';
this.table.style.position = 'absolute';
}
Menu.prototype = MenuItem;
Menu.prototype.add = function (menuItem) {
if (!menuItem || !menuItem.type || (menuItem.type != 'MenuItem' && menuItem.type != 'Menu')) {
throw 'A non-null MenuItem or Menu must be supplied for addition to any Menu.';
}
menuItem.index = this.length++;
menuItem.id = this.id + '.items[' + menuItem.index + ']';
menuItem.text = '<a href="' + menuItem.url + '" target="' + menuItem.target + '" onMouseover="cancel(event); ' + menuItem.id +
'.setVisible(true)" onMouseout="cancel(event); ' + menuItem.id + '.setVisible(false)">' + menuItem.label +
'&nbsp;<img src="pointer.gif" border="0"></a>';
this.items[menuItem.index] = menuItem;
this.table.insertRow(index);
this.table.rows[index].insertCell(0);
this.table.rows[index].cells[0].innerHTML = menuItem.text;
alert(menuBars[0]);
};
Menu.prototype.setVisible = function (bool) {
this.isVisible = bool;
if (this.isVisible) {
this.table.style.visibility = 'visible';
if (!this.hasShown) {
this.hasShown = true;
this.handle = findPos(this.parent.table.cells[this.index]);
this.handle[0] += this.parent.width;

this.table.style.left = this.handle[0];
this.table.style.top = this.handle[1];

this.width = this.table.width;
alert(this.width);
}
} else {
this.table.style.visibility = 'hidden';
}
};
//end class Menu

//begin class MenuBar
function MenuBar(parent, isHorizontal) {
alert(0);
this.type = 'MenuBar';
this.index = menuBarCount++;
menuBars[this.index] = this;
this.id = 'menuBars[' + this.index + ']';
if (!parent) {
throw 'The first argument of the MenuBar constructor, "parent", must be non-null.';
}
this.menus = [];
this.length = 0;
this.parent = parent;
this.isHorizontal = isHorizontal;
this.table = document.createElement('table');
if (isHorizontal) {
this.table.insertRow(0);
}
this.width = null;
}
MenuBar.prototype.add = function (menu) {
if (!menu || !menu.type || menu.type != 'Menu') {
throw 'A non-null Menu must be supplied for addition to any MenuBar.';
}
menu.index = this.length++;
this.menus[menu.index] = menu;
menu.parent = this;
menu.id = this.id + '.menus[' + menu.index + ']';
menu.text = '<a href="' + menu.url + '" target="' + menu.target + '" onMouseover="cancel(event); ' + menu.id +
'.setVisible(true)" onMouseout="cancel(event); ' + menu.id + '.setVisible(false)">' + menu.label +
'&nbsp;<img src="pointer.gif" border="0"></a>';
if (this.isHorizontal) {
this.table.rows[0].insertCell(menu.index);
this.table.rows[0].cells[menu.index].innerHTML = menu.text;
} else {
this.table.insertRow(menu.index);
this.table.rows[menu.index].insertCell(0);
this.table.rows[menu.index].cells[0].innerHTML = menu.text;
}
};
MenuBar.prototype.remove = function (index) {
if (index < 0 || index >= this.length) {
throw 'To remove a Menu from this MenuBar, you must supply an index > -1 and < ' +
this.length + '.';
}
for (var i = index; i < this.length; i++) {
this.menus[i] = this.menus[i + 1];
}
};
MenuBar.prototype.setVisible = function (bool) {
this.isVisible = bool;
if (this.isVisible) {
this.table.style.visibility = 'visible';
this.parent.appendChild(this.table);

this.width = this.table.width;
alert(this.width);
} else {
this.table.style.visibility = 'hidden';
}
};
//end class MenuBar

function cancel(evnt) {
if (window.event) {
event.cancelBubble = true;
} else if (evnt.stopPropagation) {
evnt.stopPropagation();
}
}

function findPos(obj) {
var left = 0;
var top = 0;
if (obj.offsetParent) {
left = obj.offsetLeft;
top = obj.offsetTop;
while (obj = obj.offsetParent) {
left += obj.offsetLeft;
top += obj.offsetTop;
}
}
return [left, top];
}


<html>
<head>
<title>Untitled Document</title>
<script type="text/javascript" src="menus.js"></script>
<script type="text/javascript">
function init() {
alert(0);
var menu = new MenuBar(document.body, false);
menu.add(new Menu('Test1', '#', '_self'));
menu.setVisible(true);
}
</script>
</head>
<!-- <body onLoad="new MenuBar(this, false)"> <!--This one alerts.-->
<body onLoad="init()"><!--But this one doesn't.-->
</body>
</html>

EDIT: I had missed the last parenthesis in menu.add(new Menu('Test1', '#', '_self'));. I'll continue to test, and make a new reply when I find a problem I can't seem to solve.

Jesdisciple
08-18-2007, 03:59 PM
I found a very strange error, and it looks like it's in the language, not my code. Look for the two red lines in Menu(). The first assigns this.length = 0; and the second alerts alert(this.length);, outputting 3. Moving the assignment to inside the alert outputs 0; the language seems to change the value somewhere in between.

EDIT: IE6 and Firefox output 3, Opera outputs 0.


<html>
<head>
<title>Untitled Document</title>
<script type="text/javascript" src="menus.js"></script>
<script type="text/javascript">
function init() {
var menuBar = new MenuBar(document.body, false);
var menu1 = new Menu('Test1', 'menus.html', '_self');
var menuItem1_1 = new MenuItem('Test1.1', 'menus.html', '_self');
menu1.add(menuItem1_1);
menuBar.add(menu1);
menuBar.setVisible(true);
}
</script>
</head>
<body onLoad="init()">
</body>
</html>


// JavaScript Document

var menuBarCount = 0;
var menuBars = [];

//begin class MenuItem
function MenuItem(label, url, target) {
this.type = 'MenuItem';
label = label.replace(/ /, '&nbsp;');
this.text = '<a href="' + url + '" target="' + target + '">' + label + '</a>';
}
//end class MenuItem

//begin class Menu
function Menu(label, url, target) {
this.type = 'Menu';
this.label = label.replace(/ /, '&nbsp;');
this.url = url;
this.target = target;
this.items = [];
this.length = 0;
alert(this.length);
this.width = null;
this.isVisible = false;
this.hasShown = false;
this.table = document.createElement('table');
this.table.style.visibility = 'hidden';
this.table.style.position = 'absolute';
}
Menu.prototype = MenuItem;
Menu.prototype.add = function (menuItem) {
if (!menuItem || !menuItem.type || (menuItem.type != 'MenuItem' && menuItem.type != 'Menu')) {
throw 'A non-null MenuItem or Menu must be supplied for addition to any Menu.';
}
menuItem.index = this.length++;
menuItem.id = this.id + '.items[' + menuItem.index + ']';
menuItem.text = '<a href="' + menuItem.url + '" target="' + menuItem.target + '" onMouseover="' + menuItem.id +
'.setVisible(true)" onMouseout="' + menuItem.id + '.setVisible(false)">' + menuItem.label +
'&nbsp;<img src="pointer.gif" border="0"></a>';
this.items[menuItem.index] = menuItem;
this.table.insertRow(menuItem.index);
this.table.rows[index].insertCell(0);
this.table.rows[index].cells[0].innerHTML = menuItem.text;
alert(menuBars[0]);
};
Menu.prototype.setVisible = function (bool) {
alert(0);
this.isVisible = bool;
if (this.isVisible) {
this.table.style.visibility = 'visible';
if (!this.hasShown) {
this.hasShown = true;
this.handle = findPos(this.parent.table.cells[this.index]);
this.handle[0] += this.parent.width;

this.table.style.left = this.handle[0];
this.table.style.top = this.handle[1];

this.width = this.table.width;
alert(this.width);
}
} else {
this.table.style.visibility = 'hidden';
}
};
//end class Menu

//begin class MenuBar
function MenuBar(parent, isHorizontal) {
alert(0);
this.type = 'MenuBar';
this.index = menuBarCount++;
menuBars[this.index] = this;
this.id = 'menuBars[' + this.index + ']';
if (!parent) {
throw 'The first argument of the MenuBar constructor, "parent", must be non-null.';
}
this.menus = [];
this.length = 0;
this.parent = parent;
this.isHorizontal = isHorizontal;
this.table = document.createElement('table');
if (isHorizontal) {
this.table.insertRow(0);
}
this.width = null;
}
MenuBar.prototype.add = function (menu) {
if (!menu || !menu.type || menu.type != 'Menu') {
throw 'A non-null Menu must be supplied for addition to any MenuBar.';
}
menu.index = this.length++;
this.menus[menu.index] = menu;
menu.parent = this;
menu.id = this.id + '.menus[' + menu.index + ']';
menu.text = '<a href="' + menu.url + '" target="' + menu.target + '" onMouseover="cancel(event); ' + menu.id +
'.setVisible(true)" onMouseout="cancel(event); ' + menu.id + '.setVisible(false)">' + menu.label +
'&nbsp;<img src="pointer.gif" border="0"></a>';
if (this.isHorizontal) {
this.table.rows[0].insertCell(menu.index);
this.table.rows[0].cells[menu.index].innerHTML = menu.text;
} else {
this.table.insertRow(menu.index);
this.table.rows[menu.index].insertCell(0);
this.table.rows[menu.index].cells[0].innerHTML = menu.text;
}
};
MenuBar.prototype.remove = function (index) {
if (index < 0 || index >= this.length) {
throw 'To remove a Menu from this MenuBar, you must supply an index > -1 and < ' +
this.length + '.';
}
for (var i = index; i < this.length; i++) {
this.menus[i] = this.menus[i + 1];
}
};
MenuBar.prototype.setVisible = function (bool) {
this.isVisible = bool;
if (this.isVisible) {
this.table.style.visibility = 'visible';
this.parent.appendChild(this.table);

this.width = this.table.width;
alert(this.width);
} else {
this.table.style.visibility = 'hidden';
}
};
//end class MenuBar

function cancel(evnt) {
if (window.event) {
event.cancelBubble = true;
} else if (evnt.stopPropagation) {
evnt.stopPropagation();
}
}

function findPos(obj) {
var left = 0;
var top = 0;
if (obj.offsetParent) {
left = obj.offsetLeft;
top = obj.offsetTop;
while (obj = obj.offsetParent) {
left += obj.offsetLeft;
top += obj.offsetTop;
}
}
return [left, top];
}



EZ Archive Ads Plugin for vBulletin Copyright 2006 Computer Help Forum