D
David Mark
MooTools: An Objective Look
Seems this oddity is now creeping into public perception. So is it
any good at all?
As an aside, the "builder" is enhanced to the point of inaccessibility
and it is one of those pages that is falling off the edge of the left
side of the window (at least in FF3.) Not promising.
Excerpts:
- Some functionality inspired by [Prototype.js](http://
prototypejs.org) Copyright (c) 2005-2007 Sam Stephenson, [MIT License]
(http://opensource.org/licenses/mit-license.php)
*/
There's a big red flag right off the bat.
var Hash = new Native({
name: 'Hash',
initialize: function(object){
if ($type(object) == 'hash') object = $unlink(object.getClean());
for (var key in object) this[key] = object[key];
return this;
}
});
They are aping the initial effort of a Javascript programmer who
obviously hadn't yet learned Javascript. Note the incessant use of
"$" as well as the "initialize" method.
And why isn't that for-in loop filtered? This is supposed to be a
drop-in solution, yet it is clearly vulnerable to the machinations of
other scripts.
function $arguments(i){
return function(){
return arguments;
};
};
Useless syntactic sugar (and for what?)
function $chk(obj){
return !!(obj || obj === 0);
};
Try to guess what that's for. Then wonder how it came to be called
"$chk".
function $defined(obj){
return (obj != undefined);
};
Hard to botch a one-line function such as this, but I spot no less
than four mistakes, including the aforementioned use of "$".
function $lambda(value){
return (typeof value == 'function') ? value : function(){
return value;
};
};
So why would you pass a function to this in the first place?
function $splat(obj){
var type = $type(obj);
return (type) ? ((type != 'array' && type != 'arguments') ? [obj] :
obj) : [];
};
Splat indeed.
function $try(){
for (var i = 0, l = arguments.length; i < l; i++){
try {
return arguments();
} catch(e){}
}
return null;
};
That lets out a lot of older browsers (syntax error) and it appears to
be part of the core.
function $type(obj){
if (obj == undefined) return false;
if (obj.$family) return (obj.$family.name == 'number' && !isFinite
(obj)) ? false : obj.$family.name;
if (obj.nodeName){
switch (obj.nodeType){
case 1: return 'element';
case 3: return (/\S/).test(obj.nodeValue) ? 'textnode' :
'whitespace';
}
} else if (typeof obj.length == 'number'){
if (obj.callee) return 'arguments';
else if (obj.item) return 'collection';
}
return typeof obj;
};
I don't know what this is supposed to be, but I don't like it. And
something tells me the whole script hinges on it.
var Browser = $merge({
Engine: {name: 'unknown', version: 0},
Platform: {name: (window.orientation != undefined) ? 'ipod' :
(navigator.platform.match(/mac|win|linux/i) || ['other'])
[0].toLowerCase()},
Here we go.
Features: {xpath: !!(document.evaluate), air: !!(window.runtime),
query: !!(document.querySelector)},
This is stupid. Methods that rely on missing features should
themselves be missing from the API. No extraneous collection of flags
necessary.
Plugins: {},
Engines: {
Wonder how many the authors have heard of (and how many they know how
to detect?)
presto: function(){
return (!window.opera) ? false : ((arguments.callee.caller) ? 960 :
((document.getElementsByClassName) ? 950 : 925));
Jesus. The versions?!
},
There's none.
trident: function(){
return (!window.ActiveXObject) ? false : ((window.XMLHttpRequest) ?
5 : 4);
},
And none.
webkit: function(){
return (navigator.taintEnabled) ? false :
((Browser.Features.xpath) ? ((Browser.Features.query) ? 525 : 420) :
419);
},
Still none.
gecko: function(){
return (document.getBoxObjectFor == undefined) ? false :
((document.getElementsByClassName) ? 19 : 18);
The gBOF method is deprecated and will be removed in the next release
of FF. So this "detection" already has an expiration date.
}
And none. So, this was all a waste of time.
}
}, Browser || {});
Browser.Platform[Browser.Platform.name] = true;
For your sniffing convenience.
Browser.detect = function(){
for (var engine in this.Engines){
var version = this.Engines[engine]();
if (version){
this.Engine = {name: engine, version: version};
this.Engine[engine] = this.Engine[engine + version] = true;
break;
}
}
return {name: engine, version: version};
};
Browser.detect();
Well, at least they are honest about it. This doesn't even aspire to
be cross-browser (or maintainable.)
Browser.Features.xhr = !!(Browser.Request());
Another extraneous flag.
Browser.Plugins.Flash = (function(){
var version = ($try(function(){
return navigator.plugins['Shockwave Flash'].description;
}, function(){
return new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable
('$version');
}) || '0 r0').match(/\d+/g);
return {version: parseInt(version[0] || 0 + '.' + version[1] || 0),
build: parseInt(version[2] || 0)};
})();
That dog don't hunt. The first "try" doesn't need try-catch and the
second is just wrong. Granted, Adobe's own examples are abominable,
but they at least attempt to address the myriad issues involved with
sniffing Flash.
function $exec(text){
if (!text) return text;
if (window.execScript){
window.execScript(text);
} else {
var script = document.createElement('script');
script.setAttribute('type', 'text/javascript');
Why would anyone use setAttribute for this? Perhaps because dot
notation wouldn't work.
script[(Browser.Engine.webkit && Browser.Engine.version < 420) ?
'innerText' : 'text'] = text;
Now we see the incompetence inherent in the system. And how old is
this script? You can't buy that sort of ineptitude, so why not
download it for free?
document.head.appendChild(script);
document.head.removeChild(script);
}
return text;
};
var $uid = (Browser.Engine.trident) ? function(item){
return (item.uid || (item.uid = [Native.UID++]))[0];
} : function(item){
return item.uid || (item.uid = Native.UID++);
};
Similar nonsense.
var Window = new Native({
name: 'Window',
legacy: (Browser.Engine.trident) ? null: window.Window,
Isn't that something.
initialize: function(win){
$uid(win);
if (!win.Element){
win.Element = $empty;
if (Browser.Engine.webkit) win.document.createElement("iframe"); //
fixes safari 2
Oh I bet it does. And what of Safari 3? And WTF are they trying to
fix?
win.Element.prototype = (Browser.Engine.webkit) ? window
["[[DOMElement.prototype]]"] : {};
That does it.
}
win.document.window = win;
A document expando to boot. And that sure looks like a circular
reference to me.
return $extend(win, Window.Prototype);
},
I don't think it warrants any further study or consideration.
Seems this oddity is now creeping into public perception. So is it
any good at all?
As an aside, the "builder" is enhanced to the point of inaccessibility
and it is one of those pages that is falling off the edge of the left
side of the window (at least in FF3.) Not promising.
Excerpts:
- Some functionality inspired by [Prototype.js](http://
prototypejs.org) Copyright (c) 2005-2007 Sam Stephenson, [MIT License]
(http://opensource.org/licenses/mit-license.php)
*/
There's a big red flag right off the bat.
var Hash = new Native({
name: 'Hash',
initialize: function(object){
if ($type(object) == 'hash') object = $unlink(object.getClean());
for (var key in object) this[key] = object[key];
return this;
}
});
They are aping the initial effort of a Javascript programmer who
obviously hadn't yet learned Javascript. Note the incessant use of
"$" as well as the "initialize" method.
And why isn't that for-in loop filtered? This is supposed to be a
drop-in solution, yet it is clearly vulnerable to the machinations of
other scripts.
function $arguments(i){
return function(){
return arguments;
};
};
Useless syntactic sugar (and for what?)
function $chk(obj){
return !!(obj || obj === 0);
};
Try to guess what that's for. Then wonder how it came to be called
"$chk".
function $defined(obj){
return (obj != undefined);
};
Hard to botch a one-line function such as this, but I spot no less
than four mistakes, including the aforementioned use of "$".
function $lambda(value){
return (typeof value == 'function') ? value : function(){
return value;
};
};
So why would you pass a function to this in the first place?
function $splat(obj){
var type = $type(obj);
return (type) ? ((type != 'array' && type != 'arguments') ? [obj] :
obj) : [];
};
Splat indeed.
function $try(){
for (var i = 0, l = arguments.length; i < l; i++){
try {
return arguments();
} catch(e){}
}
return null;
};
That lets out a lot of older browsers (syntax error) and it appears to
be part of the core.
function $type(obj){
if (obj == undefined) return false;
if (obj.$family) return (obj.$family.name == 'number' && !isFinite
(obj)) ? false : obj.$family.name;
if (obj.nodeName){
switch (obj.nodeType){
case 1: return 'element';
case 3: return (/\S/).test(obj.nodeValue) ? 'textnode' :
'whitespace';
}
} else if (typeof obj.length == 'number'){
if (obj.callee) return 'arguments';
else if (obj.item) return 'collection';
}
return typeof obj;
};
I don't know what this is supposed to be, but I don't like it. And
something tells me the whole script hinges on it.
var Browser = $merge({
Engine: {name: 'unknown', version: 0},
Platform: {name: (window.orientation != undefined) ? 'ipod' :
(navigator.platform.match(/mac|win|linux/i) || ['other'])
[0].toLowerCase()},
Here we go.
Features: {xpath: !!(document.evaluate), air: !!(window.runtime),
query: !!(document.querySelector)},
This is stupid. Methods that rely on missing features should
themselves be missing from the API. No extraneous collection of flags
necessary.
Plugins: {},
Engines: {
Wonder how many the authors have heard of (and how many they know how
to detect?)
presto: function(){
return (!window.opera) ? false : ((arguments.callee.caller) ? 960 :
((document.getElementsByClassName) ? 950 : 925));
Jesus. The versions?!
},
There's none.
trident: function(){
return (!window.ActiveXObject) ? false : ((window.XMLHttpRequest) ?
5 : 4);
},
And none.
webkit: function(){
return (navigator.taintEnabled) ? false :
((Browser.Features.xpath) ? ((Browser.Features.query) ? 525 : 420) :
419);
},
Still none.
gecko: function(){
return (document.getBoxObjectFor == undefined) ? false :
((document.getElementsByClassName) ? 19 : 18);
The gBOF method is deprecated and will be removed in the next release
of FF. So this "detection" already has an expiration date.
}
And none. So, this was all a waste of time.
}
}, Browser || {});
Browser.Platform[Browser.Platform.name] = true;
For your sniffing convenience.
Browser.detect = function(){
for (var engine in this.Engines){
var version = this.Engines[engine]();
if (version){
this.Engine = {name: engine, version: version};
this.Engine[engine] = this.Engine[engine + version] = true;
break;
}
}
return {name: engine, version: version};
};
Browser.detect();
Well, at least they are honest about it. This doesn't even aspire to
be cross-browser (or maintainable.)
Browser.Features.xhr = !!(Browser.Request());
Another extraneous flag.
Browser.Plugins.Flash = (function(){
var version = ($try(function(){
return navigator.plugins['Shockwave Flash'].description;
}, function(){
return new ActiveXObject('ShockwaveFlash.ShockwaveFlash').GetVariable
('$version');
}) || '0 r0').match(/\d+/g);
return {version: parseInt(version[0] || 0 + '.' + version[1] || 0),
build: parseInt(version[2] || 0)};
})();
That dog don't hunt. The first "try" doesn't need try-catch and the
second is just wrong. Granted, Adobe's own examples are abominable,
but they at least attempt to address the myriad issues involved with
sniffing Flash.
function $exec(text){
if (!text) return text;
if (window.execScript){
window.execScript(text);
} else {
var script = document.createElement('script');
script.setAttribute('type', 'text/javascript');
Why would anyone use setAttribute for this? Perhaps because dot
notation wouldn't work.
script[(Browser.Engine.webkit && Browser.Engine.version < 420) ?
'innerText' : 'text'] = text;
Now we see the incompetence inherent in the system. And how old is
this script? You can't buy that sort of ineptitude, so why not
download it for free?
document.head.appendChild(script);
document.head.removeChild(script);
}
return text;
};
var $uid = (Browser.Engine.trident) ? function(item){
return (item.uid || (item.uid = [Native.UID++]))[0];
} : function(item){
return item.uid || (item.uid = Native.UID++);
};
Similar nonsense.
var Window = new Native({
name: 'Window',
legacy: (Browser.Engine.trident) ? null: window.Window,
Isn't that something.
initialize: function(win){
$uid(win);
if (!win.Element){
win.Element = $empty;
if (Browser.Engine.webkit) win.document.createElement("iframe"); //
fixes safari 2
Oh I bet it does. And what of Safari 3? And WTF are they trying to
fix?
win.Element.prototype = (Browser.Engine.webkit) ? window
["[[DOMElement.prototype]]"] : {};
That does it.
}
win.document.window = win;
A document expando to boot. And that sure looks like a circular
reference to me.
return $extend(win, Window.Prototype);
},
I don't think it warrants any further study or consideration.