sproutcore 1.0.1008 → 1.0.1009
Sign up to get free protection for your applications and to get access to all the features.
- data/VERSION.yml +2 -2
- data/frameworks/sproutcore/README +1 -1
- data/frameworks/sproutcore/frameworks/datastore/system/record_array.js +2 -2
- data/frameworks/sproutcore/frameworks/desktop/views/list.js +18 -0
- data/frameworks/sproutcore/frameworks/desktop/views/list_item.js +29 -0
- data/frameworks/sproutcore/frameworks/desktop/views/split.js +8 -4
- data/frameworks/sproutcore/frameworks/foundation/system/json.js +90 -18
- data/frameworks/sproutcore/themes/standard_theme/english.lproj/collection.css +8 -0
- data/gen/data-source/templates/data_sources/@filename@.js +1 -1
- data/sproutcore-abbot.gemspec +2 -2
- metadata +2 -2
data/VERSION.yml
CHANGED
@@ -446,7 +446,7 @@ SC.RecordArray = SC.Object.extend(SC.Enumerable, SC.Array,
|
|
446
446
|
changed.forEach(function(storeKey) {
|
447
447
|
// get record - do not include EMPTY or DESTROYED records
|
448
448
|
status = store.peekStatus(storeKey);
|
449
|
-
if (!(status & K.EMPTY) && !(status & K.DESTROYED)) {
|
449
|
+
if (!(status & K.EMPTY) && !((status & K.DESTROYED) || (status === K.BUSY_DESTROYING))) {
|
450
450
|
rec = store.materializeRecord(storeKey);
|
451
451
|
included = !!(rec && query.contains(rec));
|
452
452
|
} else included = NO ;
|
@@ -490,7 +490,7 @@ SC.RecordArray = SC.Object.extend(SC.Enumerable, SC.Array,
|
|
490
490
|
storeKeys = [];
|
491
491
|
sourceKeys.forEach(function(storeKey) {
|
492
492
|
status = store.peekStatus(storeKey);
|
493
|
-
if (!(status & K.EMPTY) && !(status & K.DESTROYED)) {
|
493
|
+
if (!(status & K.EMPTY) && !((status & K.DESTROYED) || (status === K.BUSY_DESTROYING))) {
|
494
494
|
rec = store.materializeRecord(storeKey);
|
495
495
|
if (rec && query.contains(rec)) storeKeys.push(storeKey);
|
496
496
|
}
|
@@ -61,6 +61,24 @@ SC.ListView = SC.CollectionView.extend(
|
|
61
61
|
classNames: ['sc-list-view'],
|
62
62
|
|
63
63
|
acceptsFirstResponder: YES,
|
64
|
+
|
65
|
+
/**
|
66
|
+
* If set to YES, the default theme will show alternating rows
|
67
|
+
* for the views this ListView created through exampleView property.
|
68
|
+
*
|
69
|
+
* @property {Boolean}
|
70
|
+
*/
|
71
|
+
showAlternatingRows: NO,
|
72
|
+
|
73
|
+
// ..........................................................
|
74
|
+
// METHODS
|
75
|
+
//
|
76
|
+
|
77
|
+
render: function(context, firstTime) {
|
78
|
+
context.setClass('alternating', this.get('showAlternatingRows'));
|
79
|
+
|
80
|
+
return sc_super();
|
81
|
+
},
|
64
82
|
|
65
83
|
// ..........................................................
|
66
84
|
// COLLECTION ROW DELEGATE SUPPORT
|
@@ -127,6 +127,7 @@ SC.ListItemView = SC.View.extend(
|
|
127
127
|
*/
|
128
128
|
contentIsBranchKey: null,
|
129
129
|
|
130
|
+
|
130
131
|
/**
|
131
132
|
YES if the item view is currently editing.
|
132
133
|
*/
|
@@ -152,9 +153,22 @@ SC.ListItemView = SC.View.extend(
|
|
152
153
|
|
153
154
|
contentPropertyDidChange: function() {
|
154
155
|
//if (this.get('isEditing')) this.discardEditing() ;
|
156
|
+
if (this.get('contentIsEditable') !== this.contentIsEditable()) {
|
157
|
+
this.notifyPropertyChange('contentIsEditable');
|
158
|
+
}
|
159
|
+
|
155
160
|
this.displayDidChange();
|
156
161
|
},
|
157
162
|
|
163
|
+
/**
|
164
|
+
Determines if content is editable or not. Checkboxes and other related
|
165
|
+
components will render disabled if an item is not editable.
|
166
|
+
*/
|
167
|
+
contentIsEditable: function() {
|
168
|
+
var content = this.get('content');
|
169
|
+
return content && (content.get('isEditable')!==NO);
|
170
|
+
}.property('content').cacheable(),
|
171
|
+
|
158
172
|
/**
|
159
173
|
Fills the passed html-array with strings that can be joined to form the
|
160
174
|
innerHTML of the receiver element. Also populates an array of classNames
|
@@ -171,6 +185,10 @@ SC.ListItemView = SC.View.extend(
|
|
171
185
|
indent = this.get('outlineIndent'),
|
172
186
|
key, value, working ;
|
173
187
|
|
188
|
+
// add alternating row classes
|
189
|
+
context.addClass((this.get('contentIndex')%2 === 0) ? 'even' : 'odd');
|
190
|
+
context.setClass('disabled', !this.get('isEnabled'));
|
191
|
+
|
174
192
|
// outline level wrapper
|
175
193
|
working = context.begin("div").addClass("sc-outline");
|
176
194
|
if (level>=0 && indent>0) working.addStyle("left", indent*(level+1));
|
@@ -282,8 +300,10 @@ SC.ListItemView = SC.View.extend(
|
|
282
300
|
|
283
301
|
var key = (state === SC.MIXED_STATE) ? "mixed" : state ? "sel" : "nosel",
|
284
302
|
cache = this._scli_checkboxHtml,
|
303
|
+
isEnabled = this.get('contentIsEditable') && this.get('isEnabled'),
|
285
304
|
html, tmp;
|
286
305
|
|
306
|
+
if (!isEnabled) key = SC.keyFor('disabled', key);
|
287
307
|
if (!cache) cache = this.constructor.prototype._scli_checkboxHtml = {};
|
288
308
|
html = cache[key];
|
289
309
|
|
@@ -294,6 +314,9 @@ SC.ListItemView = SC.View.extend(
|
|
294
314
|
// set state on html
|
295
315
|
if (state === SC.MIXED_STATE) tmp.addClass('mixed');
|
296
316
|
else tmp.setClass('sel', state);
|
317
|
+
|
318
|
+
// disabled
|
319
|
+
tmp.setClass('disabled', !isEnabled);
|
297
320
|
|
298
321
|
// now add inner content. note we do not add a real checkbox because
|
299
322
|
// we don't want to have to setup a change observer on it.
|
@@ -463,6 +486,11 @@ SC.ListItemView = SC.View.extend(
|
|
463
486
|
button.
|
464
487
|
*/
|
465
488
|
mouseDown: function(evt) {
|
489
|
+
|
490
|
+
// if content is not editable, then always let collection view handle the
|
491
|
+
// event.
|
492
|
+
if (!this.get('contentIsEditable')) return NO ;
|
493
|
+
|
466
494
|
// if occurred inside checkbox, item view should handle the event.
|
467
495
|
if (this._isInsideCheckbox(evt)) {
|
468
496
|
this._addCheckboxActiveState() ;
|
@@ -608,6 +636,7 @@ SC.ListItemView = SC.View.extend(
|
|
608
636
|
|
609
637
|
beginEditing: function() {
|
610
638
|
if (this.get('isEditing')) return YES ;
|
639
|
+
//if (!this.get('contentIsEditable')) return NO ;
|
611
640
|
return this._beginEditing(YES);
|
612
641
|
},
|
613
642
|
|
@@ -512,10 +512,14 @@ SC.SplitView = SC.View.extend(
|
|
512
512
|
mouseUp: function(evt) {
|
513
513
|
// console.log('%@.mouseUp(%@, %@)'.fmt(this, evt));
|
514
514
|
// console.log(evt.originalEvent);
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
515
|
+
if (this._inLiveResize === YES) {
|
516
|
+
this._thumbView = null ; // avoid memory leaks
|
517
|
+
this._inLiveResize = NO ;
|
518
|
+
this.endLiveResize() ;
|
519
|
+
return YES ;
|
520
|
+
}
|
521
|
+
|
522
|
+
return NO ;
|
519
523
|
},
|
520
524
|
|
521
525
|
doubleClickInThumbView: function(evt, thumbView) {
|
@@ -33,7 +33,7 @@ SC.json = {
|
|
33
33
|
|
34
34
|
/*
|
35
35
|
http://www.JSON.org/json2.js
|
36
|
-
|
36
|
+
2009-09-29
|
37
37
|
|
38
38
|
Public Domain.
|
39
39
|
|
@@ -66,7 +66,7 @@ SC.json = {
|
|
66
66
|
value represented by the name/value pair that should be serialized,
|
67
67
|
or undefined if nothing should be serialized. The toJSON method
|
68
68
|
will be passed the key associated with the value, and this will be
|
69
|
-
bound to the
|
69
|
+
bound to the value
|
70
70
|
|
71
71
|
For example, this would serialize Dates as ISO strings.
|
72
72
|
|
@@ -177,9 +177,7 @@ SC.json = {
|
|
177
177
|
NOT CONTROL.
|
178
178
|
*/
|
179
179
|
|
180
|
-
/*jslint evil: true */
|
181
|
-
|
182
|
-
/*global JSON */
|
180
|
+
/*jslint evil: true, strict: false */
|
183
181
|
|
184
182
|
/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
|
185
183
|
call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
|
@@ -188,12 +186,14 @@ SC.json = {
|
|
188
186
|
test, toJSON, toString, valueOf
|
189
187
|
*/
|
190
188
|
|
189
|
+
|
191
190
|
// Create a JSON object only if one does not already exist. We create the
|
192
191
|
// methods in a closure to avoid creating global variables.
|
193
192
|
|
194
193
|
if (!this.JSON) {
|
195
|
-
JSON = {};
|
194
|
+
this.JSON = {};
|
196
195
|
}
|
196
|
+
|
197
197
|
(function () {
|
198
198
|
|
199
199
|
function f(n) {
|
@@ -205,12 +205,13 @@ if (!this.JSON) {
|
|
205
205
|
|
206
206
|
Date.prototype.toJSON = function (key) {
|
207
207
|
|
208
|
-
return this.
|
208
|
+
return isFinite(this.valueOf()) ?
|
209
|
+
this.getUTCFullYear() + '-' +
|
209
210
|
f(this.getUTCMonth() + 1) + '-' +
|
210
211
|
f(this.getUTCDate()) + 'T' +
|
211
212
|
f(this.getUTCHours()) + ':' +
|
212
213
|
f(this.getUTCMinutes()) + ':' +
|
213
|
-
f(this.getUTCSeconds()) + 'Z';
|
214
|
+
f(this.getUTCSeconds()) + 'Z' : null;
|
214
215
|
};
|
215
216
|
|
216
217
|
String.prototype.toJSON =
|
@@ -267,14 +268,9 @@ if (!this.JSON) {
|
|
267
268
|
value = holder[key];
|
268
269
|
|
269
270
|
// If the value has a toJSON method, call it to obtain a replacement value.
|
270
|
-
|
271
|
-
/* FIXME: Prototype.js is creating an object.toJSON function which is not
|
272
|
-
is not playing well with json2.js. Arrays are not being JSON.stringify
|
273
|
-
correctly. Someone may want to check that this is correct.
|
274
|
-
*/
|
271
|
+
|
275
272
|
if (value && typeof value === 'object' &&
|
276
|
-
typeof value.toJSON === 'function'
|
277
|
-
Object.prototype.toString.apply(value) !== '[object Array]') {
|
273
|
+
typeof value.toJSON === 'function') {
|
278
274
|
value = value.toJSON(key);
|
279
275
|
}
|
280
276
|
|
@@ -344,7 +340,7 @@ if (!this.JSON) {
|
|
344
340
|
mind + ']' :
|
345
341
|
'[' + partial.join(',') + ']';
|
346
342
|
gap = mind;
|
347
|
-
|
343
|
+
return v;
|
348
344
|
}
|
349
345
|
|
350
346
|
// If the replacer is an array, use it to select the members to be stringified.
|
@@ -435,6 +431,82 @@ if (!this.JSON) {
|
|
435
431
|
// If the JSON object does not yet have a parse method, give it one.
|
436
432
|
|
437
433
|
if (typeof JSON.parse !== 'function') {
|
438
|
-
|
434
|
+
JSON.parse = function (text, reviver) {
|
435
|
+
|
436
|
+
// The parse method takes a text and an optional reviver function, and returns
|
437
|
+
// a JavaScript value if the text is a valid JSON text.
|
438
|
+
|
439
|
+
var j;
|
440
|
+
|
441
|
+
function walk(holder, key) {
|
442
|
+
|
443
|
+
// The walk method is used to recursively walk the resulting structure so
|
444
|
+
// that modifications can be made.
|
445
|
+
|
446
|
+
var k, v, value = holder[key];
|
447
|
+
if (value && typeof value === 'object') {
|
448
|
+
for (k in value) {
|
449
|
+
if (Object.hasOwnProperty.call(value, k)) {
|
450
|
+
v = walk(value, k);
|
451
|
+
if (v !== undefined) {
|
452
|
+
value[k] = v;
|
453
|
+
} else {
|
454
|
+
delete value[k];
|
455
|
+
}
|
456
|
+
}
|
457
|
+
}
|
458
|
+
}
|
459
|
+
return reviver.call(holder, key, value);
|
460
|
+
}
|
461
|
+
|
462
|
+
|
463
|
+
// Parsing happens in four stages. In the first stage, we replace certain
|
464
|
+
// Unicode characters with escape sequences. JavaScript handles many characters
|
465
|
+
// incorrectly, either silently deleting them, or treating them as line endings.
|
466
|
+
|
467
|
+
cx.lastIndex = 0;
|
468
|
+
if (cx.test(text)) {
|
469
|
+
text = text.replace(cx, function (a) {
|
470
|
+
return '\\u' +
|
471
|
+
('0000' + a.charCodeAt(0).toString(16)).slice(-4);
|
472
|
+
});
|
473
|
+
}
|
474
|
+
|
475
|
+
// In the second stage, we run the text against regular expressions that look
|
476
|
+
// for non-JSON patterns. We are especially concerned with '()' and 'new'
|
477
|
+
// because they can cause invocation, and '=' because it can cause mutation.
|
478
|
+
// But just to be safe, we want to reject all unexpected forms.
|
479
|
+
|
480
|
+
// We split the second stage into 4 regexp operations in order to work around
|
481
|
+
// crippling inefficiencies in IE's and Safari's regexp engines. First we
|
482
|
+
// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
|
483
|
+
// replace all simple value tokens with ']' characters. Third, we delete all
|
484
|
+
// open brackets that follow a colon or comma or that begin the text. Finally,
|
485
|
+
// we look to see that the remaining characters are only whitespace or ']' or
|
486
|
+
// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.
|
487
|
+
|
488
|
+
if (/^[\],:{}\s]*$/.
|
489
|
+
test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@').
|
490
|
+
replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']').
|
491
|
+
replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {
|
492
|
+
|
493
|
+
// In the third stage we use the eval function to compile the text into a
|
494
|
+
// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
|
495
|
+
// in JavaScript: it can begin a block or an object literal. We wrap the text
|
496
|
+
// in parens to eliminate the ambiguity.
|
497
|
+
|
498
|
+
j = eval('(' + text + ')');
|
499
|
+
|
500
|
+
// In the optional fourth stage, we recursively walk the new structure, passing
|
501
|
+
// each name/value pair to a reviver function for possible transformation.
|
502
|
+
|
503
|
+
return typeof reviver === 'function' ?
|
504
|
+
walk({'': j}, '') : j;
|
505
|
+
}
|
506
|
+
|
507
|
+
// If the text is not JSON parseable, then a SyntaxError is thrown.
|
508
|
+
|
509
|
+
throw new SyntaxError('JSON.parse');
|
510
|
+
};
|
439
511
|
}
|
440
|
-
}
|
512
|
+
}());
|
@@ -10,11 +10,19 @@
|
|
10
10
|
color: #000;
|
11
11
|
}
|
12
12
|
|
13
|
+
.sc-theme .sc-collection-view.alternating .sc-collection-item.even {
|
14
|
+
background-color: #e4e4e4;
|
15
|
+
}
|
16
|
+
|
13
17
|
.sc-theme .sc-collection-view .sc-collection-item.sel {
|
14
18
|
background-color: #ddd;
|
15
19
|
color: #333;
|
16
20
|
}
|
17
21
|
|
22
|
+
.sc-theme.focus .sc-collection-view.alternating .sc-collection-item.even {
|
23
|
+
background-color: #f4f7fb;
|
24
|
+
}
|
25
|
+
|
18
26
|
.sc-theme.focus .sc-collection-view.focus .sc-collection-item.sel {
|
19
27
|
background-color: #2370d8;
|
20
28
|
color: white ;
|
@@ -10,7 +10,7 @@
|
|
10
10
|
|
11
11
|
@extends <%= base_class_name || 'SC.DataSource' %>
|
12
12
|
*/
|
13
|
-
<%= namespace_class_name %> = <%= base_class_name || 'SC.DataSource' %>.
|
13
|
+
<%= namespace_class_name %> = <%= base_class_name || 'SC.DataSource' %>.extend(
|
14
14
|
/** @scope <%= namespace_class_name %>.prototype */ {
|
15
15
|
|
16
16
|
// ..........................................................
|
data/sproutcore-abbot.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{sproutcore}
|
8
|
-
s.version = "1.0.
|
8
|
+
s.version = "1.0.1009"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Sprout Systems, Inc. Apple Inc. and contributors"]
|
12
|
-
s.date = %q{2009-10-
|
12
|
+
s.date = %q{2009-10-26}
|
13
13
|
s.description = %q{sproutcore - abbot
|
14
14
|
by Charles Jolley and contributors
|
15
15
|
http://www.sproutcore.com
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: sproutcore
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.1009
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Sprout Systems, Inc. Apple Inc. and contributors
|
@@ -9,7 +9,7 @@ autorequire:
|
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
11
|
|
12
|
-
date: 2009-10-
|
12
|
+
date: 2009-10-26 00:00:00 -07:00
|
13
13
|
default_executable:
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|