Simpler loading through jQuery

D

David Mark

I believe David is suggesting something vaguely like the following in
the head of the document.

<script type="text/javascript">

  if (feature tests for showing the div pass) {
    document.write('<style type="text/css">#magicDiv
{visibility:hidden;}<\/style>');
    window.onload = function() {
      document.getElementById('magicDiv').style.visibility =
'visible';
    };
  }

</script>

The important part is before the document.write is used to hide the
magicDiv, you need to know that you will be able to unhide it later.
Perhaps checking that the documentElement.style.visibility property is
a string type is sufficient to think it will be possible to unhide it
when the page has loaded.

Yes, but I think creating a DIV to test is a better strategy, at least
if there is the possibility of other scripts in the document. As plug-
ins allow users to inject scripts, I think it is best to assume there
will always be other scripts (and they will likely do strange things
to the DOM.)

And you must detect document.write as well.
 
P

Peter Michaux

kangax wrote:

Look further.

Are you implying that

1) such a browser exists or
2) he should spend an indefinite amount of time looking for one or
3) since he cannot realistically test all browsers he shouldn't
depend on such behavior?
In any case, in an (X)HTML document it is not only
unnecessarily unreliable (as pointed out), but also unnecessarily
inefficient to let every bubbling event bubble up to the root
element node; for most cases it suffices and is more efficient
to use the body element node or a closer ancestor of the target
element instead.

Since these bubbling events are initiated by the (slow-brained) user,
the amount of time spent bubbling is undetectable by the user.
Bubbling all the way up even a "deep" DOM is relatively instant. Using
the body element rather than the documentElement element to increase
efficiency is not a very strong argument in practice. (Using the body
element for other reasons may be a strong argument.)

Peter
 
P

Peter Michaux

Thomas said:
kangax said:
[...]
I have been using this approach for a while as well and it's been
working fine so far. I actually mentioned it here recently in a
conversation with D. Mark:
<http://groups.google.com/group/comp.lang.javascript/msg/518d3c8817cdb24a>
PointedEars then expressed concerns about potential problems with this
approach:
<cite>
Proprietary DOM implementations may not consider the root element an
event target for an event, and AIUI even standards-compliant DOM
implementations do not need to.  Insofar the "weirdness" of this
approach constitutes an argument against it.

Looking further at the specs, I see that DOM L3 Events module says that
`EventTarget` interface is implemented by all DOM `Nodes`
<http://www.w3.org/TR/DOM-Level-3-Events/events.html#Events-EventTarget>

[...]
When used with the DOM event flow, this interface is implemented by all
target nodes and target ancestors, i.e. all DOM Nodes of the tree
support this interface when the implementation conforms to DOM Level 3
Events and, therefore, this interface can be obtained by using
binding-specific casting methods on an instance of the Node interface.
[...]

DOM L2 Core says that `Document::documentElement` implements `Element`
interface, which as we know inherits from `Node` one.

Doesn't this prove that `document.documentElement` must implement
TargetEvent interface?

I was just looking in the DOM2 spec.

The document.documentElement implements Document which implements
Node.

http://www.w3.org/TR/DOM-Level-2-Core/core.html#i-Document

All Node elements in an implementation supporting the event module
must support the EventTarget interface.

http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-EventTarget

This seems to indicate that the documentElement should have events
bubble all the way up to it. This would mean that documentElement is
the ultimate global delegate element.

Peter
 
D

David Mark

Peter said:
Peter Michaux wrote: [...]
I experimented with this sort of global delegation quite a bit. Wrote
a library that was kind of neat to enable handlers to be specified
with CSS selectors. One very nice feature of global delegation is that
widgets HTML can be added to the page and the delegation just works.
I have been using this approach for a while as well and it's been
working fine so far. I actually mentioned it here recently in a
conversation with D. Mark:
<http://groups.google.com/group/comp.lang.javascript/msg/518d3c8817cdb24a>
PointedEars then expressed concerns about potential problems with this
approach:
<cite>
Proprietary DOM implementations may not consider the root element an
event target for an event, and AIUI even standards-compliant DOM
implementations do not need to.  Insofar the "weirdness" of this
approach constitutes an argument against it.
Just because David finds the technique "odd" and Pointy Ears finds it
"weird", that doesn't mean it is a flawed approach. For example, a lot

