sproutcore 1.0.1009 → 1.0.1024
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/DISTRIBUTION.yml +14 -0
- data/Rakefile +150 -23
- data/VERSION.yml +4 -2
- data/frameworks/sproutcore/Buildfile +1 -1
- data/frameworks/sproutcore/frameworks/bootstrap/system/loader.js +1 -0
- data/frameworks/sproutcore/frameworks/datastore/models/record.js +66 -5
- data/frameworks/sproutcore/frameworks/datastore/models/record_attribute.js +14 -0
- data/frameworks/sproutcore/frameworks/datastore/tests/models/record_attribute.js +28 -3
- data/frameworks/sproutcore/frameworks/desktop/english.lproj/alert.css +1 -1
- data/frameworks/sproutcore/frameworks/desktop/english.lproj/menu_item_view.css +22 -2
- data/frameworks/sproutcore/frameworks/desktop/english.lproj/panel.css +5 -1
- data/frameworks/sproutcore/frameworks/desktop/english.lproj/well.css +72 -0
- data/frameworks/sproutcore/frameworks/desktop/panes/alert.js +1 -1
- data/frameworks/sproutcore/frameworks/desktop/panes/picker.js +1 -1
- data/frameworks/sproutcore/frameworks/desktop/panes/select_button.js +33 -7
- data/frameworks/sproutcore/frameworks/desktop/system/root_responder.js +24 -23
- data/frameworks/sproutcore/frameworks/desktop/tests/views/list/ui_alternatingrows.js +130 -0
- data/frameworks/sproutcore/frameworks/desktop/tests/views/list/ui_row_heights.js +9 -10
- data/frameworks/sproutcore/frameworks/desktop/tests/views/list_item.js +4 -0
- data/frameworks/sproutcore/frameworks/desktop/tests/views/progress/ui.js +18 -9
- data/frameworks/sproutcore/frameworks/desktop/tests/views/scroll/methods.js +7 -6
- data/frameworks/sproutcore/frameworks/desktop/tests/views/well/ui.js +54 -0
- data/frameworks/sproutcore/frameworks/desktop/views/button.js +21 -9
- data/frameworks/sproutcore/frameworks/desktop/views/checkbox.js +4 -3
- data/frameworks/sproutcore/frameworks/desktop/views/collection.js +1 -1
- data/frameworks/sproutcore/frameworks/desktop/views/grid.js +23 -14
- data/frameworks/sproutcore/frameworks/desktop/views/list_item.js +2 -2
- data/frameworks/sproutcore/frameworks/desktop/views/menu_item.js +3 -3
- data/frameworks/sproutcore/frameworks/desktop/views/radio.js +1 -2
- data/frameworks/sproutcore/frameworks/desktop/views/scroll.js +1 -1
- data/frameworks/sproutcore/frameworks/desktop/views/segmented.js +1 -1
- data/frameworks/sproutcore/frameworks/desktop/views/slider.js +1 -1
- data/frameworks/sproutcore/frameworks/desktop/views/source_list_group.js +1 -1
- data/frameworks/sproutcore/frameworks/desktop/views/well.js +80 -0
- data/frameworks/sproutcore/frameworks/foundation/fixtures/malformed.json +11 -0
- data/frameworks/sproutcore/frameworks/foundation/mixins/button.js +1 -1
- data/frameworks/sproutcore/frameworks/foundation/mixins/inline_text_field.js +5 -1
- data/frameworks/sproutcore/frameworks/foundation/panes/pane.js +1 -1
- data/frameworks/sproutcore/frameworks/foundation/system/cursor.js +11 -10
- data/frameworks/sproutcore/frameworks/foundation/system/event.js +16 -15
- data/frameworks/sproutcore/frameworks/foundation/system/render_context.js +3 -3
- data/frameworks/sproutcore/frameworks/foundation/system/request.js +6 -5
- data/frameworks/sproutcore/frameworks/foundation/system/response.js +26 -8
- data/frameworks/sproutcore/frameworks/foundation/system/root_responder.js +2 -2
- data/frameworks/sproutcore/frameworks/foundation/system/timer.js +2 -2
- data/frameworks/sproutcore/frameworks/foundation/system/utils.js +122 -13
- data/frameworks/sproutcore/frameworks/foundation/tests/system/core_query/jquery_core.js +2 -3
- data/frameworks/sproutcore/frameworks/foundation/tests/system/render_context/tag.js +9 -9
- data/frameworks/sproutcore/frameworks/foundation/tests/system/render_context/update.js +3 -3
- data/frameworks/sproutcore/frameworks/foundation/tests/system/request.js +27 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/system/utils/rect.js +99 -0
- data/frameworks/sproutcore/frameworks/foundation/tests/views/image/ui.js +1 -1
- data/frameworks/sproutcore/frameworks/foundation/tests/views/view/updateLayer.js +1 -1
- data/frameworks/sproutcore/frameworks/foundation/views/image.js +3 -1
- data/frameworks/sproutcore/frameworks/foundation/views/label.js +1 -1
- data/frameworks/sproutcore/frameworks/runtime/system/cookie.js +160 -0
- data/frameworks/sproutcore/frameworks/runtime/system/object.js +1 -1
- data/frameworks/sproutcore/frameworks/runtime/tests/system/cookie.js +163 -0
- data/frameworks/sproutcore/themes/standard_theme/english.lproj/pane.css +12 -2
- data/lib/sproutcore/rack/proxy.rb +4 -2
- data/sproutcore-abbot.gemspec +23 -9
- metadata +32 -5
- data/frameworks/sproutcore/frameworks/desktop/english.lproj/images/standard_fade/000000.png +0 -0
- data/frameworks/sproutcore/frameworks/desktop/english.lproj/images/standard_fade/ffffff.png +0 -0
@@ -113,7 +113,9 @@ SC.Response = SC.Object.extend(
|
|
113
113
|
}.property('request').cacheable(),
|
114
114
|
|
115
115
|
/**
|
116
|
-
The response status code.
|
116
|
+
The response status code.
|
117
|
+
|
118
|
+
@property {Number}
|
117
119
|
*/
|
118
120
|
status: -100, // READY
|
119
121
|
|
@@ -133,14 +135,24 @@ SC.Response = SC.Object.extend(
|
|
133
135
|
encodedBody: null,
|
134
136
|
|
135
137
|
/**
|
136
|
-
Response body.
|
138
|
+
Response body. If isJSON was set, will be parsed automatically.
|
137
139
|
|
138
|
-
@
|
140
|
+
@response {Hash|String|SC.Error} the response body or the parsed JSON.
|
141
|
+
Returns a SC.Error instance if there is a JSON parsing error.
|
139
142
|
*/
|
140
143
|
body: function() {
|
141
144
|
// TODO: support XML
|
142
145
|
var ret = this.get('encodedBody');
|
143
|
-
if (ret && this.get('isJSON'))
|
146
|
+
if (ret && this.get('isJSON')) {
|
147
|
+
try {
|
148
|
+
ret = SC.json.decode(ret);
|
149
|
+
} catch(e) {
|
150
|
+
return SC.Error.create({
|
151
|
+
message: e.name + ': ' + e.message,
|
152
|
+
label: 'Response',
|
153
|
+
errorValue: this });
|
154
|
+
}
|
155
|
+
}
|
144
156
|
return ret;
|
145
157
|
}.property('encodedBody').cacheable(),
|
146
158
|
|
@@ -251,6 +263,10 @@ SC.Response = SC.Object.extend(
|
|
251
263
|
*/
|
252
264
|
cancelTransport: function() {},
|
253
265
|
|
266
|
+
|
267
|
+
/** @private
|
268
|
+
Will notify each listener.
|
269
|
+
*/
|
254
270
|
_notifyListener: function(listeners, status) {
|
255
271
|
var info = listeners[status], params, target, action;
|
256
272
|
if (!info) return NO ;
|
@@ -287,6 +303,9 @@ SC.Response = SC.Object.extend(
|
|
287
303
|
return this ;
|
288
304
|
},
|
289
305
|
|
306
|
+
/**
|
307
|
+
String representation of the response object
|
308
|
+
*/
|
290
309
|
toString: function() {
|
291
310
|
var ret = sc_super();
|
292
311
|
return "%@<%@ %@, status=%@".fmt(ret, this.get('type'), this.get('address'), this.get('status'));
|
@@ -385,7 +404,7 @@ SC.XHRResponse = SC.Response.extend({
|
|
385
404
|
handleReadyStateChange = function() {
|
386
405
|
if (!transport) return null ;
|
387
406
|
var ret = transport.finishRequest();
|
388
|
-
transport = null ; // cleanup memory
|
407
|
+
if (ret) transport = null ; // cleanup memory
|
389
408
|
return ret ;
|
390
409
|
};
|
391
410
|
rawRequest.onreadystatechange = handleReadyStateChange;
|
@@ -445,12 +464,11 @@ SC.XHRResponse = SC.Response.extend({
|
|
445
464
|
this.set('status', status);
|
446
465
|
|
447
466
|
}, this);
|
448
|
-
}
|
449
|
-
|
450
|
-
if (readyState === 4) {
|
451
467
|
// avoid memory leak in MSIE: clean up
|
452
468
|
rawRequest.onreadystatechange = function() {} ;
|
469
|
+
return YES;
|
453
470
|
}
|
471
|
+
return NO;
|
454
472
|
}
|
455
473
|
|
456
474
|
|
@@ -149,7 +149,7 @@ SC.RootResponder = SC.Object.extend({
|
|
149
149
|
// the top of the stack and make the specified pane the new keyPane.
|
150
150
|
// First, though, do a sanity-check to make sure it's not already the
|
151
151
|
// key pane, in which case we have nothing to do.
|
152
|
-
|
152
|
+
previousKeyPane = this.get('keyPane') ;
|
153
153
|
if (previousKeyPane === pane) {
|
154
154
|
return this ;
|
155
155
|
}
|
@@ -172,7 +172,7 @@ SC.RootResponder = SC.Object.extend({
|
|
172
172
|
previousKeyPane = this.get('keyPane') ;
|
173
173
|
previousKeyPanes = this.get('previousKeyPanes') ;
|
174
174
|
|
175
|
-
|
175
|
+
newKeyPane = null ;
|
176
176
|
while (previousKeyPanes.length > 0) {
|
177
177
|
var candidate = previousKeyPanes.pop();
|
178
178
|
if (candidate.get('isPaneAttached') && candidate.get('acceptsKeyPane')) {
|
@@ -150,7 +150,7 @@ SC.Timer = SC.Object.extend(
|
|
150
150
|
|
151
151
|
@property {Boolean}
|
152
152
|
*/
|
153
|
-
isPooled:
|
153
|
+
isPooled: NO,
|
154
154
|
|
155
155
|
/**
|
156
156
|
The time interval in milliseconds.
|
@@ -408,7 +408,7 @@ SC.Timer = SC.Object.extend(
|
|
408
408
|
/** @private - Default values to reset reused timers to. */
|
409
409
|
RESET_DEFAULTS: {
|
410
410
|
target: null, action: null,
|
411
|
-
isPooled:
|
411
|
+
isPooled: NO, isPaused: NO, isScheduled: NO, isValid: YES,
|
412
412
|
interval: 0, repeats: NO, until: null,
|
413
413
|
startTime: null, lastFireTime: 0
|
414
414
|
},
|
@@ -12,6 +12,12 @@ SC.mixin( /** @scope SC */ {
|
|
12
12
|
|
13
13
|
_downloadFrames: 0, // count of download frames inserted into document
|
14
14
|
|
15
|
+
_copy_computed_props: [
|
16
|
+
"maxWidth", "maxHeight", "paddingLeft", "paddingRight", "paddingTop", "paddingBottom",
|
17
|
+
"fontFamily", "fontSize", "fontStyle", "fontWeight", "fontVariant", "lineHeight",
|
18
|
+
"whiteSpace"
|
19
|
+
],
|
20
|
+
|
15
21
|
/**
|
16
22
|
Starts a download of the file at the named path.
|
17
23
|
|
@@ -132,13 +138,13 @@ SC.mixin( /** @scope SC */ {
|
|
132
138
|
*/
|
133
139
|
rectsEqual: function(r1, r2, delta) {
|
134
140
|
if (!r1 || !r2) return (r1 == r2) ;
|
135
|
-
|
136
|
-
if (delta
|
141
|
+
|
142
|
+
if (!delta && delta !== 0) delta = 0.1;
|
137
143
|
if ((r1.y != r2.y) && (Math.abs(r1.y - r2.y) > delta)) return NO ;
|
138
144
|
if ((r1.x != r2.x) && (Math.abs(r1.x - r2.x) > delta)) return NO ;
|
139
145
|
if ((r1.width != r2.width) && (Math.abs(r1.width - r2.width) > delta)) return NO ;
|
140
146
|
if ((r1.height != r2.height) && (Math.abs(r1.height - r2.height) > delta)) return NO ;
|
141
|
-
return
|
147
|
+
return YES ;
|
142
148
|
},
|
143
149
|
|
144
150
|
/** Returns the insersection between two rectangles.
|
@@ -269,19 +275,122 @@ SC.mixin( /** @scope SC */ {
|
|
269
275
|
}
|
270
276
|
|
271
277
|
style = '%@; width: %@px; left: %@px; position: absolute'.fmt(style, width, (-1*width));
|
272
|
-
elem.
|
278
|
+
SC.$(elem).attr('style', style);
|
273
279
|
|
274
280
|
if (classes !== '') {
|
275
|
-
elem.
|
281
|
+
SC.$(elem).attr('class', classes);
|
276
282
|
}
|
277
283
|
|
278
|
-
elem.
|
284
|
+
elem.innerHTML = str;
|
279
285
|
height = elem.clientHeight;
|
280
286
|
|
281
287
|
elem = null; // don't leak memory
|
282
288
|
return height;
|
283
289
|
},
|
284
290
|
|
291
|
+
/**
|
292
|
+
Given a string and an example element or style string, and an optional
|
293
|
+
set of class names, calculates the width and height of that block of text.
|
294
|
+
|
295
|
+
To constrain the width, set max-width on the exampleElement or in the style string.
|
296
|
+
|
297
|
+
@param string {String} The string to measure.
|
298
|
+
@param exampleElement The example element to grab styles from, or the style string to use.
|
299
|
+
@param classNames {String} (Optional) Class names to add to the test element.
|
300
|
+
*/
|
301
|
+
metricsForString: function(string, exampleElement, classNames)
|
302
|
+
{
|
303
|
+
var element = this._metricsCalculationElement, width, height, classes, styles, style;
|
304
|
+
|
305
|
+
// collect the class names
|
306
|
+
classes = SC.A(classNames).join(' ');
|
307
|
+
|
308
|
+
// get the calculation element
|
309
|
+
if (!element) {
|
310
|
+
element = this._metricsCalculationElement = document.createElement("div");
|
311
|
+
document.body.insertBefore(element, null);
|
312
|
+
}
|
313
|
+
|
314
|
+
// two possibilities: example element or type string
|
315
|
+
if (SC.typeOf(exampleElement) != SC.T_STRING) {
|
316
|
+
var computed = null;
|
317
|
+
if (document.defaultView && document.defaultView.getComputedStyle) {
|
318
|
+
computed = document.defaultView.getComputedStyle(exampleElement, null);
|
319
|
+
} else {
|
320
|
+
computed = exampleElement.currentStyle;
|
321
|
+
}
|
322
|
+
|
323
|
+
// set (lovely cssText property here helps a lot—if it works. Unfortunately, only Safari supplies it.)
|
324
|
+
style = computed.cssText;
|
325
|
+
|
326
|
+
// if that didn't work (Safari-only?) go alternate route. This is SLOW code...
|
327
|
+
if (!style || style.trim() === "") {
|
328
|
+
// there is only one way to do it...
|
329
|
+
var props = this._copy_computed_props;
|
330
|
+
|
331
|
+
// firefox ONLY allows this method
|
332
|
+
for (var i = 0; i < props.length; i++) {
|
333
|
+
var prop = props[i], val = computed[prop];
|
334
|
+
element.style[prop] = val;
|
335
|
+
}
|
336
|
+
|
337
|
+
// and why does firefox specifically need "font" set?
|
338
|
+
var cs = element.style; // cached style
|
339
|
+
if (cs.font === "") {
|
340
|
+
var font = "";
|
341
|
+
if (cs.fontStyle) font += cs.fontStyle + " ";
|
342
|
+
if (cs.fontVariant) font += cs.fontVariant + " ";
|
343
|
+
if (cs.fontWeight) font += cs.fontWeight + " ";
|
344
|
+
if (cs.fontSize) font += cs.fontSize; else font += "10px"; //force a default
|
345
|
+
if (cs.lineHeight) font += "/" + cs.lineHeight;
|
346
|
+
font += " ";
|
347
|
+
if (cs.fontFamily) font += cs.fontFamily; else cs += "sans-serif";
|
348
|
+
|
349
|
+
element.style.font = font;
|
350
|
+
}
|
351
|
+
|
352
|
+
SC.mixin(element.style, {
|
353
|
+
left: "0px", top: "0px", position: "absolute", bottom: "auto", right: "auto", width: "auto", height: "auto"
|
354
|
+
});
|
355
|
+
}
|
356
|
+
else
|
357
|
+
{
|
358
|
+
// set style
|
359
|
+
element.setAttribute("style", style + "; position:absolute; left: 0px; top: 0px; bottom: auto; right: auto; width: auto; height: auto;");
|
360
|
+
}
|
361
|
+
|
362
|
+
// clean up
|
363
|
+
computed = null;
|
364
|
+
} else {
|
365
|
+
// it is a style string already
|
366
|
+
style = exampleElement;
|
367
|
+
|
368
|
+
// set style
|
369
|
+
element.setAttribute("style", style + "; position:absolute; left: 0px; top: 0px; bottom: auto; right: auto; width: auto; height: auto;");
|
370
|
+
}
|
371
|
+
|
372
|
+
// the conclusion of which to use (innerText or textContent) should be cached
|
373
|
+
if (typeof element.innerText != "undefined") element.innerText = string;
|
374
|
+
else element.textContent = string;
|
375
|
+
|
376
|
+
element.className = classes;
|
377
|
+
|
378
|
+
// measure
|
379
|
+
var result = {
|
380
|
+
width: element.clientWidth,
|
381
|
+
height: element.clientHeight
|
382
|
+
};
|
383
|
+
|
384
|
+
// clear element
|
385
|
+
element.innerHTML = "";
|
386
|
+
element.className = "";
|
387
|
+
element.setAttribute("style", ""); // get rid of any junk from computed style.
|
388
|
+
|
389
|
+
// clean up
|
390
|
+
element = null;
|
391
|
+
return result;
|
392
|
+
},
|
393
|
+
|
285
394
|
/** Finds the absolute viewportOffset for a given element.
|
286
395
|
This method is more accurate than the version provided by prototype.
|
287
396
|
|
@@ -378,8 +487,8 @@ SC.mixin( /** @scope SC */ {
|
|
378
487
|
/** Returns the union of two ranges. If one range is null, the other
|
379
488
|
range will be returned. */
|
380
489
|
unionRanges: function(r1, r2) {
|
381
|
-
if ((r1
|
382
|
-
if ((r2
|
490
|
+
if ((r1 == null) || (r1.length < 0)) return r2 ;
|
491
|
+
if ((r2 == null) || (r2.length < 0)) return r1 ;
|
383
492
|
|
384
493
|
var min = Math.min(r1.start, r2.start) ;
|
385
494
|
var max = Math.max(SC.maxRange(r1), SC.maxRange(r2)) ;
|
@@ -388,7 +497,7 @@ SC.mixin( /** @scope SC */ {
|
|
388
497
|
|
389
498
|
/** Returns the intersection of the two ranges or SC.RANGE_NOT_FOUND */
|
390
499
|
intersectRanges: function(r1, r2) {
|
391
|
-
if ((r1
|
500
|
+
if ((r1 == null) || (r2 == null)) return SC.RANGE_NOT_FOUND ;
|
392
501
|
if ((r1.length < 0) || (r2.length < 0)) return SC.RANGE_NOT_FOUND;
|
393
502
|
var min = Math.max(SC.minRange(r1), SC.minRange(r2)) ;
|
394
503
|
var max = Math.min(SC.maxRange(r1), SC.maxRange(r2)) ;
|
@@ -398,7 +507,7 @@ SC.mixin( /** @scope SC */ {
|
|
398
507
|
|
399
508
|
/** Returns the difference of the two ranges or SC.RANGE_NOT_FOUND */
|
400
509
|
subtractRanges: function(r1, r2) {
|
401
|
-
if ((r1
|
510
|
+
if ((r1 == null) || (r2 == null)) return SC.RANGE_NOT_FOUND ;
|
402
511
|
if ((r1.length < 0) || (r2.length < 0)) return SC.RANGE_NOT_FOUND;
|
403
512
|
var max = Math.max(SC.minRange(r1), SC.minRange(r2)) ;
|
404
513
|
var min = Math.min(SC.maxRange(r1), SC.maxRange(r2)) ;
|
@@ -416,8 +525,8 @@ SC.mixin( /** @scope SC */ {
|
|
416
525
|
*/
|
417
526
|
rangesEqual: function(r1, r2) {
|
418
527
|
if (r1===r2) return true ;
|
419
|
-
if (r1
|
420
|
-
if (r2
|
528
|
+
if (r1 == null) return r2.length < 0 ;
|
529
|
+
if (r2 == null) return r1.length < 0 ;
|
421
530
|
return (r1.start == r2.start) && (r1.length == r2.length) ;
|
422
531
|
},
|
423
532
|
|
@@ -449,7 +558,7 @@ SC.mixin( /** @scope SC */ {
|
|
449
558
|
|
450
559
|
var h = (max == min) ? 0 : ((max == rgb[0]) ? ((rgb[1]-rgb[2])/(max-min)/6) : ((max == rgb[1]) ? ((rgb[2]-rgb[0])/(max-min)/6+1/3) : ((rgb[0]-rgb[1])/(max-min)/6+2/3)));
|
451
560
|
h = (h < 0) ? (h + 1) : ((h > 1) ? (h - 1) : h);
|
452
|
-
var s = (max
|
561
|
+
var s = (max == 0) ? 0 : (1 - min/max);
|
453
562
|
var v = max/255;
|
454
563
|
return [h, s, v];
|
455
564
|
},
|
@@ -213,7 +213,6 @@ div#show-tests * { display: none; }\
|
|
213
213
|
<b id="floatTest">Float test.</b>\
|
214
214
|
<iframe id="iframe" name="iframe"></iframe>\
|
215
215
|
<form id="lengthtest">\
|
216
|
-
<input type="text" id="length" name="test"/>\
|
217
216
|
<input type="text" id="idTest" name="id"/>\
|
218
217
|
</form>\
|
219
218
|
<table id="table"></table>\
|
@@ -663,7 +662,7 @@ test("width()", function() {
|
|
663
662
|
// IE is off by one on this. We don't really care at this point since ems
|
664
663
|
// is not really central to most SC apps.
|
665
664
|
$div.css("padding", "2em");
|
666
|
-
var e = SC.browser.msie ? 29 : 30;
|
665
|
+
var e = SC.browser.msie==8 ? 29 : 30;
|
667
666
|
equals($div.width(), e, "Test padding specified with ems");
|
668
667
|
|
669
668
|
$div.css("border", "1em solid #fff");
|
@@ -697,7 +696,7 @@ test("height()", function() {
|
|
697
696
|
// IE is off by one on this. We don't really care at this point since ems
|
698
697
|
// is not really central to most SC apps.
|
699
698
|
$div.css("padding", "2em");
|
700
|
-
var e = SC.browser.msie ? 29 : 30;
|
699
|
+
var e = SC.browser.msie==8 ? 29 : 30;
|
701
700
|
equals($div.height(), e, "Test padding specified with ems");
|
702
701
|
|
703
702
|
$div.css("border", "1em solid #fff");
|
@@ -17,30 +17,30 @@ module("SC.RenderContext#tag", {
|
|
17
17
|
|
18
18
|
test("should emit a self closing tag. like calling begin().end()", function() {
|
19
19
|
context.tag("input");
|
20
|
-
equals(context.get(1), "<input />");
|
20
|
+
equals(SC.RenderContext.escapeHTML(context.get(1)), SC.RenderContext.escapeHTML("<input />"));
|
21
21
|
});
|
22
22
|
|
23
23
|
test("should respect passed opts when emitting", function() {
|
24
24
|
context.tag("foo") ;
|
25
25
|
equals(context.length, 3);
|
26
|
-
equals(context.get(1), "<foo>");
|
27
|
-
equals(context.get(2), '<'+'/foo>');
|
26
|
+
equals(SC.RenderContext.escapeHTML(context.get(1)), SC.RenderContext.escapeHTML("<foo>"));
|
27
|
+
equals(SC.RenderContext.escapeHTML(context.get(2)), SC.RenderContext.escapeHTML('<'+'/foo>'));
|
28
28
|
});
|
29
29
|
|
30
30
|
test("should NOT emit self closing tag if tag is script", function() {
|
31
31
|
context.tag("script");
|
32
|
-
equals(context.get(1), '<script>');
|
33
|
-
equals(context.get(2), '<'+'/script>');
|
32
|
+
equals(SC.RenderContext.escapeHTML(context.get(1)), SC.RenderContext.escapeHTML('<script>'));
|
33
|
+
equals(SC.RenderContext.escapeHTML(context.get(2)), SC.RenderContext.escapeHTML('<'+'/script>'));
|
34
34
|
});
|
35
35
|
|
36
36
|
test("should NOT emit self closing tag if tag is div", function() {
|
37
37
|
context.tag("div");
|
38
|
-
equals(context.get(1), '<div>');
|
39
|
-
equals(context.get(2), '<'+'/div>');
|
38
|
+
equals(SC.RenderContext.escapeHTML(context.get(1)), SC.RenderContext.escapeHTML('<div>'));
|
39
|
+
equals(SC.RenderContext.escapeHTML(context.get(2)), SC.RenderContext.escapeHTML('<'+'/div>'));
|
40
40
|
});
|
41
41
|
|
42
42
|
test("should NOT emit self closing tag if no tag is passed", function() {
|
43
43
|
context.tag();
|
44
|
-
equals(context.get(1), '<div>');
|
45
|
-
equals(context.get(2), '<'+'/div>');
|
44
|
+
equals(SC.RenderContext.escapeHTML(context.get(1)), SC.RenderContext.escapeHTML('<div>'));
|
45
|
+
equals(SC.RenderContext.escapeHTML(context.get(2)), SC.RenderContext.escapeHTML('<'+'/div>'));
|
46
46
|
});
|
@@ -137,20 +137,20 @@ module("SC.RenderContext#update - className", {
|
|
137
137
|
test("does not change class names if retrieved but not edited", function() {
|
138
138
|
context.classNames();
|
139
139
|
context.update();
|
140
|
-
equals(elem.
|
140
|
+
equals(SC.$(elem).attr("class"), "foo bar", "class");
|
141
141
|
});
|
142
142
|
|
143
143
|
test("replaces class name if classNames edited", function() {
|
144
144
|
context.classNames('bar baz'.w());
|
145
145
|
context.update();
|
146
|
-
equals(elem.
|
146
|
+
equals(SC.$(elem).attr("class"), "bar baz", "attribute");
|
147
147
|
});
|
148
148
|
|
149
149
|
test("set class names override class attr", function() {
|
150
150
|
context.attr("class", "bar");
|
151
151
|
context.classNames('baz'.w());
|
152
152
|
context.update();
|
153
|
-
equals(elem.
|
153
|
+
equals(SC.$(elem).attr("class"), "baz", "should use classNames");
|
154
154
|
});
|
155
155
|
|
156
156
|
// ..........................................................
|
@@ -83,6 +83,33 @@ test("Test Asynchronous GET Request, auto-deserializing JSON", function() {
|
|
83
83
|
|
84
84
|
});
|
85
85
|
|
86
|
+
test("Test auto-deserializing malformed JSON", function() {
|
87
|
+
request = SC.Request.getUrl(sc_static('malformed.json')).set('isJSON', YES);
|
88
|
+
|
89
|
+
var timer = setTimeout(function() {
|
90
|
+
ok(false, 'response did not invoke notify()');
|
91
|
+
window.start();
|
92
|
+
}, 1000);
|
93
|
+
|
94
|
+
request.notify(this, function(response) {
|
95
|
+
ok(SC.ok(response), 'response should not be error');
|
96
|
+
|
97
|
+
try {
|
98
|
+
var body = response.get('body');
|
99
|
+
ok(!SC.ok(body), 'body should be an error');
|
100
|
+
} catch(e) {
|
101
|
+
ok(false, 'getting the body should not throw an exception');
|
102
|
+
}
|
103
|
+
|
104
|
+
clearTimeout(timer);
|
105
|
+
window.start();
|
106
|
+
});
|
107
|
+
|
108
|
+
request.send();
|
109
|
+
|
110
|
+
stop();
|
111
|
+
});
|
112
|
+
|
86
113
|
test("Test Synchronous GET Request, auto-deserializing JSON", function() {
|
87
114
|
request.set("isAsynchronous", false);
|
88
115
|
request.set("isJSON", true);
|
@@ -0,0 +1,99 @@
|
|
1
|
+
// ========================================================================
|
2
|
+
// Rect utility Tests
|
3
|
+
// ========================================================================
|
4
|
+
|
5
|
+
|
6
|
+
module("Rect utilities");
|
7
|
+
|
8
|
+
test("Get the X & Y points of a rect", function() {
|
9
|
+
var frame = { x: 50, y: 40, width: 700, height: 9000 };
|
10
|
+
expect(6);
|
11
|
+
equals(SC.minX(frame),50,'Left edge');
|
12
|
+
equals(SC.maxX(frame),750,'Right edge');
|
13
|
+
equals(SC.midX(frame),400,'Horizontal midpoint');
|
14
|
+
|
15
|
+
equals(SC.minY(frame),40, 'Top edge');
|
16
|
+
equals(SC.maxY(frame),9040,'Bottom edge');
|
17
|
+
equals(SC.midY(frame),4540,'Vertical midpoint');
|
18
|
+
});
|
19
|
+
|
20
|
+
test("Treat empty object as frame with 0 width and height", function() {
|
21
|
+
var frame = { };
|
22
|
+
expect(6);
|
23
|
+
equals(SC.minX(frame),0,'Left edge');
|
24
|
+
equals(SC.maxX(frame),0,'Right edge');
|
25
|
+
equals(SC.midX(frame),0,'Horizontal midpoint');
|
26
|
+
|
27
|
+
equals(SC.minY(frame),0,'Top edge');
|
28
|
+
equals(SC.maxY(frame),0,'Bottom edge');
|
29
|
+
equals(SC.midY(frame),0,'Vertical midpoint');
|
30
|
+
});
|
31
|
+
|
32
|
+
test("pointInRect() to test if a given point is inside the rect", function(){
|
33
|
+
var frame = { x: 50, y: 40, width: 700, height: 9000 };
|
34
|
+
|
35
|
+
ok(SC.pointInRect({ x: 100, y: 100 }, frame), "Point in rect");
|
36
|
+
equals(NO, SC.pointInRect({ x: 40, y: 100 }, frame), "Point out of rect horizontally");
|
37
|
+
equals(NO, SC.pointInRect({ x: 600, y: 9100 }, frame), "Point out of rect vertically");
|
38
|
+
equals(NO, SC.pointInRect({ x: 0, y: 0 }, frame), "Point up and left from rect");
|
39
|
+
equals(NO, SC.pointInRect({ x: 800, y: 9500 }, frame), "Point down and right from rect");
|
40
|
+
});
|
41
|
+
|
42
|
+
test("rectsEqual() tests equality with default delta", function() {
|
43
|
+
var frame = { x: 50, y: 50, width: 100, height: 100 };
|
44
|
+
|
45
|
+
equals(SC.rectsEqual(frame, frame), YES, "Frames are same object");
|
46
|
+
equals(SC.rectsEqual(frame, { x: 50, y: 50, width: 100, height: 100 }), YES, "Frames have same position and dimensions");
|
47
|
+
equals(SC.rectsEqual(frame, { x: 50.08, y: 50, width: 100, height: 100 }), YES, "Frame.x above, within delta");
|
48
|
+
equals(SC.rectsEqual(frame, { x: 49.92, y: 50, width: 100, height: 100 }), YES, "Frame.x below, within delta");
|
49
|
+
equals(SC.rectsEqual(frame, { x: 50, y: 50.099, width: 100, height: 100 }), YES, "Frame.y within delta");
|
50
|
+
equals(SC.rectsEqual(frame, { x: 50, y: 50, width: 100.001, height: 100 }), YES, "Frame.width within delta");
|
51
|
+
equals(SC.rectsEqual(frame, { x: 50, y: 50, width: 100, height: 100.09999 }), YES, "Frame.height within delta");
|
52
|
+
equals(SC.rectsEqual(frame, { x: 55, y: 50, width: 100, height: 100 }), NO, "Frame.x not equal");
|
53
|
+
equals(SC.rectsEqual(frame, { x: 50, y: 55, width: 100, height: 100 }), NO, "Frame.y not equal");
|
54
|
+
equals(SC.rectsEqual(frame, { x: 50, y: 50, width: 105, height: 100 }), NO, "Frame.width not equal");
|
55
|
+
equals(SC.rectsEqual(frame, { x: 50, y: 50, width: 100, height: 105 }), NO, "Frame.height not equal");
|
56
|
+
});
|
57
|
+
|
58
|
+
test("rectsEqual() tests equality with null delta", function() {
|
59
|
+
var frame = { x: 50, y: 50, width: 100, height: 100 };
|
60
|
+
|
61
|
+
equals(SC.rectsEqual(frame, frame), YES, "Frames are same object");
|
62
|
+
equals(SC.rectsEqual(frame, { x: 50, y: 50, width: 100, height: 100 }, null), YES, "Frames have same position and dimensions");
|
63
|
+
equals(SC.rectsEqual(frame, { x: 50.08, y: 50, width: 100, height: 100 }, null), YES, "Frame.x above, within delta");
|
64
|
+
equals(SC.rectsEqual(frame, { x: 49.92, y: 50, width: 100, height: 100 }, null), YES, "Frame.x below, within delta");
|
65
|
+
equals(SC.rectsEqual(frame, { x: 50, y: 50.099, width: 100, height: 100 }, null), YES, "Frame.y within delta");
|
66
|
+
equals(SC.rectsEqual(frame, { x: 50, y: 50, width: 100.001, height: 100 }, null), YES, "Frame.width within delta");
|
67
|
+
equals(SC.rectsEqual(frame, { x: 50, y: 50, width: 100, height: 100.01 }, null), YES, "Frame.height within delta");
|
68
|
+
equals(SC.rectsEqual(frame, { x: 55, y: 50, width: 100, height: 100 }, null), NO, "Frame.x not equal");
|
69
|
+
equals(SC.rectsEqual(frame, { x: 50, y: 55, width: 100, height: 100 }, null), NO, "Frame.y not equal");
|
70
|
+
equals(SC.rectsEqual(frame, { x: 50, y: 50, width: 105, height: 100 }, null), NO, "Frame.width not equal");
|
71
|
+
equals(SC.rectsEqual(frame, { x: 50, y: 50, width: 100, height: 105 }, null), NO, "Frame.height not equal");
|
72
|
+
});
|
73
|
+
|
74
|
+
test("rectsEqual() tests equality with delta of 10", function() {
|
75
|
+
var frame = { x: 50, y: 50, width: 100, height: 100 };
|
76
|
+
|
77
|
+
equals(SC.rectsEqual(frame, frame), YES, "Frames are same object");
|
78
|
+
equals(SC.rectsEqual(frame, { x: 50, y: 50, width: 100, height: 100 }, 10), YES, "Frames have same position and dimensions");
|
79
|
+
equals(SC.rectsEqual(frame, { x: 59.99, y: 50, width: 100, height: 100 }, 10), YES, "Frame.x above, within delta");
|
80
|
+
equals(SC.rectsEqual(frame, { x: 41, y: 50, width: 100, height: 100 }, 10), YES, "Frame.x below, within delta");
|
81
|
+
equals(SC.rectsEqual(frame, { x: 50, y: 59, width: 100, height: 100 }, 10), YES, "Frame.y within delta");
|
82
|
+
equals(SC.rectsEqual(frame, { x: 50, y: 50, width: 109, height: 100 }, 10), YES, "Frame.width within delta");
|
83
|
+
equals(SC.rectsEqual(frame, { x: 50, y: 50, width: 100, height: 100.000002 }, 10), YES, "Frame.height within delta");
|
84
|
+
equals(SC.rectsEqual(frame, { x: 61, y: 50, width: 100, height: 100 }, 10), NO, "Frame.x not equal");
|
85
|
+
equals(SC.rectsEqual(frame, { x: 50, y: 92, width: 100, height: 100 }, 10), NO, "Frame.y not equal");
|
86
|
+
equals(SC.rectsEqual(frame, { x: 50, y: 50, width: 89, height: 100 }, 10), NO, "Frame.width not equal");
|
87
|
+
equals(SC.rectsEqual(frame, { x: 50, y: 50, width: 100, height: 89.99999 }, 10), NO, "Frame.height not equal");
|
88
|
+
});
|
89
|
+
|
90
|
+
test("rectsEqual() tests equality with delta of 0", function() {
|
91
|
+
var frame = { x: 50, y: 50, width: 100, height: 100 };
|
92
|
+
|
93
|
+
equals(SC.rectsEqual(frame, frame), YES, "Frames are same object");
|
94
|
+
equals(SC.rectsEqual(frame, { x: 50, y: 50, width: 100, height: 100 }, 0), YES, "Frames have same position and dimensions");
|
95
|
+
equals(SC.rectsEqual(frame, { x: 50.0001, y: 50, width: 100, height: 100 }, 0), NO, "Frame.x not equal");
|
96
|
+
equals(SC.rectsEqual(frame, { x: 50, y: 51, width: 100, height: 100 }, 0), NO, "Frame.y not equal");
|
97
|
+
equals(SC.rectsEqual(frame, { x: 50, y: 50, width: 99, height: 100 }, 0), NO, "Frame.width not equal");
|
98
|
+
equals(SC.rectsEqual(frame, { x: 50, y: 50, width: 100, height: 102 }, 0), NO, "Frame.height not equal");
|
99
|
+
});
|