sproutcore 0.9.14 → 0.9.15
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/History.txt +43 -0
- data/Manifest.txt +12 -3
- data/bin/sc-build +19 -3
- data/bin/sc-install +5 -0
- data/bin/sc-remove +5 -0
- data/bin/sc-update +5 -0
- data/frameworks/prototype/prototype.js +267 -230
- data/frameworks/sproutcore/HISTORY +281 -135
- data/frameworks/sproutcore/controllers/array.js +133 -22
- data/frameworks/sproutcore/controllers/collection.js +4 -5
- data/frameworks/sproutcore/controllers/object.js +8 -2
- data/frameworks/sproutcore/core.js +361 -159
- data/frameworks/sproutcore/{foundation → debug}/unittest.js +3 -3
- data/frameworks/sproutcore/english.lproj/detect-browser +1 -1
- data/frameworks/sproutcore/english.lproj/theme.css +2 -2
- data/frameworks/sproutcore/foundation/application.js +6 -1
- data/frameworks/sproutcore/foundation/benchmark.js +37 -11
- data/frameworks/sproutcore/foundation/date.js +1 -1
- data/frameworks/sproutcore/foundation/enumerator.js +105 -0
- data/frameworks/sproutcore/foundation/object.js +19 -20
- data/frameworks/sproutcore/foundation/responder.js +1 -1
- data/frameworks/sproutcore/foundation/set.js +164 -57
- data/frameworks/sproutcore/foundation/string.js +151 -47
- data/frameworks/sproutcore/foundation/utils.js +84 -3
- data/frameworks/sproutcore/lib/collection_view.rb +1 -0
- data/frameworks/sproutcore/license.js +28 -0
- data/frameworks/sproutcore/mixins/array.js +73 -209
- data/frameworks/sproutcore/mixins/delegate_support.js +1 -1
- data/frameworks/sproutcore/mixins/enumerable.js +1006 -0
- data/frameworks/sproutcore/mixins/observable.js +153 -84
- data/frameworks/sproutcore/mixins/selection_support.js +13 -1
- data/frameworks/sproutcore/models/record.js +74 -27
- data/frameworks/sproutcore/models/store.js +7 -3
- data/frameworks/sproutcore/server/rails_server.js +82 -0
- data/frameworks/sproutcore/server/rest_server.js +178 -0
- data/frameworks/sproutcore/{foundation → server}/server.js +101 -48
- data/frameworks/sproutcore/tests/core/guidFor.rhtml +114 -0
- data/frameworks/sproutcore/tests/foundation/array.rhtml +6 -7
- data/frameworks/sproutcore/tests/foundation/set.rhtml +254 -0
- data/frameworks/sproutcore/tests/mixins/enumerable.rhtml +421 -0
- data/frameworks/sproutcore/tests/mixins/observable.rhtml +127 -0
- data/frameworks/sproutcore/tests/models/model.rhtml +23 -22
- data/frameworks/sproutcore/tests/views/collection/incremental_rendering.rhtml +2 -2
- data/frameworks/sproutcore/tests/views/view/clippingFrame.rhtml +112 -109
- data/frameworks/sproutcore/tests/views/view/frame.rhtml +91 -88
- data/frameworks/sproutcore/validators/date.js +1 -7
- data/frameworks/sproutcore/views/collection/collection.js +7 -2
- data/frameworks/sproutcore/views/list_item.js +141 -3
- data/frameworks/sproutcore/views/split.js +14 -11
- data/frameworks/sproutcore/views/view.js +9 -6
- data/lib/sproutcore/build_tools/html_builder.rb +19 -3
- data/lib/sproutcore/build_tools/resource_builder.rb +9 -3
- data/lib/sproutcore/bundle.rb +21 -0
- data/lib/sproutcore/bundle_manifest.rb +64 -20
- data/lib/sproutcore/helpers/capture_helper.rb +2 -2
- data/lib/sproutcore/library.rb +33 -9
- data/lib/sproutcore/merb/bundle_controller.rb +16 -5
- data/lib/sproutcore/version.rb +1 -1
- data/lib/sproutcore/view_helpers.rb +1 -1
- data/{sc-config.rb → sc-config} +5 -2
- metadata +24 -5
@@ -10,101 +10,102 @@
|
|
10
10
|
|
11
11
|
<script>
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
//
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
//
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
//
|
46
|
-
//
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
// //
|
54
|
-
// // CASE 2: Manual-layout of view
|
55
|
-
// Test.context("CASE 2: Manual-layout of view", {
|
56
|
-
//
|
57
|
-
// "frame should reflect current offset settings at first": function() {
|
58
|
-
// var el = this.v.rootElement ;
|
59
|
-
// var f = { x: el.offsetTop, y: el.offsetLeft, width: el.offsetWidth, height: el.offsetHeight };
|
60
|
-
// SC.rectsEqual(f, this.v.get('frame')).shouldEqual(true) ;
|
61
|
-
// },
|
13
|
+
Test.context("CASE 1: Auto-layout view with no padding & no border", {
|
14
|
+
|
15
|
+
"frame should reflect current offset settings": function() {
|
16
|
+
var el = this.v.rootElement ;
|
17
|
+
var f = { x: el.offsetTop, y: el.offsetLeft, width: el.offsetWidth, height: el.offsetHeight };
|
18
|
+
console.log(this.v.get('frame').x) ;
|
19
|
+
console.log('this.frame', this.v.get('frame')) ;
|
20
|
+
SC.rectsEqual(f, this.v.get('frame')).shouldEqual(true) ;
|
21
|
+
},
|
22
|
+
|
23
|
+
"frame should change when CSS changed": function() {
|
24
|
+
var origFrame = this.v.get('frame') ;
|
25
|
+
|
26
|
+
this.v.addClassName('half') ;
|
27
|
+
this.v.viewFrameDidChange() ;
|
28
|
+
|
29
|
+
SC.rectsEqual(this.v.get('frame'), origFrame).shouldEqual(false) ;
|
30
|
+
|
31
|
+
// remove the class. make sure we have restored the frame
|
32
|
+
this.v.removeClassName('half') ; //reset
|
33
|
+
this.v.viewFrameDidChange() ;
|
34
|
+
SC.rectsEqual(this.v.get('frame'), origFrame).shouldEqual(true) ;
|
35
|
+
},
|
36
|
+
|
37
|
+
"setting frame should change style, even if it does not impact actual value": function() {
|
38
|
+
var f = this.v.get('frame') ;
|
39
|
+
var ret = this.v.set('frame', { x: 10, y: 10 }) ;
|
40
|
+
|
41
|
+
// it should change the style though
|
42
|
+
this.v.getStyle('left').shouldEqual('10px');
|
43
|
+
this.v.getStyle('top').shouldEqual('10px');
|
44
|
+
|
45
|
+
// change the top & left. Since the layout is static here, this should not actually
|
46
|
+
// change anything.
|
47
|
+
SC.rectsEqual(ret, f).shouldEqual(true) ;
|
48
|
+
},
|
49
|
+
|
50
|
+
setup: function() { this.v = SC.page.get('case1'); }
|
51
|
+
|
52
|
+
});
|
62
53
|
//
|
63
|
-
//
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
54
|
+
// CASE 2: Manual-layout of view
|
55
|
+
Test.context("CASE 2: Manual-layout of view", {
|
56
|
+
|
57
|
+
"frame should reflect current offset settings at first": function() {
|
58
|
+
var el = this.v.rootElement ;
|
59
|
+
var f = { x: el.offsetTop, y: el.offsetLeft, width: el.offsetWidth, height: el.offsetHeight };
|
60
|
+
SC.rectsEqual(f, this.v.get('frame')).shouldEqual(true) ;
|
61
|
+
},
|
62
|
+
|
63
|
+
"should get absolute positioning": function() {
|
64
|
+
this.v.getStyle('position').shouldEqual('absolute') ;
|
65
|
+
},
|
66
|
+
|
67
|
+
"frame should reflect set values exactly": function() {
|
68
|
+
var f = { x: 10, y: 10, width: 20, height: 20 } ;
|
69
|
+
var ret = this.v.set('frame', f);
|
70
|
+
SC.rectsEqual(f,ret).shouldEqual(true) ;
|
71
|
+
SC.rectsEqual(this.v.get('frame'), f).shouldEqual(true) ;
|
72
|
+
},
|
73
|
+
|
74
|
+
"actual offset should reflect set values exactly": function() {
|
75
|
+
var f = { x: 10, y: 10, width: 20, height: 20 } ;
|
76
|
+
var ret = this.v.set('frame', f);
|
77
|
+
var el = this.v.rootElement;
|
78
|
+
el.offsetLeft.shouldEqual(10) ;
|
79
|
+
el.offsetTop.shouldEqual(10) ;
|
80
|
+
el.offsetWidth.shouldEqual(20) ;
|
81
|
+
el.offsetHeight.shouldEqual(20) ;
|
82
|
+
},
|
83
|
+
|
84
|
+
"applying CSS class should not change frame": function() {
|
85
|
+
var f = this.v.get('frame') ;
|
86
|
+
this.v.addClassName('half') ;
|
87
|
+
SC.rectsEqual(this.v.get('frame'),f).shouldEqual(true) ;
|
88
|
+
},
|
89
|
+
|
90
|
+
"getting frame should cache the value": function() {
|
91
|
+
f = this.v.get('frame') ;
|
92
|
+
this.assertNotNull(this.v._frame) ;
|
93
|
+
},
|
94
|
+
|
95
|
+
setup: function() { this.v = SC.page.get('case2'); }
|
96
|
+
|
97
|
+
});
|
98
98
|
|
99
99
|
// CASE 3: Manual-layout View with padding & border
|
100
100
|
Test.context("CASE 3: Manual-layout of view with padding & border", {
|
101
101
|
|
102
102
|
"frame size should include padding and border": function() {
|
103
|
-
var f =
|
104
|
-
var el =
|
103
|
+
var f = v.get('frame') ;
|
104
|
+
var el = v.rootElement ;
|
105
105
|
|
106
|
-
|
107
|
-
Math.round(v.get('
|
106
|
+
//debugger ;
|
107
|
+
assertEqual(Math.round(v.get('styleWidth')), f.width-24, 'width') ;
|
108
|
+
assertEqual(Math.round(v.get('styleHeight')), f.height-24, 'height') ;
|
108
109
|
},
|
109
110
|
|
110
111
|
"changing frame size should subtract padding and border": function() {
|
@@ -155,11 +156,13 @@ Test.context("CASE 4: Absolute positioned Child view inside of view with overflo
|
|
155
156
|
Test.context("CASE 5: Non-positioned Child view inside of view with overflow = hidden", {
|
156
157
|
|
157
158
|
"frame origin should be 0,0 & size should match owner's innerFrame": function() {
|
159
|
+
SC.DEBUGIT = YES ;
|
158
160
|
var vf = this.v.get('innerFrame') ;
|
159
161
|
var f = this.v.child.get('frame') ;
|
160
162
|
f.x.shouldEqual(0) ;
|
161
163
|
f.y.shouldEqual(0) ;
|
162
164
|
f.width.shouldEqual(vf.width) ;
|
165
|
+
SC.DEBUGIT = NO ;
|
163
166
|
},
|
164
167
|
|
165
168
|
"nested frame origin should be 1,1 to account for border offset of parent": function() {
|
@@ -21,12 +21,6 @@ SC.Validator.Date = SC.Validator.extend(
|
|
21
21
|
*/
|
22
22
|
format: 'NNN d, yyyy h:mm:ss a',
|
23
23
|
|
24
|
-
/**
|
25
|
-
If true, dates will be converted to a natural language format if
|
26
|
-
possible such as "Tomorrow" or "Today".
|
27
|
-
*/
|
28
|
-
naturalLanguage: true,
|
29
|
-
|
30
24
|
/**
|
31
25
|
if we have a number, then convert to a date object.
|
32
26
|
*/
|
@@ -36,7 +30,7 @@ SC.Validator.Date = SC.Validator.extend(
|
|
36
30
|
date = new Date(object) ;
|
37
31
|
} else if (object instanceof Date) { date = object; }
|
38
32
|
|
39
|
-
if (date) object = date.format(this.get('format')
|
33
|
+
if (date) object = date.format(this.get('format')) ;
|
40
34
|
|
41
35
|
return object ;
|
42
36
|
},
|
@@ -1575,14 +1575,19 @@ SC.CollectionView = SC.View.extend(SC.CollectionViewDelegate,
|
|
1575
1575
|
|
1576
1576
|
// get the content. Bail if this cannot be used as an array.
|
1577
1577
|
var content = this.get('content') ;
|
1578
|
-
if (!content
|
1578
|
+
if (!content) return NO; // nothing to do
|
1579
|
+
|
1580
|
+
// determine the method to use
|
1581
|
+
var hasDestroyObject = $type(content.destroyObject) === T_FUNCTION ;
|
1582
|
+
var hasRemoveObject = $type(content.removeObject) === T_FUNCTION ;
|
1583
|
+
if (!hasDestroyObject && !hasRemoveObject) return NO; // nothing to do
|
1579
1584
|
|
1580
1585
|
// suspend property notifications and remove the objects...
|
1581
1586
|
if (content.beginPropertyChanges) content.beginPropertyChanges();
|
1582
1587
|
var idx = sel.get('length') ;
|
1583
1588
|
while(--idx >= 0) {
|
1584
1589
|
var item = sel.objectAt(idx) ;
|
1585
|
-
content.removeObject(item)
|
1590
|
+
(hasDestroyObject) ? content.destroyObject(item) : content.removeObject(item);
|
1586
1591
|
}
|
1587
1592
|
// begin notifying again...
|
1588
1593
|
if (content.endPropertyChanges) content.endPropertyChanges() ;
|
@@ -52,6 +52,15 @@ SC.ListItemView = SC.View.extend(SC.Control, SC.InlineEditorDelegate,
|
|
52
52
|
*/
|
53
53
|
hasContentBranch: NO,
|
54
54
|
|
55
|
+
/**
|
56
|
+
(displayDelegate) The name of the property used for the checkbox value.
|
57
|
+
|
58
|
+
The checkbox will only be visible if this key is not null.
|
59
|
+
|
60
|
+
@type {String}
|
61
|
+
*/
|
62
|
+
contentCheckboxKey: null,
|
63
|
+
|
55
64
|
/**
|
56
65
|
(displayDelegate) Property key to use for the icon url
|
57
66
|
|
@@ -105,6 +114,13 @@ SC.ListItemView = SC.View.extend(SC.Control, SC.InlineEditorDelegate,
|
|
105
114
|
var content = this.get('content') ;
|
106
115
|
var del = this.displayDelegate ;
|
107
116
|
|
117
|
+
// handle checkbox
|
118
|
+
var checkboxKey = this.getDelegateProperty(del, 'contentCheckboxKey') ;
|
119
|
+
if (checkboxKey) {
|
120
|
+
var checkboxValue = (content && content.get) ? content.get(checkboxKey) : false ;
|
121
|
+
html.push(this.renderCheckboxHtml(checkboxValue)) ;
|
122
|
+
}
|
123
|
+
|
108
124
|
// handle icon
|
109
125
|
if (this.getDelegateProperty(del, 'hasContentIcon')) {
|
110
126
|
var iconKey = this.getDelegateProperty(del,'contentIconKey') ;
|
@@ -147,12 +163,50 @@ SC.ListItemView = SC.View.extend(SC.Control, SC.InlineEditorDelegate,
|
|
147
163
|
}
|
148
164
|
},
|
149
165
|
|
166
|
+
/**
|
167
|
+
Generates the HTML string used to represent the checkbox for your list
|
168
|
+
item. Override this to return your own custom HTML. The default version
|
169
|
+
will use the HTML provided by SC.CheckboxView.
|
170
|
+
|
171
|
+
@returns {String}
|
172
|
+
@param state {String} the checkbox state. YES, NO, or SC.MIXED_STATE
|
173
|
+
*/
|
174
|
+
renderCheckboxHtml: function(state) {
|
175
|
+
var ret ;
|
176
|
+
|
177
|
+
// Note: this basically takes the HTML from the checkbox view and then
|
178
|
+
// inserts class names as necessary. This is cached to avoid using too
|
179
|
+
// much memory.
|
180
|
+
if (state === SC.MIXED_STATE) {
|
181
|
+
ret = SC.ListItemView._mixedCheckboxHtml ;
|
182
|
+
if (!ret) {
|
183
|
+
ret = SC.CheckboxView.prototype.emptyElement ;
|
184
|
+
ret = ret.replace('class="', 'class="mixed ') ;
|
185
|
+
SC.ListItemView._mixedCheckboxHtml = ret ;
|
186
|
+
}
|
187
|
+
} else if (state) {
|
188
|
+
ret = SC.ListItemView._selectedCheckboxHtml ;
|
189
|
+
if (!ret) {
|
190
|
+
ret = SC.CheckboxView.prototype.emptyElement ;
|
191
|
+
ret = ret.replace('class="', 'class="sel ') ;
|
192
|
+
SC.ListItemView._selectedCheckboxHtml = ret ;
|
193
|
+
}
|
194
|
+
} else {
|
195
|
+
ret = SC.ListItemView._normalCheckboxHtml ;
|
196
|
+
if (!ret) {
|
197
|
+
ret = SC.CheckboxView.prototype.emptyElement ;
|
198
|
+
SC.ListItemView._normalCheckboxHtml = ret ;
|
199
|
+
}
|
200
|
+
}
|
201
|
+
return ret ;
|
202
|
+
},
|
203
|
+
|
150
204
|
/**
|
151
205
|
renderIconHtml generates the html string used to represent the icon for
|
152
206
|
your list item. override this to return your own custom HTML
|
153
207
|
|
154
208
|
@returns {String}
|
155
|
-
@
|
209
|
+
@param icon {String} the icon property based on your view's contentIconKey
|
156
210
|
*/
|
157
211
|
renderIconHtml: function(icon){
|
158
212
|
var html = [];
|
@@ -177,7 +231,7 @@ SC.ListItemView = SC.View.extend(SC.Control, SC.InlineEditorDelegate,
|
|
177
231
|
for your list item. override this to return your own custom HTML
|
178
232
|
|
179
233
|
@returns {String}
|
180
|
-
@
|
234
|
+
@param label {String} the label property based on your view's
|
181
235
|
contentValueKey
|
182
236
|
*/
|
183
237
|
renderLabelHtml: function(label){
|
@@ -203,7 +257,7 @@ SC.ListItemView = SC.View.extend(SC.Control, SC.InlineEditorDelegate,
|
|
203
257
|
own custom HTML
|
204
258
|
|
205
259
|
@returns {String}
|
206
|
-
@
|
260
|
+
@param count {Integer} the label property based on your view's
|
207
261
|
contentValueKey
|
208
262
|
*/
|
209
263
|
renderCountHtml: function(count) {
|
@@ -245,6 +299,90 @@ SC.ListItemView = SC.View.extend(SC.Control, SC.InlineEditorDelegate,
|
|
245
299
|
return html.join('');
|
246
300
|
},
|
247
301
|
|
302
|
+
_isInsideElementWithClassName: function(className, evt) {
|
303
|
+
var el = Event.element(evt) ;
|
304
|
+
var rootElement = this.rootElement;
|
305
|
+
var ret = NO ;
|
306
|
+
while(!ret && el && (el !== rootElement)) {
|
307
|
+
if (Element.hasClassName(el, className)) ret = YES ;
|
308
|
+
el = el.parentNode ;
|
309
|
+
}
|
310
|
+
|
311
|
+
rootElement = el = null ; //avoid memory leaks
|
312
|
+
return ret ;
|
313
|
+
},
|
314
|
+
|
315
|
+
/** @private
|
316
|
+
mouseDown is handled only for clicks on the checkbox view or or action
|
317
|
+
button.
|
318
|
+
*/
|
319
|
+
mouseDown: function(evt) {
|
320
|
+
var del = this.displayDelegate ;
|
321
|
+
var checkboxKey = this.getDelegateProperty(del, 'contentCheckboxKey') ;
|
322
|
+
if (checkboxKey) {
|
323
|
+
if (this._isInsideElementWithClassName('sc-checkbox-view', evt)) {
|
324
|
+
this._addCheckboxActiveState() ;
|
325
|
+
this._isMouseDownOnCheckbox = YES ;
|
326
|
+
this._isMouseInsideCheckbox = YES ;
|
327
|
+
return true ;
|
328
|
+
}
|
329
|
+
}
|
330
|
+
|
331
|
+
return false ; // otherwise let normal handlers do it...
|
332
|
+
},
|
333
|
+
|
334
|
+
mouseUp: function(evt) {
|
335
|
+
var ret= NO ;
|
336
|
+
if (this._isMouseDownOnCheckbox) {
|
337
|
+
|
338
|
+
// update only if mouse inside on mouse up...
|
339
|
+
if (this._isMouseInsideCheckbox) {
|
340
|
+
var del = this.displayDelegate ;
|
341
|
+
var checkboxKey = this.getDelegateProperty(del, 'contentCheckboxKey') ;
|
342
|
+
var content = this.get('content') ;
|
343
|
+
if (content && content.get) {
|
344
|
+
var value = content.get(checkboxKey) ;
|
345
|
+
value = (value === SC.MIXED_STATE) ? YES : !value ;
|
346
|
+
content.set(checkboxKey, value) ;
|
347
|
+
}
|
348
|
+
}
|
349
|
+
|
350
|
+
this._removeCheckboxActiveState() ;
|
351
|
+
ret = YES ;
|
352
|
+
}
|
353
|
+
|
354
|
+
this._isMouseInsideCheckbox = this._isMouseDownOnCheckbox = NO ;
|
355
|
+
return ret ;
|
356
|
+
},
|
357
|
+
|
358
|
+
mouseOut: function(evt) {
|
359
|
+
if (this._isMouseDownOnCheckbox) {
|
360
|
+
this._removeCheckboxActiveState() ;
|
361
|
+
this._isMouseInsideCheckbox = NO ;
|
362
|
+
}
|
363
|
+
return NO ;
|
364
|
+
},
|
365
|
+
|
366
|
+
mouseOver: function(evt) {
|
367
|
+
if (this._isMouseDownOnCheckbox) {
|
368
|
+
this._addCheckboxActiveState() ;
|
369
|
+
this._isMouseInsideCheckbox = YES ;
|
370
|
+
}
|
371
|
+
return NO ;
|
372
|
+
},
|
373
|
+
|
374
|
+
_addCheckboxActiveState: function() {
|
375
|
+
var el = this.$sel('.sc-checkbox-view') ;
|
376
|
+
if (this.get('isEnabled')) Element.addClassName(el, 'active') ;
|
377
|
+
el = null ;
|
378
|
+
},
|
379
|
+
|
380
|
+
_removeCheckboxActiveState: function() {
|
381
|
+
var el = this.$sel('.sc-checkbox-view') ;
|
382
|
+
Element.removeClassName(el, 'active') ;
|
383
|
+
el = null ;
|
384
|
+
},
|
385
|
+
|
248
386
|
/**
|
249
387
|
Returns true if a click is on the label text itself to enable editing.
|
250
388
|
|
@@ -108,17 +108,14 @@ SC.SplitView = SC.View.extend(SC.DelegateSupport,
|
|
108
108
|
|
109
109
|
// thickness cannot be greater than the total of all the other views (
|
110
110
|
// except for the flexibleView) added together.
|
111
|
-
|
112
|
-
available =
|
113
|
-
|
114
|
-
|
115
|
-
var flexibleView = this.get('flexibleView')
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
available -= this.thicknessForView(currentView) ;
|
120
|
-
}
|
121
|
-
}
|
111
|
+
|
112
|
+
// available = total minus thickness of all views except "view" and
|
113
|
+
// "flexible view" that is the same as thickness 'view' plus thickness
|
114
|
+
// 'flexible view'
|
115
|
+
var flexibleView = this.get('flexibleView');
|
116
|
+
var available = this.thicknessForView(view) +
|
117
|
+
this.thicknessForView(flexibleView);
|
118
|
+
|
122
119
|
thickness = Math.min(thickness, available) ;
|
123
120
|
|
124
121
|
// cannot be less than 0
|
@@ -160,6 +157,7 @@ SC.SplitView = SC.View.extend(SC.DelegateSupport,
|
|
160
157
|
*/
|
161
158
|
computeFlexibleView: function() {
|
162
159
|
var flexibleView = this.get('flexibleView') ;
|
160
|
+
var originalFlexibleView = flexibleView ;
|
163
161
|
if (!flexibleView) {
|
164
162
|
var views = this.get('childNodes') ;
|
165
163
|
flexibleView = views[Math.ceil(views.length/2)] ;
|
@@ -170,6 +168,11 @@ SC.SplitView = SC.View.extend(SC.DelegateSupport,
|
|
170
168
|
flexibleView = flexibleView.get('nextSibling') ;
|
171
169
|
}
|
172
170
|
|
171
|
+
// save new flexible view if we had to fix it up.
|
172
|
+
if (originalFlexibleView !== flexibleView) {
|
173
|
+
this.set('flexibleView', flexibleView);
|
174
|
+
}
|
175
|
+
|
173
176
|
return flexibleView;
|
174
177
|
},
|
175
178
|
|
@@ -711,7 +711,7 @@ SC.View = SC.Responder.extend(SC.PathModule, SC.DelegateSupport,
|
|
711
711
|
this.viewFrameDidChange() ;
|
712
712
|
}
|
713
713
|
ret = this.getStyle(key) ;
|
714
|
-
ret = (ret === 'auto') ? null :
|
714
|
+
ret = (ret === 'auto') ? null : Math.round(parseFloat(ret)) ;
|
715
715
|
|
716
716
|
// all other properties just pass through (and do not change frame)
|
717
717
|
} else {
|
@@ -960,7 +960,8 @@ SC.View = SC.Responder.extend(SC.PathModule, SC.DelegateSupport,
|
|
960
960
|
// impact the offset
|
961
961
|
if (SC.Platform.Firefox) {
|
962
962
|
var parent = el.offsetParent ;
|
963
|
-
|
963
|
+
var overflow = (parent) ? Element.getStyle(parent, 'overflow') : 'visible' ;
|
964
|
+
if (overflow && overflow !== 'visible') {
|
964
965
|
var left = parseInt(Element.getStyle(parent, 'borderLeftWidth'),0) || 0 ;
|
965
966
|
var top = parseInt(Element.getStyle(parent, 'borderTopWidth'),0) || 0 ;
|
966
967
|
f.x += left; f.y += top ;
|
@@ -1087,7 +1088,8 @@ SC.View = SC.Responder.extend(SC.PathModule, SC.DelegateSupport,
|
|
1087
1088
|
// impact the offset
|
1088
1089
|
if (SC.Platform.Firefox) {
|
1089
1090
|
var parent = el.offsetParent ;
|
1090
|
-
|
1091
|
+
var overflow = (parent) ? Element.getStyle(parent, 'overflow') : 'visible' ;
|
1092
|
+
if (overflow && overflow !== 'visible') {
|
1091
1093
|
var left = parseInt(Element.getStyle(parent, 'borderLeftWidth'),0) || 0 ;
|
1092
1094
|
var top = parseInt(Element.getStyle(parent, 'borderTopWidth'),0) || 0 ;
|
1093
1095
|
f.x += left; f.y += top ;
|
@@ -1321,7 +1323,7 @@ SC.View = SC.Responder.extend(SC.PathModule, SC.DelegateSupport,
|
|
1321
1323
|
prect.x -= scrollFrame.x ;
|
1322
1324
|
prect.y -= scrollFrame.y ;
|
1323
1325
|
}
|
1324
|
-
|
1326
|
+
|
1325
1327
|
// blend with current frame
|
1326
1328
|
f = SC.intersectRects(f, prect) ;
|
1327
1329
|
} else {
|
@@ -2026,7 +2028,7 @@ SC.View.mixin({
|
|
2026
2028
|
if (el && el._configured) return SC.View.findViewForElement(el);
|
2027
2029
|
|
2028
2030
|
// Now that we have found an element, instantiate the view.
|
2029
|
-
var args =
|
2031
|
+
var args = SC.$A(arguments) ; args[0] = { rootElement: el } ;
|
2030
2032
|
if (r) vStart = new Date().getTime();
|
2031
2033
|
var ret = new this(args,this) ; // create instance.
|
2032
2034
|
if (r) SC.idt.v_t += (new Date().getTime()) - vStart;
|
@@ -2039,7 +2041,7 @@ SC.View.mixin({
|
|
2039
2041
|
|
2040
2042
|
// create in the view work is like viewFor but with 'null' for el
|
2041
2043
|
create: function(configs) {
|
2042
|
-
var args =
|
2044
|
+
var args = SC.$A(arguments) ;
|
2043
2045
|
args.unshift(null) ;
|
2044
2046
|
return this.viewFor.apply(this,args) ;
|
2045
2047
|
},
|
@@ -2106,6 +2108,7 @@ SC.View.mixin({
|
|
2106
2108
|
break;
|
2107
2109
|
case SC.window.rootElement:
|
2108
2110
|
parentView = SC.window ;
|
2111
|
+
break;
|
2109
2112
|
default:
|
2110
2113
|
node = node.parentNode ;
|
2111
2114
|
}
|
@@ -8,7 +8,7 @@ module SproutCore
|
|
8
8
|
|
9
9
|
# Whenever you build an HTML file for a SproutCore client, an instance of
|
10
10
|
# this class is created to actually process and build the HTML using
|
11
|
-
# Erubus. If you want to add more methods to use in your HTML files, just
|
11
|
+
# Erubus or Haml. If you want to add more methods to use in your HTML files, just
|
12
12
|
# include them in HtmlContext.
|
13
13
|
#
|
14
14
|
class HtmlContext
|
@@ -67,7 +67,15 @@ module SproutCore
|
|
67
67
|
# Finally, render the layout. This should produce the final output to
|
68
68
|
# return
|
69
69
|
input = File.read(@layout_path)
|
70
|
-
|
70
|
+
|
71
|
+
# render using either erb or haml
|
72
|
+
case File.extname(@layout_path)
|
73
|
+
when /\.rhtml$/, /\.html.erb$/
|
74
|
+
return eval(Erubis::Eruby.new.convert(input))
|
75
|
+
when /\.haml$/, /\.html.haml$/
|
76
|
+
require 'haml'
|
77
|
+
return Haml::Engine.new(input).to_html(self)
|
78
|
+
end
|
71
79
|
end
|
72
80
|
|
73
81
|
# render a single entry
|
@@ -80,7 +88,15 @@ module SproutCore
|
|
80
88
|
|
81
89
|
# render. Result goes into @content_for_resources
|
82
90
|
input = File.read(@entry.source_path)
|
83
|
-
|
91
|
+
|
92
|
+
# render using either erb or haml
|
93
|
+
case File.extname(@entry.source_path)
|
94
|
+
when /\.rhtml$/, /\.html.erb$/
|
95
|
+
@content_for_resources += eval(Erubis::Eruby.new.convert(input))
|
96
|
+
when /\.haml$/, /\.html.haml$/
|
97
|
+
require 'haml'
|
98
|
+
@content_for_resources += Haml::Engine.new(input).to_html(self)
|
99
|
+
end
|
84
100
|
|
85
101
|
@filename =nil
|
86
102
|
@entry = nil
|
@@ -59,9 +59,9 @@ module SproutCore
|
|
59
59
|
#
|
60
60
|
# The default will rewrite calls to static_url().
|
61
61
|
def rewrite_inline_code(line, filename)
|
62
|
-
line.gsub(/static_url\([\'\"](
|
62
|
+
line.gsub(/static_url\([\'\"](.+?)[\'\"]\)/) do | rsrc |
|
63
63
|
entry = bundle.find_resource_entry($1, :language => language)
|
64
|
-
static_url(entry.nil? ? '' : entry.
|
64
|
+
static_url(entry.nil? ? '' : entry.cacheable_url)
|
65
65
|
end
|
66
66
|
end
|
67
67
|
|
@@ -205,7 +205,13 @@ module SproutCore
|
|
205
205
|
end
|
206
206
|
end
|
207
207
|
|
208
|
-
def self.build_fixture(entry, bundle)
|
208
|
+
def self.build_fixture(entry, bundle)
|
209
|
+
build_javascript(entry, bundle)
|
210
|
+
end
|
211
|
+
|
212
|
+
def self.build_debug(entry, bundle)
|
213
|
+
build_javascript(entry, bundle)
|
214
|
+
end
|
209
215
|
|
210
216
|
end
|
211
217
|
|
data/lib/sproutcore/bundle.rb
CHANGED
@@ -66,6 +66,14 @@ module SproutCore
|
|
66
66
|
# bundle_name:relative_path/to/client. Default:
|
67
67
|
# sproutcore:lib/index.html
|
68
68
|
#
|
69
|
+
# autobuild?: True if the bundle should be included in default builds.
|
70
|
+
# If set to false, then you must ASK for the bundle specifically to be
|
71
|
+
# built.
|
72
|
+
#
|
73
|
+
# use_digest_token: If true, the unique tokens adds to files will be
|
74
|
+
# MD5 digests instead of timestamps. This will ensure uniqueness when
|
75
|
+
# building on multiple machines.
|
76
|
+
#
|
69
77
|
class Bundle
|
70
78
|
|
71
79
|
LONG_LANGUAGE_MAP = { :english => :en, :french => :fr, :german => :de, :japanese => :ja, :spanish => :es, :italian => :it }
|
@@ -85,6 +93,7 @@ module SproutCore
|
|
85
93
|
attr_reader :source_root, :build_root, :url_root, :index_root
|
86
94
|
attr_reader :build_mode, :layout
|
87
95
|
attr_reader :make_resources_relative
|
96
|
+
attr_reader :use_digest_tokens
|
88
97
|
|
89
98
|
def library_root
|
90
99
|
@library_root ||= library.nil? ? nil : library.root_path
|
@@ -116,6 +125,12 @@ module SproutCore
|
|
116
125
|
library.minify_build_modes.include?(build_mode)
|
117
126
|
end
|
118
127
|
|
128
|
+
# ==== Returns
|
129
|
+
# true if this bundle should be auto-built.
|
130
|
+
def autobuild?
|
131
|
+
@autobuild.nil? ? true : @autobuild
|
132
|
+
end
|
133
|
+
|
119
134
|
# ==== Returns
|
120
135
|
# The computed path to the layout rhtml.
|
121
136
|
def layout_path
|
@@ -215,6 +230,12 @@ module SproutCore
|
|
215
230
|
# layout: Path to the layout resource. This should be of the form
|
216
231
|
@layout = opts[:layout] || 'sproutcore:lib/index.rhtml'
|
217
232
|
|
233
|
+
# autobuild?: Determines if you should autobuild...
|
234
|
+
@autobuild = opts[:autobuild]
|
235
|
+
@autobuild = true if @autobuild.nil?
|
236
|
+
|
237
|
+
@use_digest_tokens = opts[:use_digest_tokens] || (@build_mode == :production)
|
238
|
+
|
218
239
|
reload!
|
219
240
|
end
|
220
241
|
|