I'm trying to get and set an element's opacity, but I'm stuck with,
what a hell of surprise, Internet Explorer. As for getting the
element's opacity, I have the following (not working) lines of code:
if ( targetObject.filters && targetObject.filters.length > 0 )
opacity =
targetObject.filters.item("DXImageTransform.Microsoft.Alpha").Opacity;
Setting it, I tried:
if ( targetObject.filters && targetObject.filters.length > 0 )
targetObject.setAttribute( "style", "filter: alpha(opacity=" +
opacity + ")" );
None work. I have digged these out from some MSDN article, but they
aren't working, at least they don't work in to me available IE 6.0. Do
you have better (i.e. working) ways of yours?
Thanks
Darko
I don't know what was wrong there, but I see you think that opacity is
only available for IE. There's an equivalent feature in Mozilla browsers
using custom CSS properties. You'll have to sniff for the browsers and
branch your code to handle it (totally) differently, but it's definitely
possible. Not that I've ever used it, but I have seen itt.
Do you still remember which one?
> but they
> aren't working, at least they don't work in to me available IE 6.0.
Of course they don't: setAttribute method has nothing to do with it.
> Do you have better (i.e. working) ways of yours?
Not mine, but tested working:
I knew I'd seen it somewhere :)
Probably
http://msdn2.microsoft.com/en-us/library/ms532847.aspx#Scripting_Filters or
a previous version.
>> but they
>> aren't working, at least they don't work in to me available IE 6.0.
>
> Of course they don't: setAttribute method has nothing to do with it.
To be precise, setAttribute() does not seem to work there *for IE*.
>> Do you have better (i.e. working) ways of yours?
>
> Not mine, but tested working:
>
> http://www.quirksmode.org/js/opacity.html
However, it does not make sense in passing ranges from 0 to 10 and then
computing the required value twice. With the division for `opacity', there
is even a rounding error involved, needlessly. It makes more sense have
`value' range from 0 to 1 (thereby to pass the percentage x% as 0.0x to the
function); the computation will have to be done only once (for `filter'),
and the used values will be as exact as the layout engine allows it:
function setOpacity(value)
{
testObj.style.opacity = value;
testObj.style.filter = 'alpha(opacity=' + value * 100 + ')';
}
PointedEars
--
Prototype.js was written by people who don't know javascript for people
who don't know javascript. People who don't know javascript are not
the best source of advice on designing systems that use javascript.
-- Richard Cornford, cljs, <f806at$ail$1$8300...@news.demon.co.uk>
Does the element have a layout? In IE terms, it's gotta have position
or height/width for proprietary hasLayout to be be true.
DXImageTransform can work for background images, too, but doesn't let
you set any other background-properties (like background-position).
Regarding other comments on this thread: Opacity is CSS3, not a moz-
specific css. it works in Mozilla, Webkit and Opera.
Garrett
> Thanks
>
> Darko
No, I don't think that. I use "opacity" regularly for other browsers,
but
it doesn't work with IE. So I googled out that IE needs this filter
thing,
which they claim works by accessing .filters subobject, but it seems
as if it
does not. So I gave up and did as it was only possible, using
.style.filter = ..., which I like less than the proposed solution from
MSDN
(which doesn't work). Never mind.
As for opacity, now that I gave in and had it .style.filter = "...",
it finally
works well with IE, too. Another problem though - Konqueror. It seems
to ignore:
opacity
-moz-opacity
-khtml-opacity
filter
Wtf. does it need? Does Konqueror actually support element's opacity?
I wouldn't mind
the bloody Konqueror not working properly with my site, but as I
understand Safari uses
the same KHTML engine, so I reckon if Konqueror doesn't work (as it
doesn't), then Safari
won't neither. Am I right? Or Safari uses a KHTML branch that actually
supports the standard?
Thanks
The issue is not that the element has "no layout" which you could
have figured out by now. And nobody mentioned `hasLayout' (whatever
that might be) until now.
> DXImageTransform can work for background images, too,
I have to see that before I believe it.
> but doesn't let you set any other background-properties (like
> background-position).
You are probably describing the following PNGA workaround for IE 6:
#portal-logo {
background: none;
filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true,
sizingMethod=scale src='bannertop_right.png');
}
In which case the background image is *disabled* in order to apply the
filter. The result is not a real background image.
Please learn to quote.
PointedEars
--
realism: HTML 4.01 Strict
evangelism: XHTML 1.0 Strict
madness: XHTML 1.1 as application/xhtml+xml
-- Bjoern Hoehrmann
and with his subsequent corrections I believe he intended to post the
following
var global = this;
var setOpacity = (function() {
var i, l, html;
var doc = global.document;
var opacityStyles = ['opacity', 'MozOpacity', 'KhtmlOpacity'];
if (doc) {
html = (doc.all[0].tagName == '!')?doc.all[1]:doc.all[0];
if (!html && doc.all && doc.all[0]) {
html = (doc.all[0].tagName == '!')?doc.all[0]:doc.all[1];
}
}
if (html && html.style) {
if (typeof html.style.filter != 'undefined') {
return function(el, o) {
var f;
if (el.filters) {
if (el.currentStyle && !el.currentStyle.hasLayout) {
el.style.zoom = 1;
}
f = el.filters.alpha;
if (typeof(f) != 'undefined') {
if (o == 1) {
f.enabled = false;
}
else {
f.enabled = true;
f.opacity = o * 100;
}
}
else {
if (el.style && typeof(el.style.filter) != 'undefined') {
el.style.filter += "alpha(opacity=" + (o * 100) + ")";
}
}
}
};
}
i = 0;
l = opacityStyles.length;
while (i < l) {
if (typeof(html.style[opacityStyles[i]]) == 'string') {
return (function(s) {
return function(el, o) {
el.style[s] = o;
};
})(opacityStyles[i]);
}
i++;
}
}
})();
I don't know what is trying to be accomplished with this part which
doesn't work in Firefox as document.all is not available. Is this a
way to get the document.documentElement object?
if (doc) {
html = (doc.all[0].tagName == '!')?doc.all[1]:doc.all[0];
if (!html && doc.all && doc.all[0]) {
html = (doc.all[0].tagName == '!')?doc.all[0]:doc.all[1];
}
}
--------------------------------------------
The code I have been using is the following
function setOpacity(el, val) {
// If "val" is very small then when converted to a string
// may will use scientific notation. This is not allowed in CSS.
// For example, in Firefox 1.5
// (0.0000001).toString() --> "1e-7"
if (val<0.00001) {
val = 0;
}
var s = el.style;
if (typeof s.filter == 'string') {
s.filter = s.filter.replace(/alpha\([^\)]*\)/gi,'') +
((val < 1) ? 'alpha(opacity='+val*100+')' : '');
// alpha opacity only applies if the element "has layout".
// IE4 has alpha but does not have currentStyle
if (!el.currentStyle ||
//IE 5+ can determine if element "has layout"
!el.currentStyle.hasLayout) {
// setting zoom is one of the ways to insure
// an element "has layout"
el.style.zoom = 1;
}
} else {
// if (early release edition of Firefox && val === 1) {
// // This trick is from Scriptaculous
// // Some version of Firefox (before 1.5?) flickers
// // when animating opacity up to a value of 1.
// // If this trick is to be used the test will probably be
// // expensive and should only be preformed the first time.
// //
// // Apparently using this trick increases the weight of
// // the DOM, for rendering speed?
//
// val = 0.999999;
// }
// Mac/Firefox-1.5, Mac/Opera-9, Mac/Safari-2,
// Win/NetscapeNavigator-8.0, KDE4/Konqueror
s.opacity = val;
// Win/NetscapeNavigator 6.0/7.0/8.0, Mac/Firefox-1.5
s.MozOpacity = val;
// -khtml-opacity does not apply to any version of Konqueror
// according to the
// folks on irc.freenode.net#kde. I set up some tests and
// one person ran them on
// development versions of KDE 4 and this is not supported
// Konqueror for KDE 4
// will be the first Konqueror version to support opacity
// settings.
// These KDE folks also told me that it was Safari 1.1 that
// supported the
// property below. I don't have anything less then 1.3
// anymore and have only tested
// on 2.0 so far. This does not work with Safari 2.0
s.KhtmlOpacity = val; // TODO some net sources have KHTMLOpacity
// YUI had this and I don't think it would work since
// their -moz-opacity didn't work
//s['-khtml-opacity'] = val;
}
}
Peter
This looks correct up until the capital 'O' on "Opacity" -- it should be
lowercase.
You would set the opacity the same way:
targetObject.filters.item("DXImageTransform.Microsoft.Alpha").opacity =
value;
Not shown here is whether "targetObject" is equivalent to:
document.getElementByID("theID") or actually "theID" ...
with IE, it is NOT document.getElementById("theID") but in fact, simply
'theID' of the element whose filters you are accessing or setting. (go
figure...)
To confuse things further, another method (and previously stated in
another post, i believe) of *setting* the opacity in IE 6+ (and possibly
5.5) is:
document.getElementById("theID").style.filter="alpha(opacity=" + value +
")";
// notice 'filter', not 'filters' here!
// also note that the filter object is an IE-only addition
// and that it's elem.style.opacity, not elem.style.filter.opacity
// in other browsers
Aside:
I don't do a lot of javascript programming anymore, so I'm not entirely
sure, but I believe most "modern" versions of *other* browsers (FF,
Konqueror, Safari, etc...) have dropped their proprietary prefixes (such
as -moz, -khtml, etc...) and simply use 'opacity' as the style property
these days. The likelihood of somebody still using a version of these
browsers that requires the prefixes is fairly slim (since almost all of
them have automatic updates to keep them secure and current.) I can be
absolutely sure about Firefox, whose last several (minor) versions do
not even support the old -moz prefix for backward compatibility! (I've
been using opacities for a long time now and was really ticked when I
had to go back and *fix* a lot of old pages for this aspect.)
fox
There appears to be a missing line from this transcription:
html = (doc.getElementsByTagName)?doc.getElementsByTagName('html')
[0]:doc.documentElement;
And since I posted that, I updated the function to deal with an IE5
DirectX incompatibility. I just updated it again to deal with the
float to string issue you mention in your version, as well as to force
the layout fix for IE4. I haven't tested the updated version.
setOpacity = (function(el) {
var i, l;
var reOpacity = new RegExp('alpha\\(opacity=[^\\)]+\\)', 'i');
var opacityStyles = ['opacity', 'MozOpacity', 'KhtmlOpacity'];
if (typeof el.style.filter == 'string') {
return function(el, o) {
var f;
if (el.filters) {
if (!el.currentStyle || !el.currentStyle.hasLayout)
{ el.style.zoom = 1; }
f = el.filters.alpha;
if (typeof(f) != 'undefined') {
f.enabled = o != 1;
f.opacity = o * 100;
}
else {
if (el.style.filter.indexOf('alpha(opacity=') == -1) {
el.style.filter = 'alpha(opacity=' + (o * 100) + ')';
}
else {
el.style.filter = el.style.filter.replace(reOpacity,
"alpha(opacity=" + (o * 100) + ")");
}
}
}
};
}
i = 0;
l = opacityStyles.length;
while (i < l) {
if (typeof(el.style[opacityStyles[i]]) == 'string') {
return (function(s) { return function(el, o) { el.style[s] = (o < .
00001)?0:o; }; })(opacityStyles[i]);
}
i++;
}
})(html);
The html variable passed to the one-off function is defined by a
dependant function, which calls other dependant functions, etc., so I
won't post that, but in a nutshell: try the documentElement, then try
getElementsByTagName if it is a feature of the document object, then
try doc.all.tags('html'). Otherwise, you are out of luck as there is
nothing to test with and you shouldn't run the above code at all.
>
> if (doc) {
> html = (doc.all[0].tagName == '!')?doc.all[1]:doc.all[0];
> if (!html && doc.all && doc.all[0]) {
> html = (doc.all[0].tagName == '!')?doc.all[0]:doc.all[1];
> }
>
This was a silly way to get around doc.all returning the docType
declaration. I had forgotten all about the tags method of the all
object.
> }
>
> --------------------------------------------
>
> The code I have been using is the following
>
> function setOpacity(el, val) {
>
> // If "val" is very small then when converted to a string
> // may will use scientific notation. This is not allowed in CSS.
> // For example, in Firefox 1.5
> // (0.0000001).toString() --> "1e-7"
> if (val<0.00001) {
> val = 0;
> }
>
> var s = el.style;
>
> if (typeof s.filter == 'string') {
>
> s.filter = s.filter.replace(/alpha\([^\)]*\)/gi,'') +
> ((val < 1) ? 'alpha(opacity='+val*100+')' : '');
>
> // alphaopacityonly applies if the element "has layout".
> // IE4 has alpha but does not have currentStyle
> if (!el.currentStyle ||
> //IE 5+ can determine if element "has layout"
> !el.currentStyle.hasLayout) {
> // setting zoom is one of the ways to insure
> // an element "has layout"
It's the best way I know to do it.
> el.style.zoom = 1;
> }
> } else {
> // if (early release edition of Firefox && val === 1) {
> // // This trick is from Scriptaculous
> // // Some version of Firefox (before 1.5?) flickers
I've seen this recently. It drove me to distraction while I was
working on a special effects module. I don't think it was an early
release though. I am pretty sure it was the latest major release.
> // // when animatingopacityup to a value of 1.
> // // If this trick is to be used the test will probably be
> // // expensive and should only be preformed the first time.
> // //
> // // Apparently using this trick increases the weight of
> // // the DOM, for rendering speed?
I am not sure what that means, but as I recall, setting .999999
instead of 1 makes no visible difference, other than to eliminate the
annoying flicker.
> //
> // val = 0.999999;
> // }
>
> // Mac/Firefox-1.5, Mac/Opera-9, Mac/Safari-2,
> // Win/NetscapeNavigator-8.0, KDE4/Konqueror
> s.opacity= val;
> // Win/NetscapeNavigator 6.0/7.0/8.0, Mac/Firefox-1.5
> s.MozOpacity = val;
> // -khtml-opacitydoes not apply to any version of Konqueror
> // according to the
> // folks on irc.freenode.net#kde. I set up some tests and
> // one person ran them on
> // development versions of KDE 4 and this is not supported
> // Konqueror for KDE 4
> // will be the first Konqueror version to supportopacity
> // settings.
> // These KDE folks also told me that it was Safari 1.1 that
> // supported the
> // property below. I don't have anything less then 1.3
> // anymore and have only tested
> // on 2.0 so far. This does not work with Safari 2.0
> s.KhtmlOpacity = val; // TODO some net sources have KHTMLOpacity
I can't help verify the original opacity code was written five or six
years ago and I can't remember if I ever tested it with Safari back
then. I have tested recently with Windows Safari, but I am pretty
sure it used the standard opacity style. That being said,
KHTMLOpacity just looks wrong to me.
> // YUI had this and I don't think it would work since
> // their -moz-opacitydidn't work
> //s['-khtml-opacity'] = val;
Clearly YUI is wrong in both cases.
[snip]
> And since I posted that, I updated the function to deal with an IE5
> DirectX incompatibility.
What is that and what part of your code relates to this problem?
[code below slightly reformatted to avoid wrapping]
> I just updated it again to deal with the
> float to string issue you mention in your version, as well as to force
> the layout fix for IE4. I haven't tested the updated version.
>
> setOpacity = (function(el) {
>
> var i,l;
> var reOpacity = new RegExp('alpha\\(opacity=[^\\)]+\\)', 'i');
> var opacityStyles = ['opacity', 'MozOpacity', 'KhtmlOpacity'];
>
> if (typeof el.style.filter == 'string') {
>
> return function(el, o) {
>
> var f;
>
> if (el.filters) {
> if (!el.currentStyle || !el.currentStyle.hasLayout) {
> el.style.zoom = 1;
> }
>
> f = el.filters.alpha;
>
> if (typeof(f) != 'undefined') {
> f.enabled = o != 1;
> f.opacity = o * 100;
> }
> else {
> if (el.style.filter.indexOf('alpha(opacity=') == -1) {
> el.style.filter = 'alpha(opacity=' + (o * 100) + ')';
> }
> else {
> el.style.filter = el.style.filter.replace(reOpacity,
> "alpha(opacity=" + (o * 100) + ")");
> }
> }
What is the benefit of the above if-else with the first f.enabled/
f.opacity branch? It is quite a bit of code bulk. Do you know of a
browser with el.filters that will not work with the else branch above?
Instead of the above 13 lines, in my version, I just write the
following
s.filter = s.filter.replace(/alpha\([^\)]*\)/gi,'') +
((val < 1) ? 'alpha(opacity='+val*100+')' : '');
> }
> };
>
> }
>
> i = 0;
>
> l = opacityStyles.length;
>
> while (i < l) {
> if (typeof(el.style[opacityStyles[i]]) == 'string') {
> return (function(s) {
> return function(el, o) {
> el.style[s] = (o < .00001)?0:o;
> };
> })(opacityStyles[i]);
> }
> i++;
> }
>
> })(html);
>
> The html variable passed to the one-off function is defined by a
> dependant function, which calls other dependant functions, etc., so I
> won't post that, but in a nutshell: try the documentElement, then try
> getElementsByTagName if it is a feature of the document object, then
> try doc.all.tags('html'). Otherwise, you are out of luck as there is
> nothing to test with and you shouldn't run the above code at all.
I can see that checking for document.documentElement and then falling
back to document.all.tags('html')[0] is beneficial as IE4 can set
opacity but doesn't have document.documentElement; however, what
browser is enabled by adding a check with getElementsByTagName into
the mix? I tested a bunch of browsers around the correct vintage and
didn't find one where adding the getElementsByTagName check helps. I
can see having the getElementsByTagName check for completeness but do
you happen to know of a browser where this check is the one that works
and document.documentElement and document.all.tags('html')[0] both
don't work?
Opera 5.02
document.documentElement // undefined
document.getElementsByTagName // undefined
document.all.tags('html').length // 0
document.all.tags('body').length // 1
Opera 6.0
document.documentElement // undefined
document.getElementsByTagName('html').length // 0
document.getElementsByTagName('body').length // 1
document.all.tags('html').length // 0
document.all.tags('body').length // 1
Opera 7.02
document.documentElement // [object HTMLHtmlElement]
document.getElementsByTagName('html').length // 1
document.getElementsByTagName('body').length // 1
document.all.tags('html').length // 0
document.all.tags('body').length // 1
Opera 8.0
document.documentElement // [object HTMLHtmlElement]
document.getElementsByTagName('html').length // 1
document.getElementsByTagName('body').length // 1
document.all.tags('html').length // 1
document.all.tags('body').length // 1
IE 4
document.documentElement // undefined
document.getElementsByTagName // undefined
document.all.tags('html').length // 1
IE 5.0
document.documentElement // [Object]
document.getElementsByTagName('html').length // 1
document.all.tags('html').length // 1
NN4.0 & NN4.08 & NN4.5
document.documentElement // undefined
document.getElementsByTagName // undefined
document.all // undefined
NN6.0
document.documentElement // [object HTMLHtmlElement]
document.getElementsByTagName('html').length // 1
document.all // undefined
> > if (doc) {
> > html = (doc.all[0].tagName == '!')?doc.all[1]:doc.all[0];
> > if (!html && doc.all && doc.all[0]) {
> > html = (doc.all[0].tagName == '!')?doc.all[0]:doc.all[1];
> > }
>
> This was a silly way to get around doc.all returning the docType
> declaration. I had forgotten all about the tags method of the all
> object.
I didn't even know about it.
[snip]
> > // if (early release edition of Firefox && val === 1) {
> > // // This trick is from Scriptaculous
> > // // Some version of Firefox (before 1.5?) flickers
>
> I've seen this recently. It drove me to distraction while I was
> working on a special effects module. I don't think it was an early
> release though. I am pretty sure it was the latest major release.
I've never managed to make it flicker on any version.
> > // // when animatingopacityup to a value of 1.
> > // // If this trick is to be used the test will probably be
> > // // expensive and should only be preformed the first time.
> > // //
> > // // Apparently using this trick increases the weight of
> > // // the DOM, for rendering speed?
>
> I am not sure what that means, but as I recall, setting .999999
> instead of 1 makes no visible difference, other than to eliminate the
> annoying flicker.
Someone told me or I read that by setting several elements with
opacity makes the DOM "heavier". I can only assume they mean it takes
longer to render or that it takes more RAM or something like that. The
idea of limiting this 0.99999 trick to only the versions of FF that
need it was to avoid adding this "weight" to browsers that don't need
the trick. The importance given to this "weight" issue sounded a
little like flaky to me.
I have personally tested opacity on Safari 1.0 and Safari 1.2+. Safari
1.0 does not support any opacity setting, as far as I could tell.
Safari 1.2 and up supports the standard CSS "opacity" and no option
related to any string with "khtml" in any case. By process of
elimination,Safari 1.1 must be the browser that had this khtml opacity
business. I cannot find a built copy of this version and have not been
able to test it.
I chatted with the folks on IRC freenode#webkit (users proton and
bdash, in particular) and they had some helpful information...
On the following page you can see which webkit build goes with which
svn repository tag goes with which version of Safari
http://developer.apple.com/internet/safari/uamatrix.html
Safari 1.1 has the "Safari-100" build and the approriate bit of code
is a function called "jsNameToProp"
<URL: http://trac.webkit.org/projects/webkit/browser/tags/Safari-100/WebCore/khtml/ecma/kjs_css.cpp#L34>
static QString jsNameToProp( const Identifier &p )
{
QString prop = p.qstring();
int i = prop.length();
while( --i ) {
char c = prop[i].latin1();
if ( c < 'A' || c > 'Z' )
continue;
prop.insert( i, '-' );
}
return prop.lower();
}
A '-' character will be inserted before any capital letter and then
the whole string is lowercased. So "KhtmlOpacity" will be converted to
"-khtml-opacity". This is the desired output.
------------------
The confusion comes later in Safari-110 when "jsNameToProp" is
replaced with "cssPropertyName". The new "cssPropertyName" function
will convert both "KhtmlOpacity" and "khtmlOpacity" to "-khtml-
opacity"
<URL: http://trac.webkit.org/projects/webkit/browser/tags/Safari-110/WebCore/khtml/ecma/kjs_css.cpp#L34>
static QString cssPropertyName(const Identifier &p, bool
*hadPixelOrPosPrefix = 0)
{
QString prop = p.qstring();
int i = prop.length();
while (--i) {
char c = prop[i].latin1();
if (c >= 'A' && c <= 'Z')
prop.insert(i, '-');
}
prop = prop.lower();
if (hadPixelOrPosPrefix)
*hadPixelOrPosPrefix = false;
if (prop.startsWith("css-")) {
prop = prop.mid(4);
} else if (prop.startsWith("pixel-")) {
prop = prop.mid(6);
if (hadPixelOrPosPrefix)
*hadPixelOrPosPrefix = true;
} else if (prop.startsWith("pos-")) {
prop = prop.mid(4);
if (hadPixelOrPosPrefix)
*hadPixelOrPosPrefix = true;
} else if (prop.startsWith("khtml-")) {
prop.insert(0, '-');
}
return prop;
}
In conclusion (without testing), the most backwards compatible option
is to use "KhtmlOpacity" and I really think open source software is
cool.
[snip]
On the Quirksmode site it states that opacity cannot be set on tbody
and tr elements in many browsers. So just because the setOpacity
function is defined in a particular browser based on analysis of the
<html> element, it doesn't mean that setting opacity on any element
will "just work".
Cross browser opacity setting is just so much fun! :-S
Peter
el.style.filter += 'alpha(opacity=' + (o * 100) + ')';
This was incorrectly posted as:
el.style.filter = 'alpha(opacity=' + (o * 100) + ')';
If you don't check first, IE5 will tack that on over and over as that
browser never creates the el.filters.alpha property. The regex was
added to update the filter property in IE5.
The first branch is cleaner and faster. You don't want to get into
string concatenation and/or regex manipulation unless it is necessary
(the first time for each element in IE6/7 and every time in IE5.)
That being said, it looks like the else branch could be tightened up a
bit in terms of size. No need to figure the opacity filter string in
two different places.
>
> Instead of the above 13 lines, in my version, I just write the
> following
>
> s.filter = s.filter.replace(/alpha\([^\)]*\)/gi,'') +
> ((val < 1) ? 'alpha(opacity='+val*100+')' : '');
>
Smaller in size, but slower in IE6/7. I think this is as small as it
gets without compromising performance:
f = el.filters.alpha;
if (f) {
f.enabled = o != 1; // IE screws up some fonts when filter is left
enabled
f.opacity = o * 100; // This has got to be faster than string
concatenation
}
else { // IE6/7 never get here unless an opacity has never been set
s = 'alpha(opacity=' + (o * 100) + ')';
if (reOpacity.test(el.style.filter)) { // IE5 every time
el.style.filter = el.style.filter.replace(reOpacity, s);
}
else { // IE6/7 once
el.style.filter += s;
}
}
It would have to be a browser without document.documentElement and
with gEBTN. No idea is such an animal exists.
>
> Opera 5.02
> document.documentElement // undefined
> document.getElementsByTagName // undefined
> document.all.tags('html').length // 0
That's odd.
> document.all.tags('body').length // 1
>
> Opera 6.0
> document.documentElement // undefined
> document.getElementsByTagName('html').length // 0
So is that.
> document.getElementsByTagName('body').length // 1
> document.all.tags('html').length // 0
And that. I realize Opera 5/6 were lousy browsers, but how could they
dispute the existence of at least one HTML element? Do these support
opacity? If so, and you really want to support them, then defer the
feature test until the body element is parsed and pass it to the one-
off. I do that for some things that don't need to be used until the
document is ready.
> document.all.tags('body').length // 1
>
> Opera 7.02
> document.documentElement // [object HTMLHtmlElement]
> document.getElementsByTagName('html').length // 1
> document.getElementsByTagName('body').length // 1
> document.all.tags('html').length // 0
Stupid.
> document.all.tags('body').length // 1
>
> Opera 8.0
> document.documentElement // [object HTMLHtmlElement]
> document.getElementsByTagName('html').length // 1
> document.getElementsByTagName('body').length // 1
> document.all.tags('html').length // 1
> document.all.tags('body').length // 1
>
> IE 4
> document.documentElement // undefined
> document.getElementsByTagName // undefined
> document.all.tags('html').length // 1
That's really the case I was thinking of when I added the document.all
check.
>
> IE 5.0
> document.documentElement // [Object]
> document.getElementsByTagName('html').length // 1
> document.all.tags('html').length // 1
>
> NN4.0 & NN4.08 & NN4.5
> document.documentElement // undefined
> document.getElementsByTagName // undefined
> document.all // undefined
Never mind these.
>
> NN6.0
> document.documentElement // [object HTMLHtmlElement]
> document.getElementsByTagName('html').length // 1
> document.all // undefined
>
> > > if (doc) {
> > > html = (doc.all[0].tagName == '!')?doc.all[1]:doc.all[0];
> > > if (!html && doc.all && doc.all[0]) {
> > > html = (doc.all[0].tagName == '!')?doc.all[0]:doc.all[1];
> > > }
>
> > This was a silly way to get around doc.all returning the docType
> > declaration. I had forgotten all about the tags method of the all
> > object.
>
> I didn't even know about it.
>
> [snip]
>
> > > // if (early release edition of Firefox && val === 1) {
> > > // // This trick is from Scriptaculous
> > > // // Some version of Firefox (before 1.5?) flickers
>
> > I've seen this recently. It drove me to distraction while I was
> > working on a special effects module. I don't think it was an early
> > release though. I am pretty sure it was the latest major release.
>
> I've never managed to make it flicker on any version.
It only seems to happen when animating the opacity with a timer and
only when starting from 1. Start from .99999 or whatever and it goes
away. I eventually changed the timing of something and got it worked
out of my effects module without resorting to the .99999 hack.
>
> > > // // when animatingopacityup to a value of 1.
> > > // // If this trick is to be used the test will probably be
> > > // // expensive and should only be preformed the first time.
> > > // //
> > > // // Apparently using this trick increases the weight of
> > > // // the DOM, for rendering speed?
>
> > I am not sure what that means, but as I recall, setting .999999
> > instead of 1 makes no visible difference, other than to eliminate the
> > annoying flicker.
>
> Someone told me or I read that by setting several elements with
> opacity makes the DOM "heavier". I can only assume they mean it takes
> longer to render or that it takes more RAM or something like that. The
> idea of limiting this 0.99999 trick to only the versions of FF that
> need it was to avoid adding this "weight" to browsers that don't need
> the trick. The importance given to this "weight" issue sounded a
> little like flaky to me.
I think it does take a little more work to render a semi-transparent
element, but the idea of using .999999 in lieu of 1 is silly.
> <URL:http://trac.webkit.org/projects/webkit/browser/tags/Safari-100/WebCor...>
>
> static QString jsNameToProp( const Identifier &p )
> {
> QString prop = p.qstring();
> int i = prop.length();
> while( --i ) {
> char c = prop[i].latin1();
> if ( c < 'A' || c > 'Z' )
> continue;
> prop.insert( i, '-' );
> }
>
> return prop.lower();
>
> }
>
> A '-' character will be inserted before any capital letter and then
> the whole string is lowercased. So "KhtmlOpacity" will be converted to
> "-khtml-opacity". This is the desired output.
I thought that was the right one.
>
> ------------------
>
> The confusion comes later in Safari-110 when "jsNameToProp" is
> replaced with "cssPropertyName". The new "cssPropertyName" function
> will convert both "KhtmlOpacity" and "khtmlOpacity" to "-khtml-
> opacity"
>
> <URL:http://trac.webkit.org/projects/webkit/browser/tags/Safari-110/WebCor...>
>
> static QString cssPropertyName(const Identifier &p, bool
> *hadPixelOrPosPrefix = 0)
> {
> QString prop = p.qstring();
[snip]
> In conclusion (without testing), the most backwards compatible option
> is to use "KhtmlOpacity" and I really think open source software is
> cool.
[snip]
>On the Quirksmode site it states that opacity cannot be set on tbody
>and tr elements in many browsers. So just because the setOpacity
>function is defined in a particular browser based on analysis of the
><html> element, it doesn't mean that setting opacity on any element
>will "just work".
For the most part it does. Doing it for table rows or groups of table
rows would seem an odd thing to do anyway. Add a disclaimer about
table rows at the top and you are done. Feel free to add it to your
repository.
>Cross browser opacity setting is just so much fun! :-S
It's a picnic compared to some things.
A couple other notes.
The original stand-alone version tested for the existence of the style
object. The recently posted version comes from a module that checks
that elsewhere. So that check should be added.
And seeing that Opera 5/6 refuse to find the html element using gEBTN
or the all object, I updated my code to use the previously posted
check of all[0] and all[1] if the html variable cannot be set any
other way. That branch will only run for Opera 5/6 or antiquated
mobile browsers and is only a couple of extra lines. It is a moot
point for this example if Opera 5/6 do not support opacity, but the
function that finds the html element is crucial for lots of other
feature tests (at least if they are to be run in the head of the
document.)
If this is to be added to your repository, it would be a good
foundation for it and other style-related code to have functions that
find the html element for a given document and determine if the host
is capable of CSS manipulation by testing for the presence of the
element's style object.
[snip]
> > > > // if (early release edition of Firefox && val === 1) {
> > > > // // This trick is from Scriptaculous
> > > > // // Some version of Firefox (before 1.5?) flickers
>
> > > I've seen this recently. It drove me to distraction while I was
> > > working on a special effects module. I don't think it was an early
> > > release though. I am pretty sure it was the latest major release.
>
> > I've never managed to make it flicker on any version.
>
> It only seems to happen when animating the opacity with a timer and
> only when starting from 1. Start from .99999 or whatever and it goes
> away. I eventually changed the timing of something and got it worked
> out of my effects module without resorting to the .99999 hack.
>
> > > > // // when animatingopacityup to a value of 1.
> > > > // // If this trick is to be used the test will probably be
> > > > // // expensive and should only be preformed the first time.
> > > > // //
> > > > // // Apparently using this trick increases the weight of
> > > > // // the DOM, for rendering speed?
>
> > > I am not sure what that means, but as I recall, setting .999999
> > > instead of 1 makes no visible difference, other than to eliminate the
> > > annoying flicker.
>
> > Someone told me or I read that by setting several elements with
> > opacity makes the DOM "heavier". I can only assume they mean it takes
> > longer to render or that it takes more RAM or something like that. The
> > idea of limiting this 0.99999 trick to only the versions of FF that
> > need it was to avoid adding this "weight" to browsers that don't need
> > the trick. The importance given to this "weight" issue sounded a
> > little like flaky to me.
>
> I think it does take a little more work to render a semi-transparent
> element, but the idea of using .999999 in lieu of 1 is silly.
I believe the flicker issue included animating from an opacity below 1
up to 1 in which case the animation needed to stop before 1. I can't
say this is silly.
[snip]
> For the most part it does. Doing it for table rows or groups of table
> rows would seem an odd thing to do anyway. Add a disclaimer about
> table rows at the top and you are done. Feel free to add it to your
> repository.
I'm starting a branch for opacity. I think it will serve as a good
first DHTML example.
Peter
Would you mind posting your function that finds the html element?
Peter
Okay. I just updated it this morning and haven't had time to test it
thoroughly.
var doc = this.document;
var isRealObject = function(o) {
return !!(o && typeof(o) == 'object');
};
var htmlElement = function(docNode) {
var html;
docNode = docNode || doc;
html = isRealObject(docNode.documentElement)?docNode.documentElement:
(documentElementsByTagName)?documentElementsByTagName('html', docNode)
[0]:null);
if (!html && docNode.all && docNode.all[0]) {
html = docNode.all[(docNode.all[0].tagName == '!')?1:0] || null;
if (html && html.tagName.toLowerCase() != 'html') { html = null; }
}
return html;
};
The missing documentElementsByTagName function is a wrapper for gEBTN
that only exists if the document object features such a method. It
exists to smooth out problems with the "*" parameter, as well as using
the all object for agents that don't feature gEBTN. It isn't really
needed now that the additional clause has been added to handle Opera
5/6, so you should just change it to doc.getElementsByTagName. And if
you are wondering why these are created with variable assignments, it
is because they create object methods in the original code.
If docNode.documentElement is defined, will it ever be any type other
than 'object'? It seems like checking this is unnecessary if there has
never been a known problem.
> ?docNode.documentElement:
> (documentElementsByTagName)?documentElementsByTagName('html', docNode)
If documentElementsByTagName may be undefined then the above ternary
conditional will error in browsers where it is undefined. I think it
should be
(typeof documentElementsByTagName != 'undefined')?
documentElementsByTagName('html', docNode)
> [0]:null);
> if (!html && docNode.all && docNode.all[0]) {
> html = docNode.all[(docNode.all[0].tagName == '!')?1:0] || null;
> if (html && html.tagName.toLowerCase() != 'html') { html = null; }
> }
> return html;
>
> };
>
> The missing documentElementsByTagName function is a wrapper for gEBTN
> that only exists if the document object features such a method. It
> exists to smooth out problems with the "*" parameter, as well as using
> the all object for agents that don't feature gEBTN. It isn't really
> needed now that the additional clause has been added to handle Opera
> 5/6, so you should just change it to doc.getElementsByTagName.
When I looked at document.documentElement, document.all.tags and
document.getElementsByTagName, I stated that in IE4
document.all.tags('html').length is 1. That is only true after
window.onload fires. Before window.onload the length is 0. Since
feature testing is preferably done in the head right when the script
loads, the document.all.tags check isn't really enabling any
particular browsers, as far as I know. This goes along with your "It
isn't really needed now...."
Of the browsers I checked that can set opacity, only IE4 and Opera 6-
don't have document.documentElement. I don't mind degrading those
browsers to not use opacity setting. This would make the setOpacity
and all other functions requiring an element for feature testing not
dependent on an htmlElement function like you've outlined. In my eyes,
that is a nice reduction in code size. Code always might contain bugs
and needs testing as we have seen even here (not meant as criticism
but as an argument to reduce code size where reasonable). I think that
only checking for document.documentElement is a reasonable place to
draw the line in browser history given the approximate distribution of
browser version in use today. Any non-trivial CSS that may need the
fallbacks in the htmlElement function for a feature tests likely won't
work in IE4 anyway. Sound reasonable?
As a reference for this threshold, I don't wrap document.all and
document.getElementById together in a function. I just check for
document.getElementById.
[snip]
Peter
There is the possibility, however remote, that it could be a null
object.
>
> > ?docNode.documentElement:
> > (documentElementsByTagName)?documentElementsByTagName('html', docNode)
>
> If documentElementsByTagName may be undefined then the above ternary
> conditional will error in browsers where it is undefined. I think it
> should be
>
> (typeof documentElementsByTagName != 'undefined')?
> documentElementsByTagName('html', docNode)
If you mean that documentElementsByTagName has never been declared,
that is impossible in the context this code came from (it is a
declared variable.) It may have an undefined value, but that won't
throw an error.
>
> > [0]:null);
> > if (!html && docNode.all && docNode.all[0]) {
> > html = docNode.all[(docNode.all[0].tagName == '!')?1:0] || null;
> > if (html && html.tagName.toLowerCase() != 'html') { html = null; }
> > }
> > return html;
>
> > };
>
> > The missing documentElementsByTagName function is a wrapper for gEBTN
> > that only exists if the document object features such a method. It
> > exists to smooth out problems with the "*" parameter, as well as using
> > the all object for agents that don't feature gEBTN. It isn't really
> > needed now that the additional clause has been added to handle Opera
> > 5/6, so you should just change it to doc.getElementsByTagName.
>
> When I looked at document.documentElement, document.all.tags and
> document.getElementsByTagName, I stated that in IE4
> document.all.tags('html').length is 1. That is only true after
> window.onload fires. Before window.onload the length is 0. Since
> feature testing is preferably done in the head right when the script
> loads, the document.all.tags check isn't really enabling any
> particular browsers, as far as I know. This goes along with your "It
> isn't really needed now...."
Were all of those results determined after onload? If so, I would
like to see what they look like when run in the head. Regardless, I
assume that document.all[0] is defined before the onload event fires,
so the added test should be sufficient.
>
> Of the browsers I checked that can set opacity, only IE4 and Opera 6-
> don't have document.documentElement. I don't mind degrading those
> browsers to not use opacity setting. This would make the setOpacity
> and all other functions requiring an element for feature testing not
> dependent on an htmlElement function like you've outlined. In my eyes,
Opacity yes, but all other style-related functions? That seems
extreme. Also, there is no reason why such functions can't run after
the body has been parsed (e.g. in a real or simulated DOMContentLoaded
listener.) I do that for several functions that have to create
elements and append them to the body to detect quirks like Opera's
botched offsetLeft/Top reporting. It seems like setOpacity is
something that wouldn't be needed until the document is ready, else
how would you reliably find the element you want to fade?
> that is a nice reduction in code size. Code always might contain bugs
> and needs testing as we have seen even here (not meant as criticism
> but as an argument to reduce code size where reasonable). I think that
Well, it turned out that it wasn't a bug, but I get your point.
> only checking for document.documentElement is a reasonable place to
> draw the line in browser history given the approximate distribution of
> browser version in use today. Any non-trivial CSS that may need the
> fallbacks in the htmlElement function for a feature tests likely won't
> work in IE4 anyway. Sound reasonable?
Sort of. How would a script determine if CSS is even available when
running in IE4, Opera 6, etc.? One of the first flags I set is based
on the presence of a style object. If it doesn't exist then lots of
unneeded feature testing is skipped and style-related functions are
not created. Next I check the types of the display, visibility and
position properties of the object (typically strings, but not always)
and those three results determine which style-related modules should
be initialized. They are also referenced by applications to determine
if it is possible to hide dynamically replaced content during the page
load (i.e. if a style rule is added before the body is parsed, will it
be possible to overrule it with an inline style once the content is
replaced after parsing.) Can you confirm if IE4 can get the HTML
element via document.all[0] (or document.all[1]?) If not, can it get
any element during page load?
>
> As a reference for this threshold, I don't wrap document.all and
> document.getElementById together in a function. I just check for
> document.getElementById.
>
I still allow for the use of document.all when gEBI isn't present, but
I did remove support for document.layers a few years back.
I asked about this sort of testing on c.l.js a when I was first
venturing into feature testing. I thought I'd have to test everything.
If document.getElementsById is present then I'd have to check if it
was callable before calling it. There is a chance it may not be
callable; however, since this situation has never been observed, the
general feeling was to trust is it callable until it is observed to be
not callable in at least one browser. Feature testing even when no
problems has ever been observed could balloon the feature tests to
hugely paranoid proportions.
That said, I understand you may have had the isRealObject function
around for another situation and it was just handy to use in this
case.
[snip]
> > > [0]:null);
> > > if (!html && docNode.all && docNode.all[0]) {
> > > html = docNode.all[(docNode.all[0].tagName == '!')?1:0] || null;
> > > if (html && html.tagName.toLowerCase() != 'html') { html = null; }
> > > }
> > > return html;
>
> > > };
>
> > > The missing documentElementsByTagName function is a wrapper for gEBTN
> > > that only exists if the document object features such a method. It
> > > exists to smooth out problems with the "*" parameter, as well as using
> > > the all object for agents that don't feature gEBTN. It isn't really
> > > needed now that the additional clause has been added to handle Opera
> > > 5/6, so you should just change it to doc.getElementsByTagName.
>
> > When I looked at document.documentElement, document.all.tags and
> > document.getElementsByTagName, I stated that in IE4
> > document.all.tags('html').length is 1. That is only true after
> > window.onload fires. Before window.onload the length is 0. Since
> > feature testing is preferably done in the head right when the script
> > loads, the document.all.tags check isn't really enabling any
> > particular browsers, as far as I know. This goes along with your "It
> > isn't really needed now...."
>
> Were all of those results determined after onload?
Yes
> If so, I would
> like to see what they look like when run in the head. Regardless, I
> assume that document.all[0] is defined before the onload event fires,
> so the added test should be sufficient.
The added test seems to be fine in IE4 at least with the HTML page I
tested.
> > Of the browsers I checked that can set opacity, only IE4 and Opera 6-
> > don't have document.documentElement. I don't mind degrading those
> > browsers to not use opacity setting. This would make the setOpacity
> > and all other functions requiring an element for feature testing not
> > dependent on an htmlElement function like you've outlined. In my eyes,
>
> Opacity yes, but all other style-related functions? That seems
> extreme.
Can you think of an example of a browser without
document.documentElement where style-related functions would work if
the document.all fallback is used for testing? Do the entire scripts
associated with these style-related functions work in these browsers?
> Also, there is no reason why such functions can't run after
> the body has been parsed (e.g. in a real or simulated DOMContentLoaded
> listener.) I do that for several functions that have to create
> elements and append them to the body to detect quirks like Opera's
> botched offsetLeft/Top reporting. It seems like setOpacity is
> something that wouldn't be needed until the document is ready, else
> how would you reliably find the element you want to fade?
Since document.all[0] or document.all[1] seems to work in the head
this point may be moot.
[snip]
> > only checking for document.documentElement is a reasonable place to
> > draw the line in browser history given the approximate distribution of
> > browser version in use today. Any non-trivial CSS that may need the
> > fallbacks in the htmlElement function for a feature tests likely won't
> > work in IE4 anyway. Sound reasonable?
>
> Sort of. How would a script determine if CSS is even available when
> running in IE4, Opera 6, etc.? One of the first flags I set is based
> on the presence of a style object. If it doesn't exist then lots of
> unneeded feature testing is skipped and style-related functions are
> not created. Next I check the types of the display, visibility and
> position properties of the object (typically strings, but not always)
> and those three results determine which style-related modules should
> be initialized.
This is exactly the direction in which I'd like to go with this code
repository.
> They are also referenced by applications to determine
> if it is possible to hide dynamically replaced content during the page
> load (i.e. if a style rule is added before the body is parsed, will it
> be possible to overrule it with an inline style once the content is
> replaced after parsing.) Can you confirm if IE4 can get the HTML
> element via document.all[0] (or document.all[1]?)
It can.
> If not, can it get
> any element during page load?
>
> > As a reference for this threshold, I don't wrap document.all and
> > document.getElementById together in a function. I just check for
> > document.getElementById.
>
> I still allow for the use of document.all when gEBI isn't present,
How many of your pages have enabled JavaScript functionality because
of these archaic checks and how many actual visitors benefit? If there
are pages that do become enabled with these checks that would not
become enabled with the modern checks only, it still may be better
overall (faster download times, less code to maintain) to just slide
these down the degradation path given how few users benefit. They
still do get a perfectly working HTML page, after all.
I think setting the feature threshold at document.getElementById and
document.documentElement is ok today. If there is outrage over this
then the code repository could allow for the the document.all
fallbacks. I cringe a little when I type that thought. I strongly vote
we go "modern" (NN6 November 2000, IE5.5 July 2000).
> but I did remove support for document.layers a few years back.
Peter
For that host object methods I use:
isFeature = function(o) {
return !!(o && (typeof(o) == 'object' || typeof(o) == 'function'));
};
This is because there is no reliable way to determine if host object
methods are callable.
> general feeling was to trust is it callable until it is observed to be
> not callable in at least one browser. Feature testing even when no
> problems has ever been observed could balloon the feature tests to
> hugely paranoid proportions.
I agree.
>
> That said, I understand you may have had the isRealObject function
> around for another situation and it was just handy to use in this
> case.
Yes, it is used by lots of functions.
That's good to know.
>
> > > Of the browsers I checked that can set opacity, only IE4 and Opera 6-
> > > don't have document.documentElement. I don't mind degrading those
> > > browsers to not use opacity setting. This would make the setOpacity
> > > and all other functions requiring an element for feature testing not
> > > dependent on an htmlElement function like you've outlined. In my eyes,
>
> > Opacity yes, but all other style-related functions? That seems
> > extreme.
>
> Can you think of an example of a browser without
> document.documentElement where style-related functions would work if
> the document.all fallback is used for testing? Do the entire scripts
> associated with these style-related functions work in these browsers?
For example, a function that shows and/or hides elements. The
requirements are that CSS is supported (style object exists) and
visibility can be adjusted by script (the visibility property of the
style object is a string.) I don't think it would make sense to
exclude IE4, Opera 5/6, etc. from using such a function. Another
example is a function that adds and/or removes elements from the
layout, which requires a working display property. Also, a function
that attaches a listener for drag and drop operations requires a
working position property (assuming it needs to work with statically
positioned elements.) All three of these examples can be written to
work with IE4, and two of the three can work with Opera 5/6 (IIRC,
those browsers cannot update the display property.)
>
> > Also, there is no reason why such functions can't run after
> > the body has been parsed (e.g. in a real or simulated DOMContentLoaded
> > listener.) I do that for several functions that have to create
> > elements and append them to the body to detect quirks like Opera's
> > botched offsetLeft/Top reporting. It seems like setOpacity is
> > something that wouldn't be needed until the document is ready, else
> > how would you reliably find the element you want to fade?
>
> Since document.all[0] or document.all[1] seems to work in the head
> this point may be moot.
For these examples yes. Other functionality (e.g. calculating an
element's offset position) require feature detection to occur after
the closing body tag has been parsed (thanks to IE's ridiculous
"Operation Aborted" bug.) I haven't found this to be a hindrance as I
never reference DOM nodes before the document is ready anyway (let
alone try to compute their position.)
>
> [snip]
>
> > > only checking for document.documentElement is a reasonable place to
> > > draw the line in browser history given the approximate distribution of
> > > browser version in use today. Any non-trivial CSS that may need the
> > > fallbacks in the htmlElement function for a feature tests likely won't
> > > work in IE4 anyway. Sound reasonable?
>
> > Sort of. How would a script determine if CSS is even available when
> > running in IE4, Opera 6, etc.? One of the first flags I set is based
> > on the presence of a style object. If it doesn't exist then lots of
> > unneeded feature testing is skipped and style-related functions are
> > not created. Next I check the types of the display, visibility and
> > position properties of the object (typically strings, but not always)
> > and those three results determine which style-related modules should
> > be initialized.
>
> This is exactly the direction in which I'd like to go with this code
> repository.
Seeing as you are like-minded and are willing to handle the
documentation and administration of the project, I am willing to help
you fill it up one function at a time. I've got a module for
virtually everything and they all use similar feature detection. It
will take a while, but eventually the result will be a competent
alternative to dreck like jQuery. I for one am tired of seeing
constant script errors in IE every time I browse the Web. I can't
imagine what the Web is like in less-supported agents. It must be
hell for mobile users, people who never upgrade their browsers, Mac
users, etc.
>
> > They are also referenced by applications to determine
> > if it is possible to hide dynamically replaced content during the page
> > load (i.e. if a style rule is added before the body is parsed, will it
> > be possible to overrule it with an inline style once the content is
> > replaced after parsing.) Can you confirm if IE4 can get the HTML
> > element via document.all[0] (or document.all[1]?)
>
> It can.
That's good to know.
>
> > If not, can it get
> > any element during page load?
>
> > > As a reference for this threshold, I don't wrap document.all and
> > > document.getElementById together in a function. I just check for
> > > document.getElementById.
>
> > I still allow for the use of document.all when gEBI isn't present,
>
> How many of your pages have enabled JavaScript functionality because
> of these archaic checks and how many actual visitors benefit? If there
I can't get IE4 to load in XP for some reason and AFAIK, nobody uses
anything I write with IE4 (or Opera 5/6.) I figure a couple of extra
lines doesn't hurt and allows very simple enhancements (e.g. hiding
and showing elements) to work with older mobile devices.
> are pages that do become enabled with these checks that would not
> become enabled with the modern checks only, it still may be better
> overall (faster download times, less code to maintain) to just slide
> these down the degradation path given how few users benefit. They
> still do get a perfectly working HTML page, after all.
Yes, I agree with that, especially since most widgets I build with my
API have requirements that are beyond the ancient browsers (e.g.
Function.prototype.call.) So despite the fact that basic style-
related functions are available to browsers like IE4, they typically
don't get the chance to use them (the test for call short circuits the
widgets' initialization.)
>
> I think setting the feature threshold at document.getElementById and
> document.documentElement is ok today. If there is outrage over this
> then the code repository could allow for the the document.all
> fallbacks. I cringe a little when I type that thought. I strongly vote
> we go "modern" (NN6 November 2000, IE5.5 July 2000).
I'd say that makes sense. I can't remember when Opera 7 was released
though. It seems like it was a two or three years into the century.
I've heard that some older mobile devices use an Opera 6 image, but
those will probably all be in landfills soon (if not already.)
[snip]
> > > > Of the browsers I checked that can set opacity, only IE4 and Opera 6-
> > > > don't have document.documentElement. I don't mind degrading those
> > > > browsers to not use opacity setting. This would make the setOpacity
> > > > and all other functions requiring an element for feature testing not
> > > > dependent on an htmlElement function like you've outlined. In my eyes,
>
> > > Opacity yes, but all other style-related functions? That seems
> > > extreme.
>
> > Can you think of an example of a browser without
> > document.documentElement where style-related functions would work if
> > the document.all fallback is used for testing? Do the entire scripts
> > associated with these style-related functions work in these browsers?
>
> For example, a function that shows and/or hides elements. The
> requirements are that CSS is supported (style object exists) and
> visibility can be adjusted by script (the visibility property of the
> style object is a string.) I don't think it would make sense to
> exclude IE4, Opera 5/6, etc. from using such a function.
I know what you mean. The feature threshold has to be placed somewhere
in the history of browsers. Right around the border where the browsers
transition to a standard is tricky to decide where to draw the line.
> Another
> example is a function that adds and/or removes elements from the
> layout, which requires a working display property. Also, a function
> that attaches a listener for drag and drop operations requires a
> working position property (assuming it needs to work with statically
> positioned elements.) All three of these examples can be written to
> work with IE4, and two of the three can work with Opera 5/6 (IIRC,
> those browsers cannot update the display property.)
[snip]
> > > > only checking for document.documentElement is a reasonable place to
> > > > draw the line in browser history given the approximate distribution of
> > > > browser version in use today. Any non-trivial CSS that may need the
> > > > fallbacks in the htmlElement function for a feature tests likely won't
> > > > work in IE4 anyway. Sound reasonable?
>
> > > Sort of. How would a script determine if CSS is even available when
> > > running in IE4, Opera 6, etc.? One of the first flags I set is based
> > > on the presence of a style object. If it doesn't exist then lots of
> > > unneeded feature testing is skipped and style-related functions are
> > > not created. Next I check the types of the display, visibility and
> > > position properties of the object (typically strings, but not always)
> > > and those three results determine which style-related modules should
> > > be initialized.
>
> > This is exactly the direction in which I'd like to go with this code
> > repository.
>
> Seeing as you are like-minded and are willing to handle the
> documentation and administration of the project, I am willing to help
> you fill it up one function at a time.
Great!
> I've got a module for
> virtually everything and they all use similar feature detection. It
> will take a while,
Yes it will. Fortunately there is no particular hurry.
> but eventually the result will be a competent
> alternative to dreck like jQuery. I for one am tired of seeing
> constant script errors in IE every time I browse the Web. I can't
> imagine what the Web is like in less-supported agents. It must be
> hell for mobile users, people who never upgrade their browsers, Mac
> users, etc.
[snip]
> I can't get IE4 to load in XP
The IE4 program loads for me. To get the program to load a page I have
to use the File > Open menu option and type the url into the dialog
and press OK. The URL never shows in the browser's URL bar.
> for some reason and AFAIK, nobody uses
> anything I write with IE4 (or Opera 5/6.) I figure a couple of extra
> lines doesn't hurt and allows very simple enhancements (e.g. hiding
> and showing elements) to work with older mobile devices.
>
> > are pages that do become enabled with these checks that would not
> > become enabled with the modern checks only, it still may be better
> > overall (faster download times, less code to maintain) to just slide
> > these down the degradation path given how few users benefit. They
> > still do get a perfectly working HTML page, after all.
>
> Yes, I agree with that, especially since most widgets I build with my
> API have requirements that are beyond the ancient browsers (e.g.
> Function.prototype.call.) So despite the fact that basic style-
> related functions are available to browsers like IE4, they typically
> don't get the chance to use them (the test for call short circuits the
> widgets' initialization.)
>
>
>
> > I think setting the feature threshold at document.getElementById and
> > document.documentElement is ok today. If there is outrage over this
> > then the code repository could allow for the the document.all
> > fallbacks. I cringe a little when I type that thought. I strongly vote
> > we go "modern" (NN6 November 2000, IE5.5 July 2000).
>
> I'd say that makes sense. I can't remember when Opera 7 was released
> though.
January 1, 2003
<URL: http://reviews.cnet.com/software/opera-7-for-windows/4505-3513_7-20832789.html>
> It seems like it was a two or three years into the century.
> I've heard that some older mobile devices use an Opera 6 image, but
> those will probably all be in landfills soon (if not already.)
I use try-catch and Randy Webb's cell phone only updated last month to
support that. It didn't cause me any grief knowing a syntax error
would occur on his browser. Go back far enough and almost any new
script will syntax error in some ancient browser.
I'm going to go with just checking document.documentElement for now
and if we see this was a particularly bad choice we can change in the
future.
Peter
I agree. The Web is already such a mess of misguided scripts and
misinformation that it would take years to make a significant impact,
even if a complete alternative to Prototype, jQuery, etc. existed
yesterday. Those miserable things have got a lot of momentum, with
people writing books about them, building widgets on top of them, etc.
>
> > but eventually the result will be a competent
> > alternative to dreck like jQuery. I for one am tired of seeing
> > constant script errors in IE every time I browse the Web. I can't
> > imagine what the Web is like in less-supported agents. It must be
> > hell for mobile users, people who never upgrade their browsers, Mac
> > users, etc.
>
> [snip]
>
> > I can't get IE4 to load in XP
>
> The IE4 program loads for me. To get the program to load a page I have
> to use the File > Open menu option and type the url into the dialog
> and press OK. The URL never shows in the browser's URL bar.
I have IE4, 5, 5.5 and 6 on one machine and all but 4 load and run. 4
blows up instantly (I don't even see the interface.) One interesting
thing with 5.x is that neither can do opacity manipulations in this
environment (even on Microsoft's test pages.) One throws a "library
not registered" error and the other fails silently.
>
>
>
>
>
> > for some reason and AFAIK, nobody uses
> > anything I write with IE4 (or Opera 5/6.) I figure a couple of extra
> > lines doesn't hurt and allows very simple enhancements (e.g. hiding
> > and showing elements) to work with older mobile devices.
>
> > > are pages that do become enabled with these checks that would not
> > > become enabled with the modern checks only, it still may be better
> > > overall (faster download times, less code to maintain) to just slide
> > > these down the degradation path given how few users benefit. They
> > > still do get a perfectly working HTML page, after all.
>
> > Yes, I agree with that, especially since most widgets I build with my
> > API have requirements that are beyond the ancient browsers (e.g.
> > Function.prototype.call.) So despite the fact that basic style-
> > related functions are available to browsers like IE4, they typically
> > don't get the chance to use them (the test for call short circuits the
> > widgets' initialization.)
>
> > > I think setting the feature threshold at document.getElementById and
> > > document.documentElement is ok today. If there is outrage over this
> > > then the code repository could allow for the the document.all
> > > fallbacks. I cringe a little when I type that thought. I strongly vote
> > > we go "modern" (NN6 November 2000, IE5.5 July 2000).
>
> > I'd say that makes sense. I can't remember when Opera 7 was released
> > though.
>
> January 1, 2003
>
> <URL:http://reviews.cnet.com/software/opera-7-for-windows/4505-3513_7-2083...>
>
> > It seems like it was a two or three years into the century.
> > I've heard that some older mobile devices use an Opera 6 image, but
> > those will probably all be in landfills soon (if not already.)
>
> I use try-catch and Randy Webb's cell phone only updated last month to
> support that. It didn't cause me any grief knowing a syntax error
> would occur on his browser. Go back far enough and almost any new
> script will syntax error in some ancient browser.
Only a couple of my modules (Ajax and Flash) use try/catch and I never
concatenate them with scripts that do not use try/catch, so that if
they fail to parse, they don't take other modules with them.
>
> I'm going to go with just checking document.documentElement for now
> and if we see this was a particularly bad choice we can change in the
> future.
>
As there will have to be a common initialization script to avoid
duplication of code, I recommend something like:
var htmlElement, isStyleCapable, doc = this.document;
if (doc) {
htmlElement = function(docNode) {
return (docNode || doc).documentElement;
};
isStyleCapable = function(docNode) {
var html = htmlElement(docNode);
return !!(html && html.style);
};
}
That way one could replace the htmlElement function like all of the
rest if backward compatibility with IE4, Opera 5, etc. is a
requirement. Same goes for gEBTN and gEBI. The difference with the
two document methods is that other low-level library functions don't
use them (they come into play at the widget level), so the wrappers
for them could be optional.
[this quoted code is a composite of David Mark's code snips and
changes]
> > setOpacity = (function(el) {
> >
> > var i,l;
> > var reOpacity = new RegExp('alpha\\(opacity=[^\\)]+\\)', 'i');
> > var opacityStyles = ['opacity', 'MozOpacity', 'KhtmlOpacity'];
> >
> > if (typeof el.style.filter == 'string') {
> >
> > return function(el, o) {
> >
> > var f;
> >
> > if (el.filters) {
> > if (!el.currentStyle || !el.currentStyle.hasLayout) {
> > el.style.zoom = 1;
> > }
> >
> > f = el.filters.alpha;
> > if (f) {
> > // IE screws up some fonts when filter is leftenabled
> > f.enabled = o != 1;
> > // This has got to be faster than string concatenation
> > f.opacity = o * 100;
> > }
> > else { // IE6/7 never get here unless an opacity has never been set
> > s = 'alpha(opacity=' + (o * 100) + ')';
> > if (reOpacity.test(el.style.filter)) { // IE5 every time
> > el.style.filter = el.style.filter.replace(reOpacity, s);
> > }
> > else { // IE6/7 once
> > el.style.filter += s;
> > }
> >
> > }
> >
> > }
> > };
> >
> > }
> >
> > i = 0;
> >
> > l = opacityStyles.length;
> >
> > while (i < l) {
> > if (typeof(el.style[opacityStyles[i]]) == 'string') {
> > return (function(s) {
> > return function(el, o) {
> > el.style[s] = (o < .00001)?0:o;
> > };
> > })(opacityStyles[i]);
> > }
> > i++;
> > }
> >
> > })(html);
I propose the following code
var setOpacity = (function() {
var html,
// Reverse order in next array for use with reverse for loop.
// Saves a length variable in the loop and a few characters.
props = ['KhtmlOpacity', 'MozOpacity', 'opacity'];
if (typeof document != 'undefined' &&
(html = document.documentElement) &&
html.style) {
if (typeof html.style.filter == 'string' &&
html.currentStyle &&
''.replace) {
return function(el, o) {
if (!el.currentStyle.hasLayout) {
el.style.zoom = 1;
}
var s = el.style;
s.filter = s.filter.replace(/alpha\([^\)]*\)/gi,'') +
((o < 1) ? 'alpha(opacity='+o*100+')' : '');
};
}
for (var i=props.length; i--; ) {
var p = props[i];
if (typeof(html.style[p]) == 'string') {
return function(el, o) {
el.style[p] = (o < .00001) ? 0 : o;
};
}
}
}
})();
I just quickly tested this code in FF2, S3, O9, S1.2, FF1, IE5, IE5.5,
NN6.2, NN7 and it worked nicely. In a sampling of slightly older
browsers there were no errors and the setOpacity function was left
undefined.
Some identifiers have been shortened compared with the quoted code
above.
I decided to use regular expression literals. I think that, as a
policy, it is not a good idea to be shy of ECMAScript edition 3 syntax
unless it is known to cause a problem in a quite recent browser (IE5+,
NN6+). For example, NN4 syntax errors reasons other than the regexp
literal anyway.
By only using document.documentElement and not a document.all fallback
to find the root element for feature testing. Of the browsers known to
have opacity setting ability this only sacrifices IE4. Because of this
known sacrifice I made the html.currentStyle object mandatory for the
filters branch.
I'm surprised something like "(o < .00001) ? 0 : o" is not needed in
the filters branch. I seems ok to use "alpha(opacity=1e-7)".
The f.enabled code has not been used because it errors in IE5.5. The
error message said something like "library not installed". I also
don't think that the time taken for the string concatenation would be
substantial compared to the time to render the element with changed
opacity. RobG and I did some testing about a year ago and the
rendering time seemed to eclipse any actual code running time. This
really needs formal testing but this certainly was impression. RobG
suggested the graphics card may be a substantial factor. (It may be
that with this method of setting opacity that the issue about font
rendering in IE is not a problem?) The error in IE5.5 was the
fundamental reason for not using the f.enabled code.
The feature testing from David's quoted code above seems great. I
hadn't used any feature testing on my old opacity code because I had
never looked into feature testing with CSS related properties. I'd
like to know why, for the browsers using the non-filters part, that
even when the opacity of an element has not been set the
html.style[props[i]] object is a string. This really does seem to be
constantly implemented in the browsers that support opacity. Is this
part of some standard?
In the non-filters part of the code the the "(function(s){...})
(opacityStyles[i])" wrapper isn't particularly needed. In the code
I've proposed the "p" variable will never be changed again after the
setOpacity function is created.
Way too much thinking about opacity...and opacity setting is supposed
to be a picnic?
Peter
Makes sense.
>
> if (typeof document != 'undefined' &&
> (html = document.documentElement) &&
> html.style) {
I prefer:
var doc = this.document;
if (doc && doc.documentElement) {
html = this.documentElement;
if (html.style) {
I concur with JSLint that assignments in conditions are a bad
practice. I also think that the creation of doc and html should
definitely be in a seperate (and required) snippet. You will find
that virtually every function that feature tests will need them.
>
> if (typeof html.style.filter == 'string' &&
> html.currentStyle &&
> ''.replace) {
I don't think you need the test for replace, especially since the
currentStyle test precedes it.
>
> return function(el, o) {
>
> if (!el.currentStyle.hasLayout) {
> el.style.zoom = 1;
> }
>
> var s = el.style;
> s.filter = s.filter.replace(/alpha\([^\)]*\)/gi,'') +
> ((o < 1) ? 'alpha(opacity='+o*100+')' : '');
>
> };
>
> }
>
> for (var i=props.length; i--; ) {
Personally I prefer:
var i = props.length;
while (i--) {
I don't think that one needs to be debated though as it is just a
preference.
> var p = props[i];
> if (typeof(html.style[p]) == 'string') {
> return function(el, o) {
> el.style[p] = (o < .00001) ? 0 : o;
> };
> }
Works for me.
> }
> }
>
> })();
>
> I just quickly tested this code in FF2, S3, O9, S1.2, FF1, IE5, IE5.5,
> NN6.2, NN7 and it worked nicely. In a sampling of slightly older
I had previously tested the original version in all but the old Safari
browser. Can multiple versions of that co-exist on the same box?
> browsers there were no errors and the setOpacity function was left
> undefined.
>
> Some identifiers have been shortened compared with the quoted code
> above.
>
> I decided to use regular expression literals. I think that, as a
> policy, it is not a good idea to be shy of ECMAScript edition 3 syntax
> unless it is known to cause a problem in a quite recent browser (IE5+,
> NN6+). For example, NN4 syntax errors reasons other than the regexp
> literal anyway.
I agree that NN4 should not be a consideration.
>
> By only using document.documentElement and not a document.all fallback
> to find the root element for feature testing. Of the browsers known to
> have opacity setting ability this only sacrifices IE4. Because of this
> known sacrifice I made the html.currentStyle object mandatory for the
> filters branch.
Okay. But I still think it makes sense to use a one-line function to
return doc.documentElement. Then if somebody really wants to support
IE4, they can swap it for the version that checks doc.all.
>
> I'm surprised something like "(o < .00001) ? 0 : o" is not needed in
> the filters branch. I seems ok to use "alpha(opacity=1e-7)".
Right.
>
> The f.enabled code has not been used because it errors in IE5.5. The
> error message said something like "library not installed". I also
So it worked without the f.enabled line? That surprises me. I got
the same errors on the MSDN opacity demos and chalked it up to IE5.5
co-existing with IE6 on XP.
> don't think that the time taken for the string concatenation would be
> substantial compared to the time to render the element with changed
> opacity. RobG and I did some testing about a year ago and the
I don't know about that. The DirectX manipulation should be very
fast. It probably isn't worth worrying about until special effect
transitions are added.
> rendering time seemed to eclipse any actual code running time. This
> really needs formal testing but this certainly was impression. RobG
> suggested the graphics card may be a substantial factor. (It may be
Yes it would.
> that with this method of setting opacity that the issue about font
> rendering in IE is not a problem?) The error in IE5.5 was the
> fundamental reason for not using the f.enabled code.
I don't think it will affect the font rendering issue. I'll try
updating mine to skip the part you removed and see if it makes a
difference.
>
> The feature testing from David's quoted code above seems great. I
> hadn't used any feature testing on my old opacity code because I had
> never looked into feature testing with CSS related properties. I'd
> like to know why, for the browsers using the non-filters part, that
> even when the opacity of an element has not been set the
> html.style[props[i]] object is a string. This really does seem to be
Because an inline style can be an empty string, which means that only
cascaded styles are applied to the element. If the property were
undefined, that would indicate that the agent doesn't support that
inline style.
> constantly implemented in the browsers that support opacity. Is this
> part of some standard?
Ask Richard Cornford. It was his idea.
>
> In the non-filters part of the code the the "(function(s){...})
> (opacityStyles[i])" wrapper isn't particularly needed. In the code
> I've proposed the "p" variable will never be changed again after the
> setOpacity function is created.
Makes sense.
>
> Way too much thinking about opacity...and opacity setting is supposed
> to be a picnic?
It might seem that way, but in fact issues larger than opacity are
being worked out. That is why I keep mentioning the doc variable and
htmlElement function as virtually every other style-related function
that comes after this will need them. I think the next logical step
is getOpacity; however, that one references my getComputedStyle
wrapper (when available.) So once we get the central support details
worked out, I think we would deal with getComputedStyle. It happens I
recently worked on that function to untangle cascaded and computed
styles (where possible) and I will be interested to hear feedback on
it. First things first though. Looking over the code for that one, I
see dependant functions that reference doc. Example:
elementDocument = function(el) { return el.ownerDocument || doc; };
As you can see, it needs the doc reference and like the htmlElement
function, is designed to work in any document context, which enables
its use with documents pulled down with Ajax, documents in IFrames,
etc.
This is why I propose this function, which shortens virtually all of
the other functions. As it is referenced in so many places, I think
it makes sense to allow for the possibility of multiple documents.
htmlElement = function(docNode) { return (docNode ||
doc).documentElement; };
Another depencency of getComputedStyle (one branch of it anyway) is
elementParent, which I have never been particularly confident in:
api.elementParent = function(el) { return el.parentNode ||
el.parentElement; };
I have no idea if ancient versions of IE (or anything else) fail to
support parentNode or if parentElement is a proper substitute in all
cases, but I have used that code for years without incident.
Anyway, I think it is apparent that virtually none of these functions
will be able to exist as islands, without a lot of repetitive code. I
don't know of a simple build process that can consolidate such
repetition, so I think it is best to avoid it from the start.
[snip proposed code and discussion of personal style. This could go on
forever :-S]
> > I just quickly tested this code in FF2, S3, O9, S1.2, FF1, IE5, IE5.5,
> > NN6.2, NN7 and it worked nicely. In a sampling of slightly older
>
> I had previously tested the original version in all but the old Safari
> browser. Can multiple versions of that co-exist on the same box?
Multiple versions of Safari 1.3- can exist on a OS X 10.3 box.
Multiple versions of Safari 2.0+ can exist on a OS X 10.4 box.
<URL: http://michelf.com/projects/multi-safari/>
[snip]
> > The f.enabled code has not been used because it errors in IE5.5. The
> > error message said something like "library not installed". I also
>
> So it worked without the f.enabled line?
The f.enabled and f.opacity lines will both case the "library not
installed" error.
> That surprises me. I got
> the same errors on the MSDN opacity demos and chalked it up to IE5.5
> co-existing with IE6 on XP.
It could be.
With regard to the proposed setOpacity code, even if your code works
with the f.enabled and f.opacity and a single IE 5.5 install, it
doesn't work with either of our installs or likely with any web
developer's mutliple IE installs. So, in fact, the proposed code
without f.enabled actually works in a wider set of browsers/os/
installation combinations. Also, I would definitely like to have code
that I can verify works. My proposed code tests successfully on my
install.
[snip]
> > Way too much thinking about opacity...and opacity setting is supposed
> > to be a picnic?
>
> It might seem that way, but in fact issues larger than opacity are
> being worked out. That is why I keep mentioning the doc variable and
> htmlElement function as virtually every other style-related function
> that comes after this will need them. I think the next logical step
> is getOpacity; however, that one references my getComputedStyle
> wrapper (when available.)
After the holidays ;-)
> So once we get the central support details
> worked out, I think we would deal with getComputedStyle. It happens I
> recently worked on that function to untangle cascaded and computed
> styles (where possible) and I will be interested to hear feedback on
> it. First things first though. Looking over the code for that one, I
> see dependant functions that reference doc. Example:
>
> elementDocument = function(el) { return el.ownerDocument || doc; };
>
> As you can see, it needs the doc reference and like the htmlElement
> function, is designed to work in any document context, which enables
> its use with documents pulled down with Ajax, documents in IFrames,
> etc.
>
> This is why I propose this function, which shortens virtually all of
> the other functions. As it is referenced in so many places, I think
> it makes sense to allow for the possibility of multiple documents.
>
> htmlElement = function(docNode) { return (docNode ||
> doc).documentElement; };
[snip]
You seem convinced and your work with many of these CSS related
functions far out weighs mine.
How about this...
if (typeof document != 'undefined') {
var getHtmlElement = function(docNode) {
return (docNode || document).documentElement;
};
}
The two changes I made above:
I still don't understand the need for your "doc" variable. There is
already a "document" host object for that.
I think the function should be called "getHtmlElement" or
"getDocumentElement". The former options is shorter so I used it
above.
My proposed code then changes to the following
if (typeof getHtmlElement != 'undefined') {
var setOpacity = (function() {
var html = getHtmlElement(),
props = ['KhtmlOpacity', 'MozOpacity', 'opacity'];
if (html &&
html.style) {
if (typeof html.style.filter == 'string' &&
''.replace) {
return function(el, o) {
if (!el.currentStyle ||
!el.currentStyle.hasLayout) {
el.style.zoom = 1;
}
var s = el.style;
s.filter = s.filter.replace(/alpha\([^\)]*\)/gi,'') +
((o < 1) ? 'alpha(opacity='+o*100+')' : '');
};
}
for (var i=props.length; i--; ) {
var p = props[i];
if (typeof(html.style[p]) == 'string') {
return function(el, o) {
el.style[p] = (o < .00001) ? 0 : o;
};
}
}
}
})();
}
If a developer wants to use a getHTMLElement that works with IE4 then
this will work with IE4 and I'll test that later.
Peter
But evaluating the reference before testing its type is more error-prone
than doing it vice-versa. Hence my isMethodType() approach.
> This is because there is no reliable way to determine if host object
> methods are callable.
It would seem there is. There does not seem to be a reliable way yet to
determine whether or not an arbitrary value is callable, though. However,
in reasonably written no-debug scripts the latter question will never come up.
>> Can you think of an example of a browser without
>> document.documentElement where style-related functions would work if
>> the document.all fallback is used for testing? Do the entire scripts
>> associated with these style-related functions work in these browsers?
>
> For example, a function that shows and/or hides elements. The
> requirements are that CSS is supported (style object exists) and
> visibility can be adjusted by script (the visibility property of the
> style object is a string.)
Showing or hiding elements is ambiguous. There are *two* CSS properties and
therefore two properties of "style objects" that are to consider: `display'
and `visibility'.
> I don't think it would make sense to exclude IE4, Opera 5/6, etc. from
> using such a function.
Or NN4 which does not need a "style object" for that.
PointedEars
--
var bugRiddenCrashPronePieceOfJunk = (
navigator.userAgent.indexOf('MSIE 5') != -1
&& navigator.userAgent.indexOf('Mac') != -1
) // Plone, register_function.js:16
Right. It would work in standard IE5.5 installations.
>
> > That surprises me. I got
> > the same errors on the MSDN opacity demos and chalked it up to IE5.5
> > co-existing with IE6 on XP.
>
> It could be.
It is, but I agree that it makes sense to make it work for developers,
not to mention for your own testing.
It will become apparent on adding additional style functions (or DOM,
events, etc.)
>
> How about this...
>
> if (typeof document != 'undefined') {
>
> var getHtmlElement = function(docNode) {
> return (docNode || document).documentElement;
> };
>
> }
That looks good.
>
> The two changes I made above:
>
> I still don't understand the need for your "doc" variable. There is
> already a "document" host object for that.
One reason is that it is shorter than this.document. Referring to it
as "document" alone implies that such a global property exists
(typically a good assumption in a browser, but not the best practice
as it will error otherwise.) I think it is a good idea to run all of
these functions through JSLint as it is good for pointing out
potential pitfalls.
>
> I think the function should be called "getHtmlElement" or
> "getDocumentElement". The former options is shorter so I used it
> above.
getHtmlElement (or getHTMLElement) sounds good to me, though if that
becomes the standard for the library, every function that fetches a
property will have to be start with "get." I typically use a "set"
prefix on functions that set properties, which differentiates them
from the more numerous getters. I have a function that dumps all
defined methods to the console (and/or a supplied element), sorted by
name, and the output would be harder to wade through if everything
started with "g" or "s". Another popular alternative (which I don't
care for) is to combine get/set in one function and branch on the
number of arguments passed.
>
> My proposed code then changes to the following
>
> if (typeof getHtmlElement != 'undefined') {
>
> var setOpacity = (function() {
>
> var html = getHtmlElement(),
> props = ['KhtmlOpacity', 'MozOpacity', 'opacity'];
>
> if (html &&
> html.style) {
>
> if (typeof html.style.filter == 'string' &&
> ''.replace) {
>
> return function(el, o) {
>
> if (!el.currentStyle ||
> !el.currentStyle.hasLayout) {
> el.style.zoom = 1;
> }
>
> var s = el.style;
> s.filter = s.filter.replace(/alpha\([^\)]*\)/gi,'') +
> ((o < 1) ? 'alpha(opacity='+o*100+')' : '');
>
> };
>
> }
>
> for (var i=props.length; i--; ) {
> var p = props[i];
> if (typeof(html.style[p]) == 'string') {
> return function(el, o) {
> el.style[p] = (o < .00001) ? 0 : o;
> };
> }
> }
> }
>
> })();
>
> }
>
> If a developer wants to use a getHTMLElement that works with IE4 then
> this will work with IE4 and I'll test that later.
Makes sense to me. You've got the code for the alternative
getHTMLElement (or getHtmlElement as it is spelled in the code.) My
preference for the name would have HTML in caps, but only because that
is the convention I use.
I don't see that. The reference is evaluated before the function ever
runs (when it is passed.) That's why I don't check for typeof
'unknown' in that function as it would error when passing the
reference to the function.
>
> > This is because there is no reliable way to determine if host object
> > methods are callable.
>
> It would seem there is. There does not seem to be a reliable way yet to
How do you figure?
> determine whether or not an arbitrary value is callable, though. However,
As long as it isn't a host object, typeof(arbitrary) == 'function'
should suffice.
> in reasonably written no-debug scripts the latter question will never come up.
Agreed.
>
> >> Can you think of an example of a browser without
> >> document.documentElement where style-related functions would work if
> >> the document.all fallback is used for testing? Do the entire scripts
> >> associated with these style-related functions work in these browsers?
>
> > For example, a function that shows and/or hides elements. The
> > requirements are that CSS is supported (style object exists) and
> > visibility can be adjusted by script (the visibility property of the
> > style object is a string.)
>
> Showing or hiding elements is ambiguous. There are *two* CSS properties and
> therefore two properties of "style objects" that are to consider: `display'
> and `visibility'.
And two different functions in a competently written library. Only
one has to do with logical visibility. The other removes elements
from the layout (or changes their display mode), which does indeed
make them invisible to the eye, but logically they are still visible.
One wouldn't consider setting an element's opacity to 0 or moving it
to negative coordinates to hide it either, despite the fact that the
element becomes empirically invisible as a result.
We'll talk about this further when we get to the toggle-related
functions.
>
> > I don't think it would make sense to exclude IE4, Opera 5/6, etc. from
> > using such a function.
>
> Or NN4 which does not need a "style object" for that.
Never mind that one. It can make due without such scripted
enhancements.
Which is the problem with that approach. You overlook the possibility that
the argument may have to be an unqualified reference or can be a qualified
reference to a host object. Evaluating that reference before the call is
error-prone, especially as a host object may implement the [[Get]] method in
any way the implementor saw fit. Unqualified references are necessary at
times, and there are host objects that are callable but throw an exception
on read access.
>>> This is because there is no reliable way to determine if host object
>>> methods are callable.
>> It would seem there is. There does not seem to be a reliable way yet to
>
> How do you figure?
Because evaluating the type before and trying read access only if the type
indicates feasibility has not caused unexpected behavior so far.
>> determine whether or not an arbitrary value is callable, though. However,
>
> As long as it isn't a host object, typeof(arbitrary) == 'function'
> should suffice.
No, it should not. See above.
>>> I don't think it would make sense to exclude IE4, Opera 5/6, etc. from
>>> using such a function.
>> Or NN4 which does not need a "style object" for that.
>
> Never mind that one. It can make due without such scripted
> enhancements.
That is a choice that can be made. However, supporting document.all and
not supporting NN4's style properties at the same time appears a bit weird.
My display() and visibility() methods in
http://PointedEars.de/scripts/dhtml.js support NN4 as well, with little
extra effort.
PointedEars
I know that and they will throw that exception when passed to the test
function, which means that the test function will never evaluate such
objects.
>
> >>> This is because there is no reliable way to determine if host object
> >>> methods are callable.
> >> It would seem there is. There does not seem to be a reliable way yet to
>
> > How do you figure?
>
> Because evaluating the type before and trying read access only if the type
> indicates feasibility has not caused unexpected behavior so far.
And if you get typeof(o) == 'object', how does that tell you it is
callable?
>
> >> determine whether or not an arbitrary value is callable, though. However,
>
> > As long as it isn't a host object, typeof(arbitrary) == 'function'
> > should suffice.
>
> No, it should not. See above.
See what above? If a non-host object is of type function, then it has
an internal [[call]] method and is therefore callable.
>
> >>> I don't think it would make sense to exclude IE4, Opera 5/6, etc. from
> >>> using such a function.
> >> Or NN4 which does not need a "style object" for that.
>
> > Never mind that one. It can make due without such scripted
> > enhancements.
>
> That is a choice that can be made. However, supporting document.all and
> not supporting NN4's style properties at the same time appears a bit weird.
Doesn't appear that way to me.
> My display() and visibility() methods inhttp://PointedEars.de/scripts/dhtml.jssupport NN4 as well, with little
> extra effort.
I am aware of the syntax. I pruned it out of my stock show/hide code
years ago, along with any reference to layers. They were just taking
up space.
[snip]
> > How about this...
>
> > if (typeof document != 'undefined') {
>
> > var getHtmlElement = function(docNode) {
> > return (docNode || document).documentElement;
> > };
>
> > }
Testing in IE4 with the document.all fallback showed some problems.
While the script is running in the head
document.all[0] // !
document.all[1] // HEAD
after the window.onload event
document.all[0] // !
document.all[1] // HTML
That seems to make it impossible to use the html element to check for
the style object while head scripts are evaluated. However it is just
as easy to use the head element to check for the style object. I
prefer to do feature tests in the head as the code is first evaluated
if possible. An entire Ajax library can be feature tested in the head
but we need one element for form serialization to check for the
attributes property.
The only change this requires is changing the name from
"getHtmlElement" to "getAnElement" which actually make makes more
semantic sense. It isn't really that we want the documentElement in
particular but we just need some element to test.
Here are the two versions I have. The second one could be a bit more
elegant so toLowerCase is called only once. I just wanted to post that
this change is necessary and get any feedback about the change in
general.
// -------------------------------------
if (typeof document != 'undefined' &&
document.documentElement) {
var getAnElement = function(d) {
return (d || document).documentElement;
};
}
// -------------------------------------
// (I know I went a bit extreme on the short identifiers)
if (typeof document != 'undefined') {
var getAnElement = (function() {
function f(d) {
d = d || document;
var g = 'getElementsByTagName',
t = d.documentElement ||
// The following line doesn't seem to add any benefit
// in any of the tested browsers.
// ((t=d.all) && t.tags && (t=t.tags('html')) && t[0])
||
(d[g] && d[g]('html')[0]);
if (!t && d.all && (t=d.all[0])) {
t = d.all[(t.tagName == '!')?1:0] || null;
if (t &&
t.tagName.toLowerCase() != 'html' &&
// for during load in IE4
t.tagName.toLowerCase() != 'head') {
t = null;
}
}
return t;
};
if (f()) {
return f;
}
})();
}
// -------------------------------
Peter
There will be times when it is useful to get the HTML element (and
only the HTML element.) Numerous functions related to scrolling,
viewport size, element positioning, etc. rely on such a function.
>
> Here are the two versions I have. The second one could be a bit more
> elegant so toLowerCase is called only once. I just wanted to post that
> this change is necessary and get any feedback about the change in
> general.
>
> // -------------------------------------
>
> if (typeof document != 'undefined' &&
> document.documentElement) {
>
> var getAnElement = function(d) {
>
> return (d || document).documentElement;
>
> };
>
Strictly, that should be this.document, which is why I always assign
that to a variable named "doc" at the top of each module. I think
that all of these functions should pass JSLint. I know it will
complain that is an implied global. Obviously in the context of a
function running in the global context that already checked the
existence of a global document property, it is a moot point, but I
still think it should be made to pass. That way there is no need to
document any ignored errors.
Another style point is that variables shouldn't be declared inside if
blocks. I think JSLint complains about that too.
> }
>
> // -------------------------------------
> // (I know I went a bit extreme on the short identifiers)
>
> if (typeof document != 'undefined') {
>
> var getAnElement = (function() {
>
> function f(d) {
>
> d = d || document;
>
> var g = 'getElementsByTagName',
> t = d.documentElement ||
> // The following line doesn't seem to add any benefit
> // in any of the tested browsers.
> // ((t=d.all) && t.tags && (t=t.tags('html')) && t[0])
> ||
> (d[g] && d[g]('html')[0]);
>
> if (!t && d.all && (t=d.all[0])) {
> t = d.all[(t.tagName == '!')?1:0] || null;
> if (t &&
> t.tagName.toLowerCase() != 'html' &&
> // for during load in IE4
> t.tagName.toLowerCase() != 'head') {
I changed my version of htmlElement to check that a second parameter
(bAnyElement) isn't truthy here, which allows it to return anything it
finds at position 1. If you want to keep it as getAnElement, you
could use a tag parameter that if present would dictate what tag is
allowed. Or perhaps you want to break this up into two functions?
And speaking of base functions, I do think we should have wrappers for
gEBI and certainly for gEBTN (if only for the "*" issue.) The gEBTN
wrapper is required by my bodyElement and headElement functions. The
other one does little besides enable the use of document.all, but I
think that is a good idea to have as an option (if we are going to
support opacity for IE4, document.all would seem a must.) The
bodyElement and headElement functions are called during feature
detection for some modules. That's why some functions cannot
initialize until after the DOM is ready and a few cannot run their
feature tests in the head (e.g. the module that adds scripts to the
head of the document.)
That it can throw an exception is the major flaw of this approach.
Because the intention behind all feature-testing is to determine
whether or not a property is viable for further operations *without*
allowing the possibility of the corresponding script to *break*.
> > >>> This is because there is no reliable way to determine if host object
> > >>> methods are callable.
> > >> It would seem there is. There does not seem to be a reliable way yet to
> > >
> > > How do you figure?
> >
> > Because evaluating the type before and trying read access only if the type
> > indicates feasibility has not caused unexpected behavior so far.
>
> And if you get typeof(o) == 'object', how does that tell you it is
> callable?
If I get that result and *then* the value is not a false-value and I
am expecting the identifier to designate a host object's method, at
the least I can be pretty sure that it is callable.
> > >> determine whether or not an arbitrary value is callable, though. However,
> > >
> > > As long as it isn't a host object, typeof(arbitrary) == 'function'
> > > should suffice.
> >
> > No, it should not. See above.
>
> See what above? If a non-host object is of type function, then it has
> an internal [[call]] method and is therefore callable.
Even if the property owner is a native object, you require the caller
of the method to provide a qualified reference for a feature test if
that test is not supposed to be error-prone. That is not necessary if
you pass the `typeof' result instead. And since there is also the
[[Get]] issue with host objects, the latter is without doubt the less
error-prone and more reasonable approach.
PointedEars
[begin quotations from a previous post]
David Mark wrote:
> Peter Michaux wrote:
>
> > I still don't understand the need for your "doc" variable. There is
> > already a "document" host object for that.
>
> One reason is that it is shorter than this.document. Referring to it
> as "document" alone implies that such a global property exists
> (typically a good assumption in a browser, but not the best practice
> as it will error otherwise.)
[end quotations from a previous post]
I don't understand your argument for a few reasons but most
importantly there seems to be a logical inconstancy. If you write "var
doc = this.document" in the global scope and then check for "doc"
later you are doing exactly what I am doing when I check "typeof
document != 'undefined'". If there is any chance that your "doc" could
be shadowed in another scope, the same chance exists for "document".
You also state that "this is typically a good assumption in a browser"
and this is a body of code specifically for browsers.
> I think that all of these functions should pass JSLint.
I don't.
JSLint is not an ECMAScript v3 validator.
For example, give JSLint the script "new Foo();" and it actually
cannot continue even though the script is a valid ExpressionStatement.
> I know it will complain that is an implied global.
If I give JSLint the script "alert('a')" it complains about an implied
global. I don't think writing that script is risky for a browser
environment.
If you click the "Assume a brower" box in JSLint then the implied
global warnings for "document" and "alert" go away.
Give JSLint the script "var a = new Foo();" and it complains about an
implied global but I may know that my target host has a "Foo" or that
I declared it elsewhere.
> Obviously in the context of a
> function running in the global context that already checked the
> existence of a global document property, it is a moot point, but I
> still think it should be made to pass. That way there is no need to
> document any ignored errors.
JSLint "errors" are not necessarily ECMAScript errors. I wouldn't
document what JSLint has to say. Try turning on Firefox's strict
warnings and see all its warnings about the valid ECMAScript.
Development tools should help develop code but not dictate the code.
> Another style point is that variables shouldn't be declared inside if
> blocks. I think JSLint complains about that too.
I believe JSLint used to complain about this but it doesn't today. For
example,
function a() {
if (true) {
var b = 1;
}
}
seems to be ok with JSLint. So if my memory is correct, JSLint is a
moving target.
The only reason I can see to avoid declaring variables inside a set of
curly brackets that are not a function body, is because of experience/
baggage coming from programming in another language.
I also think assignment in conditionals can be very handy and elegant
for if-else-else... statements.
JSLint is a great tool to learn what another JavaScript programmer
thinks is good style but I certainly don't agree with many of
Crockford's opinions.
> > // -------------------------------------
> > // (I know I went a bit extreme on the short identifiers)
>
> > if (typeof document != 'undefined') {
>
> > var getAnElement = (function() {
>
> > function f(d) {
>
> > d = d || document;
>
> > var g = 'getElementsByTagName',
> > t = d.documentElement ||
> > // The following line doesn't seem to add any benefit
> > // in any of the tested browsers.
> > // ((t=d.all) && t.tags && (t=t.tags('html')) && t[0])
> > ||
> > (d[g] && d[g]('html')[0]);
>
> > if (!t && d.all && (t=d.all[0])) {
> > t = d.all[(t.tagName == '!')?1:0] || null;
> > if (t &&
> > t.tagName.toLowerCase() != 'html' &&
> > // for during load in IE4
> > t.tagName.toLowerCase() != 'head') {
>
> I changed my version of htmlElement to check that a second parameter
> (bAnyElement) isn't truthy here, which allows it to return anything it
> finds at position 1. If you want to keep it as getAnElement, you
> could use a tag parameter that if present would dictate what tag is
> allowed. Or perhaps you want to break this up into two functions?
I would break this into two functions.
> And speaking of base functions, I do think we should have wrappers for
> gEBI
NOOOOOOOOOOoooooooooo............. ;-)
[begin quotations from a previous post]
David wrote:
> Peter wrote:
>
> > I think setting the feature threshold at document.getElementById and
> > document.documentElement is ok today. If there is outrage over this
> > then the code repository could allow for the the document.all
> > fallbacks. I cringe a little when I type that thought. I strongly vote
> > we go "modern" (NN6 November2000, IE5.5July2000).
>
> I'd say that makes sense.
[end quotations from a previous post]
You can see my confusion on your stance here. This will likely not a
affect many functions but this is an important design decision. This
is the perfect place for me to lean on the "many implementations"
philosophy.
A web page is going to work with just plain HTML and no JavaScirpt
because that is the right way to build a web page. We choose to
enhance some web pages with JavaScript if the features of the browser
meet some feature threshold. We decide what features are required
based on what we know about the history of browsers.
Browsers without document.getElementById are old and/or not common. By
choosing to not enhance pages in these browsers we are reducing the
code base size and complexity with almost no impact on the user
population. Other than trivial enhancements supporting fallbacks to
document.getElementById will not result in enhanced pages anyway as
the more modern feature requirements will not exist. I also agree with
Thomas Lahn (I can't believe I wrote that!) that if the code supports
IE4 it should probably also support NN4.
Not that this should necessarily mean much but worrying about
fallbacks for document.getElementById will make the code look archaic.
So this is where multiple implementations come in. It is possible to
have implementations of functions that do and don't allow for
document.getElementById fallbacks. This doubles the code in the
repository for some functions. Unfortunately that means more
maintenance and it is more maintanence for no real practical benefit
in my mind.
For the time being, I am going to commit code to the repository that
follows this design principle.
==============
Code in this repository should not make any special concessions to
enable functionality in browsers older than IE5 or NN6.
==============
I hope this doesn't scare anyone off but it seems well within the
range of sensible to me given how few users this will impact. By the
way, I lay awake thinking about this for quite a while.
By the time this repository is ready (>8 years after IE5 and NN6 were
released), if implementations of functions that do support IE4 and NN4
are really wanted by the group then they can be added to the
repository.
[snip]
Peter
I don't define it in the global scope, but inside each anonymous
function that wraps a module.
>
> You also state that "this is typically a good assumption in a browser"
> and this is a body of code specifically for browsers.
Fair enough. Some of it could be used in other environments, but
mostly not.
>
> > I think that all of these functions should pass JSLint.
>
> I don't.
>
> JSLint is not an ECMAScript v3 validator.
Right.
>
> For example, give JSLint the script "new Foo();" and it actually
> cannot continue even though the script is a valid ExpressionStatement.
Haven't tried that one.
>
> > I know it will complain that is an implied global.
>
> If I give JSLint the script "alert('a')" it complains about an implied
> global. I don't think writing that script is risky for a browser
> environment.
I typically use this.alert or global.alert, depending on the context.
>
> If you click the "Assume a brower" box in JSLint then the implied
> global warnings for "document" and "alert" go away.
Right.
>
> Give JSLint the script "var a = new Foo();" and it complains about an
> implied global but I may know that my target host has a "Foo" or that
> I declared it elsewhere.
Right. But if you validate an entire file (e.g. a build with the
various functions from the repository), it should be declared
somewhere within. I realize that it could be declared in another
file, but there is always the possibility that that file fails to
download.
>
> > Obviously in the context of a
> > function running in the global context that already checked the
> > existence of a global document property, it is a moot point, but I
> > still think it should be made to pass. That way there is no need to
> > document any ignored errors.
>
> JSLint "errors" are not necessarily ECMAScript errors. I wouldn't
> document what JSLint has to say. Try turning on Firefox's strict
> warnings and see all its warnings about the valid ECMAScript.
> Development tools should help develop code but not dictate the code.
I use Firebug, but haven't tried the strict mode. I'm not even sure
where to turn it on.
>
> > Another style point is that variables shouldn't be declared inside if
> > blocks. I think JSLint complains about that too.
>
> I believe JSLint used to complain about this but it doesn't today. For
> example,
>
> function a() {
> if (true) {
> var b = 1;
> }
>
> }
>
> seems to be ok with JSLint. So if my memory is correct, JSLint is a
> moving target.
It is.
>
> The only reason I can see to avoid declaring variables inside a set of
> curly brackets that are not a function body, is because of experience/
> baggage coming from programming in another language.
That's what I was getting at.
>
> I also think assignment in conditionals can be very handy and elegant
> for if-else-else... statements.
I always declare the variables at the top of each function, which
sometimes adds a few extra characters, but I think it is easier to
maintain.
>
> JSLint is a great tool to learn what another JavaScript programmer
> thinks is good style but I certainly don't agree with many of
> Crockford's opinions.
I find that I agree with most of what it complains about. It is
certainly an invaluable tool.
I know I said that, but looking at my gEBI wrapper later changed my
mind, due to one concern: IE's insistence on returning elements with
names that match the id queried (even when these elements have no ID.)
>
> [end quotations from a previous post]
>
> You can see my confusion on your stance here. This will likely not a
> affect many functions but this is an important design decision. This
> is the perfect place for me to lean on the "many implementations"
> philosophy.
Right. I think it makes sense to have the wrapper that fixes the name
problem in IE and then a second one that includes the .all fallback
(else, how could one use the IE4 opacity support?)
>
> A web page is going to work with just plain HTML and no JavaScirpt
> because that is the right way to build a web page. We choose to
> enhance some web pages with JavaScript if the features of the browser
> meet some feature threshold. We decide what features are required
> based on what we know about the history of browsers.
Right.
>
> Browsers without document.getElementById are old and/or not common. By
> choosing to not enhance pages in these browsers we are reducing the
> code base size and complexity with almost no impact on the user
> population. Other than trivial enhancements supporting fallbacks to
> document.getElementById will not result in enhanced pages anyway as
> the more modern feature requirements will not exist. I also agree with
> Thomas Lahn (I can't believe I wrote that!) that if the code supports
I can't believe you did either.
> IE4 it should probably also support NN4.
I do not agree with that as NN4 would require new branches for
virtually all of the style-related code, whereas IE4 will work with
the simpler functions as is (e.g. opacity, show/hide element, etc.)
>
> Not that this should necessarily mean much but worrying about
> fallbacks for document.getElementById will make the code look archaic.
An alternate version that adds an extra line for document.all seems
like it wouldn't hurt anything. We already have at least one function
with an .all fallback. But at the very least, I think the name
attribute issue should be smoothed out with a wrapper.
>
> So this is where multiple implementations come in. It is possible to
> have implementations of functions that do and don't allow for
> document.getElementById fallbacks. This doubles the code in the
What I am saying is that all functions should call an "element"
function. Then there is no extra maintenance. One version (the
preferred one IMO) would just fix the name attribute problem. Another
can add support for document.all (which would be needed if IE4 opacity
is to be supported.) I do not recommend a third that uses
document.layers as that doesn't work the same as gEBI or document.all.
> repository for some functions. Unfortunately that means more
> maintenance and it is more maintanence for no real practical benefit
> in my mind.
>
> For the time being, I am going to commit code to the repository that
> follows this design principle.
>
> ==============
>
> Code in this repository should not make any special concessions to
> enable functionality in browsers older than IE5 or NN6.
But we already did this with opacity.
>
> ==============
>
> I hope this doesn't scare anyone off but it seems well within the
> range of sensible to me given how few users this will impact. By the
> way, I lay awake thinking about this for quite a while.
No need to. If wrappers are used, then people can plug in whatever
version fits their needs.
>
> By the time this repository is ready (>8 years after IE5 and NN6 were
> released), if implementations of functions that do support IE4 and NN4
> are really wanted by the group then they can be added to the
> repository.
That's what I am saying, but if a wrapper is not used (e.g. functions
call gEBI directly), then that will require rewrites.
[snip]
> > > I know it will complain that is an implied global.
>
> > If I give JSLint the script "alert('a')" it complains about an implied
> > global. I don't think writing that script is risky for a browser
> > environment.
>
> I typically use this.alert or global.alert, depending on the context.
I think you are exhibiting unique behavior here.
[snip]
> > Give JSLint the script "var a = new Foo();" and it complains about an
> > implied global but I may know that my target host has a "Foo" or that
> > I declared it elsewhere.
>
> Right. But if you validate an entire file (e.g. a build with the
> various functions from the repository), it should be declared
> somewhere within. I realize that it could be declared in another
> file, but there is always the possibility that that file fails to
> download.
If having a variable declared in one file and used in another is a
possibility and the first file may not load then the second file must
check for that variable. In this case JSLint will complain when
validating the second file. These sorts of things make me take
JSLint's output with a box of salt.
> > > Obviously in the context of a
> > > function running in the global context that already checked the
> > > existence of a global document property, it is a moot point, but I
> > > still think it should be made to pass. That way there is no need to
> > > document any ignored errors.
>
> > JSLint "errors" are not necessarily ECMAScript errors. I wouldn't
> > document what JSLint has to say. Try turning on Firefox's strict
> > warnings and see all its warnings about the valid ECMAScript.
> > Development tools should help develop code but not dictate the code.
>
> I use Firebug, but haven't tried the strict mode. I'm not even sure
> where to turn it on.
<URL: https://addons.mozilla.org/en-US/firefox/addon/60>
Then in the menus
Tools
Web Developer
Disable
Disable JavaScript
Strict Warnings
[snip]
> > JSLint is a great tool to learn what another JavaScript programmer
> > thinks is good style but I certainly don't agree with many of
> > Crockford's opinions.
>
> I find that I agree with most of what it complains about. It is
> certainly an invaluable tool.
I do use JSLint sometimes to catch missing semi-colons and similar
little things. I've encountered many JavaScript developers have hacked
versions of JSLint where they have removed many of Crockfords
preferences. The preferences certainly aren't universally liked.
<URL: http://dean.edwards.name/weblog/2006/06/jslint/>
[snip]
> > > And speaking of base functions, I do think we should have wrappers for
> > > gEBI
>
> > NOOOOOOOOOOoooooooooo............. ;-)
>
> > [begin quotations from a previous post]
>
> > David wrote:
> > > Peter wrote:
>
> > > > I think setting the feature threshold at document.getElementById and
> > > > document.documentElement is ok today. If there is outrage over this
> > > > then the code repository could allow for the the document.all
> > > > fallbacks. I cringe a little when I type that thought. I strongly vote
> > > > we go "modern" (NN6 November2000, IE5.5July2000).
>
> > > I'd say that makes sense.
>
> I know I said that, but looking at my gEBI wrapper later changed my
> mind, due to one concern: IE's insistence on returning elements with
> names that match the id queried (even when these elements have no ID.)
My feeling is developers just shouldn't cause this problem; however,
do you have a solution for this problem? This may be more persuasive
than enabling IE4.
Just out of interest, do you ever depend on this fallback? I don't
think it is a good idea to spend time on features that no one using
the library will utilize.
> > [end quotations from a previous post]
>
> > You can see my confusion on your stance here. This will likely not a
> > affect many functions but this is an important design decision. This
> > is the perfect place for me to lean on the "many implementations"
> > philosophy.
>
> Right. I think it makes sense to have the wrapper that fixes the name
> problem in IE and then a second one that includes the .all fallback
> (else, how could one use the IE4 opacity support?)
If the gEBID wrapper is there then surely a document.all fallback
could be written.
[snip]
> > Browsers without document.getElementById are old and/or not common. By
> > choosing to not enhance pages in these browsers we are reducing the
> > code base size and complexity with almost no impact on the user
> > population. Other than trivial enhancements supporting fallbacks to
> > document.getElementById will not result in enhanced pages anyway as
> > the more modern feature requirements will not exist. I also agree with
> > Thomas Lahn (I can't believe I wrote that!) that if the code supports
>
> I can't believe you did either.
>
> > IE4 it should probably also support NN4.
>
> I do not agree with that as NN4 would require new branches for
> virtually all of the style-related code, whereas IE4 will work with
> the simpler functions as is (e.g. opacity, show/hide element, etc.)
If "as is" means that IE4 can use the same code as newer browser then
that just isn't true. Already we've seen substantial work solely
dedicated to enabling IE4.
> > Not that this should necessarily mean much but worrying about
> > fallbacks for document.getElementById will make the code look archaic.
>
> An alternate version that adds an extra line for document.all seems
> like it wouldn't hurt anything.
No but it is a slippery slope. If it is only a little effort to enable
some functions for IE4 then for the medium difficulty implementations
we will feel some pressure to do those ones to. Where to draw the line
for which of the possible "many implementations" to include in the
repository that do or don't support IE4. I think it makes sense to
choose the least grey decisions and said no special effort for IE4.
The user base is small and shrinking daily and they will still get
working pages. Also the things that can be wrapped and enabled in IE4
are likely not the limiting features for widgets as more modern
features will be required.
The reason I continue discussing this is because I'm hoping you will
see the practical side of what I'm saying. There isn't a right or
wrong answer and the multiple implementations can handle accommodate
every option. I just don't see that it is worth *any* extra effort to
enable functions on IE4.
[snip]
> But at the very least, I think the name
> attribute issue should be smoothed out with a wrapper.
I'd like to see your code and how your fallback will find the element
with the id if an element with the same name exists.
> > By the time this repository is ready (>8 years after IE5 and NN6 were
> > released), if implementations of functions that do support IE4 and NN4
> > are really wanted by the group then they can be added to the
> > repository.
>
> That's what I am saying, but if a wrapper is not used (e.g. functions
> call gEBI directly), then that will require rewrites.
Consider Function.prototype.apply. That can be simulated in older
browsers. Do you want to put that in a wrapper?
I don't want to have to wrap apply and then need to include code like
the following.
if (Function.prototype.apply) {
function myApply(obj, f) {
var args = [];
for (var i=2, ilen=arguments.length; i<ilen; i++) {
args[args.length] = arguments[i];
}
return f.apply(obj, args);
}
}
Yes by using this wrapper it would allow someone to write an
implementation like this.
function myApply(obj, f) {
obj._temp = f;
// some number of arguments
obj._temp(args, arguments[1], arguments[2],
arguments[3], arguments[4]);
delete obj._temp;
}
So many things can be wrapped which causes bloat. There needs to be a
limit on what is wrapped. I don't think we should wrap when the
wrapping is just for IE4.
BTW, this is an interesting turn in the design requirements for the
library. To IE4 or not to IE4? That is the question. The multiple
implementations approach can satisfy everyone but script download
times and maintenance of the project are the underlying issue.
Peter
> Yes by using this wrapper it would allow someone to write an
> implementation like this.
>
> function myApply(obj, f) {
> obj._temp = f;
> // some number of arguments
> obj._temp(args, arguments[1], arguments[2],
> arguments[3], arguments[4]);
> delete obj._temp;
>
> }
Never mind the bugs :)
--
Peter
Code Worth Recommending Project
http://cljs.michaux.ca/trac
Perhaps.
>
> [snip]
>
> > > Give JSLint the script "var a = new Foo();" and it complains about an
> > > implied global but I may know that my target host has a "Foo" or that
> > > I declared it elsewhere.
>
> > Right. But if you validate an entire file (e.g. a build with the
> > various functions from the repository), it should be declared
> > somewhere within. I realize that it could be declared in another
> > file, but there is always the possibility that that file fails to
> > download.
>
> If having a variable declared in one file and used in another is a
> possibility and the first file may not load then the second file must
> check for that variable. In this case JSLint will complain when
Right.
I simply check to see if the element to be returned actually has the
appropriate id.
>
> Just out of interest, do you ever depend on this fallback? I don't
> think it is a good idea to spend time on features that no one using
> the library will utilize.
No, but as it would fail when names conflict with id's, rather than
enable such a bad practice, I think it is good to have.
>
> > > [end quotations from a previous post]
>
> > > You can see my confusion on your stance here. This will likely not a
> > > affect many functions but this is an important design decision. This
> > > is the perfect place for me to lean on the "many implementations"
> > > philosophy.
>
> > Right. I think it makes sense to have the wrapper that fixes the name
> > problem in IE and then a second one that includes the .all fallback
> > (else, how could one use the IE4 opacity support?)
>
> If the gEBID wrapper is there then surely a document.all fallback
> could be written.
That's what I am saying. I just don't think it makes sense to call
gEBI directly in higher-level functions.
>
> [snip]
>
> > > Browsers without document.getElementById are old and/or not common. By
> > > choosing to not enhance pages in these browsers we are reducing the
> > > code base size and complexity with almost no impact on the user
> > > population. Other than trivial enhancements supporting fallbacks to
> > > document.getElementById will not result in enhanced pages anyway as
> > > the more modern feature requirements will not exist. I also agree with
> > > Thomas Lahn (I can't believe I wrote that!) that if the code supports
>
> > I can't believe you did either.
>
> > > IE4 it should probably also support NN4.
>
> > I do not agree with that as NN4 would require new branches for
> > virtually all of the style-related code, whereas IE4 will work with
> > the simpler functions as is (e.g. opacity, show/hide element, etc.)
>
> If "as is" means that IE4 can use the same code as newer browser then
> that just isn't true. Already we've seen substantial work solely
> dedicated to enabling IE4.
I'm talking about code like:
el.style.visibility = 'hidden';
The syntax is NN4 is different.
>
> > > Not that this should necessarily mean much but worrying about
> > > fallbacks for document.getElementById will make the code look archaic.
>
> > An alternate version that adds an extra line for document.all seems
> > like it wouldn't hurt anything.
>
> No but it is a slippery slope. If it is only a little effort to enable
> some functions for IE4 then for the medium difficulty implementations
> we will feel some pressure to do those ones to. Where to draw the line
I don't know. If the alternate version of the gEBI wrapper's only
function is to enable finding an element by ID, then I don't think
that implies that everything else can work with IE4.
> for which of the possible "many implementations" to include in the
> repository that do or don't support IE4. I think it makes sense to
> choose the least grey decisions and said no special effort for IE4.
> The user base is small and shrinking daily and they will still get
> working pages. Also the things that can be wrapped and enabled in IE4
> are likely not the limiting features for widgets as more modern
> features will be required.
That's true.
>
> The reason I continue discussing this is because I'm hoping you will
> see the practical side of what I'm saying. There isn't a right or
> wrong answer and the multiple implementations can handle accommodate
> every option. I just don't see that it is worth *any* extra effort to
> enable functions on IE4.
But we already broke that rule with the opacity function. It wasn't
much extra effort and I think it was worth it to make that basic
function optionally work for IE4.
>
> [snip]
>
> > But at the very least, I think the name
> > attribute issue should be smoothed out with a wrapper.
>
> I'd like to see your code and how your fallback will find the element
> with the id if an element with the same name exists.
It doesn't, it just disallows returning the wrong one. That provides
a clue to the caller that there is a mistake in their markup.
>
> > > By the time this repository is ready (>8 years after IE5 and NN6 were
> > > released), if implementations of functions that do support IE4 and NN4
> > > are really wanted by the group then they can be added to the
> > > repository.
>
> > That's what I am saying, but if a wrapper is not used (e.g. functions
> > call gEBI directly), then that will require rewrites.
>
> Consider Function.prototype.apply. That can be simulated in older
> browsers. Do you want to put that in a wrapper?
The only simulation I have seen for that was pretty ugly (used eval.)
I don't use a wrapper for it myself. I instead avoid using call and
apply unless absolutely necessary and only if those features are
detected.
>
> I don't want to have to wrap apply and then need to include code like
> the following.
Neither do I.
>
> if (Function.prototype.apply) {
>
> function myApply(obj, f) {
> var args = [];
> for (var i=2, ilen=arguments.length; i<ilen; i++) {
> args[args.length] = arguments[i];
> }
> return f.apply(obj, args);
You can use slice for this, but either way is a performance hit.
> }
>
> }
>
> Yes by using this wrapper it would allow someone to write an
> implementation like this.
>
> function myApply(obj, f) {
> obj._temp = f;
> // some number of arguments
> obj._temp(args, arguments[1], arguments[2],
> arguments[3], arguments[4]);
> delete obj._temp;
>
> }
I definitely don't see any value in that.
>
> So many things can be wrapped which causes bloat. There needs to be a
> limit on what is wrapped. I don't think we should wrap when the
> wrapping is just for IE4.
For the most part I agree. In this case, I think the name vs. id
issue is sufficient to warrant a wrapper for gEBI.
>
> BTW, this is an interesting turn in the design requirements for the
> library. To IE4 or not to IE4? That is the question. The multiple
It isn't exactly the question for me. But I think we've already
answered it to some extent. When it is simple to include an
additional version of a function that enables IE4 and somebody is
willing to write it, then it makes sense to include it. Most
applications won't need it, but why not have it available for those
that do?
> implementations approach can satisfy everyone but script download
> times and maintenance of the project are the underlying issue.
Those who don't use the alternate versions of getAnElement, etc. won't
incur the extra download time. Other than that one and the gEBI
wrapper, I don't have any additional functions that warrant
alternative IE4-friendly versions. My gEBTN wrapper fixes a problem
with IE5.x as well. And other than that, I can't think of anything
else I've written that specifically addresses pre-IE6 issues.
Ahh, ok. I thought you might be doing an elaborate DOM walk to find
the element that really has the correct id. This would have saved me
from a problem in a mashup that burned about an hour of my time last
week. In fact I think this would be a good function to have because it
fixes a bug in recent browsers. You win :-)
> > The reason I continue discussing this is because I'm hoping you will
> > see the practical side of what I'm saying. There isn't a right or
> > wrong answer and the multiple implementations can handle accommodate
> > every option. I just don't see that it is worth *any* extra effort to
> > enable functions on IE4.
>
> But we already broke that rule with the opacity function.
The rule was a result of that experience.
> It wasn't
> much extra effort and I think it was worth it to make that basic
> function optionally work for IE4.
I think that the time to enabled opacity on IE4 was plenty. I had to
figure out about document.all.tags and document.all[] during page load
and after. I had all sorts of browsers fired up. This sort of testing
isn't free.
[snip]
> > So many things can be wrapped which causes bloat. There needs to be a
> > limit on what is wrapped. I don't think we should wrap when the
> > wrapping is just for IE4.
>
> For the most part I agree. In this case, I think the name vs. id
> issue is sufficient to warrant a wrapper for gEBI.
I agree. I had never even thought about writing code to fix that
problem before. It is a good idea. That is a bug that can be fixed.
> > BTW, this is an interesting turn in the design requirements for the
> > library. To IE4 or not to IE4? That is the question. The multiple
>
> It isn't exactly the question for me. But I think we've already
> answered it to some extent. When it is simple to include an
> additional version of a function that enables IE4
This is a grey area with the "simple". I'm looking for a consistent
rule for what to include. If a bit of code in the repository happens
to work on IE4 great but if not that is ok with me.
> and somebody is
> willing to write it, then it makes sense to include it. Most
> applications won't need it, but why not have it available for those
> that do?
I suppose it comes down to the fact that I'll probably have to write
the documentation, tests and almost certainly maintain it. These are
big time commitments. I'm not interested for IE4 having enhanced
JavaScript pages. Just HTML is fine.
> > implementations approach can satisfy everyone but script download
> > times and maintenance of the project are the underlying issue.
>
> Those who don't use the alternate versions of getAnElement, etc. won't
> incur the extra download time. Other than that one and the gEBI
> wrapper, I don't have any additional functions that warrant
> alternative IE4-friendly versions. My gEBTN wrapper fixes a problem
> with IE5.x as well. And other than that, I can't think of anything
> else I've written that specifically addresses pre-IE6 issues.
Ok! I see a solution. So you need only two functions to help you
support IE4 at the level that satisfies you (but perhaps not someone
else). If the gEBID wrapper is included in the library to fix the IE5+
bug then there is only one issue for you: getAnElement.
I never intended that the repository would have all the multiple
implementations possible. The repository should have the ones that are
commonly used. A developer using the repository may have extenuating
circumstances that require an implementation not suitable to whatever
the guidelines are for the repository. The developer is free to
maintain an implementation of a particular function outside the
repository and include it in his build process. This is what I
envisioned from the beginning.
So if you were going to use the repository you would just maintain
your own getAnElement. That is just one function outside the
repository. How does that sound?
Peter
I kind of mucked up that explanation. You would need to maintain your
own gEBID and getAnElement to have your level of support for IE4. The
logic that a developer with uncommon requirements maintains his own
implementations was the point.
Peter
That would be going too far.
> from a problem in a mashup that burned about an hour of my time last
> week. In fact I think this would be a good function to have because it
> fixes a bug in recent browsers. You win :-)
Okay, let me know when you want to put the wrappers in for gEBI and
gEBTN. Once those are in, we can add getBodyElement and
getHeadElement. Then the basic foundation for feature detection will
be in place. Speaking of that, I finally figured out what Thomas
Lahn was saying about error-prone method checking of host objects. I
deprecated my "isFeature" function in favor of:
var reFeaturedMethod = new RegExp('^function|object$', 'i');
isFeaturedMethod = api.isFeaturedMethod = function(o, m) {
var t = typeof(o[m]);
return !!((reFeaturedMethod.test(t) && o[m]) || t == 'unknown');
};
Ex.
if (this.external) { alert(isFeaturedMethod(this.external,
'addFavorite')); }
alert(isFeaturedMethod(this.document, 'all'));
This is similar to Thomas' oft-mentioned isFeatureType function, but
is slightly in improved in that it does the truthy test internal and
covers ActiveX methods. Point to PointedEars. On the downside, the
fact that I am agreeing with him may signal the end of the world.
>
> > > The reason I continue discussing this is because I'm hoping you will
> > > see the practical side of what I'm saying. There isn't a right or
> > > wrong answer and the multiple implementations can handle accommodate
> > > every option. I just don't see that it is worth *any* extra effort to
> > > enable functions on IE4.
>
> > But we already broke that rule with the opacity function.
>
> The rule was a result of that experience.
>
> > It wasn't
> > much extra effort and I think it was worth it to make that basic
> > function optionally work for IE4.
I agree.
>
> I think that the time to enabled opacity on IE4 was plenty. I had to
> figure out about document.all.tags and document.all[] during page load
> and after. I had all sorts of browsers fired up. This sort of testing
> isn't free.
But it enabled far more possibilities than just getOpacity.
Especially in feature testing, where retrieving the html element (or
any element in some cases) is typically step one.
>
> [snip]
>
> > > So many things can be wrapped which causes bloat. There needs to be a
> > > limit on what is wrapped. I don't think we should wrap when the
> > > wrapping is just for IE4.
>
> > For the most part I agree. In this case, I think the name vs. id
> > issue is sufficient to warrant a wrapper for gEBI.
>
> I agree. I had never even thought about writing code to fix that
> problem before. It is a good idea. That is a bug that can be fixed.
>
> > > BTW, this is an interesting turn in the design requirements for the
> > > library. To IE4 or not to IE4? That is the question. The multiple
>
> > It isn't exactly the question for me. But I think we've already
> > answered it to some extent. When it is simple to include an
> > additional version of a function that enables IE4
>
> This is a grey area with the "simple". I'm looking for a consistent
> rule for what to include. If a bit of code in the repository happens
> to work on IE4 great but if not that is ok with me.
I agree. Most of what I write degrades to plain HTML in IE4.
>
> > and somebody is
> > willing to write it, then it makes sense to include it. Most
> > applications won't need it, but why not have it available for those
> > that do?
>
> I suppose it comes down to the fact that I'll probably have to write
> the documentation, tests and almost certainly maintain it. These are
> big time commitments. I'm not interested for IE4 having enhanced
> JavaScript pages. Just HTML is fine.
Right. But at least it will be able to find documents and set their
opacity (for starters.) It will also be able to show, hide and toggle
elements, remove them from the layout, change their display style,
etc. As a matter of fact, all of my special effects should work in
IE4. A few of them were originally written back in the IE4 days.
>
> > > implementations approach can satisfy everyone but script download
> > > times and maintenance of the project are the underlying issue.
>
> > Those who don't use the alternate versions of getAnElement, etc. won't
> > incur the extra download time. Other than that one and the gEBI
> > wrapper, I don't have any additional functions that warrant
> > alternative IE4-friendly versions. My gEBTN wrapper fixes a problem
> > with IE5.x as well. And other than that, I can't think of anything
> > else I've written that specifically addresses pre-IE6 issues.
>
> Ok! I see a solution. So you need only two functions to help you
> support IE4 at the level that satisfies you (but perhaps not someone
> else). If the gEBID wrapper is included in the library to fix the IE5+
No. The gEBTN wrapper fixes an IE5 bug.
> bug then there is only one issue for you: getAnElement.
Why is that one an issue? We just need to make sure there is also a
getHTMLElement.
>
> I never intended that the repository would have all the multiple
> implementations possible. The repository should have the ones that are
> commonly used. A developer using the repository may have extenuating
> circumstances that require an implementation not suitable to whatever
> the guidelines are for the repository. The developer is free to
> maintain an implementation of a particular function outside the
> repository and include it in his build process. This is what I
> envisioned from the beginning.
>
> So if you were going to use the repository you would just maintain
> your own getAnElement. That is just one function outside the
> repository. How does that sound?
I don't understand why there is an issue at all. We know gEBTN is
broken in IE5, so that needs a wrapper. It sounds like you are now in
favor of a gEBI wrapper and we can break mine up into two (one of
which will support IE4, just like getAnElement/getHTMLElement.) If
you mean that you don't want to include the backward compatible
versions of these in the repository, that makes no difference to me.
My main point has always been to avoid calling things like gEBI in the
higher-level functions. That way anybody can override the stock
wrapper with whatever they need.
Sounds good to me.
It's contagious.
> may signal the end of the world.
:-)
> > > > The reason I continue discussing this is because I'm hoping you will
> > > > see the practical side of what I'm saying. There isn't a right or
> > > > wrong answer and the multiple implementations can handle accommodate
> > > > every option. I just don't see that it is worth *any* extra effort to
> > > > enable functions on IE4.
>
> > > But we already broke that rule with the opacity function.
>
> > The rule was a result of that experience.
>
> > > It wasn't
> > > much extra effort and I think it was worth it to make that basic
> > > function optionally work for IE4.
>
> I agree.
You must be getting blurry eyed too. You are agreeing with yourself
now! ;-)
[snip]
> > > > implementations approach can satisfy everyone but script download
> > > > times and maintenance of the project are the underlying issue.
>
> > > Those who don't use the alternate versions of getAnElement, etc. won't
> > > incur the extra download time. Other than that one and the gEBI
> > > wrapper, I don't have any additional functions that warrant
> > > alternative IE4-friendly versions. My gEBTN wrapper fixes a problem
> > > with IE5.x as well. And other than that, I can't think of anything
> > > else I've written that specifically addresses pre-IE6 issues.
>
> > Ok! I see a solution. So you need only two functions to help you
> > support IE4 at the level that satisfies you (but perhaps not someone
> > else). If the gEBID wrapper is included in the library to fix the IE5+
>
> No. The gEBTN wrapper fixes an IE5 bug.
That is the '*' bug but I was referring to the name/id bug.
> > bug then there is only one issue for you: getAnElement.
>
> Why is that one an issue? We just need to make sure there is also a
> getHTMLElement.
>
>
>
> > I never intended that the repository would have all the multiple
> > implementations possible. The repository should have the ones that are
> > commonly used. A developer using the repository may have extenuating
> > circumstances that require an implementation not suitable to whatever
> > the guidelines are for the repository. The developer is free to
> > maintain an implementation of a particular function outside the
> > repository and include it in his build process. This is what I
> > envisioned from the beginning.
>
> > So if you were going to use the repository you would just maintain
> > your own getAnElement. That is just one function outside the
> > repository. How does that sound?
>
> I don't understand why there is an issue at all. We know gEBTN is
> broken in IE5, so that needs a wrapper.
Yes.
> It sounds like you are now in
> favor of a gEBI wrapper and we can break mine up into two (one of
> which will support IE4, just like getAnElement/getHTMLElement.)
Yes.
> If
> you mean that you don't want to include the backward compatible
> versions of these in the repository, that makes no difference to me.
I do not want to include them (at least for now).
> My main point has always been to avoid calling things like gEBI in the
> higher-level functions.
I just really don't want things like Function.prototype.apply to
become "things like gEBI"....wrapper hell.
> That way anybody can override the stock
> wrapper with whatever they need.
Yes.
I think we are finished. It has been very informative. Thanks. No
doubt this is some of the most heavily scrutinized code around.
If you want to post a new thread for gEBI and a separate thread for
gEBTN please do. (Please put the project name in parens in the
subject)
I hope not.
>
> > may signal the end of the world.
>
> :-)
>
This is how it starts. Next thing you know, people will start
agreeing with VK. I think one of Nostradamus' quatrains referenced
such events as a prelude to the apocalypse.
> > > > > The reason I continue discussing this is because I'm hoping you will
> > > > > see the practical side of what I'm saying. There isn't a right or
> > > > > wrong answer and the multiple implementations can handle accommodate
> > > > > every option. I just don't see that it is worth *any* extra effort to
> > > > > enable functions on IE4.
>
> > > > But we already broke that rule with the opacity function.
>
> > > The rule was a result of that experience.
>
> > > > It wasn't
> > > > much extra effort and I think it was worth it to make that basic
> > > > function optionally work for IE4.
>
> > I agree.
>
> You must be getting blurry eyed too. You are agreeing with yourself
> now! ;-)
I always agree with myself.
>
> [snip]
>
> > > > > implementations approach can satisfy everyone but script download
> > > > > times and maintenance of the project are the underlying issue.
>
> > > > Those who don't use the alternate versions of getAnElement, etc. won't
> > > > incur the extra download time. Other than that one and the gEBI
> > > > wrapper, I don't have any additional functions that warrant
> > > > alternative IE4-friendly versions. My gEBTN wrapper fixes a problem
> > > > with IE5.x as well. And other than that, I can't think of anything
> > > > else I've written that specifically addresses pre-IE6 issues.
>
> > > Ok! I see a solution. So you need only two functions to help you
> > > support IE4 at the level that satisfies you (but perhaps not someone
> > > else). If the gEBID wrapper is included in the library to fix the IE5+
>
> > No. The gEBTN wrapper fixes an IE5 bug.
>
> That is the '*' bug but I was referring to the name/id bug.
>
Right.
As long as there are wrappers to override for cases of specific need,
then everyone should be happy.
>
> > My main point has always been to avoid calling things like gEBI in the
> > higher-level functions.
>
> I just really don't want things like Function.prototype.apply to
> become "things like gEBI"....wrapper hell.
Definitely not. Though I am glad to see you are feature testing apply
and call. I had wondered recently if doing so was overly paranoid,
but then I found out that IE5.0 doesn't quite support all of
Javascript 1.2.
>
> > That way anybody can override the stock
> > wrapper with whatever they need.
>
> Yes.
>
> I think we are finished. It has been very informative. Thanks. No
> doubt this is some of the most heavily scrutinized code around.
Which is good as everything else will sit on top of it. We don't want
to duplicate the (currently) popular libraries by building towers on a
swampy foundation.
>
> If you want to post a new thread for gEBI and a separate thread for
> gEBTN please do. (Please put the project name in parens in the
> subject)
I should have some time for that tomorrow. I've had enough JavaScript
for today.
I should note that there are actually two wrappers for gEBTN. They
were posted here about a month ago. One is for document nodes and the
other for elements. I'll explain why when I post them tomorrow.
No, it does not. You have still not understood that the problem with the
encapsulation of the testing algorithm is the early evaluation of the
property value. `this.external' is such one; `typeof this.external', which
really should be `typeof window.external', is not. The bottom line is that
there is a part of a reliable feature test that can not be encapsulated in a
method.
> Point to PointedEars. On the downside, the fact that I am agreeing with
> him may signal the end of the world.
You are much farther from the truth than you think you are.
PointedEars
--
realism: HTML 4.01 Strict
evangelism: XHTML 1.0 Strict
madness: XHTML 1.1 as application/xhtml+xml
-- Bjoern Hoehrmann
Generally, understanding will be helped greatly by considering the argument
before the name. That is where many people fail to make the distinction.
PointedEars
I understand perfectly. A slightly improved version would add a
similar function to test the object that exposes the method:
isRealObjectProperty = api.isRealObjectProperty = function(o, p) {
return !!(typeof(o[p]) == 'object' && o[p]);
};
if (isRealObjectProperty(this, 'external'))
{ alert(isFeaturedMethod(this.external, 'addFavorite')); }
Granted, this one would fail if the external object were an ActiveX
method (which it isn't.) I really should have used a simpler
example. See below.
> really should be `typeof window.external', is not. The bottom line is that
No it shouldn't. If there is no global window property, then that
will error. Talk about error-prone.
> there is a part of a reliable feature test that can not be encapsulated in a
> method.
I don't agree. What's wrong with this:
alert(isFeaturedMethod(this, 'addEventListener'));
Or as you would put it:
alert(isFeaturedMethod(this.window, 'addEventListener'));
Of course, considering your position, you would consider that error-
prone as window is a host object.
Looking at the function:
var reFeaturedMethod = new RegExp('^function|object$', 'i');
isFeaturedMethod = function(o, m) {
var t = typeof(o[m]);
return !!((reFeaturedMethod.test(t) && o[m]) || t == 'unknown');
};
The first parameter is the global object (window object), the second
is a string. No possibility of an evaluation error there. The first
line assigns the type of a method of a known object (a string) to a
variable. No issue there. The second line performs a test on a
string and if it indicates that o[m] is an object or method, then it
is evaluated to assure it isn't null. If the conjunction is false,
then a final string comparison adds support for ActiveX methods, which
I tested with the first posted example. No problem.
>
> > Point to PointedEars. On the downside, the fact that I am agreeing with
> > him may signal the end of the world.
>
> You are much farther from the truth than you think you are.
I sure hope so.
I don't see the improvement of this over
if (typeof this.external != "undefined")
{
// ...
}
You are assuming that a value needs to yield typeof "object" in order to
allow property access; however, that is not the case.
> Granted, this one would fail if the external object were an ActiveX
> method (which it isn't.)
It will fail in a great many other cases, too.
>> really should be `typeof window.external', is not. The bottom line is that
>
> No it shouldn't. If there is no global window property, then that
> will error. Talk about error-prone.
Correct. It should be
typeof window != "undefined"
&& typeof window.external ...
But you miss the point.
>> there is a part of a reliable feature test that can not be encapsulated in a
>> method.
>
> I don't agree. What's wrong with this:
>
> alert(isFeaturedMethod(this, 'addEventListener'));
In the case of `this' that would be OK. However, we are talking about the
general use of a feature test.
> Or as you would put it:
>
> alert(isFeaturedMethod(this.window, 'addEventListener'));
I would most certainly not perform this feature test.
> Of course, considering your position, you would consider that error-
> prone as window is a host object.
>
> Looking at the function:
>
> var reFeaturedMethod = new RegExp('^function|object$', 'i');
>
> isFeaturedMethod = function(o, m) {
> var t = typeof(o[m]);
> return !!((reFeaturedMethod.test(t) && o[m]) || t == 'unknown');
> };
>
> The first parameter is the global object (window object),
The Global Object is not necessarily the object that the host-defined
`window' property of Global Object refers to. Until you got that it does
not make sense to continue discussing with you about proper feature tests.
> [...]
> I tested with the first posted example. No problem.
You have tested with a subset of user agents and leap to the conclusion that
there can never be a problem.
PointedEars
--
Prototype.js was written by people who don't know javascript for people
who don't know javascript. People who don't know javascript are not
the best source of advice on designing systems that use javascript.
-- Richard Cornford, cljs, <f806at$ail$1$8300...@news.demon.co.uk>
Obviously, it takes care of the case where this.external === null.
>
> You are assuming that a value needs to yield typeof "object" in order to
> allow property access; however, that is not the case.
What a ridiculous assumption that would be in an ECMAScript
implementation. However, I do rightly assume that a null object won't
allow property access.
>
> > Granted, this one would fail if the external object were an ActiveX
> > method (which it isn't.)
>
> It will fail in a great many other cases, too.
Yes. Any circumstance where a host environment's implementation of
external throws an exception on [[get]]. Methods of ActiveX objects
are the most common example.
>
> >> really should be `typeof window.external', is not. The bottom line is that
>
> > No it shouldn't. If there is no global window property, then that
> > will error. Talk about error-prone.
>
> Correct. It should be
>
> typeof window != "undefined"
> && typeof window.external ...
Which is basically what my functions do.
>
> But you miss the point.
Perhaps. It is often difficult to tell what your point is.
>
> >> there is a part of a reliable feature test that can not be encapsulated in a
> >> method.
>
> > I don't agree. What's wrong with this:
>
> > alert(isFeaturedMethod(this, 'addEventListener'));
>
> In the case of `this' that would be OK. However, we are talking about the
> general use of a feature test.
Right. You have to know what you are doing when you call these
functions. See the above example with external.
>
> > Or as you would put it:
>
> > alert(isFeaturedMethod(this.window, 'addEventListener'));
>
> I would most certainly not perform this feature test.
Right. If you were to use this.window (as opposed to just "this")
then you would need two calls like in the external example. And that
one would turn into three tests. I still say this is needless
redundancy.
>
> > Of course, considering your position, you would consider that error-
> > prone as window is a host object.
>
> > Looking at the function:
>
> > var reFeaturedMethod = new RegExp('^function|object$', 'i');
>
> > isFeaturedMethod = function(o, m) {
> > var t = typeof(o[m]);
> > return !!((reFeaturedMethod.test(t) && o[m]) || t == 'unknown');
> > };
>
> > The first parameter is the global object (window object),
>
> The Global Object is not necessarily the object that the host-defined
> `window' property of Global Object refers to. Until you got that it does
> not make sense to continue discussing with you about proper feature tests.
You have just changed the subject. Never mind your insistence on
introducing redundant testing related to the window object. Your
original argument was that my functions couldn't encapsulate the check
for a non-null object. It appears you were mistaken.
>
> > [...]
> > I tested with the first posted example. No problem.
>
> You have tested with a subset of user agents and leap to the conclusion that
> there can never be a problem.
You have snipped out the context of that quote. It referred to the
testing of ActiveX methods. And I tested with virtually every version
of Windows IE, which is the only browser that exposes ActiveX
methods. If you think there is a problem related to the global/window
issue that you keep coming back to, that is another matter (and I
still disagree with you.)
Or any other false-value. However, that is hardly sufficient.
>> You are assuming that a value needs to yield typeof "object" in order to
>> allow property access; however, that is not the case.
>
> What a ridiculous assumption that would be in an ECMAScript
> implementation. [...]
Exactly. Yet you are making it.
>>> Granted, this one would fail if the external object were an ActiveX
>>> method (which it isn't.)
>> It will fail in a great many other cases, too.
>
> Yes. Any circumstance where a host environment's implementation of
> external throws an exception on [[get]]. Methods of ActiveX objects
> are the most common example.
And any circumstance where a primitive value or native object different from
Object or Object objects are involved.
>>>> really should be `typeof window.external', is not. The bottom line is that
>>> No it shouldn't. If there is no global window property, then that
>>> will error. Talk about error-prone.
>> Correct. It should be
>>
>> typeof window != "undefined"
>> && typeof window.external ...
>
> Which is basically what my functions do.
But they don't, and they can't. For `foo.bar' you would have to pass the
`foo' reference to them which, as it may be not qualified, may cause a
ReferenceError exception.
>> But you miss the point.
>
> Perhaps. It is often difficult to tell what your point is.
My point is that you can not perform all feature testing with passing plain
values to a method.
>>> Or as you would put it:
>>> alert(isFeaturedMethod(this.window, 'addEventListener'));
>> I would most certainly not perform this feature test.
>
> Right. If you were to use this.window (as opposed to just "this")
> then you would need two calls like in the external example. [...]
No, I would not attempt to access the Global Object with `this' as this code
would be part of local code, probably a user-defined object's method, and I
would most certainly not call the addEventListener() method of DOM Level 2
on a proprietary host object.
>>> Of course, considering your position, you would consider that error-
>>> prone as window is a host object.
>>> Looking at the function:
>>> var reFeaturedMethod = new RegExp('^function|object$', 'i');
>>> isFeaturedMethod = function(o, m) {
>>> var t = typeof(o[m]);
>>> return !!((reFeaturedMethod.test(t) && o[m]) || t == 'unknown');
>>> };
>>> The first parameter is the global object (window object),
>> The Global Object is not necessarily the object that the host-defined
>> `window' property of Global Object refers to. Until you got that it does
>> not make sense to continue discussing with you about proper feature tests.
>
> You have just changed the subject. [...]
I have not. You have, by posting your misconception again.
>>> [...]
>>> I tested with the first posted example. No problem.
>> You have tested with a subset of user agents and leap to the conclusion that
>> there can never be a problem.
>
> You have snipped out the context of that quote. It referred to the
> testing of ActiveX methods. And I tested with virtually every version
> of Windows IE, which is the only browser that exposes ActiveX
> methods. [...]
Wrong.
PointedEars
--
"Use any version of Microsoft Frontpage to create your site. (This won't
prevent people from viewing your source, but no one will want to steal it.)"
-- from <http://www.vortex-webdesign.com/help/hidesource.htm>
I certainly am not. And you snipped my explanation as to why.
>
> >>> Granted, this one would fail if the external object were an ActiveX
> >>> method (which it isn't.)
> >> It will fail in a great many other cases, too.
>
> > Yes. Any circumstance where a host environment's implementation of
> > external throws an exception on [[get]]. Methods of ActiveX objects
> > are the most common example.
>
> And any circumstance where a primitive value or native object different from
> Object or Object objects are involved.
>
> >>>> really should be `typeof window.external', is not. The bottom line is that
> >>> No it shouldn't. If there is no global window property, then that
> >>> will error. Talk about error-prone.
> >> Correct. It should be
>
> >> typeof window != "undefined"
> >> && typeof window.external ...
>
> > Which is basically what my functions do.
>
> But they don't, and they can't. For `foo.bar' you would have to pass the
> `foo' reference to them which, as it may be not qualified, may cause a
> ReferenceError exception.
See my examples. They all start at the global object, passed as
"this."
>
> >> But you miss the point.
>
> > Perhaps. It is often difficult to tell what your point is.
>
> My point is that you can not perform all feature testing with passing plain
> values to a method.
I have no idea what that means.
>
> >>> Or as you would put it:
> >>> alert(isFeaturedMethod(this.window, 'addEventListener'));
> >> I would most certainly not perform this feature test.
>
> > Right. If you were to use this.window (as opposed to just "this")
> > then you would need two calls like in the external example. [...]
>
> No, I would not attempt to access the Global Object with `this' as this code
> would be part of local code, probably a user-defined object's method, and I
What code would be part of a user-defined object's method? You are
going off on a tangent. The examples I posted should be assumed to
run in the global context.
> would most certainly not call the addEventListener() method of DOM Level 2
> on a proprietary host object.
We all know about your stance on that. However, this example didn't
do that (it just detected that the method was featured.)
>
> >>> Of course, considering your position, you would consider that error-
> >>> prone as window is a host object.
> >>> Looking at the function:
> >>> var reFeaturedMethod = new RegExp('^function|object$', 'i');
> >>> isFeaturedMethod = function(o, m) {
> >>> var t = typeof(o[m]);
> >>> return !!((reFeaturedMethod.test(t) && o[m]) || t == 'unknown');
> >>> };
> >>> The first parameter is the global object (window object),
> >> The Global Object is not necessarily the object that the host-defined
> >> `window' property of Global Object refers to. Until you got that it does
> >> not make sense to continue discussing with you about proper feature tests.
>
> > You have just changed the subject. [...]
>
> I have not. You have, by posting your misconception again.
>
> >>> [...]
> >>> I tested with the first posted example. No problem.
> >> You have tested with a subset of user agents and leap to the conclusion that
> >> there can never be a problem.
>
> > You have snipped out the context of that quote. It referred to the
> > testing of ActiveX methods. And I tested with virtually every version
> > of Windows IE, which is the only browser that exposes ActiveX
> > methods. [...]
>
> Wrong.
>
We're done here.
You do, and there was no explanation of that. (How could you explain
something that is obviously ridiculous?)
>>>>>> really should be `typeof window.external', is not. The bottom line is that
>>>>> No it shouldn't. If there is no global window property, then that
>>>>> will error. Talk about error-prone.
>>>> Correct. It should be
>>>> typeof window != "undefined"
>>>> && typeof window.external ...
>>> Which is basically what my functions do.
>> But they don't, and they can't. For `foo.bar' you would have to pass the
>> `foo' reference to them which, as it may be not qualified, may cause a
>> ReferenceError exception.
>
> See my examples. They all start at the global object, passed as
> "this."
First, your examples are insufficient for proof of general applicability,
which is what should be targeted with such a method (else no method would be
required). Second, `this' does not always refer to the Global Object, so if
that is an argument you are trying to make here with that sentence, it is
not at all a solid one.
>>>> But you miss the point.
>>> Perhaps. It is often difficult to tell what your point is.
>> My point is that you can not perform all feature testing with passing plain
>> values to a method.
>
> I have no idea what that means.
Although it does have meaning for people who know what they are doing.
>>>>> Or as you would put it:
>>>>> alert(isFeaturedMethod(this.window, 'addEventListener'));
>>>> I would most certainly not perform this feature test.
>>> Right. If you were to use this.window (as opposed to just "this")
>>> then you would need two calls like in the external example. [...]
>> No, I would not attempt to access the Global Object with `this' as this code
>> would be part of local code, probably a user-defined object's method, and I
>
> What code would be part of a user-defined object's method?
The code to be feature-tested, of course.
> You are going off on a tangent.
I am not.
> The examples I posted should be assumed to run in the global context.
Which merely demonstrates your shortsightedness.
>> would most certainly not call the addEventListener() method of DOM Level 2
>> on a proprietary host object.
>
> We all know about your stance on that. However, this example didn't
> do that (it just detected that the method was featured.)
It does not make sense to test for a feature that is not used afterwards, so
yes, either you were about to call that method or you have a lot more to
learn than I thought.
>>>>> [...]
>>>>> I tested with the first posted example. No problem.
>>>> You have tested with a subset of user agents and leap to the conclusion that
>>>> there can never be a problem.
>>> You have snipped out the context of that quote. It referred to the
>>> testing of ActiveX methods. And I tested with virtually every version
>>> of Windows IE, which is the only browser that exposes ActiveX
>>> methods. [...]
>> Wrong.
>
> We're done here.
Apparently *you* are done here, i.e. you refuse to think about it, and
so, inevitably, you will produce error-prone code. Code that cannot be
recommended to others at all in good faith.
Please trim your quotes as you can see in each and every posting of
mine (and other posters) and as described in the FAQ and FAQ Notes:
http://www.jibbering.com/faq/#FAQ2_3
http://www.jibbering.com/faq/faq_notes/clj_posts.html#ps1Trim
[snip]
> > > >>> This is because there is no reliable way to determine if host object
> > > >>> methods are callable.
> > > >> It would seem there is. There does not seem to be a reliable way yet to
>
> > > > How do you figure?
>
> > > Because evaluating the type before and trying read access only if the type
> > > indicates feasibility has not caused unexpected behavior so far.
>
> > And if you get typeof(o) == 'object', how does that tell you it is
> > callable?
>
> If I get that result and *then* the value is not a false-value and I
> am expecting the identifier to designate a host object's method, at
> the least I can be pretty sure that it is callable.
That seems reasonable.
[snip]
[snip]
> > > [...]
> > > I tested with the first posted example. No problem.
>
> > You have tested with a subset of user agents and leap to the conclusion that
> > there can never be a problem.
>
> You have snipped out the context of that quote. It referred to the
> testing of ActiveX methods. And I tested with virtually every version
> of Windows IE, which is the only browser that exposes ActiveX
> methods. If you think there is a problem related to the global/window
> issue that you keep coming back to, that is another matter (and I
> still disagree with you.)
Were these IE browser versions all on the same install of windows? I
am getting more sceptical of this type of testing lately.
Unfortunately a solution costs real dollars :-S
[snip]
> >>>> really should be `typeof window.external', is not. The bottom line is that
> >>> No it shouldn't. If there is no global window property, then that
> >>> will error. Talk about error-prone.
> >> Correct. It should be
>
> >> typeof window != "undefined"
> >> && typeof window.external ...
>
> > Which is basically what my functions do.
>
> But they don't, and they can't. For `foo.bar' you would have to pass the
> `foo' reference to them which, as it may be not qualified, may cause a
> ReferenceError exception.
I've read some of David Mark's code lately. It seems that when he
calls one of his functions like isRealObjectProperty(o,p) or
isFeaturedMethod(o, m) he has already checked properly that the 'o'
argument is qualified. For example, from David's code
if (isRealObjectProperty(this, 'document')) {
doc = this.document;
// snip ...
if (isFeaturedMethod(doc, 'getElementById')) {
return function(id, docNode) {
return idCheck((docNode || doc).getElementById(id), id);
};
}
In the call to isFeaturedMethod there is no need to check the typeof
doc. It is already known from the isRealObjectProperty call. This
statement assumes that the isFeaturedMethod and isRealObjects work as
advertised.
I think David will never have the error that you are concerned about
when you write about unqualified references causing an error when the
call is made.
ACK. However, this will require at least one reference to be qualified, and
be it only a reference to the global object. With this approach, if you are
going to test e.g. whether or not the global encodeURIComponent() method is
supported, or if you have to fall back to escape() or even a dummy method,
you will have to write
var _global = this;
// local context only for the sake of the argument
function foo()
{
if (isFeaturedMethod(_global, 'encodeURIComponent'))
{
// ...
}
}
as opposed to
function foo()
{
if (typeof encodeURIComponent == "function")
{
// ...
}
}
Not only is one call more on the stack, there is also a dependency on
`_global'. Now consider a host object's method and the calls that would
be involved in testing it.
I don't know what this means. I rarely know what your abbreviations
mean.
> However, this will require at least one reference to be qualified, and
> be it only a reference to the global object.
That could be done with the following around all the code.
if (typeof this != 'unknown') {
}
> With this approach, if you are
> going to test e.g. whether or not the global encodeURIComponent() method is
> supported, or if you have to fall back to escape() or even a dummy method,
> you will have to write
>
> var _global = this;
>
> // local context only for the sake of the argument
> function foo()
> {
> if (isFeaturedMethod(_global, 'encodeURIComponent'))
> {
> // ...
> }
> }
>
> as opposed to
>
> function foo()
> {
> if (typeof encodeURIComponent == "function")
> {
> // ...
> }
> }
>
> Not only is one call more on the stack, there is also a dependency on
> `_global'.
Yes yours is simpler and so if it is sufficient would be the sensible
choice.
> Now consider a host object's method and the calls that would
> be involved in testing it.
If you just mean there are many more calls to the testing functions
then I understand your point.
Yes.
> am getting more sceptical of this type of testing lately.
There can be issues, like the DirectX opacity "library not registered"
snafu (which can safely be ignored unless you are worried about
developers' test machines.) I have the ActiveX feature testing on
Win98 in the past though.
And I can't get IE4 to work at all on my primary test machine. No
idea why. IE3 works (sometimes) and I use it to make sure that
scripts degrade properly as virtually nothing I write will enhance
pages in that browser.
> Unfortunately a solution costs real dollars :-S
I've got enough machines, but I don't feel like uninstalling IE6/7
from any of them as I worry it will screw up Windows or other
applications. I still have a Win98 box, but I haven't turned it on in
years. If I determine that the multiple IE on XP approach has
problems I can't work around or discount, perhaps I will uninstall IE6
on the Win98 box and use it to test IE5.x.
It means ACKnowledge(d) (from the ASCII mnemonic), and it is not my
invention: http://catb.org/~esr/jargon/html/A/ACK.html
You can also find explanations for (hacker) jargon like those abbreviations
in the Wikipedia, e.g. http://en.wikipedia.org/wiki/ACK
>> However, this will require at least one reference to be qualified, and
>> be it only a reference to the global object.
>
> That could be done with the following around all the code.
>
> if (typeof this != 'unknown') {
>
> }
Certainly not. `this' is a reference to the Activation Object which can
only be typeof "unknown" if that is a host object. What I meant was that
you will need the equivalent of `global' unless the called context is that
of a user-defined method of the Global Object (where you can use `this').
PointedEars
--
var bugRiddenCrashPronePieceOfJunk = (
navigator.userAgent.indexOf('MSIE 5') != -1
&& navigator.userAgent.indexOf('Mac') != -1
) // Plone, register_function.js:16
I meant "undefined"
> Certainly not. `this' is a reference to the Activation Object which can
> only be typeof "unknown" if that is a host object. What I meant was that
> you will need the equivalent of `global' unless the called context is that
> of a user-defined method of the Global Object (where you can use `this').
--
And I said:
>> Certainly not. `this' is a reference to the Activation Object which can
>> only be typeof "unknown" if that is a host object. What I meant was that
>> you will need the equivalent of `global' unless the called context is that
>> of a user-defined method of the Global Object (where you can use `this').
So what you meant does not matter here. Unless the Activation Object is a
host object (which may yield any value in a typeof operation, see ES3 Final,
11.4.3), `this' is (also) *never* (typeof) "undefined".
Would you *please* trim your quotes?
>Code Worth Recommending Project
>http://cljs.michaux.ca
I've looked at this, and have seen no indication of how to find code.
To the incomer, it looks like an amusement park for experts, of no
practical use. IMHO, it should be rapidly seeded with some known-not-
too-bad code (which can be improved later, if needed), so that it can be
seen, rapidly, to be of some possible use.
International forms should be used in all cases, not merely local ones.
This, in <http://cljs.michaux.ca/trac/timeline>, the date sequence looks
ludicrous to all non-Americans. Use YYYY-MM-DD, as in ISO 8601 - even
Americans can understand it, and there's no need for them to like it.
Page <http://cljs.michaux.ca/trac/changeset/8> and no doubt others - in
my IE6, the monospace text is unreasonably small. Zoom does not work.
Search results : unreadably small, no Zoom, FFF dates.
--
(c) John Stockton, Surrey, UK. ?@merlyn.demon.co.uk Turnpike v6.05 MIME.
Web <URL:http://www.merlyn.demon.co.uk/> - FAQish topics, acronyms, & links.
Proper <= 4-line sig. separator as above, a line exactly "-- " (SonOfRFC1036)
Do not Mail News to me. Before a reply, quote with ">" or "> " (SonOfRFC1036)
There are two ways on the front page: a browse source link and a
subversion command to get the code. Sure one day the project may be a
success and deserve a flashy page but that is not a priority right
now, at least for me.
> To the incomer, it looks like an amusement park for experts, of no
> practical use. IMHO, it should be rapidly seeded with some known-not-
> too-bad code (which can be improved later, if needed), so that it can be
> seen, rapidly, to be of some possible use.
Having code in the repository is a priority and it will be there at
least "rapidly" on a geological scale. There is no time line for the
project.
> International forms should be used in all cases, not merely local ones.
> This, in <http://cljs.michaux.ca/trac/timeline>, the date sequence looks
> ludicrous to all non-Americans. Use YYYY-MM-DD, as in ISO 8601 - even
> Americans can understand it, and there's no need for them to like it.
trac is a prepackaged piece of software that is good on the whole.
> Page <http://cljs.michaux.ca/trac/changeset/8> and no doubt others - in
> my IE6, the monospace text is unreasonably small. Zoom does not work.
>
> Search results : unreadably small, no Zoom, FFF dates.
This is not a priority, at least for me. I can read the pages just
fine and know how to adjust my browser when that is not the case with
some pages on the web. If you are passionate about this and want to
find the CSS that causes the problem. You can send a patch.
--
Peter
Code Worth Recommending Project
http://cljs.michaux.ca/