Skip to content

Commit 9e058b4

Browse files
Merge branch 'master' of github.com:sstephenson/prototype
2 parents beb5dbc + adb6479 commit 9e058b4

File tree

18 files changed

+256
-81
lines changed

18 files changed

+256
-81
lines changed

src/prototype/ajax/request.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@
4949
* status-specific callback is defined, it gets invoked. Otherwise, if
5050
* `onSuccess` is defined and the response is deemed a success (see below), it
5151
* is invoked. Otherwise, if `onFailure` is defined and the response is *not*
52-
* deemed a sucess, it is invoked. Only after that potential first callback is
52+
* deemed a success, it is invoked. Only after that potential first callback is
5353
* `onComplete` called.
5454
*
5555
* ##### A note on portability
@@ -259,8 +259,10 @@ Ajax.Request = Class.create(Ajax.Base, {
259259
$H(extras).each(function(pair) { headers[pair.key] = pair.value });
260260
}
261261

262+
// skip null or undefined values
262263
for (var name in headers)
263-
this.transport.setRequestHeader(name, headers[name]);
264+
if (headers[name] != null)
265+
this.transport.setRequestHeader(name, headers[name]);
264266
},
265267

266268
/**

src/prototype/dom/dom.js

Lines changed: 16 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1486,6 +1486,7 @@
14861486

14871487
/**
14881488
* Element.siblings(@element) -> [Element...]
1489+
*
14891490
* Collects all of element's siblings and returns them as an [[Array]] of
14901491
* elements.
14911492
*
@@ -1793,6 +1794,7 @@
17931794
* // -> undefined
17941795
**/
17951796
function down(element, expression, index) {
1797+
if (arguments.length === 1) return firstDescendant(element);
17961798
element = $(element), expression = expression || 0, index = index || 0;
17971799

17981800
if (Object.isNumber(expression))
@@ -2369,7 +2371,7 @@
23692371
name = table.names[attr] || attr;
23702372
value = attributes[attr];
23712373
if (table.values[attr])
2372-
name = table.values[attr](element, value);
2374+
name = table.values[attr](element, value) || name;
23732375
if (value === false || value === null)
23742376
element.removeAttribute(name);
23752377
else if (value === true)
@@ -2928,7 +2930,7 @@
29282930
}
29292931

29302932
function hasLayout_IE(element) {
2931-
if (!element.currentStyle.hasLayout)
2933+
if (!element.currentStyle || !element.currentStyle.hasLayout)
29322934
element.style.zoom = 1;
29332935
return element;
29342936
}
@@ -3016,7 +3018,7 @@
30163018
var filter = Element.getStyle(element, 'filter');
30173019
if (filter.length === 0) return 1.0;
30183020
var match = (filter || '').match(/alpha\(opacity=(.*)\)/);
3019-
if (match[1]) return parseFloat(match[1]) / 100;
3021+
if (match && match[1]) return parseFloat(match[1]) / 100;
30203022
return 1.0;
30213023
}
30223024

@@ -3484,5 +3486,14 @@
34843486
}
34853487

34863488
Element.addMethods(methods);
3487-
3488-
})(this);
3489+
3490+
// Prevent IE leaks on DIV and ELEMENT_CACHE
3491+
function destroyCache_IE() {
3492+
DIV = null;
3493+
ELEMENT_CACHE = null;
3494+
}
3495+
3496+
if (window.attachEvent)
3497+
window.attachEvent('onunload', destroyCache_IE);
3498+
3499+
})(this);

src/prototype/dom/event.js

Lines changed: 29 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -244,10 +244,7 @@
244244

245245
// Fix a Safari bug where a text node gets passed as the target of an
246246
// anchor click rather than the anchor itself.
247-
if (node.nodeType == Node.TEXT_NODE)
248-
node = node.parentNode;
249-
250-
return Element.extend(node);
247+
return node.nodeType == Node.TEXT_NODE ? node.parentNode : node;
251248
}
252249

