Prototype 1.6--Somebody Stop These People

D

David Mark

/* Prototype JavaScript framework, version 1.6.1
* (c) 2005-2009 Sam Stephenson
*
* Prototype is freely distributable under the terms of an MIT-style
license.
* For details, see the Prototype web site: http://www.prototypejs.org/
*

*--------------------------------------------------------------------------
*/

var Prototype = {
Version: '1.6.1',

Browser: (function(){
var ua = navigator.userAgent;
var isOpera = Object.prototype.toString.call(window.opera) ==
'[object Opera]';


Not a bad test for Opera, but who needs to test for Opera in 2010? :)


return {
IE: !!window.attachEvent && !isOpera,


Sure, anything not Opera with attachEvent is bound to be IE. :)


Opera: isOpera,
WebKit: ua.indexOf('AppleWebKit/') > -1,
Gecko: ua.indexOf('Gecko') > -1 && ua.indexOf('KHTML')
=== -1,
MobileSafari: /Apple.*Mobile.*Safari/.test(ua)


They can't even do browser sniffing "right". ;)


}
})(),

BrowserFeatures: {
XPath: !!document.evaluate,
SelectorsAPI: !!document.querySelector,
ElementExtensions: (function() {
var constructor = window.Element || window.HTMLElement;
return !!(constructor && constructor.prototype);
})(),


Haven't these guys figured out that "extending" Elements is a bad
idea? They must develop in a vacuum.


SpecificElementExtensions: (function() {
if (typeof window.HTMLDivElement !== 'undefined')
return true;

var div = document.createElement('div');
var form = document.createElement('form');
var isSupported = false;

if (div['__proto__'] && (div['__proto__'] !== form
['__proto__'])) {
isSupported = true;
}

div = form = null;

return isSupported;
})()
},


Sheesh.


ScriptFragment: '<script[^>]*>([\\S\\s]*?)<\/script>',
JSONFilter: /^\/\*-secure-([\s\S]*)\*\/\s*$/,

emptyFunction: function() { },
K: function(x) { return x }
};

if (Prototype.Browser.MobileSafari)
Prototype.BrowserFeatures.SpecificElementExtensions = false;


Browser sniffing to "enable" bizarre hacks is about as poor as
strategies come (see also MooTools).


var Abstract = { };


var Try = {
these: function() {
var returnValue;

for (var i = 0, length = arguments.length; i < length; i++) {
var lambda = arguments;
try {
returnValue = lambda();
break;
} catch (e) { }
}

return returnValue;
}
};

/* Based on Alex Arnell's inheritance implementation. */


Do not accept inheritance implementations from this man. ;)


