Kewl debugger

2 views
Skip to first unread message

Robert Skidmore

unread,
Jun 4, 2004, 3:08:44 PM6/4/04
to
Debugger.js 1.0

This is my Javascript debugger.

What it does:
After you displaying the debug window (see tip 1) you can move your
mouse over any element on the page and the window will populate with
all the properties, events, and objects of that element.

Instructions:
Place the following line in your page you wish to debug:
<script language="JavaScript" src="js/Debugger.js"></script>

Tips:
1. You can make the debug window appear by pressing "ctrl+shift+d"
2. You can stop the debug window from following your mouse by pressing
ctrl
3. You can click on a object listed in the object tag and the debug
window will populate with that objects data
4. You can click on the property name, event name, or the word msdn on
the object tab to goto the msdn definition of that property.

You can freely use this with only one condition, credit goes to me.
That mean if you tell your boss you wrote this, I will hunt you down
and feed your ears to my pet sloth.

PS: Please post any impovement to this thread. Thx

document.onmousemove = document_onmousemove;
document.onkeypress = document_onkeypress;

var lastobject;
var currenttab = "properties";
var keyspressed = false;
var lastx;
var lasty;

function document_onkeypress(){
if ((event.ctrlKey) && (event.shiftKey) && (event.keyCode == 4)){
if (keyspressed == true){
document.getElementById("floatingdiv").style.display = "none";
keyspressed = false;
}else{
keyspressed = true;
try{
document.getElementById("floatingdiv").style.display = "block";
}catch(ex){}
}
}
}

function document_onmousemove(){
try{
if (!event.ctrlKey){
lastx = event.clientX + 10;
lasty = event.clientY + 10;
var theobject = document.elementFromPoint(lastx - 10, lasty - 10);
if ((theobject != null) && (theobject != lastobject) &&
(hasParent(theobject, 'floatingdiv') == false) && (keyspressed ==
true)){
switch(currenttab){
case "properties":
buildProperties(theobject, lastx, lasty);
break;
case "objects":
buildObjects(theobject, lastx, lasty);
break;
case "events":
buildEvents(theobject, lastx, lasty);
break;
}
}
try{
div_for_object = document.getElementById("floatingdiv")
div_for_object.style.top = lasty;
div_for_object.style.left = lastx;
}catch(ex){}
lastobject = theobject;
}
}catch(ex){
window.alert(ex.message);
}
}
function WriteTable(theobject, x, y){
var table_for_object
try{
table_for_object = document.getElementById("floatingtable")
}catch(ex){
table_for_object = null;
window.alert(ex.message);
}

if (table_for_object == null){
//div
div_for_object = document.createElement('div');
div_for_object.id = 'floatingdiv';
div_for_object.style.position = 'absolute';
div_for_object.style.top = x;
div_for_object.style.left = y;
div_for_object.style.overflow = 'auto';
div_for_object.style.width = '220px';
div_for_object.style.height = '350px';
div_for_object.style.backgroundColor = 'white';
div_for_object.style.borderRight = '#ff0066 1px solid';
div_for_object.style.borderTop = '#ff0066 1px solid';
div_for_object.style.borderLeft = '#ff0066 1px solid';
div_for_object.style.borderBottom = '#ff0066 1px solid';

//table
outer_table = document.createElement('table');
outer_table.style.width='195px';

//row
var tb=document.createElement('tbody');
var tr=document.createElement('tr');

//cell tab properties
var td=document.createElement('td');
td.style.borderRight = 'gray 1px solid';
td.style.borderTop = 'gray 1px solid';
td.style.borderLeft = 'gray 1px solid';
td.innerText='Properties';
td.style.textAlign='center';
td.style.cursor = 'hand';
td.style.padding='2px';
td.onclick = buildProperties;
tr.appendChild(td);

//cell tab events
var td=document.createElement('td');
td.style.borderRight = 'gray 1px solid';
td.style.borderTop = 'gray 1px solid';
td.style.borderLeft = 'gray 1px solid';
td.style.borderBottom = 'gray 1px solid';
td.innerText='Events';
td.style.textAlign='center';
td.style.cursor = 'hand';
td.style.padding='2px';
td.onclick = buildEvents;
tr.appendChild(td);

//cell tab objects
var td=document.createElement('td');
td.style.borderRight = 'gray 1px solid';
td.style.borderTop = 'gray 1px solid';
td.style.borderLeft = 'gray 1px solid';
td.style.borderBottom = 'gray 1px solid';
td.innerText='Objects';
td.style.textAlign='center';
td.style.cursor = 'hand';
td.style.padding='2px';
td.onclick = buildObjects;
tr.appendChild(td);

//append the tab row
tb.appendChild(tr);

//create content row
var tr=document.createElement('tr');

//create content cell
var td=document.createElement('td');
td.style.borderRight = 'gray 1px solid';
td.style.borderLeft = 'gray 1px solid';
td.style.borderBottom = 'gray 1px solid';
td.colSpan = '3';

//create content table in cell
table_for_object = document.createElement('table');
table_for_object.id = 'floatingtable';
table_for_object.style.width='190px';
table_for_object.border = '2';

//row
var tb2=document.createElement('tbody');
var tr2=document.createElement('tr');

//cell tab properties
var td2=document.createElement('td');
td2.style.borderRight = 'gray 1px solid';
td2.style.borderTop = 'gray 1px solid';
td2.style.borderLeft = 'gray 1px solid';
td2.innerText='Properties';
td2.style.textAlign='center';
td2.style.padding='2px';
td2.colSpan = '2';
tr2.appendChild(td2);

tb2.appendChild(tr2);
table_for_object.appendChild(tb2);

td.appendChild(table_for_object);
tr.appendChild(td);
tb.appendChild(tr);

outer_table.appendChild(tb);
div_for_object.appendChild(outer_table);

document.body.appendChild(div_for_object);
return document.getElementById("floatingtable");
}else{
return document.getElementById("floatingtable");
}
}

