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.
- data/History.txt +233 -0
- data/Manifest.txt +67 -34
- data/bin/sc-build +12 -1
- data/bin/sc-gen +1 -1
- data/bin/sproutcore +14 -0
- data/clients/sc_docs/controllers/docs.js +38 -8
- data/clients/sc_docs/english.lproj/body.css +80 -127
- data/clients/sc_docs/english.lproj/body.rhtml +43 -23
- data/clients/sc_docs/english.lproj/no_docs.rhtml +2 -1
- data/clients/sc_docs/english.lproj/tabs.rhtml +16 -0
- data/clients/sc_docs/main.js +14 -9
- data/clients/sc_docs/models/doc.js +1 -1
- data/clients/sc_docs/tests/controllers/docs.rhtml +1 -2
- data/clients/sc_docs/tests/models/doc.rhtml +1 -2
- data/clients/sc_docs/tests/views/doc_frame.rhtml +1 -2
- data/clients/sc_docs/tests/views/doc_label_view.rhtml +1 -2
- data/clients/sc_docs/views/doc_frame.js +1 -1
- data/clients/sc_test_runner/controllers/runner.js +31 -8
- data/clients/sc_test_runner/english.lproj/body.css +62 -122
- data/clients/sc_test_runner/english.lproj/body.rhtml +62 -26
- data/clients/sc_test_runner/main.js +1 -6
- data/clients/sc_test_runner/models/test.js +14 -1
- data/clients/sc_test_runner/views/runner_frame.js +4 -2
- data/clients/view_builder/builders/builder.js +339 -0
- data/clients/view_builder/builders/button.js +81 -0
- data/clients/view_builder/controllers/document.js +21 -0
- data/clients/view_builder/core.js +19 -0
- data/clients/view_builder/english.lproj/body.css +77 -0
- data/clients/view_builder/english.lproj/body.rhtml +41 -0
- data/clients/{sc_docs → view_builder}/english.lproj/controls.css +0 -0
- data/clients/view_builder/english.lproj/strings.js +14 -0
- data/clients/view_builder/main.js +38 -0
- data/clients/view_builder/tests/controllers/document.rhtml +20 -0
- data/clients/view_builder/tests/views/builder.rhtml +20 -0
- data/clients/view_builder/views/builder.js +23 -0
- data/frameworks/prototype/prototype.js +1 -1
- data/frameworks/sproutcore/Core.js +32 -7
- data/frameworks/sproutcore/README +1 -1
- data/frameworks/sproutcore/animation/animation.js +411 -0
- data/frameworks/sproutcore/controllers/array.js +17 -9
- data/frameworks/sproutcore/controllers/collection.js +9 -110
- data/frameworks/sproutcore/controllers/controller.js +1 -1
- data/frameworks/sproutcore/controllers/object.js +2 -1
- data/frameworks/sproutcore/drag/drag.js +267 -56
- data/frameworks/sproutcore/drag/drag_data_source.js +24 -16
- data/frameworks/sproutcore/drag/drag_source.js +53 -42
- data/frameworks/sproutcore/drag/drop_target.js +2 -2
- data/frameworks/sproutcore/english.lproj/buttons.css +337 -236
- data/frameworks/sproutcore/english.lproj/core.css +115 -0
- data/frameworks/sproutcore/english.lproj/icons.css +227 -0
- data/{clients/sc_docs → frameworks/sproutcore}/english.lproj/images/indicator.gif +0 -0
- data/frameworks/sproutcore/english.lproj/images/sc-theme-sprite.png +0 -0
- data/frameworks/sproutcore/english.lproj/images/sc-theme-ysprite.png +0 -0
- data/frameworks/sproutcore/english.lproj/images/shared-icons.png +0 -0
- data/frameworks/sproutcore/english.lproj/menu.css +1 -1
- data/frameworks/sproutcore/english.lproj/strings.js +1 -1
- data/frameworks/sproutcore/english.lproj/theme.css +405 -31
- data/frameworks/sproutcore/foundation/application.js +15 -11
- data/frameworks/sproutcore/foundation/benchmark.js +1 -1
- data/frameworks/sproutcore/foundation/binding.js +2 -2
- data/frameworks/sproutcore/foundation/date.js +1 -1
- data/frameworks/sproutcore/foundation/error.js +1 -1
- data/frameworks/sproutcore/foundation/input_manager.js +32 -21
- data/frameworks/sproutcore/foundation/mock.js +1 -1
- data/frameworks/sproutcore/foundation/node_descriptor.js +9 -6
- data/frameworks/sproutcore/foundation/object.js +249 -177
- data/frameworks/sproutcore/foundation/page.js +5 -2
- data/frameworks/sproutcore/foundation/path_module.js +11 -10
- data/frameworks/sproutcore/foundation/responder.js +5 -2
- data/frameworks/sproutcore/foundation/routes.js +17 -13
- data/frameworks/sproutcore/foundation/run_loop.js +249 -11
- data/frameworks/sproutcore/foundation/server.js +1 -1
- data/frameworks/sproutcore/foundation/set.js +3 -3
- data/frameworks/sproutcore/foundation/string.js +5 -3
- data/frameworks/sproutcore/foundation/timer.js +371 -0
- data/frameworks/sproutcore/foundation/undo_manager.js +1 -1
- data/frameworks/sproutcore/foundation/unittest.js +3 -3
- data/frameworks/sproutcore/foundation/utils.js +161 -2
- data/frameworks/sproutcore/globals/panels.js +1 -1
- data/frameworks/sproutcore/globals/popups.js +4 -3
- data/frameworks/sproutcore/globals/window.js +44 -4
- data/frameworks/sproutcore/lib/button_views.rb +328 -0
- data/frameworks/sproutcore/lib/collection_view.rb +80 -0
- data/frameworks/sproutcore/lib/core_views.rb +281 -0
- data/frameworks/sproutcore/lib/form_views.rb +253 -0
- data/frameworks/sproutcore/lib/index.rhtml +2 -0
- data/frameworks/sproutcore/lib/menu_views.rb +88 -0
- data/frameworks/sproutcore/{foundation → mixins}/array.js +60 -29
- data/frameworks/sproutcore/mixins/control.js +265 -0
- data/frameworks/sproutcore/mixins/delegate_support.js +66 -0
- data/frameworks/sproutcore/{foundation → mixins}/observable.js +176 -6
- data/frameworks/sproutcore/mixins/scrollable.js +245 -0
- data/frameworks/sproutcore/mixins/selection_support.js +148 -0
- data/frameworks/sproutcore/mixins/validatable.js +152 -0
- data/frameworks/sproutcore/models/collection.js +5 -5
- data/frameworks/sproutcore/models/record.js +1 -1
- data/frameworks/sproutcore/models/store.js +1 -1
- data/frameworks/sproutcore/panes/dialog.js +1 -1
- data/frameworks/sproutcore/panes/manager.js +1 -1
- data/frameworks/sproutcore/panes/menu.js +1 -1
- data/frameworks/sproutcore/panes/overlay.js +2 -2
- data/frameworks/sproutcore/panes/panel.js +1 -1
- data/frameworks/sproutcore/panes/picker.js +1 -1
- data/frameworks/sproutcore/tests/controllers/array.rhtml +44 -4
- data/frameworks/sproutcore/tests/foundation/timer/invalidate.rhtml +33 -0
- data/frameworks/sproutcore/tests/foundation/timer/invokeLater.rhtml +145 -0
- data/frameworks/sproutcore/tests/foundation/timer/isPaused.rhtml +70 -0
- data/frameworks/sproutcore/tests/foundation/timer/schedule.rhtml +145 -0
- data/frameworks/sproutcore/tests/views/{scroll.rhtml → checkbox.rhtml} +3 -3
- data/frameworks/sproutcore/tests/views/{collection.rhtml → collection/base.rhtml} +33 -32
- data/frameworks/sproutcore/tests/views/collection/incremental_rendering.rhtml +260 -0
- data/frameworks/sproutcore/tests/views/image_cell.rhtml +19 -0
- data/frameworks/sproutcore/tests/views/label_item.rhtml +2 -4
- data/frameworks/sproutcore/tests/views/list.rhtml +2 -3
- data/frameworks/sproutcore/tests/views/list_item.rhtml +20 -0
- data/frameworks/sproutcore/tests/views/slider.rhtml +20 -0
- data/frameworks/sproutcore/tests/views/text_cell.rhtml +19 -0
- data/frameworks/sproutcore/tests/views/view/clippingFrame.rhtml +395 -0
- data/frameworks/sproutcore/tests/views/view/frame.rhtml +353 -0
- data/frameworks/sproutcore/tests/views/view/innerFrame.rhtml +347 -0
- data/frameworks/sproutcore/tests/views/view/isVisibleInWindow.rhtml +148 -0
- data/frameworks/sproutcore/tests/views/view/scrollFrame.rhtml +468 -0
- data/frameworks/sproutcore/validators/credit_card.js +33 -13
- data/frameworks/sproutcore/validators/date.js +26 -6
- data/frameworks/sproutcore/validators/email.js +21 -3
- data/frameworks/sproutcore/validators/not_empty.js +11 -1
- data/frameworks/sproutcore/validators/number.js +18 -4
- data/frameworks/sproutcore/validators/password.js +12 -1
- data/frameworks/sproutcore/validators/validator.js +204 -194
- data/frameworks/sproutcore/views/{button.js → button/button.js} +96 -94
- data/frameworks/sproutcore/views/button/checkbox.js +29 -0
- data/frameworks/sproutcore/views/button/disclosure.js +42 -0
- data/frameworks/sproutcore/views/button/radio.js +29 -0
- data/frameworks/sproutcore/views/{collection.js → collection/collection.js} +1373 -1024
- data/frameworks/sproutcore/views/collection/grid.js +124 -46
- data/frameworks/sproutcore/views/collection/image_cell.js +17 -46
- data/frameworks/sproutcore/views/collection/list.js +45 -35
- data/frameworks/sproutcore/views/collection/source_list.js +386 -0
- data/frameworks/sproutcore/views/collection/table.js +118 -0
- data/frameworks/sproutcore/views/container.js +7 -2
- data/frameworks/sproutcore/views/error_explanation.js +23 -10
- data/frameworks/sproutcore/views/{checkbox_field.js → field/checkbox_field.js} +16 -6
- data/frameworks/sproutcore/views/field/field.js +219 -0
- data/frameworks/sproutcore/views/{radio_field.js → field/radio_field.js} +27 -12
- data/frameworks/sproutcore/views/{select_field.js → field/select_field.js} +116 -90
- data/frameworks/sproutcore/views/{text_field.js → field/text_field.js} +57 -8
- data/frameworks/sproutcore/views/{textarea_field.js → field/textarea_field.js} +13 -3
- data/frameworks/sproutcore/views/filter_button.js +2 -2
- data/frameworks/sproutcore/views/form.js +3 -3
- data/frameworks/sproutcore/views/image.js +128 -21
- data/frameworks/sproutcore/views/inline_text_editor.js +1 -1
- data/frameworks/sproutcore/views/label.js +149 -92
- data/frameworks/sproutcore/views/list_item.js +225 -0
- data/frameworks/sproutcore/views/menu_item.js +10 -4
- data/frameworks/sproutcore/views/pagination.js +11 -4
- data/frameworks/sproutcore/views/popup_button.js +25 -21
- data/frameworks/sproutcore/views/popup_menu.js +10 -4
- data/frameworks/sproutcore/views/progress.js +29 -16
- data/frameworks/sproutcore/views/radio_group.js +1 -1
- data/frameworks/sproutcore/views/scroll.js +60 -20
- data/frameworks/sproutcore/views/segmented.js +1 -1
- data/frameworks/sproutcore/views/slider.js +132 -0
- data/frameworks/sproutcore/views/source_list_group.js +130 -0
- data/frameworks/sproutcore/views/spinner.js +1 -1
- data/frameworks/sproutcore/views/split.js +292 -0
- data/frameworks/sproutcore/views/split_divider.js +109 -0
- data/frameworks/sproutcore/views/tab.js +1 -1
- data/frameworks/sproutcore/views/toolbar.js +1 -1
- data/frameworks/sproutcore/views/view.js +1272 -591
- data/generators/client/templates/english.lproj/body.css +1 -1
- data/generators/controller/controller_generator.rb +1 -1
- data/generators/controller/templates/test.rhtml +2 -1
- data/generators/model/templates/test.rhtml +1 -1
- data/generators/test/templates/test.rhtml +1 -1
- data/generators/view/templates/test.rhtml +1 -1
- data/jsdoc/templates/sproutcore/class.tmpl +241 -338
- data/jsdoc/templates/sproutcore/default.css +105 -155
- data/jsdoc/templates/sproutcore/index.tmpl +43 -8
- data/jsdoc/templates/sproutcore/publish.js +9 -4
- data/lib/sproutcore/build_tools/html_builder.rb +29 -13
- data/lib/sproutcore/build_tools/resource_builder.rb +1 -1
- data/lib/sproutcore/bundle.rb +86 -25
- data/lib/sproutcore/jsdoc.rb +2 -0
- data/lib/sproutcore/version.rb +1 -1
- data/lib/sproutcore/view_helpers.rb +36 -3
- data/tasks/deployment.rake +1 -1
- metadata +69 -36
- data/clients/sc_docs/english.lproj/icons/small/next.png +0 -0
- data/clients/sc_docs/english.lproj/icons/small/reset.png +0 -0
- data/clients/sc_docs/english.lproj/images/gradients.png +0 -0
- data/clients/sc_docs/english.lproj/images/toolbar.png +0 -0
- data/clients/sc_docs/english.lproj/warning.rhtml +0 -6
- data/clients/sc_test_runner/english.lproj/warning.rhtml +0 -6
- data/frameworks/sproutcore/english.lproj/buttons.png +0 -0
- data/frameworks/sproutcore/english.lproj/collections.css +0 -82
- data/frameworks/sproutcore/english.lproj/images/buttons-sprite.png +0 -0
- data/frameworks/sproutcore/views/collection/collection_item.js +0 -36
- data/frameworks/sproutcore/views/collection/text_cell.js +0 -128
- data/frameworks/sproutcore/views/field.js +0 -214
- data/frameworks/sproutcore/views/workspace.js +0 -170
- data/generators/client/templates/english.lproj/controls.css +0 -0
- data/generators/framework/templates/english.lproj/body.css +0 -0
- data/generators/framework/templates/english.lproj/body.rhtml +0 -3
- data/generators/framework/templates/english.lproj/controls.css +0 -0
- data/lib/sproutcore/view_helpers/button_views.rb +0 -302
- data/lib/sproutcore/view_helpers/core_views.rb +0 -292
- data/lib/sproutcore/view_helpers/form_views.rb +0 -258
- 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-
|
|
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
|
-
|
|
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-
|
|
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-
|
|
4
|
-
// (c) 2005-
|
|
5
|
-
// (c) 2005-
|
|
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-
|
|
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
|
}) ;
|