var Class = (function() {
function subclass() {};
function create() {
var parent = null, properties = $A(arguments);
if (Object.isFunction(properties[0]))


isFunction?!


parent = properties.shift();

function klass() {
this.initialize.apply(this, arguments);
}


Bullshit.


Object.extend(klass, Class.Methods);
klass.superclass = parent;
klass.subclasses = [];

if (parent) {
subclass.prototype = parent.prototype;
klass.prototype = new subclass;
parent.subclasses.push(klass);
}

for (var i = 0; i < properties.length; i++)
klass.addMethods(properties);

if (!klass.prototype.initialize)
klass.prototype.initialize = Prototype.emptyFunction;

klass.prototype.constructor = klass;
return klass;
}

function addMethods(source) {
var ancestor = this.superclass && this.superclass.prototype;
var properties = Object.keys(source);

if (!Object.keys({ toString: true }).length) {
if (source.toString != Object.prototype.toString)
properties.push("toString");
if (source.valueOf != Object.prototype.valueOf)
properties.push("valueOf");


That's hardly a complete list.


}

for (var i = 0, length = properties.length; i < length; i++) {
var property = properties, value = source[property];
if (ancestor && Object.isFunction(value) &&
value.argumentNames().first() == "$super") {
var method = value;
value = (function(m) {
return function() { return ancestor[m].apply(this,
arguments); };
})(property).wrap(method);

value.valueOf = method.valueOf.bind(method);
value.toString = method.toString.bind(method);
}
this.prototype[property] = value;
}

return this;
}

return {
create: create,
Methods: {
addMethods: addMethods
}
};
})();
(function() {

var _toString = Object.prototype.toString;


Why the funny underscore?


function extend(destination, source) {
for (var property in source)
destination[property] = source[property];
return destination;
}

function inspect(object) {
try {
if (isUndefined(object)) return 'undefined';


isUndefined?!


if (object === null) return 'null';
return object.inspect ? object.inspect() : String(object);
} catch (e) {
if (e instanceof RangeError) return '...';


Oh brother. This is their own code they are calling. :)


throw e;
}
}

[...]

function keys(object) {
var results = [];
for (var property in object)

No filter after all of these years?

results.push(property);
return results;
}

function values(object) {
var results = [];
for (var property in object)
results.push(object[property]);
return results;
}

function clone(object) {
return extend({ }, object);
}

function isElement(object) {
return !!(object && object.nodeType == 1);
}

function isArray(object) {
return _toString.call(object) == "[object Array]";
}


Of course. :(


function isHash(object) {
return object instanceof Hash;
}


Again.


function isFunction(object) {
return typeof object === "function";
}

Waste.


function isString(object) {
return _toString.call(object) == "[object String]";
}


Stupid.


function isNumber(object) {
return _toString.call(object) == "[object Number]";
}


Ditto.


function isUndefined(object) {
return typeof object === "undefined";
}


Saw that coming. ;)


[...]


function bindAsEventListener(context) {
var __method = this, args = slice.call(arguments, 1);
return function(event) {
var a = update([event || window.event], args);

That lets frames out. :(

return __method.apply(context, a);
}
}


[...]

function evalScripts() {
return this.extractScripts().map(function(script) { return eval
(script) });
}


Don't use eval for this. How many times has this come up over the
years?


function escapeHTML() {
return this.replace(/&/g,'&amp;').replace(/</g,'&lt;').replace(/>/
g,'&gt;');
}

function unescapeHTML() {
return this.stripTags().replace(/&lt;/g,'<').replace(/&gt;/
g,'>').replace(/&amp;/g,'&');
}


It's about time they fixed that one. :)


function toQueryParams(separator) {
var match = this.strip().match(/([^?#]*)(#.*)?$/);
if (!match) return { };

return match[1].split(separator || '&').inject({ }, function(hash,
pair) {
if ((pair = pair.split('='))[0]) {
var key = decodeURIComponent(pair.shift());
var value = pair.length > 1 ? pair.join('=') : pair[0];
if (value != undefined) value = decodeURIComponent(value);

if (key in hash) {
if (!Object.isArray(hash[key])) hash[key] = [hash[key]];

There it is (isArray). All incompetent JS designers think alike (plow
right into language-imposed roadblocks and let the "edge cases" fall
where they may).

hash[key].push(value);
}
else hash[key] = value;
}
return hash;
});
}

[...]

function evalJSON(sanitize) {
var json = this.unfilterJSON();
try {
if (!sanitize || json.isJSON()) return eval('(' + json + ')');

Hello? Function constructor? It's like they deliberately try to do
everything wrong.


} catch (e) { }
throw new SyntaxError('Badly formed JSON string: ' + this.inspect
());


Clueless use of try-catch. Who knows what threw the exception?


}

[...]

function concat() {
var array = slice.call(this, 0), item;
for (var i = 0, length = arguments.length; i < length; i++) {
item = arguments;
if (Object.isArray(item) && !('callee' in item)) {


Somebody stop these guys. :(


for (var j = 0, arrayLength = item.length; j < arrayLength; j+
+)
array.push(item[j]);
} else {
array.push(item);
}
}
return array;
}

Object.extend(arrayProto, Enumerable);


Still extending native objects?


if (!arrayProto._reverse)
arrayProto._reverse = arrayProto.reverse;


That's helpful. :)


[...]


function abs() {
return Math.abs(this);
}

function round() {
return Math.round(this);
}

function ceil() {
return Math.ceil(this);
}

function floor() {
return Math.floor(this);
}


Wastes.


[...]


var Ajax = {
getTransport: function() {
return Try.these(
function() {return new XMLHttpRequest()},
function() {return new ActiveXObject('Msxml2.XMLHTTP')},
function() {return new ActiveXObject('Microsoft.XMLHTTP')}
) || false;
},

activeRequestCount: 0
};


Well, at least they _tried_. :)


[...]


function $(element) {


Here we go.


if (arguments.length > 1) {
for (var i = 0, elements = [], length = arguments.length; i <
length; i++)
elements.push($(arguments));
return elements;
}
if (Object.isString(element))
element = document.getElementById(element);
return Element.extend(element);


So it is one "$" wrapper for both single and multiple elements. That
sounds familiar. :)


}

if (Prototype.BrowserFeatures.XPath) {
document._getElementsByXPath = function(expression, parentElement) {
var results = [];
var query = document.evaluate(expression, $(parentElement) ||
document,
null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
for (var i = 0, length = query.snapshotLength; i < length; i++)
results.push(Element.extend(query.snapshotItem(i)));
return results;
};
}

How do I know their "slow lane" is going to be wildly incompatible
with XPath? Just a hunch.


/
*--------------------------------------------------------------------------
*/

if (!window.Node) var Node = { };


OMFG. How about:-

var Node;
if (!Node) { Node = {}; }

I suppose that would make too much sense and leaves out the cool
window reference. ;)


if (!Node.ELEMENT_NODE) {
Object.extend(Node, {
ELEMENT_NODE: 1,
ATTRIBUTE_NODE: 2,
TEXT_NODE: 3,
CDATA_SECTION_NODE: 4,
ENTITY_REFERENCE_NODE: 5,
ENTITY_NODE: 6,
PROCESSING_INSTRUCTION_NODE: 7,
COMMENT_NODE: 8,
DOCUMENT_NODE: 9,
DOCUMENT_TYPE_NODE: 10,
DOCUMENT_FRAGMENT_NODE: 11,
NOTATION_NODE: 12
});
}


(function(global) {

var SETATTRIBUTE_IGNORES_NAME = (function(){

Poorly chosen name (betrays a misunderstanding of the problem).

var elForm = document.createElement("form");
var elInput = document.createElement("input");
var root = document.documentElement;
elInput.setAttribute("name", "test");


No need to use that method here. It's virtually never needed in an
HTML DOM (the only type of DOM available to this script).


elForm.appendChild(elInput);
root.appendChild(elForm);


For Christ's sake. There must be a book on this stuff somewhere (e.g.
Browser Scripting for the Terminally Clueless). :)

Anyway, wait until the DOM is _ready_ and append the form to the
_body_.


var isBuggy = elForm.elements
? (typeof elForm.elements.test == "undefined")
: null;


That's an odd test. When would elForm.elements be falsy?


root.removeChild(elForm);
elForm = elInput = null;
return isBuggy;
})();


And they (and Resig) got that pattern from me. Why do they have to
foul it up so badly?

var element = global.Element;
global.Element = function(tagName, attributes) {
attributes = attributes || { };
tagName = tagName.toLowerCase();
var cache = Element.cache;
if (SETATTRIBUTE_IGNORES_NAME && attributes.name) {
tagName = '<' + tagName + ' name="' + attributes.name + '">';


I knew it. :) There's no reason to do that. It's another classic
incantation passed down from one clueless developer to the next.


delete attributes.name;
return Element.writeAttribute(document.createElement(tagName),
attributes);


I can guess what _that_ method is going to look like (and everything
is hinges on it). :)


}
if (!cache[tagName]) cache[tagName] = Element.extend
(document.createElement(tagName));
return Element.writeAttribute(cache[tagName].cloneNode(false),
attributes);
};
Object.extend(global.Element, element || { });
if (element) global.Element.prototype = element.prototype;
})(this);