function buildProperties(theobject, x, y){
if (theobject == undefined){
theobject = lastobject;
}
if (x == 'undefined'){
x = lastx;
}
if (y == 'undefined'){
y = lasty;
}
var protbl = WriteTable(theobject, x, y);
try{
for (var i = 2; i <= 300; i++){
protbl.deleteRow(2);
}
}catch(ex){}
for (p in theobject){
var prop = new String(p);
var results = new String(eval("theobject." + prop));
if ((prop.substring(0, 2) != 'on') && (results != '[object]')){
aRow = protbl.insertRow();
aCell1 = aRow.insertCell();
aCell1.style.width = '40px'
aCell1.style.fontFamily = 'Arial';
aCell1.style.fontSize = '8pt';
aCell1.style.backgroundColor = '#f5f5f5';
aCell1.innerText = prop;
aCell1.onclick = new Function
("window.open('http://msdn.microsoft.com/library/default.asp?url=/workshop/author/dhtml/reference/properties/"
+ prop + ".asp')");
aCell1.style.cursor = 'hand';
aCell1.textAlign = "right";
aCell1.style.verticalAlign = "top";
aCell2 = aRow.insertCell();
aCell2.style.width = '60px'
aCell2.noWrap = 'nowrap';
aCell2.style.fontFamily = 'Arial';
aCell2.style.fontSize = '8pt';
aCell2.style.backgroundColor = '#f5f5f5';
if (results.length >= 50){
div_for_object = document.createElement('div');
div_for_object.style.overflow = 'auto';
div_for_object.style.width = '90px';
div_for_object.style.height = '120px';
div_for_object.innerText = results;
aCell2.appendChild(div_for_object);// = results;
}else{
aCell2.innerText = results;
}
}
}
currenttab = "properties";
}
function buildEvents(theobject, x, y){
if (theobject == undefined){
theobject = lastobject;
}
if (x == 'undefined'){
x = lastx;
}
if (y == 'undefined'){
y = lasty;
}
var protbl = WriteTable(theobject, x, y);
try{
for (var i = 2; i <= 300; i++){
protbl.deleteRow(2);
}
}catch(ex){}
for (p in theobject){
var prop = new String(p);
var results = new String(eval("theobject." + prop));
if (prop.substring(0, 2) == 'on'){
aRow = protbl.insertRow();
aCell1 = aRow.insertCell();
aCell1.style.width = '40px'
aCell1.style.fontFamily = 'Arial';
aCell1.style.fontSize = '8pt';
aCell1.style.backgroundColor = '#f5f5f5';
aCell1.innerText = prop;
aCell1.onclick = new Function
("window.open('http://msdn.microsoft.com/library/default.asp?url=/workshop/author/dhtml/reference/events/"
+ prop + ".asp')");
aCell1.style.cursor = 'hand';
aCell1.textAlign = "right";
aCell1.style.verticalAlign = "top";
aCell2 = aRow.insertCell();
aCell2.style.width = '60px'
aCell2.noWrap = 'nowrap';
aCell2.style.fontFamily = 'Arial';
aCell2.style.fontSize = '8pt';
aCell2.style.backgroundColor = '#f5f5f5';
if (results.length >= 10){
div_for_object = document.createElement('div');
div_for_object.style.overflow = 'auto';
div_for_object.style.width = '90px';
div_for_object.style.height = '120px';
div_for_object.innerText = results;
aCell2.appendChild(div_for_object);// = results;
}else{
aCell2.innerText = results;
}
}
}
currenttab = "events";
}

