I can work around this, by saving document.getElementsByClassName in a
(namespaced) global variable once and reassigning it before each use.
Still, this misfeature is annoying and not restricted to this
particular case. Apparently, all additions to document are affected.
Michael
--
Michael Schuerig
mailto:mic...@schuerig.de
http://www.schuerig.de/michael/
> I noticed that some of my event handlers and scripts evaluated in ajax
> responses didn't work in Konqueror (3.5.5).
I want to complain that Konqueror doesn't support this in its address bar:
javascript:void(alert('compliant'))
Other browsers respond by evaluating that JavaScript and producing an alert
box. That leads to all sorts of delicious techniques.
However, I'm doing the passive-aggressive thing by complaining here, instead
of on Konqueror's mailing list...
--
Phlip
http://www.greencheese.us/ZeekLand <-- NOT a blog!!!
Phlip a écrit :
> I want to complain that Konqueror doesn't support this in its address bar:
>
> javascript:void(alert('compliant'))
>
> Other browsers respond by evaluating that JavaScript and producing an alert
> box. That leads to all sorts of delicious techniques.
"Delicious" is very much a matter of taste. I'd like to remind you that
the javascript: URL scheme was never, ever standardized, and I, for one,
never use it. Nor do I know of a single use case that cannot be better
addressed through W3C-compliant techniques, instead of using URLs for a
purpose that was never their concern.
> However, I'm doing the passive-aggressive thing by complaining here, instead
> of on Konqueror's mailing list...
Exactly. If you have issues with Konqueror, tell them, not us... I
mean, if every IE-using dev on this list vented their frustration on
*this* list, the SvN ratio would drop dramatically...
--
Christophe Porteneuve a.k.a. TDD
"[They] did not know it was impossible, so they did it." --Mark Twain
Email: t...@tddsworld.com
Michael Schuerig a écrit :
> I noticed that some of my event handlers and scripts evaluated in ajax
> responses didn't work in Konqueror (3.5.5).
> document.getElementsByClassName is not defined in these contexts.
Well, I guess then your "document" reference is not the host page's
"document" reference. Because the method is, indeed, properly defined
(and properly behaving) on Konqueror (I just checked, "worksforme").
Can you put up a minimalistic online test page for us to tinker with?
Bummer. Do you have any idea why this might be the case? I don't have
frames and in Firefox I don't have any problems, otherwise I wouldn't
have singled out Konqueror.
> Can you put up a minimalistic online test page for us to tinker with?
Yes, I'll investigate this further, but only latter in the day.
> Nor do I know of a single use case that cannot be better
> addressed through W3C-compliant techniques, instead of using URLs
> for a
> purpose that was never their concern.
There is the use case of Bookmarklets, which rely heavily on the
javascript:... syntax.
Best,
Thomas
Thomas Fuchs a écrit :
>> Nor do I know of a single use case that cannot be better
>> addressed through W3C-compliant techniques, instead of using URLs
>> for a purpose that was never their concern.
>
> There is the use case of Bookmarklets, which rely heavily on the
> javascript:... syntax.
D'oh!!
/me hides in dark corner
However, bmklets are for use in, well, bookmarks. Not in a web page's
markup (mmm'kay, sort of grasping dead branches to arrest the fall here).
--
Christophe Porteneuve aka TDD
t...@tddsworld.com
> "Delicious" is very much a matter of taste. I'd like to remind you that
> the javascript: URL scheme was never, ever standardized, and I, for one,
> never use it. Nor do I know of a single use case that cannot be better
> addressed through W3C-compliant techniques, instead of using URLs for a
> purpose that was never their concern.
I suspect it's the cleanest possible answer to the JavaScript/DOM FAQ
"How do I inject JavaScript into another frame and force it to run
inside that frame's context?"
Not sure why you are getting self-righteously indignant about the
prospect of me abusing the technique. If I don't use it for a public
website, then what's the problem?
--
Phlip
http://c2.com/cgi/wiki?ZeekLand <-- NOT a blog!!
If you need to spend hours for finding a workaround for something
that works fine using "proprietary" stuff, it may be because the
standards are wrong or broken. Keep it mind mind that a browser is
there to display a workable interface to the user, not to test if
standards are correctly followed. ;)
The bookmarklets are a really nice example of where creative use of
something that's not really standardized but available in most
browsers totally adds value for the user.
Standards will eventually follow what is used in real-life
applications, but will always be a few years behind (Ajax, anyone?).
Be pragmatic, use what works. :)
Best,
Thomas
--
Thomas Fuchs
wollzelle
questentier on AIM
madrobby on irc.freenode.net
http://www.fluxiom.com :: online digital asset management
http://script.aculo.us :: Web 2.0 JavaScript
http://mir.aculo.us :: Where no web developer has gone before
Phlip a écrit :
> Christophe Porteneuve wrote:
> I suspect it's the cleanest possible answer to the JavaScript/DOM FAQ
> "How do I inject JavaScript into another frame and force it to run
> inside that frame's context?"
Hmmmm if that frame is yours to play with at the DOM level, you can call
JS methods in there that will have the proper window reference, even if
you call them from another frame. You could also inject a synthetic
<script> element in there. It's not necessarily cleaner, though.
Maybe you actually need to run JS in another frame's context, and maybe
not. If you're certain your need cannot be met in a less hackish way,
then so be it! Real-world apps are full of circuituous yet legitimate
needs, unfortunately.
> Not sure why you are getting self-righteously indignant about the
> prospect of me abusing the technique. If I don't use it for a public
> website, then what's the problem?
I'm sorry if I sounded like a whipmaster :-/ I'm here to help, as my
track record on this group amply states. I'm just a fierce
standardista, you know... :-)
This specific case aside, be it on a public or private site, playing the
standards as much as possible is always a good idea on the long run.
Sincerely,
> Hmmmm if that frame is yours to play with at the DOM level, you can call
> JS methods in there that will have the proper window reference, even if
> you call them from another frame. You could also inject a synthetic
> <script> element in there. It's not necessarily cleaner, though.
>
> Maybe you actually need to run JS in another frame's context, and maybe
> not. If you're certain your need cannot be met in a less hackish way,
> then so be it! Real-world apps are full of circuituous yet legitimate
> needs, unfortunately.
I guess I would prefer more violent agreement here, but sticking one
danged string into an IFRAME.src attribute is /extremely/ clean, so
its only "hackish"ness is non-compliance with broken and un-followed
standards.
> Christophe Porteneuve aka TDD
Why "TDD"? That wouldn't refer to <tremulously> Test-Driven
Development </tremulously>, would it?
> This specific case aside, be it on a public or private site, playing the
> standards as much as possible is always a good idea on the long run.
Another great thing about fuzzy standards is, if you invent a killer
app using one, you get to help resolve and focus them.
> Be pragmatic, use what works. :)
Modulo keep an eye on how compliance with the alleged "standards" are
going to evolve over time...
Phlip a écrit :
> Why "TDD"? That wouldn't refer to <tremulously> Test-Driven
> Development </tremulously>, would it?
It's *way* older than that (dates back to 1992), and the secret of its
meaning is more jealously guarded than the file proving who actually
killed JFK (although far less potent an information :-)).
When TDD got introduced a few years ago, I sure lost any hope of my nick
poiting to me in Google :-/
It's like the shiny new BDD thing, which kicked out of the way the
French fortunately-not-too-used "BDD" acronym ("Bases De Données"),
which is one of our equivalents to "DBMS."
> > Why "TDD"? That wouldn't refer to <tremulously> Test-Driven
> > Development </tremulously>, would it?
>
> It's *way* older than that (dates back to 1992)
I knew that. I was just dropping a hint... ;-)
I know that is far from cross-browser compatible and implementing it is on the night side of hackish, but I think it would be possible. The probability of more browsers supporting this even in the future is quite high in my opinion.
Mozilla/Opera have a proper events, which register cleanly. For IE there is a script defer hack and for Opera an interval timer that polls document.readyState variable.
To get around these glaring differences JQuery, another library where this "event" is implemented, binds their own function to the ready state test and then executes a member array of function pointers to give the same effect as a real event firing.
From JQuery:
------------------------------
// If Mozilla is used
if ( jQuery.browser.mozilla || jQuery.browser.opera )
// Use the handy event callback
document.addEventListener( "DOMContentLoaded", jQuery.ready, false );
// If IE is used, use the excellent hack by Matthias Miller
// http://www.outofhanwell.com/blog/index.php?title=the_window_onload_problem_revisited
else if ( jQuery.browser.msie ) {
// Only works if you document.write() it
document.write("<scr" + "ipt id=__ie_init defer=true " +
"src=//:><\/script>");
// Use the defer script hack
var script = document.getElementById("__ie_init");
// script does not exist if jQuery is loaded dynamically
if ( script )
script.onreadystatechange = function() {
if ( this.readyState != "complete" ) return;
this.parentNode.removeChild( this );
jQuery.ready();
};
// Clear from memory
script = null;
// If Safari is used
} else if ( jQuery.browser.safari )
// Continually check to see if the document.readyState is valid
jQuery.safariTimer = setInterval(function(){
// loaded and complete are both valid states
if ( document.readyState == "loaded" ||
document.readyState == "complete" ) {
// If either one are found, remove the timer
clearInterval( jQuery.safariTimer );
jQuery.safariTimer = null;
// and execute any waiting functions
jQuery.ready();
}
}, 10);
// A fallback to window.onload, that will always work
jQuery.event.add( window, "load", jQuery.ready );
-----------------------------------------
{ ...
ready: function() {
// Make sure that the DOM is not already loaded
if ( !jQuery.isReady ) {
// Remember that the DOM is ready
jQuery.isReady = true;
// If there are functions bound, to execute
if ( jQuery.readyList ) {
// Execute all of them
jQuery.each( jQuery.readyList, function(){
this.apply( document );
});
// Reset the list of functions
jQuery.readyList = null;
}
// Remove event lisenter to avoid memory leak
if ( jQuery.browser.mozilla || jQuery.browser.opera )
document.removeEventListener( "DOMContentLoaded", jQuery.ready, false );
}
}
}
-----------------------------
-Andrew Martinez
Note that in general, most stuff _can_ be done with standards-
compliant HTML/JavaScript/CSS/whatever.
However, in many of the more esoteric cases, the standards just
aren't there.
Good thing libs like Prototype do most of the h4x0r1ng for you. :)
Best,
Thomas
I know that this has been brought up before, but Is prototype going to support the on DOM ready state ability?
I know that is far from cross-browser compatible and implementing it is on the night side of hackish, but I think it would be possible. The probability of more browsers supporting this even in the future is quite high in my opinion.
Mozilla/Opera have a proper events, which register cleanly. For IE there is a script defer hack and for Opera an interval timer that polls document.readyState variable.
To get around these glaring differences JQuery, another library where this "event" is implemented, binds their own function to the ready state test and then executes a member array of function pointers to give the same effect as a real event firing.
From JQuery:
------------------------------
// If Mozilla is used
if ( jQuery.browser.mozilla || jQuery.browser.opera )
// Use the handy event callback
document.addEventListener( "DOMContentLoaded", jQuery.ready, false );
// If IE is used, use the excellent hack by Matthias Miller
// http://www.outofhanwell.com/blog/index.php?title=the_window_onload_problem_revisited
else if ( jQuery.browser.msie ) {
// Only works if you document.write() it
document.write ("<scr" + "ipt id=__ie_init defer=true " +
"src=//:><\/script>");
// Use the defer script hack
var script = document.getElementById ("__ie_init");
Thanks, that little snippet lead to the snippet I included at the bottom which other people might like. The ready state check is reverse-engineered (rather de-obfuscated ) and is then wrapped around a bit more logic. I did this because as I was de-obfuscating I decided that calling the original snippet over and over would create 1 timer for each registered “observer”. This snippet uses the same idea as JQuery and registers 1 watcher or 1 event handler and then loops over array. In the array errors are caught and pushed into another array and the first error is thrown after all other callbacks have been executed.
Feel free to use and make more prototype-ish. (The array look could be an iterator for one…)
------------------------------------------------------------------------------
var ReadyState = new Object();
ReadyState.onContentQueue = new Array();
ReadyState.onContent = function()
{
var errors = new Array();
ReadyState.isContentLoaded = true;
for( var i = 0; i < ReadyState.onContentQueue.length; i++ )
{
try
{
ReadyState.onContentQueue[i]();
}
catch(e)
{
//delay errors
errors.push(e);
}
}
if( errors.length > 0 )
{
//throw first error only.
throw errors[0];
}
}
ReadyState.addContentObserver = function ( functor )
{
ReadyState.enableOnContent();
if( functor && typeof( functor ) == "function" )
{
if( ReadyState.isContentLoaded )
{
functor();
}
else
{
ReadyState.onContentQueue.push( functor );
}
}
}
ReadyState.isContentLoaded = false;
ReadyState.isOnContentEnabled = false;
/**
* Modified from //from http://www.3site.eu/jstests/onContent/final.html
*
*
*
*/
ReadyState.enableOnContent = function( )
{
if( !ReadyState.isOnContentEnabled )
{
var ieScript = "<scr".concat("ipt defer src='//:' on", "readyState" , "change='if(this.", "readyState" ,"==\"complete\"){this.parentNode.removeChild(this);","__onContent__","()}'></scr","ipt>");
window.__onContent__ = (function(o)
{
return function()
{
window.__onContent__ = function(){};
for( var a = arguments.callee; !a.done; a.done=1 )
ReadyState.onContent(o?o():o)
}
})(window.__onContent__);
if( document.addEventListener )
{
document.addEventListener( "DOMContentLoaded", window.__onContent__, false);
}
if( /WebKit|Khtml/i.test(navigator.userAgent) || (window.opera && parseInt(window.opera.version()) < 9 ) )
{
(function(){ /loaded|complete/.test(document.readyState)?window[c]():setTimeout(arguments.callee,5)})();
}
else if(/MSIE/i.test(navigator.userAgent))
{
document.write(ieScript);
}
}
ReadyState.isOnContentEnabled = true;
}
ReadyState.enableOnContent();
ReadyState.addContentObserver( /*your code here*/ );
-----------------------------------------------------------------------------
-Andrew Martinez
<br
color=black>
After a few hours I can reproduce the problem reliably, but still don't
understand it. The culprit is the firebug logging script.
http://www.getfirebug.com/logging.html
After calling console.log, document.getElementsByClassName is undefined.
Up to that fateful call document and its properties is fine.