Maybe not.

It's just that many times "odd" things (hacks?) eventually haunt you
down and "break" in one environment or another. At least in my experience..

In this case, it would likely involve ancient browsers that do not
render the HTML element (e.g. IE < 6.) I'm not saying this strategy
won't work in IE5, just that the lack of a visible HTML element should
give you pause and is common in browsers of that era.
But then I don't see anything odd in attaching event handler to
`documentElement` and I haven't stumbled upon any problems with it just
yet. As I explained in a reply to PointedEars (in this thread), it
appears that using `documentElement` as EventTarget is just as reliable
as using `document.body` as EventTarget.

It's just a bit odd to attach all listeners to the root element.

Don't get me started on PERL programmers. :)
Ah yes, of course. Fortunately, the need for this doesn't come up often.
When it does, I use global `load` event.





Shouldn't "global delegation" involve attaching "global" event handlers,
rather than manipulating document? document should be manipulated when
it is safe to do so (i.e. after global "load" fires)

I think the point is that the listeners may mutate the DOM (and this
scheme allows them to do so before the DOM is ready.)
I think such queue would lead to an inconsistent UI behavior and would
overall be quite brittle.

It would be a workaround for a workaround. Not recommended.

[snip]
 
P

Peter Michaux

It's just that many times "odd" things (hacks?) eventually haunt you
down and "break" in one environment or another. At least in my experience.

Yes some intuition about things that might cause trouble is good to
have.
But then I don't see anything odd in attaching event handler to
`documentElement`

I don't see anything odd about it either.

Ah yes, of course. Fortunately, the need for this doesn't come up often.
When it does, I use global `load` event.

But this is one of the reasons I found the global delegate style not
so appealing. It is not a complete solution. That is not the only
problem as this thread is documenting.

Shouldn't "global delegation" involve attaching "global" event handlers,
rather than manipulating document?

Yes but it is what those handlers are supposed to do when they run is
the problem. Frequently handlers manipulate the document.

(Adding the global handers could be considered by some as manipulating
the document.)
document should be manipulated when
it is safe to do so (i.e. after global "load" fires)
Yes.


I think such queue would lead to an inconsistent UI behavior and would
overall be quite brittle.

It wouldn't be good. Someone might click on an element a couple times
because nothing seemed to happen after the first click (even though
the event had been queued to be handled later.) In that case do you
add the event to the queue twice or what?

Peter
 
P

Peter Michaux

It's just a bit odd to attach all listeners to the root element.

But that could just mean you are not accustom to doing it and we are
all less comfortable with what is unfamiliar.

I think the point is that the listeners may mutate the DOM (and this
scheme allows them to do so before the DOM is ready.)
Yes.



It would be a workaround for a workaround.  Not recommended.

It is more of a workaround for a problematic solution. This is where I
ended up after reasonably thorough investigations and experiments: the
global delegation approach creates more problems then it solves.

Peter
 
D

David Mark

But that could just mean you are not accustom to doing it and we are
all less comfortable with what is unfamiliar.

