sproutcore 0.9.0 → 0.9.1
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/Manifest.txt +42 -29
- data/README.txt +1 -1
- data/Rakefile +5 -0
- data/app_generators/sproutcore/sproutcore_generator.rb +4 -4
- data/app_generators/sproutcore/templates/sc-config.rb +72 -0
- data/bin/sc-build +2 -0
- data/clients/sc_docs/controllers/docs.js +1 -0
- data/clients/sc_docs/english.lproj/body.rhtml +5 -0
- data/clients/sc_docs/views/doc_frame.js +1 -1
- data/clients/sc_test_runner/controllers/runner.js +2 -2
- data/clients/sc_test_runner/english.lproj/body.rhtml +5 -0
- data/clients/sc_test_runner/main.js +12 -12
- data/clients/sc_test_runner/models/test.js +3 -0
- data/clients/sc_test_runner/views/test_label.js +1 -1
- data/config/hoe.rb +2 -0
- data/frameworks/sproutcore/controllers/array.js +132 -125
- data/frameworks/sproutcore/drag/drag.js +5 -2
- data/frameworks/sproutcore/english.lproj/buttons.css +64 -64
- data/frameworks/sproutcore/english.lproj/collections.css +82 -0
- data/frameworks/sproutcore/english.lproj/images/buttons-sprite.png +0 -0
- data/frameworks/sproutcore/english.lproj/images/sproutcore-logo.png +0 -0
- data/frameworks/sproutcore/english.lproj/images/sticky-note.png +0 -0
- data/frameworks/sproutcore/english.lproj/menu.css +1 -1
- data/frameworks/sproutcore/english.lproj/theme.css +13 -4
- data/frameworks/sproutcore/foundation/array.js +24 -2
- data/frameworks/sproutcore/foundation/benchmark.js +12 -5
- data/frameworks/sproutcore/foundation/observable.js +62 -1
- data/frameworks/sproutcore/foundation/utils.js +16 -0
- data/frameworks/sproutcore/tests/views/label_item.rhtml +21 -0
- data/frameworks/sproutcore/tests/views/list.rhtml +21 -0
- data/frameworks/sproutcore/tests/views/scroll.rhtml +21 -0
- data/frameworks/sproutcore/views/collection.js +401 -73
- data/frameworks/sproutcore/views/collection/collection_item.js +36 -0
- data/frameworks/sproutcore/views/collection/grid.js +149 -0
- data/frameworks/sproutcore/views/collection/image_cell.js +154 -0
- data/frameworks/sproutcore/views/collection/list.js +115 -0
- data/frameworks/sproutcore/views/collection/text_cell.js +128 -0
- data/frameworks/sproutcore/views/image.js +1 -1
- data/frameworks/sproutcore/views/label.js +6 -2
- data/frameworks/sproutcore/views/scroll.js +34 -0
- data/frameworks/sproutcore/views/view.js +12 -4
- data/generators/client/client_generator.rb +3 -11
- data/generators/client/templates/english.lproj/body.css +75 -0
- data/generators/client/templates/english.lproj/body.rhtml +17 -2
- data/generators/model/templates/fixture.js +32 -0
- data/lib/sproutcore/build_tools/html_builder.rb +29 -11
- data/lib/sproutcore/build_tools/resource_builder.rb +1 -1
- data/lib/sproutcore/bundle.rb +19 -7
- data/lib/sproutcore/library.rb +39 -21
- data/lib/sproutcore/merb/bundle_controller.rb +3 -8
- data/lib/sproutcore/version.rb +1 -1
- data/lib/sproutcore/view_helpers.rb +7 -5
- data/lib/sproutcore/view_helpers/core_views.rb +11 -3
- data/sc-config.rb +7 -0
- data/tasks/deployment.rake +15 -2
- metadata +44 -31
- data/app_generators/sproutcore/templates/environment.yml +0 -4
- data/environment.yml +0 -9
@@ -0,0 +1,128 @@
|
|
1
|
+
// ==========================================================================
|
2
|
+
// SC.TextCellView
|
3
|
+
// ==========================================================================
|
4
|
+
|
5
|
+
require('views/collection/collection_item') ;
|
6
|
+
|
7
|
+
/** @class
|
8
|
+
|
9
|
+
A Text Cell can display some textual or HTML content based on a content
|
10
|
+
object. Unlike a label view, a text cell relies on an owner view (usually
|
11
|
+
a collection view) to handle all of its event management and many of its
|
12
|
+
drawing properties and functions.
|
13
|
+
|
14
|
+
@extends SC.View
|
15
|
+
@author AuthorName
|
16
|
+
@version 0.1
|
17
|
+
*/
|
18
|
+
SC.TextCellView = SC.View.extend(SC.CollectionItem,
|
19
|
+
/** @scope SC.TextCellView.prototype */ {
|
20
|
+
|
21
|
+
emptyElement: '<div class="text-cell collection-item"></div>',
|
22
|
+
|
23
|
+
/**
|
24
|
+
The content object this text item view will display.
|
25
|
+
*/
|
26
|
+
content: null,
|
27
|
+
|
28
|
+
/**
|
29
|
+
The owner view of this cell. The TextCell relies on this
|
30
|
+
view to provide many of its behavioral defaults and for
|
31
|
+
event handling.
|
32
|
+
*/
|
33
|
+
owner: null,
|
34
|
+
|
35
|
+
/**
|
36
|
+
If true, value will be escaped to avoid scripting attacks.
|
37
|
+
|
38
|
+
This is a default value that can be overridden by the
|
39
|
+
settings on the owner view.
|
40
|
+
*/
|
41
|
+
escapeHtml: true,
|
42
|
+
|
43
|
+
/**
|
44
|
+
If true, then the value will be localized.
|
45
|
+
|
46
|
+
This is a default default that can be overidden by the
|
47
|
+
settings in the owner view.
|
48
|
+
*/
|
49
|
+
localize: false,
|
50
|
+
|
51
|
+
/**
|
52
|
+
Set this to a validator or to a function and the value
|
53
|
+
will be passed through it before being set.
|
54
|
+
|
55
|
+
This is a default default that can be overidden by the
|
56
|
+
settings in the owner view.
|
57
|
+
*/
|
58
|
+
formatter: null,
|
59
|
+
|
60
|
+
displayProperty: null,
|
61
|
+
|
62
|
+
// invoked whenever the content object changes.
|
63
|
+
_contentObserver: function() {
|
64
|
+
var content = this.get('content') ;
|
65
|
+
if (this._content == content) return ;
|
66
|
+
var f = this._boundValueDidChange() ;
|
67
|
+
|
68
|
+
// stop observing the old display property, if there is one.
|
69
|
+
if (this._content && this._displayProperty) {
|
70
|
+
this._content.removeObserver(this._displayProperty, f) ;
|
71
|
+
}
|
72
|
+
|
73
|
+
// start observing the new display property, if there is one
|
74
|
+
this._displayProperty = this._getDefault('displayProperty') ;
|
75
|
+
this._content = content ;
|
76
|
+
if (this._content && this._displayProperty) {
|
77
|
+
this._content.addObserver(this._displayProperty, f) ;
|
78
|
+
}
|
79
|
+
|
80
|
+
// notify value did change
|
81
|
+
this._valueDidChange() ;
|
82
|
+
}.observes('content'),
|
83
|
+
|
84
|
+
/**
|
85
|
+
@private
|
86
|
+
|
87
|
+
Invoked whenever the monitored value on the content object
|
88
|
+
changes.
|
89
|
+
|
90
|
+
The value processed is either the displayProperty, if set, or
|
91
|
+
it is the content object itself.
|
92
|
+
*/
|
93
|
+
_valueDidChange: function() {
|
94
|
+
var content = this.get('content') ;
|
95
|
+
var value = (content && this._displayProperty) ? content.get(this._displayProperty) : content;
|
96
|
+
var owner = this.get('owner') ;
|
97
|
+
|
98
|
+
// prepare the value...
|
99
|
+
|
100
|
+
// 1. apply the formatter
|
101
|
+
var formatter = this._getDefault('formatter') ;
|
102
|
+
if (formatter) {
|
103
|
+
var formattedValue = ($type(formatter) == T_FUNCTION) ? formatter(value, this) : formatter.fieldValueForObject(value, this) ;
|
104
|
+
if (formattedValue != null) value = formattedValue ;
|
105
|
+
}
|
106
|
+
|
107
|
+
// 2. If the returned value is not a string, convert it.
|
108
|
+
if (($type(value) != T_NULL) && value.toString) value = value.toString() ;
|
109
|
+
|
110
|
+
// 3. Localize
|
111
|
+
if (value && this._getDefault('localize')) value = value.loc() ;
|
112
|
+
|
113
|
+
// 4. Escape HTML
|
114
|
+
if (value && this._getDefault('escapeHtml')) value = value.escapeHTML() ;
|
115
|
+
|
116
|
+
this.set('asHTML', value || '') ;
|
117
|
+
},
|
118
|
+
|
119
|
+
_boundValueDidChange: function() {
|
120
|
+
return this._boundValueDidChange = this._boundValueDidChange || this._valueDidChange.bind(this);
|
121
|
+
},
|
122
|
+
|
123
|
+
// Retrieves the default value from the owner or locally.
|
124
|
+
_getDefault: function(keyName) {
|
125
|
+
var ret = (this.owner) ? this.owner.get(keyName) : null ;
|
126
|
+
return (ret != null) ? ret : this.get(keyName) ;
|
127
|
+
}
|
128
|
+
}) ;
|
@@ -19,10 +19,14 @@ SC.LabelView = SC.View.extend({
|
|
19
19
|
isEditing: false,
|
20
20
|
|
21
21
|
|
22
|
-
|
22
|
+
/**
|
23
|
+
set to true to have any markup in the content escaped.
|
24
|
+
*/
|
23
25
|
escapeHTML: true,
|
24
26
|
|
25
|
-
|
27
|
+
/**
|
28
|
+
set to true to have the value you set automatically localized.
|
29
|
+
*/
|
26
30
|
localize: false,
|
27
31
|
|
28
32
|
|
@@ -0,0 +1,34 @@
|
|
1
|
+
// ==========================================================================
|
2
|
+
// Sproutcore.ScrollView
|
3
|
+
// ==========================================================================
|
4
|
+
|
5
|
+
require('views/container') ;
|
6
|
+
|
7
|
+
/** @class
|
8
|
+
|
9
|
+
The scroll view is used throughout SproutCore anytime you need to display
|
10
|
+
content that can be scrolled. Although you can make any div scrollable in
|
11
|
+
HTML using CSS, SC.ScrollView provides a number of additional advantages
|
12
|
+
including support for incremental rendering, auto-scrolling during a
|
13
|
+
drag operations and support for custom scroll bars.
|
14
|
+
|
15
|
+
Scroll views are generally included automatically if you use the built-in
|
16
|
+
view helpers in SproutCore. Depending on the views you are writing, you may
|
17
|
+
want to use scroll views yourself as well. The following sections describe
|
18
|
+
how you can use the scroll view to support incremental rendering and auto-
|
19
|
+
scrolling dragging.
|
20
|
+
|
21
|
+
h3. Using Scroll Views for Incremental Rendering
|
22
|
+
|
23
|
+
Coming Soon...
|
24
|
+
|
25
|
+
@extends SC.View
|
26
|
+
@author Charles Jolley
|
27
|
+
@version 1.0
|
28
|
+
*/
|
29
|
+
SC.ScrollView = SC.View.extend(
|
30
|
+
/** @scope SC.ScrollView.prototype */ {
|
31
|
+
|
32
|
+
emptyElement: '<div class="sc-scroll-view"></div>'
|
33
|
+
|
34
|
+
}) ;
|
@@ -466,10 +466,8 @@ SC.View = SC.Responder.extend(SC.PathModule,
|
|
466
466
|
// if you cached the frame, you can use this to clear that cache so that it
|
467
467
|
// will now track with the frame in the document.
|
468
468
|
flushFrameCache: function() {
|
469
|
-
|
470
|
-
|
471
|
-
this._frameCached = false;
|
472
|
-
}
|
469
|
+
this._frame = null ;
|
470
|
+
this._frameCached = false;
|
473
471
|
},
|
474
472
|
|
475
473
|
// This property returns a DOM ELEMENT that is the offset parent for
|
@@ -1344,6 +1342,14 @@ SC.View.mixin({
|
|
1344
1342
|
return this.viewFor.apply(this,args) ;
|
1345
1343
|
},
|
1346
1344
|
|
1345
|
+
// extend works just like a normal extend except that we need to delete the cached empty
|
1346
|
+
// element.
|
1347
|
+
extend: function(configs) {
|
1348
|
+
var ret = SC.Object.extend.apply(this, arguments) ;
|
1349
|
+
ret.prototype._cachedEmptyElement = null ;
|
1350
|
+
return ret ;
|
1351
|
+
},
|
1352
|
+
|
1347
1353
|
// define your view as an outlet.
|
1348
1354
|
outletFor: function(path) {
|
1349
1355
|
var view = this ;
|
@@ -1387,3 +1393,5 @@ SC._ViewCreator = document.createElement('div') ;
|
|
1387
1393
|
|
1388
1394
|
// This div can be used to hold elements you don't want on the page right now.
|
1389
1395
|
SC.NodeCache = document.createElement('div') ;
|
1396
|
+
|
1397
|
+
console.log('SC.View = %@'.fmt(SC.View)) ;
|
@@ -34,20 +34,12 @@ EOS
|
|
34
34
|
end
|
35
35
|
|
36
36
|
def add_options!(opts)
|
37
|
-
|
38
|
-
# opts.separator 'Options:'
|
39
|
-
# For each option below, place the default
|
40
|
-
# at the top of the file next to "default_options"
|
41
|
-
# opts.on("-a", "--author=\"Your Name\"", String,
|
42
|
-
# "Some comment about this option",
|
43
|
-
# "Default: none") { |options[:author]| }
|
44
|
-
# opts.on("-v", "--version", "Show the #{File.basename($0)} version number and quit.")
|
37
|
+
opts.on('-l', "--library=LIBRARY_ROOT", String, "Specify an alternate library root other than current working directory", "Default: working directory") { |options[:library_root] | }
|
45
38
|
end
|
46
39
|
|
47
40
|
def extract_options
|
48
41
|
# for each option, extract it into a local variable (and create an "attr_reader :author" at the top)
|
49
|
-
|
50
|
-
# raw instance variable value.
|
51
|
-
# @author = options[:author]
|
42
|
+
@destination_root = File.expand_path(options[:library_root]) unless options[:library_root].nil?
|
52
43
|
end
|
44
|
+
|
53
45
|
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
/* Default CSS for welcome page. Delete this styling and replace it with your own. */
|
2
|
+
|
3
|
+
.sc-welcome {
|
4
|
+
position: absolute ;
|
5
|
+
top: 0px;
|
6
|
+
left: 0px;
|
7
|
+
right: 0px;
|
8
|
+
bottom: 0px;
|
9
|
+
background-color: white ;
|
10
|
+
}
|
11
|
+
|
12
|
+
.sc-welcome img.logo {
|
13
|
+
position: absolute ;
|
14
|
+
bottom: 80px;
|
15
|
+
left: 50%;
|
16
|
+
margin-left: -20px;
|
17
|
+
}
|
18
|
+
|
19
|
+
/* @group Message */
|
20
|
+
|
21
|
+
|
22
|
+
|
23
|
+
.sc-welcome .message {
|
24
|
+
max-width: 800px;
|
25
|
+
margin-left: auto ;
|
26
|
+
margin-right: auto;
|
27
|
+
margin-top: 100px;
|
28
|
+
position: relative;
|
29
|
+
}
|
30
|
+
|
31
|
+
.sc-welcome h1 {
|
32
|
+
border: none ;
|
33
|
+
padding: 0;
|
34
|
+
margin: 0;
|
35
|
+
letter-spacing: -3px;
|
36
|
+
font: normal 6.4em "Helvetica Neue", Arial, Helvetica, Geneva, sans-serif;
|
37
|
+
}
|
38
|
+
|
39
|
+
.sc-welcome h3 {
|
40
|
+
margin: 8px 12px;
|
41
|
+
padding: 0;
|
42
|
+
font: 1.5em "Helvetica Neue", Arial, Helvetica, Geneva, sans-serif;
|
43
|
+
color: #808080;
|
44
|
+
}
|
45
|
+
|
46
|
+
/* @end */
|
47
|
+
|
48
|
+
/* @group Sticky Note */
|
49
|
+
|
50
|
+
.sc-welcome .sticky-note {
|
51
|
+
position: absolute ;
|
52
|
+
right: 0;
|
53
|
+
top: -70px;
|
54
|
+
width: 320px;
|
55
|
+
height: 300px;
|
56
|
+
padding: 60px;
|
57
|
+
padding-right: 20px;
|
58
|
+
background: url(/static/sproutcore/_src/english.lproj/images/sticky-note.png) no-repeat center center;
|
59
|
+
font: 1.3em "Comic Sans MS", "Comic Sans", Arial, Helvetica, Geneva, sans-serif;
|
60
|
+
color: #5f4700;
|
61
|
+
}
|
62
|
+
|
63
|
+
.sc-welcome .sticky-note p {
|
64
|
+
font-weight: bold ;
|
65
|
+
}
|
66
|
+
|
67
|
+
.sc-welcome .sticky-note ul {
|
68
|
+
padding: 0 10px ;
|
69
|
+
}
|
70
|
+
|
71
|
+
.sc-welcome .sticky-note li {
|
72
|
+
margin: 8px 0 ;
|
73
|
+
}
|
74
|
+
|
75
|
+
/* @end */
|
@@ -1,3 +1,18 @@
|
|
1
1
|
<% content_for('body') do %>
|
2
|
-
<
|
3
|
-
|
2
|
+
<div class="sc-welcome">
|
3
|
+
<img class="logo" src="<%= static_url('images/sproutcore-logo') %>" />
|
4
|
+
<div class="message">
|
5
|
+
<h1>Welcome!</h1>
|
6
|
+
<h3>You are now running SproutCore.</h3>
|
7
|
+
<div class="sticky-note">
|
8
|
+
<p>Things to do:</p>
|
9
|
+
<ul>
|
10
|
+
<li>Add a model:<br/>sc-gen model contacts/my_model</li>
|
11
|
+
<li>Add a controller:<br/>sc-gen controller contacts/my_controller</li>
|
12
|
+
<li>Edit english.lproj/body.rhtml</li>
|
13
|
+
<li>Build for deployment:<br />sc-build</li>
|
14
|
+
</ul>
|
15
|
+
</div>
|
16
|
+
</div>
|
17
|
+
</div>
|
18
|
+
<% end %>
|
@@ -7,5 +7,37 @@ require('core') ;
|
|
7
7
|
<%= client_namespace %>.FIXTURES = <%= client_namespace %>.FIXTURES.concat([
|
8
8
|
|
9
9
|
// TODO: Add your data fixtures here.
|
10
|
+
// All fixture records must have a unique guid and a type matching the
|
11
|
+
// name of your contact. See the example below.
|
12
|
+
|
13
|
+
// { guid: 1,
|
14
|
+
// type: 'Contact',
|
15
|
+
// firstName: "Michael",
|
16
|
+
// lastName: "Scott"
|
17
|
+
// },
|
18
|
+
//
|
19
|
+
// { guid: 2,
|
20
|
+
// type: 'Contact',
|
21
|
+
// firstName: "Dwight",
|
22
|
+
// lastName: "Schrute"
|
23
|
+
// },
|
24
|
+
//
|
25
|
+
// { guid: 3,
|
26
|
+
// type: 'Contact',
|
27
|
+
// firstName: "Jim",
|
28
|
+
// lastName: "Halpert"
|
29
|
+
// },
|
30
|
+
//
|
31
|
+
// { guid: 4,
|
32
|
+
// type: 'Contact',
|
33
|
+
// firstName: "Pam",
|
34
|
+
// lastName: "Beesly"
|
35
|
+
// },
|
36
|
+
//
|
37
|
+
// { guid: 5,
|
38
|
+
// type: 'Contact',
|
39
|
+
// firstName: "Ryan",
|
40
|
+
// lastName: "Howard"
|
41
|
+
// }
|
10
42
|
|
11
43
|
]);
|
@@ -18,14 +18,30 @@ module SproutCore
|
|
18
18
|
include SproutCore::Helpers::StaticHelper
|
19
19
|
include SproutCore::ViewHelpers
|
20
20
|
|
21
|
-
attr_reader :entry, :bundle, :
|
21
|
+
attr_reader :entry, :bundle, :entries, :filename, :language, :library
|
22
22
|
|
23
|
-
def initialize(entry, bundle)
|
23
|
+
def initialize(entry, bundle, deep=true)
|
24
24
|
@entry = nil
|
25
25
|
@language = entry.language
|
26
|
-
@filenames = entry.composite.nil? ? [entry.filename] : entry.composite
|
27
26
|
@bundle = bundle
|
28
27
|
@library = bundle.library
|
28
|
+
|
29
|
+
# Find all of the entries that need to be included. If deep is true, the include
|
30
|
+
# required bundles. Example composite entries to include their members.
|
31
|
+
if deep
|
32
|
+
@entries = bundle.all_required_bundles.map do |cur_bundle|
|
33
|
+
ret = (cur_bundle == bundle) ? [entry] : cur_bundle.entries_for(:html, :language => language, :hidden => :include)
|
34
|
+
ret.map do |e|
|
35
|
+
e.composite? ? e.composite.map { |c| cur_bundle.entry_for(c, :hidden => :include) } : [e]
|
36
|
+
end
|
37
|
+
end
|
38
|
+
@entries = @entries.flatten.compact.uniq
|
39
|
+
else
|
40
|
+
@entries = entry.composite? ? entry.composite.map { |c| x.entry_for(c) } : [entry]
|
41
|
+
end
|
42
|
+
|
43
|
+
# Clean out any composites we might have collected. They have already been expanded.
|
44
|
+
@entries.reject! { |entry| entry.composite? }
|
29
45
|
end
|
30
46
|
|
31
47
|
# Actually builds the HTML file from the entry (actually from any composite entries)
|
@@ -35,7 +51,7 @@ module SproutCore
|
|
35
51
|
|
36
52
|
# Render each filename. By default, the output goes to the resources string
|
37
53
|
@content_for_resources = ''
|
38
|
-
|
54
|
+
entries.each { |fn| _render_one(fn) }
|
39
55
|
|
40
56
|
# Finally, render the layout. This should produce the final output to return
|
41
57
|
input = File.read(@layout_path)
|
@@ -43,9 +59,9 @@ module SproutCore
|
|
43
59
|
end
|
44
60
|
|
45
61
|
# render a single entry
|
46
|
-
def _render_one(
|
47
|
-
@
|
48
|
-
@
|
62
|
+
def _render_one(entry)
|
63
|
+
@entry = entry
|
64
|
+
@filename = @entry.filename
|
49
65
|
|
50
66
|
# avoid double render of layout path
|
51
67
|
return if @entry.source_path == @layout_path
|
@@ -68,11 +84,13 @@ module SproutCore
|
|
68
84
|
|
69
85
|
end
|
70
86
|
|
71
|
-
|
72
|
-
|
87
|
+
# Builds an html file for the specified entry. If deep is true, then this will also
|
88
|
+
# find all of the html entries for any required bundles and include them in the built
|
89
|
+
# html file.
|
90
|
+
def self.build_html(entry, bundle, deep=true)
|
91
|
+
context = HtmlContext.new(entry, bundle, deep)
|
73
92
|
output = context.build
|
74
93
|
|
75
|
-
puts "saving: #{entry.filename} to #{entry.build_path}: size: #{output.size}"
|
76
94
|
FileUtils.mkdir_p(File.dirname(entry.build_path))
|
77
95
|
f = File.open(entry.build_path, 'w')
|
78
96
|
f.write(output)
|
@@ -82,7 +100,7 @@ module SproutCore
|
|
82
100
|
|
83
101
|
# Building a test is just like building a single page except that we do not include
|
84
102
|
# all the other html templates in the project
|
85
|
-
def self.build_test(entry, bundle); build_html(entry, bundle); end
|
103
|
+
def self.build_test(entry, bundle); build_html(entry, bundle, false); end
|
86
104
|
|
87
105
|
end
|
88
106
|
end
|