sproutcore 0.9.14 → 0.9.15

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. data/History.txt +43 -0
  2. data/Manifest.txt +12 -3
  3. data/bin/sc-build +19 -3
  4. data/bin/sc-install +5 -0
  5. data/bin/sc-remove +5 -0
  6. data/bin/sc-update +5 -0
  7. data/frameworks/prototype/prototype.js +267 -230
  8. data/frameworks/sproutcore/HISTORY +281 -135
  9. data/frameworks/sproutcore/controllers/array.js +133 -22
  10. data/frameworks/sproutcore/controllers/collection.js +4 -5
  11. data/frameworks/sproutcore/controllers/object.js +8 -2
  12. data/frameworks/sproutcore/core.js +361 -159
  13. data/frameworks/sproutcore/{foundation → debug}/unittest.js +3 -3
  14. data/frameworks/sproutcore/english.lproj/detect-browser +1 -1
  15. data/frameworks/sproutcore/english.lproj/theme.css +2 -2
  16. data/frameworks/sproutcore/foundation/application.js +6 -1
  17. data/frameworks/sproutcore/foundation/benchmark.js +37 -11
  18. data/frameworks/sproutcore/foundation/date.js +1 -1
  19. data/frameworks/sproutcore/foundation/enumerator.js +105 -0
  20. data/frameworks/sproutcore/foundation/object.js +19 -20
  21. data/frameworks/sproutcore/foundation/responder.js +1 -1
  22. data/frameworks/sproutcore/foundation/set.js +164 -57
  23. data/frameworks/sproutcore/foundation/string.js +151 -47
  24. data/frameworks/sproutcore/foundation/utils.js +84 -3
  25. data/frameworks/sproutcore/lib/collection_view.rb +1 -0
  26. data/frameworks/sproutcore/license.js +28 -0
  27. data/frameworks/sproutcore/mixins/array.js +73 -209
  28. data/frameworks/sproutcore/mixins/delegate_support.js +1 -1
  29. data/frameworks/sproutcore/mixins/enumerable.js +1006 -0
  30. data/frameworks/sproutcore/mixins/observable.js +153 -84
  31. data/frameworks/sproutcore/mixins/selection_support.js +13 -1
  32. data/frameworks/sproutcore/models/record.js +74 -27
  33. data/frameworks/sproutcore/models/store.js +7 -3
  34. data/frameworks/sproutcore/server/rails_server.js +82 -0
  35. data/frameworks/sproutcore/server/rest_server.js +178 -0
  36. data/frameworks/sproutcore/{foundation → server}/server.js +101 -48
  37. data/frameworks/sproutcore/tests/core/guidFor.rhtml +114 -0
  38. data/frameworks/sproutcore/tests/foundation/array.rhtml +6 -7
  39. data/frameworks/sproutcore/tests/foundation/set.rhtml +254 -0
  40. data/frameworks/sproutcore/tests/mixins/enumerable.rhtml +421 -0
  41. data/frameworks/sproutcore/tests/mixins/observable.rhtml +127 -0
  42. data/frameworks/sproutcore/tests/models/model.rhtml +23 -22
  43. data/frameworks/sproutcore/tests/views/collection/incremental_rendering.rhtml +2 -2
  44. data/frameworks/sproutcore/tests/views/view/clippingFrame.rhtml +112 -109
  45. data/frameworks/sproutcore/tests/views/view/frame.rhtml +91 -88
  46. data/frameworks/sproutcore/validators/date.js +1 -7
  47. data/frameworks/sproutcore/views/collection/collection.js +7 -2
  48. data/frameworks/sproutcore/views/list_item.js +141 -3
  49. data/frameworks/sproutcore/views/split.js +14 -11
  50. data/frameworks/sproutcore/views/view.js +9 -6
  51. data/lib/sproutcore/build_tools/html_builder.rb +19 -3
  52. data/lib/sproutcore/build_tools/resource_builder.rb +9 -3
  53. data/lib/sproutcore/bundle.rb +21 -0
  54. data/lib/sproutcore/bundle_manifest.rb +64 -20
  55. data/lib/sproutcore/helpers/capture_helper.rb +2 -2
  56. data/lib/sproutcore/library.rb +33 -9
  57. data/lib/sproutcore/merb/bundle_controller.rb +16 -5
  58. data/lib/sproutcore/version.rb +1 -1
  59. data/lib/sproutcore/view_helpers.rb +1 -1
  60. data/{sc-config.rb → sc-config} +5 -2
  61. 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
- format: function() {
27
- var args = $A(arguments) ;
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 (args[parseInt(m[1],0)-1] || '').toString();
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 = args.shift() ;
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
- // localize a string. Also interpolates any items you pass just like
60
- // format().
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.format.apply(str,arguments) ;
94
+ return str.fmt.apply(str,arguments) ;
70
95
  },
71
-
72
- // this works just like loc except it will return the first argument
73
- // as a default if the matching value is not found.
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 = $A(arguments) ;
109
+ var args = SC.$A(arguments) ;
79
110
  args.shift() ; // escape def.
80
- return str.format.apply(str, args) ;
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
- toHref: function() {
100
- if (this.match(/.+@.+\...+/)) {
101
- return 'mailto:' + this;
102
- } else if (this.indexOf('http://') != 0 && this.indexOf('https://') !=0 && this.match(/[^.]+\.[^.]+/)) {
103
- return 'http://' + this;
104
- } else {
105
- return this;
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
- strip: function()
115
- {
116
- return this.trim();
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
- // Shorter alias of the format function.
122
- String.prototype.fmt = String.prototype.format ;
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
- Object.extend(SC,
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) + (element.clientTop || 0);
147
- valueL += (element.offsetLeft || 0) + (element.clientLeft || 0);
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