Element.cache = { };
Element.idCounter = 1;

Element.Methods = {
visible: function(element) {
return $(element).style.display != 'none';
},


That's worthless.


[...]


update: (function(){

var SELECT_ELEMENT_INNERHTML_BUGGY = (function(){
var el = document.createElement("select"),
isBuggy = true;
el.innerHTML = "<option value=\"test\">test</option>";
if (el.options && el.options[0]) {
isBuggy = el.options[0].nodeName.toUpperCase() !== "OPTION";
}
el = null;
return isBuggy;
})();


That's lifted (and mangled) straight from My Library.


[...]

var SCRIPT_ELEMENT_REJECTS_TEXTNODE_APPENDING = (function () {
var s = document.createElement("script"),
isBuggy = false;
try {
s.appendChild(document.createTextNode(""));
isBuggy = !s.firstChild ||
s.firstChild && s.firstChild.nodeType !== 3;
} catch (e) {
isBuggy = true;
}
s = null;
return isBuggy;
})();


That looks like one of the three feature tests for script injection (.
333 copying average).


[...]


But I guess they didn't read the attribute-related code.


readAttribute: function(element, name) {
element = $(element);


Why?


if (Prototype.Browser.IE) {


Here we go. :)


var t = Element._attributeTranslations.read;


More on those later...


if (t.values[name]) return t.values[name](element, name);
if (t.names[name]) name = t.names[name];
if (name.include(':')) {

Whatever.

return (!element.attributes || !element.attributes[name]) ?
null :
element.attributes[name].value;
}
}
return element.getAttribute(name);
},

writeAttribute: function(element, name, value) {
element = $(element);
var attributes = { }, t = Element._attributeTranslations.write;

if (typeof name == 'object') attributes = name;
else attributes[name] = Object.isUndefined(value) ? true : value;


What?! No wonder this stuff has an inch or dust on it. :)


for (var attr in attributes) {
name = t.names[attr] || attr;
value = attributes[attr];
if (t.values[attr]) name = t.values[attr](element, value);
if (value === false || value === null)
element.removeAttribute(name);

LOL. This method works completely differently in IE8 than in previous
versions. So much for browser sniffing. :)


else if (value === true)
element.setAttribute(name, name);
else element.setAttribute(name, value);

As does this one. This is a catastrophe for those who must support
IE. And this is at the _basement_ level. ;)


}
return element;
},

