document "expando" properties broken in Konqueror

2 views
Skip to first unread message

Michael Schuerig

unread,
Feb 11, 2007, 8:59:01 PM2/11/07
to rubyonrail...@googlegroups.com

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.

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/

Phlip

unread,
Feb 11, 2007, 11:07:11 PM2/11/07
to rubyonrail...@googlegroups.com
Michael Schuerig wrote:

> 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!!!

Christophe Porteneuve

unread,
Feb 12, 2007, 3:44:05 AM2/12/07
to rubyonrail...@googlegroups.com
Hey Phlip,

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

Christophe Porteneuve

unread,
Feb 12, 2007, 3:51:30 AM2/12/07
to rubyonrail...@googlegroups.com
Hey Michael,

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?

Michael Schuerig

unread,
Feb 12, 2007, 6:37:46 AM2/12/07
to rubyonrail...@googlegroups.com
On Monday 12 February 2007, Christophe Porteneuve wrote:
> Hey Michael,
>
> 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").

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.

Thomas Fuchs

unread,
Feb 12, 2007, 7:14:31 AM2/12/07
to rubyonrail...@googlegroups.com

Am 12.02.2007 um 09:44 schrieb Christophe Porteneuve:

> 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

Christophe Porteneuve

unread,
Feb 12, 2007, 7:45:47 AM2/12/07
to rubyonrail...@googlegroups.com
Hey 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

Phlip

unread,
Feb 12, 2007, 8:15:12 AM2/12/07
to rubyonrail...@googlegroups.com
Christophe Porteneuve wrote:

> "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!!

Thomas Fuchs

unread,
Feb 12, 2007, 8:36:33 AM2/12/07
to rubyonrail...@googlegroups.com
Always, always, always remember that this is the Real world(tm).

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

http://www.wollzelle.com

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


Christophe Porteneuve

unread,
Feb 12, 2007, 8:29:39 AM2/12/07
to rubyonrail...@googlegroups.com
Hey Phlip,

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,

Phlip

unread,
Feb 12, 2007, 10:42:32 AM2/12/07
to rubyonrail...@googlegroups.com
Christophe Porteneuve wrote:

> 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.

Phlip

unread,
Feb 12, 2007, 10:43:43 AM2/12/07
to rubyonrail...@googlegroups.com
Thomas Fuchs wrote:

> Be pragmatic, use what works. :)

Modulo keep an eye on how compliance with the alleged "standards" are
going to evolve over time...

Christophe Porteneuve

unread,
Feb 12, 2007, 11:08:56 AM2/12/07
to rubyonrail...@googlegroups.com
Hey,

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."

Phlip

unread,
Feb 12, 2007, 11:13:48 AM2/12/07
to rubyonrail...@googlegroups.com
Christophe Porteneuve wrote:

> > 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... ;-)

Martinez, Andrew

unread,
Feb 12, 2007, 11:24:16 AM2/12/07
to rubyonrail...@googlegroups.com
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");

// 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

Thomas Fuchs

unread,
Feb 12, 2007, 11:29:26 AM2/12/07
to rubyonrail...@googlegroups.com
Ha. :)

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

Casey O'Neill

unread,
Feb 12, 2007, 12:10:49 PM2/12/07
to rubyonrail...@googlegroups.com
I prefer to use the this implementation written by Andrea Giammarchi. It work with SSL too. Check it out in action http://www.3site.eu/jstests/onContent/final.html



function onContent(f){//from http://www.3site.eu/jstests/onContent/final.html
var a,b=navigator.userAgent,d=document,w=window,
c="__onContent__",e="addEventListener",o="opera",r="readyState",
s="<scr".concat("ipt defer src='//:' on",r,"change='if(this.",r,"==\"complete\"){this.parentNode.removeChild(this);",c,"()}'></scr","ipt>");
w[c]=(function(o){return function(){w[c]=function(){};for(a=arguments.callee;!a.done;a.done=1)f(o?o():o)}})(w[c]);
if(d[e])d[e]("DOMContentLoaded",w[c],false);
if(/WebKit|Khtml/i.test(b)||(w[o]&&parseInt(w[o].version())<9))
(function(){/loaded|complete/.test(d[r])?w[c]():setTimeout(arguments.callee,1)})();
else if(/MSIE/i.test(b))d.write(s);
};

//example
onContent(function(){
  
    foo(); //called on dom ready

})

On 2/12/07, Martinez, Andrew <Andrew....@paetec.com> wrote:

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");

Martinez, Andrew

unread,
Feb 12, 2007, 2:50:27 PM2/12/07
to rubyonrail...@googlegroups.com

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>

Michael Schuerig

unread,
Feb 14, 2007, 9:09:27 PM2/14/07
to rubyonrail...@googlegroups.com

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.

Reply all
Reply to author
Forward
0 new messages