Sometimes though, passing a string into the $() function doesn't read
well; and only makes Javascript code harder to read. For example:
$(window.button_list()[3]).hide()
Instead, it'd be nice to have normal chainability. I like the
following syntax: window.button_list()[3].$().hide().
That is, call the $() method on a string object, instead of passing the
string into the $() method.
Add this code into your application:
String.prototype.$ = function() {
return $(document.getElementById(this));
}
>From article:
http://drnicwilliams.com/2006/09/11/prototype-call-dollar-on-string/
Dr Nic a écrit :
> Sometimes though, passing a string into the $() function doesn't read
> well; and only makes Javascript code harder to read. For example:
> $(window.button_list()[3]).hide()
Actually, this is widely acclaimed as a nice way to do it. Of course,
there's no accounting for taste, but it is nicely unobstrusive, which is
the whole point of choosing such a short name.
> Instead, it'd be nice to have normal chainability. I like the
> following syntax: window.button_list()[3].$().hide().
Suit your taste, it's pretty easy to do so. But I don't think I dare
too much in asserting this will *not* happen in the official codebase.
--
Christophe Porteneuve aka TDD
t...@tddsworld.com
http://www.drnicwilliams.com - Ruby/Rails blog
skype: nicwilliams
(m) +31 62 494 8552
(p) +61 7 3102 3237 (finds me anywhere in the world)
(f) +61 7 3305 7572 (sends fax to my email)
String.prototype.$ = function() {
return $(this);
}
?
-Thomas
--
Thomas Fuchs
wollzelle
questentier on AIM
madrobby on irc.freenode.net
http://www.fluxiom.com :: online digital asset management
http://script.aculo.us :: Web 2.0 JavaScript
http://mir.aculo.us :: Where no web developer has gone before
>>> String.prototype.X = function() { return (this) }
>>> "blah".X()
["b","l","a","h"]
>>> typeof "blah".X()
"object"
>>> typeof "blah"
"string"
>>> typeof String("blah")
"string"
Not sure what this proves, except that the function returns a thing with
a type "object" rather than type "string". The way firebug displays
things probably depends on the result of typeof, and arrays give
"object", so Firebug thinks it's an array. Or something like that.
Chris
Yeah, the issue with your original implementation is due to this test in
Prototype's $:
if (typeof element == "string")
When you refer to yourself, as a String, using this, typeof says
"object". A more reference-proof way of testing whether you actually
are a string would be to say:
if (element.constructor === String)
Using this:
function $() {
var results = [], element;
for (var i = 0; i < arguments.length; i++) {
element = arguments[i];
if (element.constructor === String) {
element = document.getElementById(element);
}
results.push(Element.extend(element));
}
return results.reduce();
}
Your original implementation:
String.prototype.$ = function() { return $(this); }
works well too.
--
Christophe Porteneuve a.k.a. TDD
"[They] did not know it was impossible, so they did it." --Mark Twain
Email: t...@tddsworld.com
You're welcome :-)
As for .constructor:
- Used in Array.flatten and Form.Element.serialize.
- Specified in ECMA-262 §15.1.4
- Specified in DevMo:
http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Global_Objects:Function:constructor
http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Object:constructor
BETTER YET:
Another way to get this result would be to use the instanceof operator,
which is admittedly more readable (shame on me!):
if (element instanceof String)
- Used in Object.inspect
- Specified in ECMA-262 §11.8.6
- Specified in DevMo:
I'll offer a patch to Prototype around this.
Object.prototype.$H = function() {
return $H(this);
}
This is great for console debugging:
>>> anObject.$H().inspect()
"#<Hash:{'key1': 'value1'}>"
So much fun in 3 lines of code! :)
Nic
> So would it still be useful for a revised $() function?
There is no need to change $().
What you see is the legacy of Netscape taking a stride away from the
ECMAScript standard.
Netscape's JS engine treated (and still treats) strings as array of
strings to allow things like "test"[0] to return "t".
I do not know the internal working, but from observation:
When using "this" in a function defined in String.prototype, "this"
behaves like a string, when the context of the use requires a string.
And it looks like the engine knows document.getElementById() requires
a string. If the context does not require a string, like when using
"this" as a function argument to a user defined function, "this"
evaluates to an array of chars.
Therefore, the error is not with $(). Besides the before mentioned
$(String(this)), $(this.valueOf()) will work as well.
> Object.prototype.$H = function() {
Vade retro, Satanas!
This breaks the "Object is an empty container and can be safely looped
with for( in )" convention.
On 9/11/06, Dr Nic <drnicw...@gmail.com> wrote:
>
http://www.drnicwilliams.com - Ruby/Rails blog
Yeah, saw that. Kinda weird, btw. So we would have to use BOTH, with a ||.
Aside from the '$ overuse' issue, for/in indeed doesn't work too good on
Prototype-extended objects, what with all the methods. Which is
precisely why we now have Object.keys(). You would replace for/in with
Object.keys().each, I guess.
> Aside from the '$ overuse' issue, for/in indeed doesn't work too good on
> Prototype-extended objects, what with all the methods.
for ( in ) loops are supposed to work with Objects and they do
flawlessly. This is why Object.prototype is not tempered with. for (
in ) loops do not make sense for the other native data types, and user
defined classes can't mark properties non-enumerable anyway (a
ECMAScript omission), so for ( in ) can only be used for introspection
on them.
Object.keys() is not there because for ( in ) does not work (it does),
it is a syntactic sugar. If you look at the implementation, it is just
a for ( in ) loop. If it would not work properly, Object.keys() could
not have used it, obviously.