getHeight: function(element) {
return Element.getDimensions(element).height;
},

getWidth: function(element) {
return Element.getDimensions(element).width;
},

classNames: function(element) {
return new Element.ClassNames(element);
},

hasClassName: function(element, className) {
if (!(element = $(element))) return;

:)

var elementClassName = element.className;
return (elementClassName.length > 0 && (elementClassName ==
className ||
new RegExp("(^|\\s)" + className + "(\\s|$)").test
(elementClassName)));
},

addClassName: function(element, className) {
if (!(element = $(element))) return;

:)

if (!Element.hasClassName(element, className))
element.className += (element.className ? ' ' : '') + className;
return element;
},

removeClassName: function(element, className) {
if (!(element = $(element))) return;

:)

element.className = element.className.replace(
new RegExp("(^|\\s+)" + className + "(\\s+|$)"), ' ').strip();
return element;
},

[...]

scrollTo: function(element) {
element = $(element);

Any wonder this stuff moves at a snail's pace (the code, not the
similarly challenged development effort).

var pos = Element.cumulativeOffset(element);
window.scrollTo(pos[0], pos[1]);

No feature testing at all. :(

return element;
},

getStyle: function(element, style) {
element = $(element);
style = style == 'float' ? 'cssFloat' : style.camelize();


Are we in a browser sniffing fork? I've lost track.


var value = element.style[style];
if (!value || value == 'auto') {
var css = document.defaultView.getComputedStyle(element, null);
value = css ? css[style] : null;
}
if (style == 'opacity') return value ? parseFloat(value) : 1.0;

Not 1, but 1.0. :) And why are they converting this to a number here
anyway? That's a very goofy design. And what about the older
proprietary opacity styles?

return value == 'auto' ? null : value;
},

getOpacity: function(element) {
return $(element).getStyle('opacity');
},

setStyle: function(element, styles) {
element = $(element);
var elementStyle = element.style, match;
if (Object.isString(styles)) {
element.style.cssText += ';' + styles;
return styles.include('opacity') ?
element.setOpacity(styles.match(/opacity:\s*(\d?\.?\d*)/)
[1]) : element;


WTF?! Nothing else comes to mind.


}
for (var property in styles)
if (property == 'opacity') element.setOpacity(styles[property]);
else
elementStyle[(property == 'float' || property == 'cssFloat') ?
(Object.isUndefined(elementStyle.styleFloat) ? 'cssFloat' :
'styleFloat') :
property] = styles[property];


But that doesn't match the float handling above. (?)


return element;
},

setOpacity: function(element, value) {
element = $(element);


Why?!


element.style.opacity = (value == 1 || value === '') ? '' :
(value < 0.00001) ? 0 : value;
return element;

Oh, how "cool" is that?


},

getDimensions: function(element) {
element = $(element);
var display = Element.getStyle(element, 'display');
if (display != 'none' && display != null) // Safari bug

That's _not_ a bug.

return {width: element.offsetWidth, height:
element.offsetHeight};

var els = element.style;
var originalVisibility = els.visibility;
var originalPosition = els.position;
var originalDisplay = els.display;
els.visibility = 'hidden';
if (originalPosition != 'fixed') // Switching fixed to absolute
causes issues in Safari
els.position = 'absolute';
els.display = 'block';


This is really sad (and completely unecessary). That sums up the
whole project. :)


