sproutcore 0.9.14 → 0.9.15
Sign up to get free protection for your applications and to get access to all the features.
- 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
@@ -5,30 +5,47 @@
|
|
5
5
|
|
6
6
|
// These are basic enhancements to the string class used throughout
|
7
7
|
// SproutCore.
|
8
|
-
// capitalize a string.
|
9
|
-
Object.extend(String.prototype,{
|
10
|
-
|
11
|
-
// Capitalize a string.
|
12
|
-
//
|
13
|
-
// mode: optional. 'each' - capitalize each word. the default.
|
14
|
-
// 'first' - capitalize the first word only.
|
15
|
-
|
16
|
-
capitalize: function(mode) {
|
17
|
-
var words = (mode == 'first') ? this : this.split(' ') ;
|
18
|
-
words = words.map(function(word) {
|
19
|
-
if (word.length == 0) return word ;
|
20
|
-
return word.charAt(0).toUpperCase() + word.substring(1) ;
|
21
|
-
}) ;
|
22
|
-
return words.join(' ') ;
|
23
|
-
},
|
24
8
|
|
9
|
+
SC.STRING_TITLEIZE_REGEXP = (/([\s|\-|\_|\n])([^\s|\-|\_|\n]?)/g);
|
10
|
+
|
11
|
+
/**
|
12
|
+
@namespace
|
13
|
+
|
14
|
+
SproutCore implements a variety of enhancements to the built-in String
|
15
|
+
object that make it easy to perform common substitutions and conversions.
|
16
|
+
|
17
|
+
Most of the utility methods defined here mirror those found in Prototype
|
18
|
+
1.6.
|
19
|
+
|
20
|
+
@since SproutCore 1.0
|
21
|
+
*/
|
22
|
+
SC.String = {
|
23
|
+
|
25
24
|
// Interpolate string. looks for %@ or %@1; to control the order of params.
|
26
|
-
|
27
|
-
|
25
|
+
/**
|
26
|
+
Apply formatting options to the string. This will look for occurrences
|
27
|
+
of %@ in your string and substitute them with the arguments you pass into
|
28
|
+
this method. If you want to control the specific order of replacement,
|
29
|
+
you can add a number after the key as well to indicate which argument
|
30
|
+
you want to insert.
|
31
|
+
|
32
|
+
Ordered insertions are most useful when building loc strings where values
|
33
|
+
you need to insert may appear in different orders.
|
34
|
+
|
35
|
+
h3. Examples
|
28
36
|
|
37
|
+
{{{
|
38
|
+
"Hello %@ %@".fmt('John', 'Doe') => "Hello John Doe"
|
39
|
+
"Hello %@2, %@1".fmt('John', 'Doe') => "Hello Doe, John"
|
40
|
+
}}}
|
41
|
+
|
42
|
+
@param args {Object...} optional arguments
|
43
|
+
@returns {String} formatted string
|
44
|
+
*/
|
45
|
+
fmt: function() {
|
29
46
|
// first, replace any ORDERED replacements.
|
30
47
|
var str = this.gsub(/%@([0-9]+)/, function(m) {
|
31
|
-
return (
|
48
|
+
return (arguments[parseInt(m[1],0)-1] || '').toString();
|
32
49
|
}) ;
|
33
50
|
|
34
51
|
// now, replace any remaining %@ items. Use this indexOf() method b/c
|
@@ -36,13 +53,14 @@ Object.extend(String.prototype,{
|
|
36
53
|
var ret = [] ;
|
37
54
|
var idx = -1 ;
|
38
55
|
var loc = 0 ;
|
56
|
+
var argIdx = 0;
|
39
57
|
while((idx = str.indexOf("%@",loc)) >= 0) {
|
40
58
|
// slice off initial part of string and push into ret. update loc.
|
41
59
|
ret.push(str.slice(loc,idx)) ;
|
42
60
|
loc = idx + 2 ; // 2 to skip '%@'.
|
43
61
|
|
44
62
|
// add in replacement.
|
45
|
-
var value =
|
63
|
+
var value = arguments[argIdx++] ;
|
46
64
|
if (value && value.toString) value = value.toString() ;
|
47
65
|
ret.push(value) ;
|
48
66
|
}
|
@@ -56,8 +74,15 @@ Object.extend(String.prototype,{
|
|
56
74
|
return (ret.length > 1) ? ret.join('') : ret[0] ;
|
57
75
|
},
|
58
76
|
|
59
|
-
|
60
|
-
|
77
|
+
/**
|
78
|
+
Localizes the string. This will look up the reciever string as a key
|
79
|
+
in the current Strings hash. If the key matches, the loc'd value will be
|
80
|
+
used. The resulting string will also be passed through fmt() to insert
|
81
|
+
any variables.
|
82
|
+
|
83
|
+
@param args {Object...} optional arguments to interpolate also
|
84
|
+
@returns {String} the localized and formatted string.
|
85
|
+
*/
|
61
86
|
loc: function() {
|
62
87
|
// NB: This could be implemented as a wrapper to locWithDefault() but
|
63
88
|
// it would add some overhead to deal with the arguments and adds stack
|
@@ -66,60 +91,139 @@ Object.extend(String.prototype,{
|
|
66
91
|
var kit = String[String.currentLanguage()];
|
67
92
|
var str = kit[this] ;
|
68
93
|
if (!str) str = String.English[this] || this ;
|
69
|
-
return str.
|
94
|
+
return str.fmt.apply(str,arguments) ;
|
70
95
|
},
|
71
|
-
|
72
|
-
|
73
|
-
|
96
|
+
|
97
|
+
/**
|
98
|
+
Works just like loc() except that it will return the passed default
|
99
|
+
string if a matching key is not found.
|
100
|
+
|
101
|
+
@param def {String} the default to return
|
102
|
+
@param args {Object...} optional formatting arguments
|
103
|
+
@returns {String} localized and formatted string
|
104
|
+
*/
|
74
105
|
locWithDefault: function(def) {
|
75
106
|
var kit = String[String.currentLanguage()];
|
76
107
|
var str = kit[this] ;
|
77
108
|
if (!str) str = String.English[this] || def ;
|
78
|
-
var args =
|
109
|
+
var args = SC.$A(arguments) ;
|
79
110
|
args.shift() ; // escape def.
|
80
|
-
return str.
|
111
|
+
return str.fmt.apply(str, args) ;
|
112
|
+
},
|
113
|
+
|
114
|
+
/**
|
115
|
+
Capitalizes a string.
|
116
|
+
@return {String} capitalized string
|
117
|
+
*/
|
118
|
+
capitalize: function() {
|
119
|
+
return this.charAt(0).toUpperCase() + this.substring(1) ;
|
120
|
+
},
|
121
|
+
|
122
|
+
/**
|
123
|
+
Capitalized every word in the string, separated by spaces or dashes.
|
124
|
+
@return {String} titleized string.
|
125
|
+
*/
|
126
|
+
titleize: function() {
|
127
|
+
return this.replace(SC.STRING_TITLEIZE_REGEXP,
|
128
|
+
function(str,separater,character) {
|
129
|
+
return (character) ? (' ' + character.toUpperCase()) : ' ';
|
130
|
+
}).capitalize() ;
|
131
|
+
},
|
132
|
+
|
133
|
+
/**
|
134
|
+
Camelizes a string. This will take any words separated by spaces, dashes
|
135
|
+
or underscores and convert them into camelCase.
|
136
|
+
|
137
|
+
h3. Examples
|
138
|
+
|
139
|
+
{{{
|
140
|
+
"my favorite items".camelize() => "myFavoriteItems"
|
141
|
+
"css-class-name".camelize() => "cssClassName"
|
142
|
+
"action_name".camelize() => "actionName"
|
143
|
+
}}}
|
144
|
+
|
145
|
+
@returns {String} camelized string
|
146
|
+
*/
|
147
|
+
camelize: function() {
|
148
|
+
var parts = this.split('-'), len = parts.length;
|
149
|
+
if (len == 1) return parts[0];
|
150
|
+
|
151
|
+
var camelized = this.charAt(0) == '-'
|
152
|
+
? parts[0].charAt(0).toUpperCase() + parts[0].substring(1)
|
153
|
+
: parts[0];
|
154
|
+
|
155
|
+
for (var i = 1; i < len; i++)
|
156
|
+
camelized += parts[i].charAt(0).toUpperCase() + parts[i].substring(1);
|
157
|
+
|
158
|
+
return camelized;
|
81
159
|
},
|
160
|
+
|
82
161
|
|
162
|
+
/**
|
163
|
+
Converts the string into a class name. This method will camelize your
|
164
|
+
string and then capitalize the first letter.
|
165
|
+
*/
|
83
166
|
classify: function() {
|
84
167
|
return this.camelize().capitalize() ;
|
85
168
|
},
|
86
169
|
|
170
|
+
/**
|
171
|
+
Converts a camelized string into all lower case separated by underscores.
|
172
|
+
|
173
|
+
@returns {String} the decamelized string.
|
174
|
+
*/
|
87
175
|
decamelize: function() {
|
88
176
|
return this.replace(/([a-z])([A-Z])/g,'$1_$2').toLowerCase();
|
89
177
|
},
|
90
178
|
|
179
|
+
/**
|
180
|
+
Converts a camelized string or a string with spaces or underscores into
|
181
|
+
a string with components separated by dashes.
|
182
|
+
|
183
|
+
@returns {String} the dasherized string.
|
184
|
+
*/
|
91
185
|
dasherize: function() {
|
92
186
|
return this.decamelize().replace(/[ _]/g,'-') ;
|
93
187
|
},
|
94
188
|
|
189
|
+
/**
|
190
|
+
Converts a camelized string or a string with dashes or underscores into
|
191
|
+
a string with components separated by spaces.
|
192
|
+
|
193
|
+
@returns {String} the humanized string.
|
194
|
+
*/
|
95
195
|
humanize: function() {
|
96
196
|
return this.decamelize().replace(/[-_]/g,' ') ;
|
97
197
|
},
|
98
198
|
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
}
|
105
|
-
|
106
|
-
|
107
|
-
},
|
108
|
-
|
109
|
-
trim: function ()
|
110
|
-
{
|
199
|
+
/**
|
200
|
+
Removes any extra whitespace from the edges of the strings.
|
201
|
+
|
202
|
+
This method is also aliased as strip().
|
203
|
+
|
204
|
+
@returns {String} the trimmed string
|
205
|
+
*/
|
206
|
+
trim: function () {
|
111
207
|
return this.replace(/^\s+|\s+$/g,"");
|
112
208
|
},
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
209
|
+
|
210
|
+
/**
|
211
|
+
Explodes a string into an array of characters.
|
212
|
+
|
213
|
+
@returns {Array}
|
214
|
+
*/
|
215
|
+
toArray: function() {
|
216
|
+
return this.split('');
|
117
217
|
}
|
118
218
|
|
119
|
-
}
|
219
|
+
} ;
|
220
|
+
|
221
|
+
// Deprecated, longer version of this method.
|
222
|
+
SC.String.format = SC.String.fmt;
|
223
|
+
SC.String.strip = SC.String.trim; // convenience alias.
|
120
224
|
|
121
|
-
//
|
122
|
-
String.prototype.
|
225
|
+
// Apply SC.String mixin to built-in String object
|
226
|
+
SC.mixin(String.prototype, SC.String) ;
|
123
227
|
|
124
228
|
// Add strings for various languages to this collection. String.loc()
|
125
229
|
// method will try to localize the string passed using the current language.
|
@@ -6,10 +6,75 @@
|
|
6
6
|
// These are helpful utility functions for calculating range and rect values
|
7
7
|
|
8
8
|
|
9
|
-
|
9
|
+
SC.mixin(
|
10
10
|
/** @scope SC */
|
11
11
|
{
|
12
12
|
|
13
|
+
_downloadFrames: 0, // count of download frames inserted into document
|
14
|
+
|
15
|
+
/**
|
16
|
+
Starts a download of the file at the named path.
|
17
|
+
|
18
|
+
Use this method when you want to cause a file to be downloaded to a users
|
19
|
+
desktop instead of having it display in the web browser. Note that your
|
20
|
+
server must return a header indicating that the file is intended for
|
21
|
+
download also.
|
22
|
+
*/
|
23
|
+
download: function(path) {
|
24
|
+
var tempDLIFrame=document.createElement('iframe');
|
25
|
+
var frameId = 'DownloadFrame_' + this._downloadFrames;
|
26
|
+
tempDLIFrame.setAttribute('id',frameId);
|
27
|
+
tempDLIFrame.style.border='10px';
|
28
|
+
tempDLIFrame.style.width='0px';
|
29
|
+
tempDLIFrame.style.height='0px';
|
30
|
+
tempDLIFrame.style.position='absolute';
|
31
|
+
tempDLIFrame.style.top='-10000px';
|
32
|
+
tempDLIFrame.style.left='-10000px';
|
33
|
+
// Don't set the iFrame content yet if this is Safari
|
34
|
+
if (!(SC.isSafari())) {
|
35
|
+
tempDLIFrame.setAttribute('src',path);
|
36
|
+
}
|
37
|
+
document.getElementsByTagName('body')[0].appendChild(tempDLIFrame);
|
38
|
+
if (SC.isSafari()) {
|
39
|
+
tempDLIFrame.setAttribute('src',path);
|
40
|
+
}
|
41
|
+
this._downloadFrames = this._downloadFrames + 1;
|
42
|
+
if (!(SC.isSafari())) {
|
43
|
+
var r = function() {
|
44
|
+
document.body.removeChild(document.getElementById(frameId));
|
45
|
+
frameId = null;
|
46
|
+
} ;
|
47
|
+
var t = r.invokeLater(null, 2000);
|
48
|
+
}
|
49
|
+
//remove possible IE7 leak
|
50
|
+
tempDLIFrame = null;
|
51
|
+
},
|
52
|
+
|
53
|
+
/**
|
54
|
+
Takes a URL of any type and normalizes it into a fully qualified URL with
|
55
|
+
hostname. For example:
|
56
|
+
|
57
|
+
{{{
|
58
|
+
"some/path" => "http://localhost:4020/some/path"
|
59
|
+
"/some/path" => "http://localhost:4020/some/path"
|
60
|
+
"http://localhost:4020/some/path" => "http://localhost:4020/some/path"
|
61
|
+
}}}
|
62
|
+
|
63
|
+
@param url {String} the URL
|
64
|
+
@returns {String} the normalized URL
|
65
|
+
*/
|
66
|
+
normalizeURL: function(url) {
|
67
|
+
if (url.slice(0,1) == '/') {
|
68
|
+
url = window.location.protocol + '//' + window.location.host + url ;
|
69
|
+
} else if ((url.slice(0,5) == 'http:') || (url.slice(0,6) == 'https:')) {
|
70
|
+
// no change
|
71
|
+
} else {
|
72
|
+
url = window.location.href + '/' + url ;
|
73
|
+
}
|
74
|
+
return url ;
|
75
|
+
},
|
76
|
+
|
77
|
+
|
13
78
|
/** Return the left edge of the frame */
|
14
79
|
minX: function(frame) {
|
15
80
|
return frame.x;
|
@@ -142,9 +207,17 @@ Object.extend(SC,
|
|
142
207
|
|
143
208
|
// add up all the offsets for the element.
|
144
209
|
var element = el ;
|
210
|
+
var isFirefox3 = SC.Platform.Firefox >= 3 ;
|
145
211
|
while (element) {
|
146
|
-
valueT += (element.offsetTop || 0)
|
147
|
-
|
212
|
+
valueT += (element.offsetTop || 0);
|
213
|
+
if (!isFirefox3 || (element !== el)) {
|
214
|
+
valueT += (element.clientTop || 0);
|
215
|
+
}
|
216
|
+
|
217
|
+
valueL += (element.offsetLeft || 0);
|
218
|
+
if (!isFirefox3 || (element !== el)) {
|
219
|
+
valueL += (element.clientLeft || 0);
|
220
|
+
}
|
148
221
|
|
149
222
|
// bizarely for FireFox if your offsetParent has a border, then it can
|
150
223
|
// impact the offset.
|
@@ -158,6 +231,14 @@ Object.extend(SC,
|
|
158
231
|
}
|
159
232
|
valueL += left; valueT += top ;
|
160
233
|
}
|
234
|
+
|
235
|
+
// In FireFox 3 -- the offsetTop/offsetLeft subtracts the clientTop/
|
236
|
+
// clientLeft of the offset parent.
|
237
|
+
var offsetParent = element.offsetParent ;
|
238
|
+
if ((SC.Platform.Firefox >= 3) && offsetParent) {
|
239
|
+
valueT -= offsetParent.clientTop ;
|
240
|
+
valueL -= offsetParent.clientLeft;
|
241
|
+
}
|
161
242
|
}
|
162
243
|
|
163
244
|
// Safari fix
|
@@ -32,6 +32,7 @@ view_helper :collection_view do
|
|
32
32
|
property :can_delete_content
|
33
33
|
|
34
34
|
property :content_icon_key
|
35
|
+
property :content_checkbox_key
|
35
36
|
|
36
37
|
# Unless the developer passes something specific, automatically enable
|
37
38
|
# has_content_icon if either icon property is specified.
|
@@ -0,0 +1,28 @@
|
|
1
|
+
//@license
|
2
|
+
// ==========================================================================
|
3
|
+
// SproutCore -- JavaScript Application Framework
|
4
|
+
// copyright 2006-2008, Sprout Systems, Inc. and contributors.
|
5
|
+
//
|
6
|
+
// Permission is hereby granted, free of charge, to any person obtaining a
|
7
|
+
// copy of this software and associated documentation files (the "Software"),
|
8
|
+
// to deal in the Software without restriction, including without limitation
|
9
|
+
// the rights to use, copy, modify, merge, publish, distribute, sublicense,
|
10
|
+
// and/or sell copies of the Software, and to permit persons to whom the
|
11
|
+
// Software is furnished to do so, subject to the following conditions:
|
12
|
+
//
|
13
|
+
// The above copyright notice and this permission notice shall be included in
|
14
|
+
// all copies or substantial portions of the Software.
|
15
|
+
//
|
16
|
+
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
17
|
+
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
18
|
+
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
19
|
+
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
20
|
+
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
21
|
+
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
|
22
|
+
// DEALINGS IN THE SOFTWARE.
|
23
|
+
//
|
24
|
+
// For more information about SproutCore, visit http://www.sproutcore.com
|
25
|
+
//
|
26
|
+
//
|
27
|
+
// ==========================================================================
|
28
|
+
//@license
|