sproutcore 0.9.1 → 0.9.2

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.
Files changed (208) hide show
  1. data/History.txt +233 -0
  2. data/Manifest.txt +67 -34
  3. data/bin/sc-build +12 -1
  4. data/bin/sc-gen +1 -1
  5. data/bin/sproutcore +14 -0
  6. data/clients/sc_docs/controllers/docs.js +38 -8
  7. data/clients/sc_docs/english.lproj/body.css +80 -127
  8. data/clients/sc_docs/english.lproj/body.rhtml +43 -23
  9. data/clients/sc_docs/english.lproj/no_docs.rhtml +2 -1
  10. data/clients/sc_docs/english.lproj/tabs.rhtml +16 -0
  11. data/clients/sc_docs/main.js +14 -9
  12. data/clients/sc_docs/models/doc.js +1 -1
  13. data/clients/sc_docs/tests/controllers/docs.rhtml +1 -2
  14. data/clients/sc_docs/tests/models/doc.rhtml +1 -2
  15. data/clients/sc_docs/tests/views/doc_frame.rhtml +1 -2
  16. data/clients/sc_docs/tests/views/doc_label_view.rhtml +1 -2
  17. data/clients/sc_docs/views/doc_frame.js +1 -1
  18. data/clients/sc_test_runner/controllers/runner.js +31 -8
  19. data/clients/sc_test_runner/english.lproj/body.css +62 -122
  20. data/clients/sc_test_runner/english.lproj/body.rhtml +62 -26
  21. data/clients/sc_test_runner/main.js +1 -6
  22. data/clients/sc_test_runner/models/test.js +14 -1
  23. data/clients/sc_test_runner/views/runner_frame.js +4 -2
  24. data/clients/view_builder/builders/builder.js +339 -0
  25. data/clients/view_builder/builders/button.js +81 -0
  26. data/clients/view_builder/controllers/document.js +21 -0
  27. data/clients/view_builder/core.js +19 -0
  28. data/clients/view_builder/english.lproj/body.css +77 -0
  29. data/clients/view_builder/english.lproj/body.rhtml +41 -0
  30. data/clients/{sc_docs → view_builder}/english.lproj/controls.css +0 -0
  31. data/clients/view_builder/english.lproj/strings.js +14 -0
  32. data/clients/view_builder/main.js +38 -0
  33. data/clients/view_builder/tests/controllers/document.rhtml +20 -0
  34. data/clients/view_builder/tests/views/builder.rhtml +20 -0
  35. data/clients/view_builder/views/builder.js +23 -0
  36. data/frameworks/prototype/prototype.js +1 -1
  37. data/frameworks/sproutcore/Core.js +32 -7
  38. data/frameworks/sproutcore/README +1 -1
  39. data/frameworks/sproutcore/animation/animation.js +411 -0
  40. data/frameworks/sproutcore/controllers/array.js +17 -9
  41. data/frameworks/sproutcore/controllers/collection.js +9 -110
  42. data/frameworks/sproutcore/controllers/controller.js +1 -1
  43. data/frameworks/sproutcore/controllers/object.js +2 -1
  44. data/frameworks/sproutcore/drag/drag.js +267 -56
  45. data/frameworks/sproutcore/drag/drag_data_source.js +24 -16
  46. data/frameworks/sproutcore/drag/drag_source.js +53 -42
  47. data/frameworks/sproutcore/drag/drop_target.js +2 -2
  48. data/frameworks/sproutcore/english.lproj/buttons.css +337 -236
  49. data/frameworks/sproutcore/english.lproj/core.css +115 -0
  50. data/frameworks/sproutcore/english.lproj/icons.css +227 -0
  51. data/{clients/sc_docs → frameworks/sproutcore}/english.lproj/images/indicator.gif +0 -0
  52. data/frameworks/sproutcore/english.lproj/images/sc-theme-sprite.png +0 -0
  53. data/frameworks/sproutcore/english.lproj/images/sc-theme-ysprite.png +0 -0
  54. data/frameworks/sproutcore/english.lproj/images/shared-icons.png +0 -0
  55. data/frameworks/sproutcore/english.lproj/menu.css +1 -1
  56. data/frameworks/sproutcore/english.lproj/strings.js +1 -1
  57. data/frameworks/sproutcore/english.lproj/theme.css +405 -31
  58. data/frameworks/sproutcore/foundation/application.js +15 -11
  59. data/frameworks/sproutcore/foundation/benchmark.js +1 -1
  60. data/frameworks/sproutcore/foundation/binding.js +2 -2
  61. data/frameworks/sproutcore/foundation/date.js +1 -1
  62. data/frameworks/sproutcore/foundation/error.js +1 -1
  63. data/frameworks/sproutcore/foundation/input_manager.js +32 -21
  64. data/frameworks/sproutcore/foundation/mock.js +1 -1
  65. data/frameworks/sproutcore/foundation/node_descriptor.js +9 -6
  66. data/frameworks/sproutcore/foundation/object.js +249 -177
  67. data/frameworks/sproutcore/foundation/page.js +5 -2
  68. data/frameworks/sproutcore/foundation/path_module.js +11 -10
  69. data/frameworks/sproutcore/foundation/responder.js +5 -2
  70. data/frameworks/sproutcore/foundation/routes.js +17 -13
  71. data/frameworks/sproutcore/foundation/run_loop.js +249 -11
  72. data/frameworks/sproutcore/foundation/server.js +1 -1
  73. data/frameworks/sproutcore/foundation/set.js +3 -3
  74. data/frameworks/sproutcore/foundation/string.js +5 -3
  75. data/frameworks/sproutcore/foundation/timer.js +371 -0
  76. data/frameworks/sproutcore/foundation/undo_manager.js +1 -1
  77. data/frameworks/sproutcore/foundation/unittest.js +3 -3
  78. data/frameworks/sproutcore/foundation/utils.js +161 -2
  79. data/frameworks/sproutcore/globals/panels.js +1 -1
  80. data/frameworks/sproutcore/globals/popups.js +4 -3
  81. data/frameworks/sproutcore/globals/window.js +44 -4
  82. data/frameworks/sproutcore/lib/button_views.rb +328 -0
  83. data/frameworks/sproutcore/lib/collection_view.rb +80 -0
  84. data/frameworks/sproutcore/lib/core_views.rb +281 -0
  85. data/frameworks/sproutcore/lib/form_views.rb +253 -0
  86. data/frameworks/sproutcore/lib/index.rhtml +2 -0
  87. data/frameworks/sproutcore/lib/menu_views.rb +88 -0
  88. data/frameworks/sproutcore/{foundation → mixins}/array.js +60 -29
  89. data/frameworks/sproutcore/mixins/control.js +265 -0
  90. data/frameworks/sproutcore/mixins/delegate_support.js +66 -0
  91. data/frameworks/sproutcore/{foundation → mixins}/observable.js +176 -6
  92. data/frameworks/sproutcore/mixins/scrollable.js +245 -0
  93. data/frameworks/sproutcore/mixins/selection_support.js +148 -0
  94. data/frameworks/sproutcore/mixins/validatable.js +152 -0
  95. data/frameworks/sproutcore/models/collection.js +5 -5
  96. data/frameworks/sproutcore/models/record.js +1 -1
  97. data/frameworks/sproutcore/models/store.js +1 -1
  98. data/frameworks/sproutcore/panes/dialog.js +1 -1
  99. data/frameworks/sproutcore/panes/manager.js +1 -1
  100. data/frameworks/sproutcore/panes/menu.js +1 -1
  101. data/frameworks/sproutcore/panes/overlay.js +2 -2
  102. data/frameworks/sproutcore/panes/panel.js +1 -1
  103. data/frameworks/sproutcore/panes/picker.js +1 -1
  104. data/frameworks/sproutcore/tests/controllers/array.rhtml +44 -4
  105. data/frameworks/sproutcore/tests/foundation/timer/invalidate.rhtml +33 -0
  106. data/frameworks/sproutcore/tests/foundation/timer/invokeLater.rhtml +145 -0
  107. data/frameworks/sproutcore/tests/foundation/timer/isPaused.rhtml +70 -0
  108. data/frameworks/sproutcore/tests/foundation/timer/schedule.rhtml +145 -0
  109. data/frameworks/sproutcore/tests/views/{scroll.rhtml → checkbox.rhtml} +3 -3
  110. data/frameworks/sproutcore/tests/views/{collection.rhtml → collection/base.rhtml} +33 -32
  111. data/frameworks/sproutcore/tests/views/collection/incremental_rendering.rhtml +260 -0
  112. data/frameworks/sproutcore/tests/views/image_cell.rhtml +19 -0
  113. data/frameworks/sproutcore/tests/views/label_item.rhtml +2 -4
  114. data/frameworks/sproutcore/tests/views/list.rhtml +2 -3
  115. data/frameworks/sproutcore/tests/views/list_item.rhtml +20 -0
  116. data/frameworks/sproutcore/tests/views/slider.rhtml +20 -0
  117. data/frameworks/sproutcore/tests/views/text_cell.rhtml +19 -0
  118. data/frameworks/sproutcore/tests/views/view/clippingFrame.rhtml +395 -0
  119. data/frameworks/sproutcore/tests/views/view/frame.rhtml +353 -0
  120. data/frameworks/sproutcore/tests/views/view/innerFrame.rhtml +347 -0
  121. data/frameworks/sproutcore/tests/views/view/isVisibleInWindow.rhtml +148 -0
  122. data/frameworks/sproutcore/tests/views/view/scrollFrame.rhtml +468 -0
  123. data/frameworks/sproutcore/validators/credit_card.js +33 -13
  124. data/frameworks/sproutcore/validators/date.js +26 -6
  125. data/frameworks/sproutcore/validators/email.js +21 -3
  126. data/frameworks/sproutcore/validators/not_empty.js +11 -1
  127. data/frameworks/sproutcore/validators/number.js +18 -4
  128. data/frameworks/sproutcore/validators/password.js +12 -1
  129. data/frameworks/sproutcore/validators/validator.js +204 -194
  130. data/frameworks/sproutcore/views/{button.js → button/button.js} +96 -94
  131. data/frameworks/sproutcore/views/button/checkbox.js +29 -0
  132. data/frameworks/sproutcore/views/button/disclosure.js +42 -0
  133. data/frameworks/sproutcore/views/button/radio.js +29 -0
  134. data/frameworks/sproutcore/views/{collection.js → collection/collection.js} +1373 -1024
  135. data/frameworks/sproutcore/views/collection/grid.js +124 -46
  136. data/frameworks/sproutcore/views/collection/image_cell.js +17 -46
  137. data/frameworks/sproutcore/views/collection/list.js +45 -35
  138. data/frameworks/sproutcore/views/collection/source_list.js +386 -0
  139. data/frameworks/sproutcore/views/collection/table.js +118 -0
  140. data/frameworks/sproutcore/views/container.js +7 -2
  141. data/frameworks/sproutcore/views/error_explanation.js +23 -10
  142. data/frameworks/sproutcore/views/{checkbox_field.js → field/checkbox_field.js} +16 -6
  143. data/frameworks/sproutcore/views/field/field.js +219 -0
  144. data/frameworks/sproutcore/views/{radio_field.js → field/radio_field.js} +27 -12
  145. data/frameworks/sproutcore/views/{select_field.js → field/select_field.js} +116 -90
  146. data/frameworks/sproutcore/views/{text_field.js → field/text_field.js} +57 -8
  147. data/frameworks/sproutcore/views/{textarea_field.js → field/textarea_field.js} +13 -3
  148. data/frameworks/sproutcore/views/filter_button.js +2 -2
  149. data/frameworks/sproutcore/views/form.js +3 -3
  150. data/frameworks/sproutcore/views/image.js +128 -21
  151. data/frameworks/sproutcore/views/inline_text_editor.js +1 -1
  152. data/frameworks/sproutcore/views/label.js +149 -92
  153. data/frameworks/sproutcore/views/list_item.js +225 -0
  154. data/frameworks/sproutcore/views/menu_item.js +10 -4
  155. data/frameworks/sproutcore/views/pagination.js +11 -4
  156. data/frameworks/sproutcore/views/popup_button.js +25 -21
  157. data/frameworks/sproutcore/views/popup_menu.js +10 -4
  158. data/frameworks/sproutcore/views/progress.js +29 -16
  159. data/frameworks/sproutcore/views/radio_group.js +1 -1
  160. data/frameworks/sproutcore/views/scroll.js +60 -20
  161. data/frameworks/sproutcore/views/segmented.js +1 -1
  162. data/frameworks/sproutcore/views/slider.js +132 -0
  163. data/frameworks/sproutcore/views/source_list_group.js +130 -0
  164. data/frameworks/sproutcore/views/spinner.js +1 -1
  165. data/frameworks/sproutcore/views/split.js +292 -0
  166. data/frameworks/sproutcore/views/split_divider.js +109 -0
  167. data/frameworks/sproutcore/views/tab.js +1 -1
  168. data/frameworks/sproutcore/views/toolbar.js +1 -1
  169. data/frameworks/sproutcore/views/view.js +1272 -591
  170. data/generators/client/templates/english.lproj/body.css +1 -1
  171. data/generators/controller/controller_generator.rb +1 -1
  172. data/generators/controller/templates/test.rhtml +2 -1
  173. data/generators/model/templates/test.rhtml +1 -1
  174. data/generators/test/templates/test.rhtml +1 -1
  175. data/generators/view/templates/test.rhtml +1 -1
  176. data/jsdoc/templates/sproutcore/class.tmpl +241 -338
  177. data/jsdoc/templates/sproutcore/default.css +105 -155
  178. data/jsdoc/templates/sproutcore/index.tmpl +43 -8
  179. data/jsdoc/templates/sproutcore/publish.js +9 -4
  180. data/lib/sproutcore/build_tools/html_builder.rb +29 -13
  181. data/lib/sproutcore/build_tools/resource_builder.rb +1 -1
  182. data/lib/sproutcore/bundle.rb +86 -25
  183. data/lib/sproutcore/jsdoc.rb +2 -0
  184. data/lib/sproutcore/version.rb +1 -1
  185. data/lib/sproutcore/view_helpers.rb +36 -3
  186. data/tasks/deployment.rake +1 -1
  187. metadata +69 -36
  188. data/clients/sc_docs/english.lproj/icons/small/next.png +0 -0
  189. data/clients/sc_docs/english.lproj/icons/small/reset.png +0 -0
  190. data/clients/sc_docs/english.lproj/images/gradients.png +0 -0
  191. data/clients/sc_docs/english.lproj/images/toolbar.png +0 -0
  192. data/clients/sc_docs/english.lproj/warning.rhtml +0 -6
  193. data/clients/sc_test_runner/english.lproj/warning.rhtml +0 -6
  194. data/frameworks/sproutcore/english.lproj/buttons.png +0 -0
  195. data/frameworks/sproutcore/english.lproj/collections.css +0 -82
  196. data/frameworks/sproutcore/english.lproj/images/buttons-sprite.png +0 -0
  197. data/frameworks/sproutcore/views/collection/collection_item.js +0 -36
  198. data/frameworks/sproutcore/views/collection/text_cell.js +0 -128
  199. data/frameworks/sproutcore/views/field.js +0 -214
  200. data/frameworks/sproutcore/views/workspace.js +0 -170
  201. data/generators/client/templates/english.lproj/controls.css +0 -0
  202. data/generators/framework/templates/english.lproj/body.css +0 -0
  203. data/generators/framework/templates/english.lproj/body.rhtml +0 -3
  204. data/generators/framework/templates/english.lproj/controls.css +0 -0
  205. data/lib/sproutcore/view_helpers/button_views.rb +0 -302
  206. data/lib/sproutcore/view_helpers/core_views.rb +0 -292
  207. data/lib/sproutcore/view_helpers/form_views.rb +0 -258
  208. data/lib/sproutcore/view_helpers/menu_views.rb +0 -94