var originalWidth = element.clientWidth;
var originalHeight = element.clientHeight;
els.display = originalDisplay;
els.position = originalPosition;
els.visibility = originalVisibility;
return {width: originalWidth, height: originalHeight};
},

[...]

if (Prototype.Browser.Opera) {

Here we go again...

Element.Methods.getStyle = Element.Methods.getStyle.wrap(
function(proceed, element, style) {
switch (style) {
case 'left': case 'top': case 'right': case 'bottom':
if (proceed(element, 'position') === 'static') return null;
case 'height': case 'width':
if (!Element.visible(element)) return null;

var dim = parseInt(proceed(element, style), 10);

if (dim !== element['offset' + style.capitalize()])
return dim + 'px';

var properties;
if (style === 'height') {
properties = ['border-top-width', 'padding-top',
'padding-bottom', 'border-bottom-width'];
}
else {
properties = ['border-left-width', 'padding-left',
'padding-right', 'border-right-width'];
}
return properties.inject(dim, function(memo, property) {
var val = proceed(element, property);
return val === null ? memo : memo - parseInt(val, 10);
}) + 'px';
default: return proceed(element, style);
}
}
);

Element.Methods.readAttribute = Element.Methods.readAttribute.wrap(
function(proceed, element, attribute) {
if (attribute === 'title') return element.title;
return proceed(element, attribute);
}
);
}