var objArray = new Array();
function buildObjects(theobject, x, y){
if (theobject == undefined){
theobject = lastobject;
}
if (x == 'undefined'){
x = lastx;
}
if (y == 'undefined'){
y = lasty;
}
var protbl = WriteTable(theobject, x, y);
try{
for (var i = 2; i <= 300; i++){
protbl.deleteRow(2);
}
}catch(ex){}
var i = 0;
for (p in theobject){
var prop = new String(p);
var results = new String(eval("theobject." + prop));
if (results == '[object]'){
objArray[i] = eval("theobject." + prop);
aRow = protbl.insertRow();
aCell1 = aRow.insertCell();
aCell1.style.width = '40px'
aCell1.style.fontFamily = 'Arial';
aCell1.style.fontSize = '8pt';
aCell1.style.backgroundColor = '#f5f5f5';
aCell1.innerText = prop;
aCell1.onclick = new Function("buildProperties2(" + i + ")");
aCell1.style.cursor = 'hand';
aCell1.textAlign = "right";
aCell1.style.verticalAlign = "top";
aCell2 = aRow.insertCell();
aCell2.style.width = '60px'
aCell2.noWrap = 'nowrap';
aCell2.style.fontFamily = 'Arial';
aCell2.style.fontSize = '8pt';
aCell2.style.backgroundColor = '#f5f5f5';
aCell2.innerText = 'MSDN';
aCell2.onclick = new Function
("window.open('http://msdn.microsoft.com/library/default.asp?url=/workshop/author/dhtml/reference/objects/"
+ prop + ".asp')");
aCell2.style.cursor = 'hand';
i++;
}
}
currenttab = "objects";
}

function buildProperties2(i){
buildProperties(objArray[i]);
lastobject = objArray[i];
}

function hasParent(theobject, parentid) {
if (theobject == null) return false;
else if (theobject.nodeType == 1 && theobject.id == parentid)
return true;
else
if (theobject.parentNode != null){
return hasParent(theobject.parentNode, parentid);
}else{
return false;
}

}

Richard Cornford

unread,
Jun 5, 2004, 1:14:03 PM6/5/04
to
Robert Skidmore wrote:
> Debugger.js 1.0
>
> This is my Javascript debugger.

Debugger is probably the wrong name for this. From a debugger I expect
the ability to single step through (and over) code, set break points,
inspect the value of variables and the like. What you have created is
probably better termed and object inspector or DOM Node inspector, and
certainly could be a valuable aid in debugging browser scripts.

Indeed IMO writing (or at least attempting to write) a cross-browser
object inspector can be a very valuable learning exercise as the more
complete it becomes the more it has the potential to bring you face to
face with each of the oddities exhibited by any individual browser. And
a familiarity with browser DOMs in depth makes handling their diversity
easier.

> What it does:
> After you displaying the debug window (see tip 1) you can move your
> mouse over any element on the page and the window will populate with
> all the properties, events, and objects of that element.

^^^
As you are using a - for(prop in obj) - loop the most you can claim is
that all of the ennumerable properties of an object will be reported.
But what is wrong with reporting methods in addition to (non object and
event handler) properties, properties that refer to objects and event
handlers? (incidentally, the distinction you are drawing between
properties, events and objects is arbitrary, possibly misleading, and
ultimately wrong. They are all properties.)