@@ -1,6 +1,6 @@
1
1
  // ==========================================================================
2
2
  // SproutCore -- JavaScript Application Framework
3
- // copyright 2006-2007, Sprout Systems, Inc. and contributors.
3
+ // copyright 2006-2008, Sprout Systems, Inc. and contributors.
4
4
  // ==========================================================================
5
5
 
6
6
  // These are basic enhancements to the string class used throughout
@@ -28,7 +28,7 @@ Object.extend(String.prototype,{
28
28
 
29
29
  // first, replace any ORDERED replacements.
30
30
  var str = this.gsub(/%@([0-9]+)/, function(m) {
31
- return args[parseInt(m[1],0)-1] || '';
31
+ return (args[parseInt(m[1],0)-1] || '').toString();
32
32
  }) ;
33
33
 
34
34
  // now, replace any remaining %@ items. Use this indexOf() method b/c
@@ -42,7 +42,9 @@ Object.extend(String.prototype,{
42
42
  loc = idx + 2 ; // 2 to skip '%@'.
43
43
 
44
44
  // add in replacement.
45
- ret.push(args.shift()) ;
45
+ var value = args.shift() ;
46
+ if (value && value.toString) value = value.toString() ;
47
+ ret.push(value) ;
46
48
  }
47
49
 
48
50
  // include any remaining bits of the string.
@@ -0,0 +1,371 @@
1
+ // ========================================================================
2
+ // SproutCore
3
+ // copyright 2006-2008 Sprout Systems, Inc.
4
+ // ========================================================================
5
+
6
+ require('Core') ;
7
+
8
+ /**
9
+ @class
10
+
11
+ A Timer executes a method after a defined period of time. Timers are
12
+ significantly more efficient than using setTimeout() or setInterval()
13
+ because they are cooperatively scheduled using the run loop. Timers are
14
+ also gauranteed to fire at the same time, making it far easier to keep
15
+ multiple timers in sync.
16
+
17
+ h2. Overview
18
+
19
+ Timers were created for SproutCore as a way to efficiently defer execution
20
+ of code fragments for use in Animations, event handling, and other tasks.
21
+
22
+ Browsers are typically fairly inconsistant about when they will fire a
23
+ timeout or interval based on what the browser is currently doing. Timeouts
24
+ and intervals are also fairly expensive for a browser to execute, which
25
+ means if you schedule a large number of them it can quickly slow down the
26
+ browser considerably.
27
+
28
+ Timers, on the other handle, are scheduled cooperatively using the
29
+ SC.runLoop, which uses exactly one timeout to fire itself when needed and
30
+ then executes by timers that need to fire on its own. This approach can
31
+ be many timers faster than using timers and gaurantees that timers scheduled
32
+ to execute at the same time generally will do so, keeping animations and
33
+ other operations in sync.
34
+
35
+ h2. Scheduling a Timer
36
+
37
+ To schedule a basic timer, you can simply call SC.Timer.schedule() with
38
+ a target and action you wish to have invoked:
39
+
40
+ {{{
41
+ var timer = SC.Timer.schedule({
42
+ target: myObject, action: 'timerFired', interval: 100
43
+ });
44
+ }}}
45
+
46
+ When this timer fires, it will call the timerFired() method on myObject.
47
+
48
+ In addition to calling a method on a particular object, you can also use
49
+ a timer to execute a variety of other types of code:
50
+
51
+ - If you include an action name, but not a target object, then the action will be passed down the responder chain.
52
+ - If you include a property path for the action property (e.g. 'MyApp.someController.someMethod'), then the method you name will be executed.
53
+ - If you include a function in the action property, then the function will be executed. If you also include a target object, the function will be called with this set to the target object.
54
+
55
+ In general these properties are read-only. Changing an interval, target,
56
+ or action after creating a timer will have an unknown effect.
57
+
58
+ h2. Scheduling Repeating Timers
59
+
60
+ In addition to scheduling one time timers, you can also schedule timers to
61
+ execute periodically until some termination date. You make a timer
62
+ repeating by adding the repeats: YES property:
63
+
64
+ {{{
65
+ var timer = SC.Timer.schedule({
66
+ target: myObject,
67
+ action: 'updateAnimation',
68
+ interval: 100,
69
+ repeats: YES,
70
+ until: Time.now() + 1000
71
+ }) ;
72
+ }}}
73
+
74
+ The above example will execute the myObject.updateAnimation() every 100msec
75
+ for 1 second from the current time.
76
+
77
+ If you want a timer to repeat without expiration, you can simply omit the
78
+ until: property. The timer will then repeat until you invalidate it.
79
+
80
+ h2. Pausing and Invalidating Timers
81
+
82
+ If you have created a timer but you no longer want it to execute, you can
83
+ call the invalidate() method on it. This will remove the timer from the
84
+ run loop and clear certain properties so that it will not run again.
85
+
86
+ You can use the invalidate() method on both repeating and one-time timers.
87
+
88
+ If you do not want to invalidate a timer completely but you just want to
89
+ stop the timer from execution temporarily, you can alternatively set the
90
+ isPaused property to YES:
91
+
92
+ {{{
93
+ timer.set('isPaused', YES) ;
94
+ // Perform some critical function; timer will not execute
95
+ timer.set('isPaused', NO) ;
96
+ }}}
97
+
98
+ When a timer is paused, it will be scheduled and will fire like normal,
99
+ but it will not actually execute the action method when it fires. For a
100
+ one time timer, this means that if you have the timer paused when it fires,
101
+ it may never actually execute the action method. For repeating timers,
102
+ this means the timer will remain scheduled but simply will not execute its
103
+ action while the timer is paused.
104
+
105
+ h2. Firing Timers
106
+
107
+ If you need a timer to execute immediately, you can always call the fire()
108
+ method yourself. This will execute the timer action, if the timer is not
109
+ paused. For a one time timer, it will also invalidate the timer and remove
110
+ it from the run loop. Repeating timers can be fired anytime and it will
111
+ not interrupt their regular scheduled times.
112
+
113
+
114
+ @extends SC.Object
115
+ @author Charles Jolley
116
+ @version 1.0
117
+ @since version 1.0
118
+ */
119
+ SC.Timer = SC.Object.extend(
120
+ /** @scope SC.Timer.prototype */ {
121
+
122
+ /**
123
+ The target object whose method will be invoked when the time fires.
124
+
125
+ You can set either a target/action property or you can pass a specific
126
+ method.
127
+
128
+ @type {Object}
129
+ @field
130
+ */
131
+ target: null,
132
+
133
+ /**
134
+ The action to execute.
135
+
136
+ The action can be a method name, a property path, or a function. If you
137
+ pass a method name, it will be invoked on the target object or it will
138
+ be called up the responder chain if target is null. If you pass a
139
+ property path and it resolves to a function then the function will be
140
+ called. If you pass a function instead, then the function will be
141
+ called in the context of the target object.
142
+
143
+ @type {String, Function}
144
+ */
145
+ action: null,
146
+
147
+ /**
148
+ The time interval in milliseconds.
149
+
150
+ You generally set this when you create the timer. If you do not set it
151
+ then the timer will fire as soon as possible in the next run loop.
152
+
153
+ @type {Number}
154
+ */
155
+ interval: 0,
156
+
157
+ /**
158
+ Timer start date offset.
159
+
160
+ The start date determines when the timer will be scheduled. The first
161
+ time the timer fires will be interval milliseconds after the start
162
+ date.
163
+
164
+ Generally you will not set this property yourself. Instead it will be
165
+ set automatically to the current run loop start date when you schedule
166
+ the timer. This ensures that all timers scheduled in the same run loop
167
+ cycle will execute in the sync with one another.
168
+
169
+ The value of this property is an offset like waht you get if you call
170
+ Date.now().
171
+
172
+ @type {Number}
173
+ */
174
+ startTime: null,
175
+
176
+ /**
177
+ YES if you want the timer to execute repeatedly.
178
+
179
+ @type {Boolean}
180
+ */
181
+ repeats: NO,
182
+
183
+ /**
184
+ Last date when the timer will execute.
185
+
186
+ If you have set repeats to YES, then you can also set this property to
187
+ have the timer automatically stop executing past a certain date.
188
+
189
+ This property should contain an offset value like startOffset. However if
190
+ you set it to a Date object on create, it will be converted to an offset
191
+ for you.
192
+
193
+ If this property is null, then the timer will continue to repeat until you
194
+ call invalidate().
195
+
196
+ @type {Date, Number}
197
+ */
198
+ until: null,
199
+
200
+ /**
201
+ Set to YES to pause the timer.
202
+
203
+ Pausing a timer does not remove it from the run loop, but it will
204
+ temporarily suspend it from firing. You should use this property if
205
+ you will want the timer to fire again the future, but you want to prevent
206
+ it from firing temporarily.
207
+
208
+ If you are done with a timer, you should call invalidate() instead of
209
+ setting this property.
210
+
211
+ @type {Boolean}
212
+ */
213
+ isPaused: NO,
214
+
215
+ /**
216
+ YES onces the timer has been scheduled for the first time.
217
+ */
218
+ isScheduled: NO,
219
+
220
+ /**
221
+ YES if the timer can still execute.
222
+
223
+ This read only property will return YES as long as the timer may possibly
224
+ fire again in the future. Once a timer has become invalid, it cannot
225
+ become valid again.
226
+
227
+ @field
228
+ @type {Boolean}
229
+ */
230
+ isValid: function() {
231
+ return !this._invalid ;
232
+ }.property('isPaused'),
233
+
234
+ /**
235
+ Returns the next time offset when the property will fire.
236
+
237
+ This property changes automatically after a timer has fired. If the
238
+ timer is invalid this will return 0.
239
+
240
+ @field
241
+ @type {Number}
242
+ */
243
+ fireTime: function() {
244
+ if (this._invalid || !this.get('isValid')) return 0;
245
+
246
+ var now = Date.now() ;
247
+ var start = this.get('startTime') || now ;
248
+ if (this.until && this.until > 0 && now >= this.until) return 0;
249
+
250
+ var interval = this.get('interval') ;
251
+ var cycle = Math.ceil(((now - start) / interval)+0.01) ;
252
+ if ((cycle > 1) && !this.repeats) return 0 ;
253
+
254
+ if (cycle < 1) cycle = 1 ;
255
+ return start + (cycle * interval) ;
256
+ }.property(),
257
+
258
+ /**
259
+ Invalidates the timer so that it will not execute again. If a timer has
260
+ been scheduled, it will be removed from the run loop immediately.
261
+
262
+ @returns {SC.Timer} The receiver
263
+ */
264
+ invalidate: function() {
265
+ this.propertyWillChange('isValid') ;
266
+ this._invalid = YES ;
267
+ SC.runLoop.cancelTimer(this) ;
268
+ this.propertyDidChange('isValid') ;
269
+ this.action = this.target = null ; // avoid memory leaks
270
+ return this ;
271
+ },
272
+
273
+ /**
274
+ Immediately fires the timer.
275
+
276
+ If the timer is not-repeating, it will be invalidated. If it is repeating
277
+ you can call this method without interrupting its normal schedule.
278
+
279
+ @returns {void}
280
+ */
281
+ fire: function() {
282
+ if (this.get('isPaused') === NO) {
283
+ this.performAction() ;
284
+ }
285
+
286
+ (this.repeats && (this.get('fireTime')>0)) ? this.schedule() : this.invalidate() ;
287
+ },
288
+
289
+ /**
290
+ Actually fires the action. You can override this method if you need
291
+ to change how the timer fires its action.
292
+ */
293
+ performAction: function() {
294
+ // if the action is a function, just try to call it.
295
+ if ($type(this.action) == T_FUNCTION) {
296
+ this.action.call((this.target || this), this) ;
297
+
298
+ // otherwise, action should be a string. If it has a period, treat it
299
+ // like a property path.
300
+ } else if (this.action.indexOf('.') >= 0) {
301
+ var path = this.action.split('.') ;
302
+ var property = path.pop() ;
303
+
304
+ var target = SC.Object.objectForPropertyPath(path, window) ;
305
+ var action = (target.get) ? target.get(property) : target[property];
306
+ if (action && $type(action) == T_FUNCTION) {
307
+ action.call(target, this) ;
308
+ } else {
309
+ throw '%@: Timer could not find a function at %@'.fmt(this, this.action) ;
310
+ }
311
+
312
+ // otherwise, try to execute action direction on target or send down
313
+ // responder chain.
314
+ } else SC.app.sendAction(this.action, this.target, this) ;
315
+ },
316
+
317
+ /**
318
+ Schedules the timer to execute in the runloop.
319
+
320
+ This method is called automatically if you create the timer using the
321
+ schedule() class method. If you create the timer manually, you will
322
+ need to call this method yourself for the timer to execute.
323
+
324
+ @returns {SC.Timer} The receiver
325
+ */
326
+ schedule: function() {
327
+ if (!this._invalid) {
328
+ this.set('isScheduled', YES) ;
329
+ SC.runLoop.scheduleTimer(this, this.get('fireTime')) ;
330
+ }
331
+ return this ;
332
+ },
333
+
334
+ init: function() {
335
+ arguments.callee.base.call(this) ;
336
+
337
+ // convert startTime and until to times if they are dates.
338
+ if (this.startTime instanceof Date) {
339
+ this.startTime = this.startTime.getTime() ;
340
+ }
341
+
342
+ if (this.until instanceof Date) {
343
+ this.until = this.until.getTime() ;
344
+ }
345
+
346
+ // if start time was not set, get it from the run loop.
347
+ if (!this.startTime) this.startTime = SC.runLoop.get('startTime') ;
348
+ },
349
+
350
+ // if the paused state changes, notify the runloop so that it can
351
+ // reschedule its timeout.
352
+ _isPausedObserver: function() {
353
+ SC.runLoop.timerPausedStateDidChange(this) ;
354
+ }
355
+
356
+ }) ;
357
+
358
+ /**
359
+ @scope SC.Timer
360
+
361
+ Created a new timer with the passed properties and schedules it to
362
+ execute. This is the same as calling SC.Time.create({ props }).schedule().
363
+
364
+ @params {Hash} props Any properties you want to set on the timer.
365
+ @returns {SC.Timer} new timer instance.
366
+ */
367
+ SC.Timer.schedule = function(props) {
368
+ return this.create(props).schedule() ;
369
+ } ;
370
+
371
+
@@ -1,6 +1,6 @@
1
1
  // ==========================================================================
2
2
  // SproutCore -- JavaScript Application Framework
3
- // copyright 2006-2007, Sprout Systems, Inc. and contributors.
3
+ // copyright 2006-2008, Sprout Systems, Inc. and contributors.
4
4
  // ==========================================================================
5
5
 
6
6
  require('Core');
@@ -1,8 +1,8 @@
1
1
  // script.aculo.us unittest.js v1.8.0, Tue Nov 06 15:01:40 +0300 2007
2
2
 
3
- // Copyright (c) 2005-2007 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
4
- // (c) 2005-2007 Jon Tirsen (http://www.tirsen.com)
5
- // (c) 2005-2007 Michael Schuerig (http://www.schuerig.de/michael/)
3
+ // Copyright (c) 2005-2008 Thomas Fuchs (http://script.aculo.us, http://mir.aculo.us)
4
+ // (c) 2005-2008 Jon Tirsen (http://www.tirsen.com)
5
+ // (c) 2005-2008 Michael Schuerig (http://www.schuerig.de/michael/)
6
6
  //
7
7
  // script.aculo.us is freely distributable under the terms of an MIT-style license.
8
8
  // For details, see the script.aculo.us web site: http://script.aculo.us/
@@ -1,9 +1,9 @@
1
1
  // ==========================================================================
2
2
  // SproutCore -- JavaScript Application Framework
3
- // copyright 2006-2007, Sprout Systems, Inc. and contributors.
3
+ // copyright 2006-2008, Sprout Systems, Inc. and contributors.
4
4
  // ==========================================================================
5
5
 
6
- // These are helpful utility functions.
6
+ // These are helpful utility functions for calculating range and rect values
7
7
 
8
8
 
9
9
  Object.extend(SC,
@@ -66,12 +66,171 @@ Object.extend(SC,
66
66
  @returns {Boolean} true if rects match
67
67
  */
68
68
  rectsEqual: function(r1, r2, delta) {
69
+ if (!r1 || !r2) return (r1 == r2) ;
70
+
69
71
  if (delta == null) delta = 0.1;
70
72
  if (Math.abs(r1.y - r2.y) > delta) return false ;
71
73
  if (Math.abs(r1.x - r2.x) > delta) return false ;
72
74
  if (Math.abs(r1.width - r2.width) > delta) return false ;
73
75
  if (Math.abs(r1.height - r2.height) > delta) return false ;
74
76
  return true ;
77
+ },
78
+
79
+ /** Returns the insersection between two rectangles.
80
+
81
+ @param r1 {Rect} The first rect
82
+ @param r2 {Rect} the second rect
83
+ @returns {Rect} the intersection rect. width || height will be 0 if they do not interset.
84
+ */
85
+ intersectRects: function(r1, r2) {
86
+ // find all four edges
87
+ var ret = {
88
+ x: Math.max(SC.minX(r1), SC.minX(r2)),
89
+ y: Math.max(SC.minY(r1), SC.minY(r2)),
90
+ width: Math.min(SC.maxX(r1), SC.maxX(r2)),
91
+ height: Math.min(SC.maxY(r1), SC.maxY(r2))
92
+ } ;
93
+
94
+ // convert edges to w/h
95
+ ret.width = Math.max(0, ret.width - ret.x) ;
96
+ ret.height = Math.max(0, ret.height - ret.y) ;
97
+ return ret ;
98
+ },
99
+
100
+ /** Returns the union between two rectangles
101
+
102
+ @param r1 {Rect} The first rect
103
+ @param r2 {Rect} The second rect
104
+ @returns {Rect} The union rect.
105
+ */
106
+ unionRects: function(r1, r2) {
107
+ // find all four edges
108
+ var ret = {
109
+ x: Math.min(SC.minX(r1), SC.minX(r2)),
110
+ y: Math.min(SC.minY(r1), SC.minY(r2)),
111
+ width: Math.max(SC.maxX(r1), SC.maxX(r2)),
112
+ height: Math.max(SC.maxY(r1), SC.maxX(r2))
113
+ } ;
114
+
115
+ // convert edges to w/h
116
+ ret.width = Math.max(0, ret.width - ret.x) ;
117
+ ret.height = Math.max(0, ret.height - ret.y) ;
118
+ return ret ;
119
+ },
120
+
121
+ /** Duplicates the passed rect.
122
+
123
+ This is faster than Object.clone().
124
+
125
+ @param r {Rect} The rect to clone.
126
+ @returns {Rect} The cloned rect
127
+ */
128
+ cloneRect: function(r) {
129
+ return { x: r.x, y: r.y, width: r.width, height: r.height } ;
130
+ },
131
+
132
+
133
+ /** Finds the absolute viewportOffset for a given element.
134
+ This method is more accurate than the version provided by prototype.
135
+
136
+ @param el The DOM element
137
+ @returns {Point} A hash with x,y offsets.
138
+ */
139
+ viewportOffset: function(el) {
140
+ var valueL = 0 ; var valueT = 0;
141
+
142
+ // add up all the offsets for the element.
143
+ var element = el ;
144
+ do {
145
+ valueT += (element.offsetTop || 0) + (element.clientTop || 0);
146
+ valueL += (element.offsetLeft || 0) + (element.clientLeft || 0);
147
+
148
+ // bizarely for FireFox if your offsetParent has a border, then it can
149
+ // impact the offset.
150
+ if (SC.Platform.Firefox) {
151
+ var overflow = Element.getStyle(element, 'overflow') ;
152
+ if (overflow !== 'visible') {
153
+ var left = parseInt(Element.getStyle(element, 'borderLeftWidth'),0) || 0 ;
154
+ var top = parseInt(Element.getStyle(element, 'borderTopWidth'),0) || 0 ;
155
+ if (el !== element) {
156
+ left *= 2; top *= 2 ;
157
+ }
158
+ valueL += left; valueT += top ;
159
+ }
160
+ }
161
+
162
+ // Safari fix
163
+ if (element.offsetParent == document.body &&
164
+ Element.getStyle(element, 'position') == 'absolute') break;
165
+
166
+
167
+
168
+ } while (element = element.offsetParent);
169
+
170
+ element = el;
171
+ do {
172
+ if (!Prototype.Browser.Opera || element.tagName == 'BODY') {
173
+ valueT -= element.scrollTop || 0;
174
+ valueL -= element.scrollLeft || 0;
175
+ }
176
+ } while (element = element.parentNode);
177
+
178
+ return { x: valueL, y: valueT } ;
179
+ },
180
+
181
+ /** A Point at {0,0} */
182
+ ZERO_POINT: { x: 0, y: 0 },
183
+
184
+ /** A zero length range at zero. */
185
+ ZERO_RANGE: { start: 0, length: 0 },
186
+
187
+ RANGE_NOT_FOUND: { start: 0, length: -1 },
188
+
189
+ /** Returns true if the passed index is in the specified range */
190
+ valueInRange: function(value, range) {
191
+ return (range > 0) && (value >= range.start) && (value < (range.start + range.length));
192
+ },
193
+
194
+ /** Returns first value of the range. */
195
+ minRange: function(range) { return range.start; },
196
+
197
+ /** Returns the first value outside of the range. */
198
+ maxRange: function(range) { return (range.length < 0) ? -1 : (range.start + range.length); },
199
+
200
+ /** Returns the union of two ranges. If one range is null, the other
201
+ range will be returned. */
202
+ unionRanges: function(r1, r2) {
203
+ if ((r1 == null) || (r1.length < 0)) return r2 ;
204
+ if ((r2 == null) || (r2.length < 0)) return r1 ;
205
+
206
+ var min = Math.min(r1.start, r2.start) ;
207
+ var max = Math.max(SC.maxRange(r1), SC.maxRange(r2)) ;
208
+ return { start: min, length: max - min } ;
209
+ },
210
+
211
+ /** Returns the intersection of the two ranges or SC.RANGE_NOT_FOUND */
212
+ intersectRanges: function(r1, r2) {
213
+ if ((r1 == null) || (r2 == null)) return SC.RANGE_NOT_FOUND ;
214
+ if ((r1.length < 0) || (r2.length < 0)) return SC.RANGE_NOT_FOUND;
215
+ var min = Math.max(SC.minRange(r1), SC.minRange(r2)) ;
216
+ var max = Math.min(SC.maxRange(r1), SC.maxRange(r2)) ;
217
+ if (max < min) return SC.RANGE_NOT_FOUND ;
218
+ return { start: min, length: max-min };
219
+ },
220
+
221
+ /** Returns a clone of the range. */
222
+ cloneRange: function(r) {
223
+ return { start: r.start, length: r.length };
224
+ },
225
+
226
+ /** Returns true if the two passed ranges are equal. A null value is
227
+ treated like RANGE_NOT_FOUND.
228
+ */
229
+ rangesEqual: function(r1, r2) {
230
+ if (r1===r2) return true ;
231
+ if (r1 == null) return r2.length < 0 ;
232
+ if (r2 == null) return r1.length < 0 ;
233
+ return (r1.start == r2.start) && (r1.length == r2.length) ;
75
234
  }
76
235
 
77
236
  }) ;