else if (Prototype.Browser.IE) {
Element.Methods.getOffsetParent =
Element.Methods.getOffsetParent.wrap(
function(proceed, element) {
element = $(element);
try { element.offsetParent }
catch(e) { return $(document.body) }
var position = element.getStyle('position');
if (position !== 'static') return proceed(element);
element.setStyle({ position: 'relative' });
var value = proceed(element);
element.setStyle({ position: position });
return value;
}
);

$w('positionedOffset viewportOffset').each(function(method) {
Element.Methods[method] = Element.Methods[method].wrap(
function(proceed, element) {
element = $(element);
try { element.offsetParent }
catch(e) { return Element._returnOffset(0,0) }
var position = element.getStyle('position');
if (position !== 'static') return proceed(element);
var offsetParent = element.getOffsetParent();
if (offsetParent && offsetParent.getStyle('position') ===
'fixed')
offsetParent.setStyle({ zoom: 1 });
element.setStyle({ position: 'relative' });
var value = proceed(element);
element.setStyle({ position: position });
return value;
}
);
});

Element.Methods.cumulativeOffset =
Element.Methods.cumulativeOffset.wrap(
function(proceed, element) {
try { element.offsetParent }
catch(e) { return Element._returnOffset(0,0) }
return proceed(element);
}
);

Element.Methods.getStyle = function(element, style) {


Deja vu all over again.


[...]

Element._attributeTranslations = (function(){

var classProp = 'className';
var forProp = 'for';

var el = document.createElement('div');

el.setAttribute(classProp, 'x');

if (el.className !== 'x') {
el.setAttribute('class', 'x');
if (el.className === 'x') {
classProp = 'class';
}
}
el = null;


Where have I seen _that_ test before? Did they learn anything?


el = document.createElement('label');
el.setAttribute(forProp, 'x');
if (el.htmlFor !== 'x') {
el.setAttribute('htmlFor', 'x');
if (el.htmlFor === 'x') {
forProp = 'htmlFor';
}
}

Nope. Not a clue. It's all based on observations made by people who
don't understand what they are looking at.

el = null;

return {
read: {
names: {
'class': classProp,
'className': classProp,
'for': forProp,
'htmlFor': forProp
},

"className" and "htmlFor" are _not_ attribute names.


values: {
_getAttr: function(element, attribute) {
return element.getAttribute(attribute);
},
_getAttr2: function(element, attribute) {
return element.getAttribute(attribute, 2);
},
_getAttrNode: function(element, attribute) {
var node = element.getAttributeNode(attribute);
return node ? node.value : "";
},
_getEv: (function(){

var el = document.createElement('div');
el.onclick = Prototype.emptyFunction;
var value = el.getAttribute('onclick');

var f;

if (String(value).indexOf('{') > -1) {
f = function(element, attribute) {
attribute = element.getAttribute(attribute);
if (!attribute) return null;
attribute = attribute.toString();
attribute = attribute.split('{')[1];
attribute = attribute.split('}')[0];
return attribute.strip();
};
}
else if (value === '') {
f = function(element, attribute) {
attribute = element.getAttribute(attribute);
if (!attribute) return null;
return attribute.strip();
};
}
el = null;
return f;
})(),
_flag: function(element, attribute) {
return $(element).hasAttribute(attribute) ? attribute :
null;
},


Their hasAttribute wrapper is BS too.


style: function(element) {
return element.style.cssText.toLowerCase();
},
title: function(element) {
return element.title;
}
}
}
}
})();

Element._attributeTranslations.write = {
names: Object.extend({
cellpadding: 'cellPadding',
cellspacing: 'cellSpacing'
}, Element._attributeTranslations.read.names),
values: {
checked: function(element, value) {
element.checked = !!value;
},

style: function(element, value) {
element.style.cssText = value ? value : '';
}
}
};


It's the world according to Prototype. :)


Element._attributeTranslations.has = {};

$w('colSpan rowSpan vAlign dateTime accessKey tabIndex ' +
'encType maxLength readOnly longDesc frameBorder').each(function
(attr) {
Element._attributeTranslations.write.names[attr.toLowerCase()] =
attr;
Element._attributeTranslations.has[attr.toLowerCase()] = attr;
});


As they see it, of course.


(function(v) {
Object.extend(v, {
href: v._getAttr2,
src: v._getAttr2,
type: v._getAttr,
action: v._getAttrNode,
disabled: v._flag,
checked: v._flag,
readonly: v._flag,
multiple: v._flag,
onload: v._getEv,
onunload: v._getEv,
onclick: v._getEv,
ondblclick: v._getEv,
onmousedown: v._getEv,
onmouseup: v._getEv,
onmouseover: v._getEv,
onmousemove: v._getEv,
onmouseout: v._getEv,
onfocus: v._getEv,
onblur: v._getEv,
onkeypress: v._getEv,
onkeydown: v._getEv,
onkeyup: v._getEv,
onsubmit: v._getEv,
onreset: v._getEv,
onselect: v._getEv,
onchange: v._getEv
});
})(Element._attributeTranslations.read.values);


Can you spot the pattern for events?


[...]

else if (Prototype.Browser.Gecko && /rv:1\.8\.0/.test
(navigator.userAgent)) {
Element.Methods.setOpacity = function(element, value) {
element = $(element);
element.style.opacity = (value == 1) ? 0.999999 :
(value === '') ? '' : (value < 0.00001) ? 0 : value;
return element;
};
}

else if (Prototype.Browser.WebKit) {
Element.Methods.setOpacity = function(element, value) {
element = $(element);
element.style.opacity = (value == 1 || value === '') ? '' :
(value < 0.00001) ? 0 : value;

if (value == 1)
if(element.tagName.toUpperCase() == 'IMG' && element.width) {
element.width++; element.width--;
} else try {
var n = document.createTextNode(' ');
element.appendChild(n);
element.removeChild(n);
} catch (e) { }

return element;
};


More magic spells. And who do they think is going to maintain all of
this crap?


[...]

function findDOMClass(tagName) {
var klass;
var trans = {
"OPTGROUP": "OptGroup", "TEXTAREA": "TextArea", "P":
"Paragraph",
"FIELDSET": "FieldSet", "UL": "UList", "OL": "OList", "DL":
"DList",
"DIR": "Directory", "H1": "Heading", "H2": "Heading", "H3":
"Heading",
"H4": "Heading", "H5": "Heading", "H6": "Heading", "Q": "Quote",
"INS": "Mod", "DEL": "Mod", "A": "Anchor", "IMG": "Image",
"CAPTION":
"TableCaption", "COL": "TableCol", "COLGROUP": "TableCol",
"THEAD":
"TableSection", "TFOOT": "TableSection", "TBODY":
"TableSection", "TR":
"TableRow", "TH": "TableCell", "TD": "TableCell", "FRAMESET":
"FrameSet", "IFRAME": "IFrame"
};
if (trans[tagName]) klass = 'HTML' + trans[tagName] + 'Element';
if (window[klass]) return window[klass];
klass = 'HTML' + tagName + 'Element';
if (window[klass]) return window[klass];
klass = 'HTML' + tagName.capitalize() + 'Element';
if (window[klass]) return window[klass];

var element = document.createElement(tagName);
var proto = element['__proto__'] || element.constructor.prototype;
element = null;
return proto;
}


Wothless waste of space (and they sure can't spare any).

[...]

document.viewport = {

getDimensions: function() {
return { width: this.getWidth(), height: this.getHeight() };
},

getScrollOffsets: function() {
return Element._returnOffset(
window.pageXOffset || document.documentElement.scrollLeft ||
document.body.scrollLeft,
window.pageYOffset || document.documentElement.scrollTop ||
document.body.scrollTop);
}


LOL. It's the same BS over and over (see Closure, Qooxdoo, etc.) Why
do people waste their lives writing and maintaining such follies?


};

(function(viewport) {
var B = Prototype.Browser, doc = document, element, property = {};

function getRootElement() {
if (B.WebKit && !doc.evaluate)
return document;


OMG. That's a sniff for Safari 2, which features document.clientWidth/
Height.

http://www.cinsoft.net/viewport.asp



if (B.Opera && window.parseFloat(window.opera.version()) < 9.5)
return document.body;


Sniff for older Operas. They don't read the trades I guess.


return document.documentElement;
}

[...]

/* Portions of the Selector class are derived from Jack Slocum's
DomQuery,
* part of YUI-Ext version 0.40, distributed under the terms of an MIT-
style
* license. Please see http://www.yui-ext.com/ for more information.
*/


How does it help for these projects to copy off each other?


var Selector = Class.create({
initialize: function(expression) {
this.expression = expression.strip();

if (this.shouldUseSelectorsAPI()) {
this.mode = 'selectorsAPI';
} else if (this.shouldUseXPath()) {
this.mode = 'xpath';
this.compileXPathMatcher();
} else {
this.mode = "normal";
this.compileMatcher();
}

},

shouldUseXPath: (function() {

var IS_DESCENDANT_SELECTOR_BUGGY = (function(){
var isBuggy = false;
if (document.evaluate && window.XPathResult) {
var el = document.createElement('div');
el.innerHTML = '<ul><li></li></ul><div><ul><li></li></ul></
div>';

var xpath = ".//*[local-name()='ul' or local-name()='UL']" +
"//*[local-name()='li' or local-name()='LI']";

var result = document.evaluate(xpath, el, null,
XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);

isBuggy = (result.snapshotLength !== 2);
el = null;
}
return isBuggy;
})();

return function() {
if (!Prototype.BrowserFeatures.XPath) return false;

var e = this.expression;

if (Prototype.Browser.WebKit &&
(e.include("-of-type") || e.include(":empty")))
return false;


Just look at this shit.


if ((/(\[[\w-]*?:|:checked)/).test(e))
return false;

if (IS_DESCENDANT_SELECTOR_BUGGY) return false;

return true;
}

})(),

[...]


attrPresence: function(nodes, root, attr, combinator) {
if (!nodes) nodes = root.getElementsByTagName("*");
if (nodes && combinator) nodes = this[combinator](nodes);
var results = [];
for (var i = 0, node; node = nodes; i++)
if (Element.hasAttribute(node, attr)) results.push(node);
return results;
},

attr: function(nodes, root, attr, value, operator, combinator) {
if (!nodes) nodes = root.getElementsByTagName("*");
if (nodes && combinator) nodes = this[combinator](nodes);
var handler = Selector.operators[operator], results = [];
for (var i = 0, node; node = nodes; i++) {
var nodeValue = Element.readAttribute(node, attr);

There it is. Game, set and match (no pun intended). This BS is
incompatible with the other two (!) forks. Cross-browser consistency
is out of the question. You just can't have such breakdowns in the
boiler room.

And there's still a mile of code to go... But I think this one is
done anyway.

I'll be posting some demonstrations of the various library (and
"framework") query follies shortly (they are _all_ screwed up). At
the very least, it's hilarious seeing all of the various versions of
these things sputter and regress over the years (with no right answers
or even understanding in sight). At best, it should scare people
straight.

These developers are _incompetent_. There's no other word for it.
They are wasting their time, but they don't need to waste yours. You
can't tell these people they are wrong, because they are super-genius
JS developers (at least that's what everyone tells them). Read their
forums and mailing lists and the clouds part (they can scarcely hide
their confusion and overconfidence). Moderation is a _huge_ red flag
as it indicates an attempt to shield the developers from criticism and
preserve a "scholarly" air (hasn't worked very well).

Cross-browser scripting is _not_ impossible (except for the
incompetent, which goes without saying). It never was, but it is
hardly even a challenge these days (for those who seek to support only
modern desktop browsers). Think about that before you choose the
"simplicity" of one of these query-based pieces of junk.

Anyone who tells you different is ignorant or selling something.
 
D

David Mark

[...]
Somebody stop these guys.  :(

Doesn't look like they need any help there. A recent suggestion in
their (virtually empty) support group:-

"How 'bout something like
var paramsA = Form.serializeElements( $("frm").getInputs('checkbox',
"typeA"),true);
var paramsB = Form.serializeElements( $("frm").getInputs('checkbox',
"typeB"),true);
var paramsC = Form.serializeElements( $("frm").getInputs('checkbox',
"typeC"),true);"

How 'bout finding another hobby? Pass it along...

" var params = paramsA + '&' + paramsB + '&' + paramsC;

Yeah... I know it's not as sexy as defining the array and running
through an 'each' loop but I bet it would work :)"

I bet it would be a disaster as the OP was looking for performance
tips. ;)

"(With string concatenation, you could, of course, do it all in a
single variable)"

Oh, of course. :) This may be the worst JS-related "answer" I've
ever seen (and that's against some pretty fierce competition).

The communities usually mirror the proficiency of the code they
worship and this one is no exception.
 
G

Garrett Smith

David said:
/* Prototype JavaScript framework, version 1.6.1
* (c) 2005-2009 Sam Stephenson
*
* Prototype is freely distributable under the terms of an MIT-style
license.
* For details, see the Prototype web site: http://www.prototypejs.org/
*

*--------------------------------------------------------------------------
*/

var Prototype = {
Version: '1.6.1',

Browser: (function(){
var ua = navigator.userAgent;
var isOpera = Object.prototype.toString.call(window.opera) ==
'[object Opera]';


Not a bad test for Opera, but who needs to test for Opera in 2010? :)

PrototypeJS is legacy code. Refactoring PrototypeJS, removing those
would be a problem. Other low-level code or even code in third party
libraries should not be using that.

I would add an @deprecated comment above that.
 
D

David Mark

David said:
/*  Prototype JavaScript framework, version 1.6.1
 *  (c) 2005-2009 Sam Stephenson
 *
 *  Prototype is freely distributable under the terms of an MIT-style
license.
 *  For details, see the Prototype web site:http://www.prototypejs.org/
 *

var Prototype = {
  Version: '1.6.1',
  Browser: (function(){
    var ua = navigator.userAgent;
    var isOpera = Object.prototype.toString.call(window.opera) ==
'[object Opera]';
Not a bad test for Opera, but who needs to test for Opera in 2010?  :)

PrototypeJS is legacy code. Refactoring PrototypeJS, removing those
would be a problem.  Other low-level code or even code in third party
libraries should not be using that.

I would add an @deprecated comment above that.

Did you read the code I posted? The _entire_ thing is based on those
flags. It's not a matter of deprecation at this point (first they
have to rewrite their own code).
 
D

David Mark

"The `className' property wasn't object-oriented enough, we needed to work
around setAttribute() quirks instead." :->

Yeah, after all of these years, they are not fighting browser quirks
at all. They are fighting their own misconceptions and foolish
designs. ;)

I think it is clear how this situation came about. Various neophytes
(likely ex-Java programmers) tried to break into browser scripting
around 2005-6 when the major browsers were still fairly quirky. They
created designs that were inappropriate for JS and spent the next few
years trying to pound their square pegs into round holes (and bitching
about IE).

Not one of these projects ever figured out IE6/7 (ostensibly the main
reason for their existence). Now they want to drop "support" for
those (and never mind that IE8 can act much like IE6/7 at the touch of
a button). Of course, if they drop support for those, they are left
with a half dozen QSA-enabled browsers (all with real documentation)
that don't need 50-100K of monkey code to provide a consistent
interface (or to do queries).

So, they are all on their way out and will ultimately be remembered as
dismal failures. ;)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,764
Messages
2,569,565
Members
45,041
Latest member
RomeoFarnh

Latest Threads

Top