I don't think so in this case. It's just an odd thing to do (and
there are cases where it won't work.)
It is more of a workaround for a problematic solution. This is where I
ended up after reasonably thorough investigations and experiments: the
global delegation approach creates more problems then it solves.

I agree with that; though it's considerably less error-prone than
jQuery's nonsense. It's amazing that people who can't solve their own
problems seek to write universal solutions (even more so that others
would buy into them.)
 
T

Thomas 'PointedEars' Lahn

kangax said:
But then I don't see anything odd in attaching event handler to
`documentElement` and I haven't stumbled upon any problems with it just
yet. As I explained in a reply to PointedEars (in this thread), it
appears that using `documentElement` as EventTarget is just as reliable
as using `document.body` as EventTarget.

That I have not commented on your assumptions yet is no indication that they
are correct.


PointedEars
 
S

SAM

Le 6/24/09 11:24 AM, David Mark a écrit :
Read it again. That was the second (and less preferred) option.


As mentioned, document.write.

You mean something like :

head
styles
script
script
document.write('<style>'.hid{visibility:hidden}<\/style>');
body
div class='hid'

and if that works in any browser ... ?

No other idea ? without document.write ?
 
D

David Mark

Le 6/24/09 11:24 AM, David Mark a écrit :




You mean something like :

head
    styles
    script
    script
       document.write('<style>'.hid{visibility:hidden}<\/style>');
body
    div class='hid'

Something like that.
and if that works in any browser ... ?

What if it doesn't? FoUC is not fatal.
No other idea ? without document.write ?

I gave you two.
 
S

SAM

Le 6/25/09 12:36 AM, David Mark a écrit :
Something like that.


What if it doesn't? FoUC is not fatal.

Yes, that can be seen this way.
I gave you two.

Two others ?
Lost them.

As alternative I see only the obstructive JS.
<div id="foo"><script>foo.visibiliy='hidden'</script> ... </div>
 
S

SAM

Le 6/24/09 8:36 PM, Peter Michaux a écrit :
I believe David is suggesting something vaguely like the following in
the head of the document.

<script type="text/javascript">

if (feature tests for showing the div pass) {
document.write('<style type="text/css">#magicDiv
{visibility:hidden;}<\/style>');
window.onload = function() {
document.getElementById('magicDiv').style.visibility =
'visible';
};
}

</script>

I did understand nothing about the "feature test for showing".
At least this test would have to be launched sequentially still the div
is parsed, no?

Anyway I don't see the interest of such a manipulation
(win.onload to show).

We are OK, the div can't be hided by CSS, if not it will never be seen
if JS is disabled.
Except if the link used to show the div points to another file (instead
to show the div).
The important part is before the document.write is used to hide the
magicDiv, you need to know that you will be able to unhide it later.

abble to show the div latter wouldn't have to be a problem.
The problem is to hide it before to see it (via JS and not CSS)
Perhaps checking that the documentElement.style.visibility property is
a string type is sufficient to think it will be possible to unhide it
when the page has loaded.

I imagine that a ccs rule could hide the div if the body has a
particular class,
now the problem is : how to set this class to the body via JS
before the navigator when loading the file can read (parse ?) '<body' ?

And without having the hider JS in the bodyElement
(all from head, "Unobtrusive JavaScript")

head
style
.hid .hid { visibility: hidden }
script
function show(x) { d.gEBI(x).className = ''; return false; }
on right moment but before document.loaded or better just
when body opens { document.body.className = 'hid'; }
body
<a href="thickbox.htm" onclick="return show('thickbox)">show</a>
<div class="hid" id="thickbox"> ... </div>
 
G

Garrett Smith

I've been using bubbling for years.
I have been using this approach for a while as well and it's been
working fine so far. I actually mentioned it here recently in a
conversation with D. Mark:
[...]
<http://www.w3.org/TR/DOM-Level-3-Events/events.html#Events-EventTypes...>
</cite>

To date, I haven't seen a browser that doesn't consider
`documentElement` an EventTarget, though.

Could you expand on this?

One real problem is non-bubbling events like focus. I made a stab at
addressing this issue

What is wrong with focusin?

I don't understand. Your page uses:
| <input type="text" focus="jQuery.ready(event)"
| blur="jQuery.ready(event)">

What is that? It looks like bugs, but I am not sure.
All events go thorough the capture phase so if IE supported the DOM3
event module capture could be used for non-bubbling events. IE doesn't
so capture is out as an option.

I'm not sure what you meant to say, but as you wrote it, that is
incorrect. It is untrue that all events go through the capture phase.
Another problem is what do you do if an event bubbles up to the global
handler while the DOM is still loading? Sure you have the event but if
the handler is intended to mutate the document, is it really safe to
mutate the document at that time? Should you put the event in some
queue to handle when window.onload eventually fires?

Be careful about mutating the document at that time.

Garrett
 
P

Peter Michaux

I've been using bubbling for years.

I've been using bubbling for years too: for example, delegation for a
drag-and-drop list where the <ul> element gets mousedown events on the
<li> elements. The issue here is whether or not global delegation as a
general strategy is a good one. I found it not to be a good one for
reasons listed in this thread.

What is wrong with focusin?

My point was there are non-bubbling event types and so there is no
complete solution using global event delegation based on bubbling
alone.

I don't understand. Your page uses:
| <input type="text" focus="jQuery.ready(event)"
| blur="jQuery.ready(event)">

What is that? It looks like bugs, but I am not sure.

If you discover it is a bug then please let me know.

I'm not sure what you meant to say, but as you wrote it, that is
incorrect. It is untrue that all events go through the capture phase.

Which DOM2 event types where the event is initiated by user action
does not go through capture?

http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-flow-capture

The only qualification on which events go though capture phase is the
following

"A capturing EventListener will not be triggered by events dispatched
directly to the EventTarget upon which it is registered."

I believe the situation they mean is when a script dispatches an event
on an element using the dispatchEvent method.

Peter
 
G

Garrett Smith

Peter said:
I've been using bubbling for years too: for example, delegation for a
drag-and-drop list where the <ul> element gets mousedown events on the
<li> elements. The issue here is whether or not global delegation as a
general strategy is a good one. I found it not to be a good one for
reasons listed in this thread.



My point was there are non-bubbling event types and so there is no
complete solution using global event delegation based on bubbling
alone.



If you discover it is a bug then please let me know.

The attribute names "focus" and "blur" are invalid. Custom attributes
for same-named dom properties.
Which DOM2 event types where the event is initiated by user action
does not go through capture?

http://www.w3.org/TR/DOM-Level-2-Events/events.html#Events-flow-capture

The only qualification on which events go though capture phase is the
following

"A capturing EventListener will not be triggered by events dispatched
directly to the EventTarget upon which it is registered."

I believe the situation they mean is when a script dispatches an event
on an element using the dispatchEvent method.

That is an incorrect interpretation. What it means is that if the event
listener is a capturing listener, and the event is dispatched on the
target, it won't fire. An event being dispatched does not mean the
"dispatchEvent" method was used.

It is the same in the latest D3E WD (DOM 3 Events, Working Draft)[0]

But, it doesn't actually work that way.
https://bugzilla.mozilla.org/show_bug.cgi?id=235441
https://bugs.webkit.org/show_bug.cgi?id=9127

In fact, Opera has changed its implementation and, upon further
research, it appears that the D3E WD (DOM 3 Events Working Draft) is
different than DOM 2 Events.

From s. 1.2 Event dispatch and DOM event flow[1] contains a diagram
that depicts an event dispatched in a DOM tree using the DOM event flow.

That diagram is followed by the following text:

| Event objects are always dispatched to an event target called the
| event's target. At the beginning of the dispatch, implementations must
| first determine the event object's propagation path. This is an
| ordered list of event targets the object may propagate to. The last
| item in the list is the event's target; the preceding items in the
| list are referred to as the target's ancestors and the immediately
| preceding item as the target's parent. Once determined, the
| propagation path cannot be changed. As an example, in the DOM event
| flow event listeners might change the position of the target node in
| the document while the event object is being dispatched; such changes
| do not affect the propagation path.

So, it seems that according to this working draft, all events *do* have
a capture phase. A listener registered for bubbling will not fire on the
capture phase.

Keep in mind that D3E is a working draft and not a Technical
Recommendation. It is not done and there are compatibility issues at the
moment.

For example, D3E says scroll bubbles[1]. AFAIK, onscroll doesn't bubble
in major browsers, including IE[2], which has had onscroll for years
(deja vu).

In fact, webkit "fixed" onscroll to *not* bubble[3].

Then there is the following text from D3E:
| A DOM application may use the hasFeature(feature, version) method of
| the DOMImplementation interface with parameter values "Events" and
| "3.0" (respectively) to determine whether or not DOM Level 3 Events is
| supported by the implementation. Since DOM Level 3 Events is built on
| top of DOM Level 2 Events [DOM Level 2 Events], an implementation that
| returns true for "Events" and "3.0" will also return true for the
| parameters "Events" and "2.0".

Method hasFeature is very generalized and far removed from the detail
about any specific object feature. Expectations that the return value
provides useful information about a particular feature may disappointed.

Garrett

[0]http://www.w3.org/TR/DOM-Level-3-Events/events.html#Events-EventTarget-addEventListener
[1]http://www.w3.org/TR/DOM-Level-3-Events/events.html#event-scroll
[2]http://msdn.microsoft.com/en-us/library/ms536966(VS.85).aspx
[3]https://bugs.webkit.org/show_bug.cgi?id=18106
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,432
Messages
2,571,680
Members
48,796
Latest member
Greg L.

Latest Threads

Top