I observer, for example, that an attributes collection has a length
property of, say 86, but you are not listing any of those integer
indexed properties (which do actually refer to objects).

> Instructions:
> Place the following line in your page you wish to debug:
> <script language="JavaScript" src="js/Debugger.js"></script>
>
> Tips:
> 1. You can make the debug window appear by pressing "ctrl+shift+d"

But twice in rapid succession and a script error results (more caution
is called for).

> 2. You can stop the debug window from following your mouse by pressing
> ctrl

You should describe this a holding Ctrl down, but maybe you should
change the implementation to a toggle.

However, your window makes no allowance for the possibility that the
page is scrolled.

> 3. You can click on a object listed in the object tag and the debug
> window will populate with that objects data

That feature could do with a "back" button of some sort.

> 4. You can click on the property name, event name, or the word msdn on
> the object tab to goto the msdn definition of that property.

Not when the browser is not on line.

> You can freely use this with only one condition, credit goes to me.
> That mean if you tell your boss you wrote this, I will hunt you down
> and feed your ears to my pet sloth.
>
> PS: Please post any impovement to this thread. Thx
>
> document.onmousemove = document_onmousemove;
> document.onkeypress = document_onkeypress;
>
> var lastobject;
> var currenttab = "properties";
> var keyspressed = false;
> var lastx;
> var lasty;

<snip>

It is a pity that you did not observer the advice on posting code to
Usenet offered in the FAQ. You have indented your code with Tab
characters eve4n though it is known that newsreaders handle Tabs
inconsistently. Mine for example ignores them, so your code is presented
as not indented at all, but newsreaders that display tabs may be using
an unsuitable number of space characters per-tab (the common default of
8 is really too many in a newsgroup post). You also have not done
anything to control the way that your newsreader has wrapped your code,
rendering it broken as presented. These problems can (and so should) be
avoided.

> function document_onmousemove(){

This is a mouse move handler. Mouse move events are generated (and
queued) for virtually every transition of the mouse form pixel to pixel.
As a result the associated handlers must be fast (so usually simple)
else they cannot keep up and become a bottleneck in the browser's event
handling system. Your event handler is trying to do too much and the
result is less than responsive.

> try{
> if (!event.ctrlKey){
> lastx = event.clientX + 10;
> lasty = event.clientY + 10;

So this isn't even attempting to be cross-browser. That really makes in
next to useless in an Internet authoring context.

<snip>
<snip>

Do I observer the sort of repetition that might be better accommodated
with a parameterised function call?

<snip>


> //cell tab properties
> var td2=document.createElement('td');
> td2.style.borderRight = 'gray 1px solid';
> td2.style.borderTop = 'gray 1px solid';
> td2.style.borderLeft = 'gray 1px solid';
> td2.innerText='Properties';
> td2.style.textAlign='center';
> td2.style.padding='2px';
> td2.colSpan = '2';
> tr2.appendChild(td2);

<snip>


> var results = new String(eval("theobject." + prop));

<snip>

Using - eval - to resolve a dynamically created dot notation property
accessor? It might be an idea to learn javascript if you are planning on
scripting web browsers:-

<URL: http://jibbering.com/faq/#FAQ4_39 >

Richard.


Robert Skidmore

unread,
Jun 6, 2004, 12:35:21 AM6/6/04
to
Dick,
Thanks for all of your comments. Yea I know it's not the most
efficient code, but I've been using this script for the past month and
it has worked great for me. I also never intended this to stay
referenced to a page in production. Just want to share what I had.
Considering the fact that I write this in about an hour, I think it's
pretty good.

When I wrote this I had IE only in mind. The company I work for only
develops for IE, mostly internal apps. Guess I should have mentioned
that.

Something you don't mention is the fast that it I desperately need to
alphabetize the list being written to the debug window. It would make
it so much easer to find what you are looking for.

Thx again


"Richard Cornford" <Ric...@litotes.demon.co.uk> wrote in message news:<c9sv0t$5n2$1$8302...@news.demon.co.uk>...

Reply all
Reply to author
Forward
0 new messages