From: O. O. on
Hi,

I am new to JavaScript – but I have experience with strongly typed
object oriented languages like C# and Java. I don’t know any CSS, and
have never used a prototype based language. I don’t have much
experience with the DOM, but I can understand the basic idea.

I have a HTML table, with one column having a button in each row. The
OnClick event of the/each button is liked to a function like: (This
uses JQuery).

function deleteRow() {
$(this).parent().parent().remove();
}

I copied this from a website, and it did not work for me. So I
attempted debugging this. I think my mistake is in the number
of .parent() calls. For this I needed to figure out where each of the
objects are in the DOM. I modified my original function to look like:

function deleteRow() {
var $t = $(this);
alert($t);
var $t1 = $(this).parent();
alert($t1);
$(this).parent().parent().remove();
}

I was hoping that the above code would show me the type of object of $
(this) and $(this).parent() and from that I would have some idea of
where I am in the DOM. (This would certainly work in C# or Java).

The above code resulted in both of the alert boxes having [object
Object] – which is useless to me. I then used FireBug to step through
the modified function above, and I see $t and $t1 as [Window
temp.html] (where temp.html is the name of my HTML file.) This does
not tell me anything. I tried expanding the hierarchy of $t and $t1 in
the Watch Window of FireBug, and I could not make any sense of the
information.

I understand that this is related to JQuery – but since this is a lot
more basic, I am hoping that someone here can help me. I would like to
know how to figure out where you are in the DOM using a given object
in JavaScript.

Thanks a lot,
O. O.
From: David Mark on
O. O. wrote:
> Hi,
>
> I am new to JavaScript � but I have experience with strongly typed
> object oriented languages like C# and Java. I don�t know any CSS, and
> have never used a prototype based language. I don�t have much
> experience with the DOM, but I can understand the basic idea.
>
> I have a HTML table, with one column having a button in each row. The
> OnClick event of the/each button is liked to a function like: (This
> uses JQuery).

That's a huge mistake. For one, the library is known to be grade-Z
software. For two, it makes it much more difficult to get help (from
anyone other than jQuery devotees, whose usual "solution" to its
failings is to try upgrading or downgrading jQuery).

>
> function deleteRow() {
> $(this).parent().parent().remove();
> }

This is crazy. It creates a new jQuery object and calls two methods,
just to get a reference to a DOM node. You could simply store the
reference in a closure.

http://www.jibbering.com/faq/notes/closures/

Of you could use the parentNode property of the element (presuming the -
this - value references an element), which is all jQuery is doing behind
the scenes.

var elParent = this.parentNode;
if (elParent) {
elParent = elParent.parentNode;
} else {
// Something went wrong, log or alert it during testing
// Should never happen in production
}

Presuming you find the "grandparent" of the DOM node, you could then
call the removeChild method of its parent to remove it from the DOM.

>
> I copied this from a website, and it did not work for me.

That's the jQuery way. It leaves you with code that you don't
understand. Even if you did get it to "work" per observation in a few
browsers, you'd have no idea what to do if and when it broke down.

> So I
> attempted debugging this. I think my mistake is in the number
> of .parent() calls. For this I needed to figure out where each of the
> objects are in the DOM. I modified my original function to look like:
>
> function deleteRow() {
> var $t = $(this);
> alert($t);
> var $t1 = $(this).parent();
> alert($t1);
> $(this).parent().parent().remove();
> }
>
> I was hoping that the above code would show me the type of object of $
> (this) and $(this).parent() and from that I would have some idea of
> where I am in the DOM. (This would certainly work in C# or Java).

It would work in JS too. The trouble is you are relying on an
ill-advised interface that mutes many mistakes in the name of
"forgiveness". As you have found, this can make debugging near
impossible (but does allow neophytes to delude themselves into thinking
they are programming). Why do you think there are so many dead-end
queries in the project's support forum?

>
> The above code resulted in both of the alert boxes having [object
> Object] � which is useless to me.

Exactly. Check the "0" property of each instead. That should give you
an idea of the relative elegance of jQuery's metaphors. Everything is
abstracted as a collection of DOM nodes, even in cases where there can
be only one. References to window, document and element objects are all
jumbled up in one "magic box" called "$"; which, as an aside, is a name
that is only supposed to be used by machine-generated code (per the
specifications). I guess the thinking was that beginners could only be
expected to remember one (poorly named) identifier (and that a single
character would save typing). :) Of course, other libraries use that
same name, but for slightly different purposes and the amount of typing
is a non-issue (think macros).

> I then used FireBug to step through
> the modified function above, and I see $t and $t1 as [Window
> temp.html] (where temp.html is the name of my HTML file.)

The - this - value in functions is the Global Object (which is typically
a reference to the global window object in browsers) in JS under some
circumstances. It depends on how the function is called. I assume you
called the deleteRow function like this:-

deleteRow(...);

....which would indeed set - this - to the Global Object. Clearly
deleteRow was meant to be attached to a DOM node as a listener, which
would set the - this - to reference that node. For example:-

el.onclick = deleteRow;

> This does
> not tell me anything. I tried expanding the hierarchy of $t and $t1 in
> the Watch Window of FireBug, and I could not make any sense of the
> information.

The trouble is that you are new to JS, as well as the DOM. You need to
learn both before attempting to cobble together code found on the Web
(regardless of what jQuery fans will tell you).
From: Garrett Smith on
O. O. wrote:
> Hi,
>
> I am new to JavaScript � but I have experience with strongly typed
> object oriented languages like C# and Java. I don�t know any CSS, and
> have never used a prototype based language. I don�t have much
> experience with the DOM, but I can understand the basic idea.
>
> I have a HTML table, with one column having a button in each row. The
> OnClick event of the/each button is liked to a function like: (This
> uses JQuery).
>

The jQuery team promote bad programming practices by encouraging people
to use jQuery over educating them.

jQuery is neither needed nor desirable for your solution.

It seems you actually want to know how to solve problems.

I'd add to the previous suggestions given to use event delegation. It is
a little more sophisticated to set up but it is more efficient because
it requires no initialization routines and it requires only one event
handler.

Event delegation works by adding an event handler to an ancestor and
check the event target when that handler is called.

A diagram of event flow exists in DOM 3 Events (draft):

<http://www.w3.org/TR/DOM-Level-3-Events/#dom-event-architecture>



Set up the HTML:

<table>
<tbody id="aaa">
<tr><td>abbb</td></tr>
<tr><td>accccb</td></tr>
</tbody
</table>

The script adds an event handler and checks the target:

var aaa = document.getElementById("aaa");
aaa.onclick = aaaClickHandler;

function aaaClickHandler(ev) {
ev = ev || window.event;
var target = getEventTarget(ev),
row = findAncestorWithTagName("tr");

row.style.display = "none";
}

Since the table is clicked, you'll need to check the event.target, that
is, what the user actually clicked on.

The property for an event target is found in the event property named
"target" in w3c compliant browsers and "srcElement" in the MSIE DOM.

The event target in MSIE is called "srcElement" (see MSDN). Also, MSIE
and I believe and early version of Chrome, do not have the event payload
passed to the event handler callback, but instead have a window.event
property.

div.onclick = function(ev) {
alert(ev) ;// undefined in IE.
};

It is generally advisable to use w3c standard properties first,
conditionally, and provide an alternative feature check for a
proprietary property where that is not supported.

Further, there is a problem with some browsers, notably Safari 2 and
very old Mozillas where text nodes can be event targets for mouse
events. So, if a mouse event's target is a text node, it should be ignored.

function getEventTarget(ev) {
var target = ev.target || ev.srcElement;
if(ev.target.nodeName == "#text") {
target = target.parentNode;
}
return target;
}

After you've gotten the target, you need to know which row specifically
was clicked on. That can be found by crawling up the parentNode chain
until an element that has a tagName "TR" is found.

Note that in XHTML dom, the tagName string of HTML element is lower
case, while in HTML dom, it is UC. IF your solution needs to run in
XHTML DOM, then a case transform strategy can be used. Since it is both
unlikely and unadvisable that you'll need to support XHTML dom, and
since we already have enough complexity to worry about, I'll forgo the
details of how to do that.

function findAncestorWithTagName(el, tag) {
limit = el.ownerDocument;
if(limit) {
for(var parent = el.parentNode;parent && parent !== limit; ){
if( parent.tagName === tag )
return parent;
parent = parent.parentNode;
}
}
return null;
}

Now you have the components.

RJD - you will not be forgotten!
--
Garrett
comp.lang.javascript FAQ: http://jibbering.com/faq/
From: O. O. on
Thanks David and Garrett for your prompt responses. I am surprised
that JQuery is not liked here – but the situation that you describe is
accurate i.e. you usually cannot debug anything, and the only solution
to a plugin not working is to downgrade or upgrade JQuery itself.

I tried to understand the concept of closures – but it seems to be
beyond me for now. I guess I need to learn a lot more than I was
expecting. Over the next few months or so, I would look into these
things when I find the time.

Thanks again for responding,
O. O.
From: David Mark on
O. O. wrote:
> Thanks David and Garrett for your prompt responses. I am surprised
> that JQuery is not liked here � but the situation that you describe is
> accurate i.e. you usually cannot debug anything, and the only solution
> to a plugin not working is to downgrade or upgrade JQuery itself.

What's to like? It's 70K (disingenuously advertised as 24K) of some of
the worst browser scripting code in history. It reads like high comedy
for anyone who understands what it is trying to do (and how it is
failing miserably). And the comments of the authors rarely match
reality (but try to tell them that!)

It's amazing how vehemently defended it is by its proponents, but then
they want to keep their jobs as deluded code cobblers. The venom in
their responses to any and all criticism is a dead giveaway. They
either don't get it or don't want it. Pity anyone paying for their efforts.

>
> I tried to understand the concept of closures � but it seems to be
> beyond me for now. I guess I need to learn a lot more than I was
> expecting. Over the next few months or so, I would look into these
> things when I find the time.

Don't feel bad, it's an advanced subject. Learn the basics first.

>
> Thanks again for responding,

NP. Thanks for listening. That puts you one step ahead of the typical
jQuery zombie.