253250
/**
@@ -260,8 +257,7 @@
260257
* its ancestor chain. If `expression` is not given, the element which fired
261258
* the event is returned.
262259
*
263-
* *If no matching element is found, the document itself (`HTMLDocument` node)
264-
* is returned.*
260+
* *If no matching element is found, `undefined` is returned.*
265261
*
266262
* ##### Example
267263
*
@@ -270,15 +266,15 @@
270266
*
271267
* document.observe('click', function(event) {
272268
* var element = event.findElement('p');
273-
* if (element != document)
269+
* if (element)
274270
* $(element).hide();
275271
* });
276272
**/
277273
function findElement(event, expression) {
278-
var element = _element(event), match = Prototype.Selector.match;
274+
var element = _element(event), selector = Prototype.Selector;
279275
if (!expression) return Element.extend(element);
280276
while (element) {
281-
if (Object.isElement(element) && match(element, expression))
277+
if (Object.isElement(element) && selector.match(element, expression))
282278
return Element.extend(element);
283279
element = element.parentNode;
284280
}
@@ -898,14 +894,17 @@
898894
// for bulk removal of event listeners. We use them rather than recurse
899895
// back into `stopObserving` to avoid touching the registry more often than
900896
// necessary.
901-
897+
902898
// Stop observing _all_ listeners on an element.
903899
function stopObservingElement(element) {
904-
var uid = getUniqueElementID(element),
905-
registry = getRegistryForElement(element, uid);
906-
900+
// Do a manual registry lookup because we don't want to create a registry
901+
// if one doesn't exist.
902+
var uid = getUniqueElementID(element), registry = GLOBAL.Event.cache[uid];
903+
// This way we can return early if there is no registry.
904+
if (!registry) return;
905+
907906
destroyRegistryForElement(element, uid);
908-
907+
909908
var entries, i;
910909
for (var eventName in registry) {
911910
// Explicitly skip elements so we don't accidentally find one with a
@@ -1276,7 +1275,7 @@
12761275
stopObserving: stopObserving.methodize(),
12771276

12781277
/**
1279-
* Element.on(@element, eventName[, selector], callback) -> Event.Handler
1278+
* document.on(@element, eventName[, selector], callback) -> Event.Handler
12801279
*
12811280
* See [[Event.on]].
12821281
**/
@@ -1331,17 +1330,17 @@
13311330
return createMouseEnterLeaveResponder(uid, eventName, handler);
13321331

13331332
return function(event) {
1334-
var cacheEntry = Event.cache[uid];
1335-
var element = cacheEntry.element;
1336-
1333+
if (!Event.cache) return;
1334+
1335+
var element = Event.cache[uid].element;
13371336
Event.extend(event, element);
13381337
handler.call(element, event);
13391338
};
13401339
}
13411340

13421341
function createResponderForCustomEvent(uid, eventName, handler) {
13431342
return function(event) {
1344-
var cacheEntry = Event.cache[uid], element = cacheEntry.element;
1343+
var element = Event.cache[uid].element;
13451344

13461345
if (Object.isUndefined(event.eventName))
13471346
return false;
@@ -1356,8 +1355,8 @@
13561355

13571356
function createMouseEnterLeaveResponder(uid, eventName, handler) {
13581357
return function(event) {
1359-
var cacheEntry = Event.cache[uid], element = cacheEntry.element;
1360-
1358+
var element = Event.cache[uid].element;
1359+
13611360
Event.extend(event, element);
13621361
var parent = event.relatedTarget;
13631362

@@ -1408,6 +1407,15 @@
14081407

14091408
fireContentLoadedEvent();
14101409
}
1410+
1411+
1412+
if (document.readyState === 'complete') {
1413+
// We must have been loaded asynchronously, because the DOMContentLoaded
1414+
// event has already fired. We can just fire `dom:loaded` and be done
1415+
// with it.
1416+
fireContentLoadedEvent();
1417+
return;
1418+
}
14111419

14121420
if (document.addEventListener) {
14131421
// All browsers that support DOM L2 Events support DOMContentLoaded,

src/prototype/dom/form.js

Lines changed: 16 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -113,22 +113,27 @@ var Form = {
113113
accumulator = function(result, key, value) {
114114
if (key in result) {
115115
if (!Object.isArray(result[key])) result[key] = [result[key]];
116-
result[key].push(value);
116+
result[key] = result[key].concat(value);
117117
} else result[key] = value;
118118
return result;
119119
};
120120
} else {
121121
initial = '';
122-
accumulator = function(result, key, value) {
123-
// Normalize newlines as \r\n because the HTML spec says newlines should
124-
// be encoded as CRLFs.
125-
value = value.gsub(/(\r)?\n/, '\r\n');
126-
value = encodeURIComponent(value);
127-
// Likewise, according to the spec, spaces should be '+' rather than
128-
// '%20'.
129-
value = value.gsub(/%20/, '+');
130-
return result + (result ? '&' : '') + encodeURIComponent(key) + '=' + value;
131-
}
122+
accumulator = function(result, key, values) {
123+
if (!Object.isArray(values)) {values = [values];}
124+
if (!values.length) {return result;}
125+
// According to the spec, spaces should be '+' rather than '%20'.
126+
var encodedKey = encodeURIComponent(key).gsub(/%20/, '+');
127+
return result + (result ? "&" : "") + values.map(function (value) {
128+
// Normalize newlines as \r\n because the HTML spec says newlines should
129+
// be encoded as CRLFs.
130+
value = value.gsub(/(\r)?\n/, '\r\n');
131+
value = encodeURIComponent(value);
132+
// According to the spec, spaces should be '+' rather than '%20'.
133+
value = value.gsub(/%20/, '+');
134+
return encodedKey + "=" + value;
135+
}).join("&");
136+
};
132137
}
133138

134139
return elements.inject(initial, function(result, element) {

src/prototype/dom/layout.js

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1144,7 +1144,8 @@
11441144
function viewportOffset(forElement) {
11451145
var valueT = 0, valueL = 0, docBody = document.body;
11461146

1147-
var element = $(forElement);
1147+
forElement = $(forElement);
1148+
var element = forElement;
11481149
do {
11491150
valueT += element.offsetTop || 0;
11501151
valueL += element.offsetLeft || 0;
@@ -1187,10 +1188,11 @@
11871188
var layout = element.getLayout();
11881189

11891190
element.store('prototype_absolutize_original_styles', {
1190-
left: element.getStyle('left'),
1191-
top: element.getStyle('top'),
1192-
width: element.getStyle('width'),
1193-
height: element.getStyle('height')
1191+
position: element.getStyle('position'),
1192+
left: element.getStyle('left'),
1193+
top: element.getStyle('top'),
1194+
width: element.getStyle('width'),
1195+
height: element.getStyle('height')
11941196
});
11951197

11961198
element.setStyle({

src/prototype/lang/array.js

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -647,16 +647,15 @@ Array.from = $A;
647647
}
648648

649649
/**
650-
* Array#some([iterator = Prototype.K[, context]]) -> Array
650+
* Array#some([iterator = Prototype.K[, context]]) -> Boolean
651651
* - iterator (Function): An optional function to use to evaluate each
652652
* element in the enumeration; the function should return the value to
653653
* test. If this is not provided, the element itself is tested.
654654
* - context (Object): An optional object to use as `this` within
655655
* calls to the iterator.
656656
*
657-
* Returns the result of applying `iterator` to each item in the array. If
658-
* no iterator is provided, the elements are simply copied to the returned
659-
* array.
657+
* Determines whether at least one element is truthy (boolean-equivalent to
658+
* `true`), either directly or through computation by the provided iterator.
660659
*
661660
* `Array#some` acts as an ECMAScript 5 [polyfill](http://remysharp.com/2010/10/08/what-is-a-polyfill/).
662661
* It is only defined if not already present in the user's browser, and it
@@ -692,7 +691,7 @@ Array.from = $A;
692691
* - context (Object): An optional object to use as `this` within
693692
* calls to the iterator.
694693
*
695-
* Determines whether at least one element is truthy (boolean-equivalent to
694+
* Determines whether all elements are truthy (boolean-equivalent to
696695
* `true`), either directly or through computation by the provided iterator.
697696
*
698697
* `Array#every` acts as an ECMAScript 5 [polyfill](http://remysharp.com/2010/10/08/what-is-a-polyfill/).

src/prototype/lang/enumerable.js

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
* objects that act as collections of values. It is a cornerstone of
66
* Prototype.
77
*
8-
* [[Enumerable]] is a _mixin_: a set of methods intended not for standaone
8+
* [[Enumerable]] is a _mixin_: a set of methods intended not for standalone
99
* use, but for incorporation into other objects.
1010
*
1111
* Prototype mixes [[Enumerable]] into several classes. The most visible cases
@@ -30,7 +30,42 @@
3030
*
3131
* If there is no `context` argument, the iterator function will execute in
3232
* the scope from which the [[Enumerable]] method itself was called.
33-
*
33+
*
34+
* ##### Flow control
35+
*
36+
* You might find yourself missing the `break` and `continue` keywords that
37+
* are available in ordinary `for` loops. If you need to break out of an
38+
* enumeration before it's done, you can throw a special object named
39+
* `$break`:
40+
*
41+
* var myObject = {};
42+
*
43+
* ['foo', 'bar', 'baz', 'thud'].each( function(name, index) {
44+
* if (name === 'baz') throw $break;
45+
* myObject[name] = index;
46+
* });
47+
*
48+
* myObject;
49+
* // -> { foo: 0, bar: 1 }
50+
*
51+
* Though we're technically throwing an exception, the `each` method knows
52+
* to catch a thrown `$break` object and treat it as a command to stop
53+
* iterating. (_Any_ exception thrown within an iterator will stop
54+
* iteration, but only `$break` will be caught and suppressed.)
55+
*
56+
* If you need `continue`-like behavior, you can simply return early from
57+
* your iterator:
58+
*
59+
* var myObject = {};
60+
*
61+
* ['foo', 'bar', 'baz', 'thud'].each( function(name, index) {
62+
* if (name === 'baz') return;
63+
* myObject[name] = index;
64+
* });
65+
*
66+
* myObject;
67+
* // -> { foo: 0, bar: 1, thud: 3 }
68+
*
3469
* ##### Mixing [[Enumerable]] into your own objects
3570
*
3671
* So, let's say you've created your very own collection-like object (say,
@@ -367,8 +402,8 @@ var Enumerable = (function() {
367402
* // -> true ('3' == 3)
368403
**/
369404
function include(object) {
370-
if (Object.isFunction(this.indexOf))
371-
if (this.indexOf(object) != -1) return true;
405+
if (Object.isFunction(this.indexOf) && this.indexOf(object) != -1)
406+
return true;
372407

373408
var found = false;
374409
this.each(function(value) {

src/prototype/lang/function.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ Object.extend(Function.prototype, (function() {
123123
var __method = this, args = slice.call(arguments, 1);
124124

125125
var bound = function() {
126-
var a = merge(args, arguments), c = context;
126+
var a = merge(args, arguments);
127127
// Ignore the supplied context when the bound function is called with
128128
// the "new" keyword.
129129
var c = this instanceof bound ? this : context;

src/prototype/lang/hash.js

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -94,11 +94,13 @@ var Hash = Class.create(Enumerable, (function() {
9494

9595
// Our _internal_ each
9696
function _each(iterator, context) {
97+
var i = 0;
9798
for (var key in this._object) {
9899
var value = this._object[key], pair = [key, value];
99100
pair.key = key;
100101
pair.value = value;
101-
iterator.call(context, pair);
102+
iterator.call(context, pair, i);
103+
i++;
102104
}
103105
}
104106

@@ -289,7 +291,7 @@ var Hash = Class.create(Enumerable, (function() {
289291
function toQueryPair(key, value) {
290292
if (Object.isUndefined(value)) return key;
291293

292-
var value = String.interpret(value);
294+
value = String.interpret(value);
293295

294296
// Normalize newlines as \r\n because the HTML spec says newlines should
295297
// be encoded as CRLFs.

0 commit comments

Comments
 (0)