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
|
|
3
|
-
// copyright 2006-
|
|
3
|
+
// copyright 2006-2008 Sprout Systems, Inc.
|
|
4
4
|
// ========================================================================
|
|
5
5
|
|
|
6
6
|
require('views/view') ;
|
|
@@ -1,34 +1,74 @@
|
|
|
1
1
|
// ==========================================================================
|
|
2
|
-
//
|
|
2
|
+
// SC.ScrollView
|
|
3
3
|
// ==========================================================================
|
|
4
4
|
|
|
5
|
+
require('mixins/scrollable') ;
|
|
5
6
|
require('views/container') ;
|
|
6
7
|
|
|
7
|
-
/**
|
|
8
|
+
/**
|
|
9
|
+
@class
|
|
8
10
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
drag operations and support for custom scroll bars.
|
|
14
|
-
|
|
15
|
-
Scroll views are generally included automatically if you use the built-in
|
|
16
|
-
view helpers in SproutCore. Depending on the views you are writing, you may
|
|
17
|
-
want to use scroll views yourself as well. The following sections describe
|
|
18
|
-
how you can use the scroll view to support incremental rendering and auto-
|
|
19
|
-
scrolling dragging.
|
|
20
|
-
|
|
21
|
-
h3. Using Scroll Views for Incremental Rendering
|
|
11
|
+
Scroll Views are used throughout SproutCore to provide scrollable areas.
|
|
12
|
+
Although you can use overflow: auto to provide scrollbar anywhere, using
|
|
13
|
+
a ScrollView is preferrable because it will also notify child views anytime
|
|
14
|
+
the view is scrolled.
|
|
22
15
|
|
|
23
|
-
Coming Soon...
|
|
24
|
-
|
|
25
16
|
@extends SC.View
|
|
26
17
|
@author Charles Jolley
|
|
27
18
|
@version 1.0
|
|
28
19
|
*/
|
|
29
|
-
SC.ScrollView = SC.
|
|
30
|
-
|
|
20
|
+
SC.ScrollView = SC.ContainerView.extend(SC.Scrollable, {
|
|
21
|
+
|
|
22
|
+
emptyElement: '<div class="sc-scroll-view"></div>',
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
Determines if the view should be scrollable vertically.
|
|
26
|
+
|
|
27
|
+
If this property is set to NO then the vertical scrollbar will always
|
|
28
|
+
be hidden.
|
|
29
|
+
|
|
30
|
+
@field
|
|
31
|
+
*/
|
|
32
|
+
canScrollVertical: YES,
|
|
31
33
|
|
|
32
|
-
|
|
34
|
+
/**
|
|
35
|
+
Determines if the view should be scrollable horizontally.
|
|
36
|
+
|
|
37
|
+
If this property is set to NO then the horizontal scrollbale will always
|
|
38
|
+
be hidden.
|
|
33
39
|
|
|
40
|
+
@field
|
|
41
|
+
*/
|
|
42
|
+
canScrollHorizontal: NO,
|
|
43
|
+
|
|
44
|
+
_canScrollVerticalObserver: function() {
|
|
45
|
+
this.setClassName('sc-scroll-vertical', this.get('canScrollVertical'));
|
|
46
|
+
}.observes('canScrollVertical'),
|
|
47
|
+
|
|
48
|
+
_canScrollHorizontalObserver: function() {
|
|
49
|
+
this.setClassName('sc-scroll-horizontal', this.get('canScrollHorizontal'));
|
|
50
|
+
}.observes('canScrollHorizontal'),
|
|
51
|
+
|
|
52
|
+
init: function() {
|
|
53
|
+
arguments.callee.base.apply(this, arguments) ;
|
|
54
|
+
this._canScrollVerticalObserver() ;
|
|
55
|
+
this._canScrollHorizontalObserver() ;
|
|
56
|
+
},
|
|
57
|
+
|
|
58
|
+
// auto fit child view based on which scrollviews are visible
|
|
59
|
+
resizeChildrenWithOldSize: function(oldSize) {
|
|
60
|
+
var v = this.get('firstChild') ;
|
|
61
|
+
if (v) {
|
|
62
|
+
var f = v.get('frame');
|
|
63
|
+
var orig = Object.clone(f) ;
|
|
64
|
+
var innerFrame = this.get('innerFrame') ;
|
|
65
|
+
f.x = f.y = 0 ;
|
|
66
|
+
if (!this.get('canScrollHorizontal')) f.width = innerFrame.width ;
|
|
67
|
+
if (!this.get('canScrollVertical')) f.height = innerFrame.height ;
|
|
68
|
+
if (!SC.rectsEqual(f, orig)) v.set('frame', f) ;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
34
72
|
}) ;
|
|
73
|
+
|
|
74
|
+
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// ========================================================================
|
|
2
2
|
// SproutCore
|
|
3
|
-
// copyright 2006-
|
|
3
|
+
// copyright 2006-2008 Sprout Systems, Inc.
|
|
4
4
|
// ========================================================================
|
|
5
5
|
|
|
6
6
|
require('views/view') ;
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
// ==========================================================================
|
|
2
|
+
// SC.SliderView
|
|
3
|
+
// ==========================================================================
|
|
4
|
+
|
|
5
|
+
require('views/view');
|
|
6
|
+
require('mixins/control');
|
|
7
|
+
|
|
8
|
+
/** @class
|
|
9
|
+
|
|
10
|
+
A SliderView shows a horizontal slider control that you can use to set
|
|
11
|
+
variable values.
|
|
12
|
+
|
|
13
|
+
You can use a slider view much like you would any other control. Simply
|
|
14
|
+
set the value or content/contentValueKey to whatever value you want to
|
|
15
|
+
display. You can also set the maximumValue and minValue properties to determine
|
|
16
|
+
the mapping of the control to its children.
|
|
17
|
+
|
|
18
|
+
@extends SC.View
|
|
19
|
+
@extends SC.Control
|
|
20
|
+
|
|
21
|
+
@author Charles Jolley
|
|
22
|
+
@version 1.0
|
|
23
|
+
*/
|
|
24
|
+
SC.SliderView = SC.View.extend(SC.Control,
|
|
25
|
+
/** @scope SC.SliderView.prototype */ {
|
|
26
|
+
|
|
27
|
+
emptyElement: '<span class="sc-slider-view"><span class="inner"><img src="%@" class="sc-handle" /></span></span>'.fmt(static_url('blank')),
|
|
28
|
+
|
|
29
|
+
/** @private */
|
|
30
|
+
outlets: ['handleElement'],
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
The DOM element that displays the handle.
|
|
34
|
+
*/
|
|
35
|
+
handleElement: '.sc-handle?',
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
The minimum value of the slider.
|
|
39
|
+
*/
|
|
40
|
+
minimum: 0,
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
The maximum value of the slider.
|
|
44
|
+
*/
|
|
45
|
+
maximum: 1.0,
|
|
46
|
+
|
|
47
|
+
/**
|
|
48
|
+
Optionally set to the minimum step size allowed.
|
|
49
|
+
|
|
50
|
+
All values will be rounded to this step size when displayed.
|
|
51
|
+
*/
|
|
52
|
+
step: 0.1,
|
|
53
|
+
|
|
54
|
+
/**
|
|
55
|
+
The value of the slider. Set this property or the content property.
|
|
56
|
+
*/
|
|
57
|
+
value: 0.50,
|
|
58
|
+
|
|
59
|
+
/** @private */
|
|
60
|
+
valueBindingDefault: SC.Binding.SingleNotEmpty,
|
|
61
|
+
|
|
62
|
+
_valueDidChangeObserver: function() {
|
|
63
|
+
if (!this.didChangeFor('value', 'value', 'minimum', 'maximum')) return;
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
var min = this.get('minimum') ;
|
|
67
|
+
var max = this.get('maximum') ;
|
|
68
|
+
var value = this.get('value') ;
|
|
69
|
+
|
|
70
|
+
// constrain value. If value did not match, set it back.
|
|
71
|
+
var constrained = Math.min(Math.max(value, min), max) ;
|
|
72
|
+
|
|
73
|
+
var step = this.get('step') ;
|
|
74
|
+
if (step && step !== 0) {
|
|
75
|
+
constrained = Math.round(constrained / step) * step ;
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
if (Math.abs(value - constrained) > 0.01) this.set('value', constrained) ;
|
|
79
|
+
value = constrained ;
|
|
80
|
+
|
|
81
|
+
// determine the percent across
|
|
82
|
+
value = (value - min) / (max - min) ;
|
|
83
|
+
|
|
84
|
+
|
|
85
|
+
// convert to a value within the width of the receiver's innerFrame.
|
|
86
|
+
var f = this.get('innerFrame') ;
|
|
87
|
+
value = Math.round((f.width-18) * value) ;
|
|
88
|
+
|
|
89
|
+
// set handle. This assumes the handle is centered over its origin.
|
|
90
|
+
// adjust by 48px since this lives inside the inner div. Also the
|
|
91
|
+
// divider is shown shifted by 8 so account for that also.
|
|
92
|
+
value -= (39) ;
|
|
93
|
+
Element.setStyle(this.handleElement, { left: '%@px'.fmt(value) }) ;
|
|
94
|
+
|
|
95
|
+
}.observes('value', 'minimum', 'maximum'),
|
|
96
|
+
|
|
97
|
+
mouseDown: function(evt) {
|
|
98
|
+
|
|
99
|
+
if (!this.get('isEnabled')) return true ; // nothing to do
|
|
100
|
+
|
|
101
|
+
// add active class
|
|
102
|
+
this.addClassName('active') ;
|
|
103
|
+
|
|
104
|
+
// find new location -- adjust from left edge of display.
|
|
105
|
+
var loc = this.convertFrameFromView(Event.pointerLocation(evt), null).x ;
|
|
106
|
+
var f = this.get('innerFrame') ;
|
|
107
|
+
loc -= (f.x + 9) ;
|
|
108
|
+
|
|
109
|
+
// find percent across
|
|
110
|
+
var value = loc / (f.width - 18) ;
|
|
111
|
+
|
|
112
|
+
// convert to value and constrain
|
|
113
|
+
var min = this.get('minimum') ;
|
|
114
|
+
var max = this.get('maximum') ;
|
|
115
|
+
value = (value * (max - min)) + min ;
|
|
116
|
+
value = Math.min(Math.max(value, min), max) ;
|
|
117
|
+
|
|
118
|
+
this.setIfChanged('value', value) ;
|
|
119
|
+
|
|
120
|
+
return true;
|
|
121
|
+
},
|
|
122
|
+
|
|
123
|
+
// mouseDragged uses same technique as mouseDown.
|
|
124
|
+
mouseDragged: function(evt) { return this.mouseDown(evt); },
|
|
125
|
+
|
|
126
|
+
// remove active class
|
|
127
|
+
mouseUp: function(evt) {
|
|
128
|
+
this.removeClassName('active') ;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
|
|
132
|
+
}) ;
|
|
@@ -0,0 +1,130 @@
|
|
|
1
|
+
// ==========================================================================
|
|
2
|
+
// SC.ListItemView
|
|
3
|
+
// ==========================================================================
|
|
4
|
+
|
|
5
|
+
require('views/view') ;
|
|
6
|
+
require('mixins/delegate_support');
|
|
7
|
+
require('mixins/control') ;
|
|
8
|
+
require('views/button/disclosure');
|
|
9
|
+
|
|
10
|
+
/** @class
|
|
11
|
+
|
|
12
|
+
Displays a group view in a source list. Handles displaying a disclosure
|
|
13
|
+
triangle which can be used to show/hide children.
|
|
14
|
+
|
|
15
|
+
@extends SC.View
|
|
16
|
+
@extends SC.DelegateSupport
|
|
17
|
+
@author Charles Jolley
|
|
18
|
+
@version 0.1
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
SC.SourceListGroupView = SC.View.extend(SC.Control, SC.DelegateSupport, {
|
|
22
|
+
|
|
23
|
+
emptyElement: ['<div class="sc-source-list-group">',
|
|
24
|
+
'<a href="javascript:;" class="sc-source-list-label sc-disclosure-view sc-button-view button disclosure no-disclosure">',
|
|
25
|
+
'<img src="%@" class="button" />'.fmt(static_url('blank')),
|
|
26
|
+
'<span class="label"></span></a>',
|
|
27
|
+
'</div>'].join(''),
|
|
28
|
+
|
|
29
|
+
/**
|
|
30
|
+
The group value to display for this group.
|
|
31
|
+
*/
|
|
32
|
+
content: null,
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
The current group visibility. Used by the source list to determine
|
|
36
|
+
the layout size of the group.
|
|
37
|
+
*/
|
|
38
|
+
isGroupVisible: YES,
|
|
39
|
+
|
|
40
|
+
/**
|
|
41
|
+
YES if group is showing its titlebar.
|
|
42
|
+
|
|
43
|
+
Group views will typically hide their header if the content is set to
|
|
44
|
+
null. You can also override this method to always hide the header if
|
|
45
|
+
you want and the SourceListView will not leave room for it.
|
|
46
|
+
*/
|
|
47
|
+
hasGroupTitle: YES,
|
|
48
|
+
|
|
49
|
+
groupTitleKey: null,
|
|
50
|
+
|
|
51
|
+
groupVisibleKey: null,
|
|
52
|
+
|
|
53
|
+
contentPropertyDidChange: function(target, key) {
|
|
54
|
+
var content = this.get('content') ;
|
|
55
|
+
var labelView = this.outlet('labelView') ;
|
|
56
|
+
|
|
57
|
+
// hide labelView if content is null.
|
|
58
|
+
if (content == null) {
|
|
59
|
+
labelView.setIfChanged('isVisible', NO) ;
|
|
60
|
+
this.setIfChanged('hasGroupTitle', NO) ;
|
|
61
|
+
return ;
|
|
62
|
+
} else {
|
|
63
|
+
labelView.setIfChanged('isVisible', YES) ;
|
|
64
|
+
this.setIfChanged('hasGroupTitle', YES) ;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// set the title if that changed.
|
|
68
|
+
var groupTitleKey = this.getDelegateProperty(this.displayDelegate, 'groupTitleKey') ;
|
|
69
|
+
if ((key == '*') || (groupTitleKey && (key == groupTitleKey))) {
|
|
70
|
+
var title = (content && content.get && groupTitleKey) ? content.get(groupTitleKey) : content;
|
|
71
|
+
if (title != this._title) {
|
|
72
|
+
this._title = title ;
|
|
73
|
+
if (title) title = title.capitalize() ;
|
|
74
|
+
labelView.set('title', title) ;
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// set the group visibility if changed
|
|
79
|
+
var groupVisibleKey = this.getDelegateProperty(this.displayDelegate, 'groupVisibleKey') ;
|
|
80
|
+
if ((key == '*') || (groupVisibleKey && (key == groupVisibileKey))) {
|
|
81
|
+
|
|
82
|
+
if (groupVisibleKey) {
|
|
83
|
+
|
|
84
|
+
labelView.removeClassName('no-disclosure') ;
|
|
85
|
+
|
|
86
|
+
var isVisible = (content && content.get) ? !!content.get(groupVisibleKey) : YES ;
|
|
87
|
+
if (isVisible != this.get('isGroupVisible')) {
|
|
88
|
+
this.set('isGroupVisible', isVisible) ;
|
|
89
|
+
labelView.set('value', isVisible) ;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
} else labelView.addClassName('no-disclosure') ;
|
|
93
|
+
}
|
|
94
|
+
},
|
|
95
|
+
|
|
96
|
+
// called when the user clicks on the disclosure triangle
|
|
97
|
+
disclosureValueDidChange: function(newValue) {
|
|
98
|
+
if (newValue == this.get('isGroupVisible')) return; // nothing to do
|
|
99
|
+
|
|
100
|
+
// update group if necessary
|
|
101
|
+
var group = this.get('content') ;
|
|
102
|
+
var groupVisibleKey = this.getDelegateProperty(this.displayDelegate, 'groupVisibleKey') ;
|
|
103
|
+
if (group && group.set && groupVisibleKey) {
|
|
104
|
+
group.set(groupVisibleKey, newValue) ;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
// update my own value and then update my collection view.
|
|
108
|
+
this.set('isGroupVisible', newValue) ;
|
|
109
|
+
if (this.owner && this.owner.updateChildren) this.owner.updateChildren(true) ;
|
|
110
|
+
|
|
111
|
+
},
|
|
112
|
+
|
|
113
|
+
/** @private */
|
|
114
|
+
labelView: SC.DisclosureView.extend({
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
Always default to open disclosures.
|
|
118
|
+
*/
|
|
119
|
+
value: YES,
|
|
120
|
+
|
|
121
|
+
// if the disclosure value changes, call the owner's method. Note
|
|
122
|
+
// normally you would do this with a binding, but since this is a semi-
|
|
123
|
+
// private class anyway, there is no reason to go to all that trouble.
|
|
124
|
+
_valueObserver: function() {
|
|
125
|
+
if (this.owner) this.owner.disclosureValueDidChange(this.get('value'));
|
|
126
|
+
}.observes('value')
|
|
127
|
+
|
|
128
|
+
}).outletFor('.sc-source-list-label:1:1')
|
|
129
|
+
|
|
130
|
+
}) ;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
// ========================================================================
|
|
2
2
|
// SproutCore
|
|
3
|
-
// copyright 2006-
|
|
3
|
+
// copyright 2006-2008 Sprout Systems, Inc.
|
|
4
4
|
// ========================================================================
|
|
5
5
|
|
|
6
6
|
require('views/view') ;
|
|
@@ -0,0 +1,292 @@
|
|
|
1
|
+
// ========================================================================
|
|
2
|
+
// SproutCore
|
|
3
|
+
// copyright 2006-2008 Sprout Systems, Inc.
|
|
4
|
+
// ========================================================================
|
|
5
|
+
|
|
6
|
+
require('views/view') ;
|
|
7
|
+
require('mixins/delegate_support');
|
|
8
|
+
|
|
9
|
+
SC.HORIZONTAL = 'horizontal' ;
|
|
10
|
+
SC.VERTICAL = 'vertical' ;
|
|
11
|
+
|
|
12
|
+
/**
|
|
13
|
+
@class
|
|
14
|
+
|
|
15
|
+
A split view is used to show views that the user can resize or collapse.
|
|
16
|
+
To use the split view, you need to add the child views you want layed out
|
|
17
|
+
separated by divider views (instances of SC.SplitDividerView).
|
|
18
|
+
|
|
19
|
+
When the user clicks and drags on a divider view, it will automatically
|
|
20
|
+
resize the views immediately before and after the view. You can constrain
|
|
21
|
+
the resizing allowed by the split view either by setting a minThickness and
|
|
22
|
+
maxThickness property on the views themselves or by implementing methods
|
|
23
|
+
on a delegate object.
|
|
24
|
+
|
|
25
|
+
In addition to resizing views, users can also collapse views by double
|
|
26
|
+
clicking on a divider view. When a view is collapsed, it's isVisible
|
|
27
|
+
property is set to NO and its space it removed from the view. Double
|
|
28
|
+
clicking on a divider again will restore a collapse view. A user can also
|
|
29
|
+
start to drag the divider to show the collapsed view.
|
|
30
|
+
|
|
31
|
+
You can programmatically control collapsing behavior by setting the
|
|
32
|
+
canCollapseViews property on the SplitView, a canCollapse property on each
|
|
33
|
+
child view, or by implementing the appropriate delegate method.
|
|
34
|
+
|
|
35
|
+
Finally, SplitViews can layout their child views either horizontally or
|
|
36
|
+
vertically. To choose the direction of layout set the layoutDirection
|
|
37
|
+
property on the view. This property should be set when the view is created.
|
|
38
|
+
Changing it dynamically will have an unknown effect.
|
|
39
|
+
|
|
40
|
+
@extends SC.View
|
|
41
|
+
@extends SC.DelegateSupport
|
|
42
|
+
|
|
43
|
+
@author Charles Jolley
|
|
44
|
+
*/
|
|
45
|
+
SC.SplitView = SC.View.extend(SC.DelegateSupport,
|
|
46
|
+
/** @scope SC.SplitView.prototype */ {
|
|
47
|
+
|
|
48
|
+
emptyElement: '<div class="sc-split-view"></div>',
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
delegate for controlling split view behavior.
|
|
52
|
+
*/
|
|
53
|
+
delegate: null,
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
Direction of layout. Must be SC.HORIZONTAL || SC.VERTICAL.
|
|
57
|
+
*/
|
|
58
|
+
layoutDirection: SC.HORIZONTAL,
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
Set to NO to disable collapsing for all views.
|
|
62
|
+
*/
|
|
63
|
+
canCollapseViews: YES,
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
Used by split divider to decide if the view can be collapsed.
|
|
67
|
+
*/
|
|
68
|
+
canCollapseView: function(view) {
|
|
69
|
+
if (!this.get('canCollapseViews')) return NO ;
|
|
70
|
+
if (view.get('canCollapse') === NO) return NO ;
|
|
71
|
+
return this.invokeDelegateMethod(this.delegate, 'splitViewCanCollapse', this, view) ;
|
|
72
|
+
},
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
One view in your array must have a flexible width to allow proper
|
|
76
|
+
resizing. You can set this view manually with this outlet or you can
|
|
77
|
+
just let the split view choose the center-most view.
|
|
78
|
+
|
|
79
|
+
Views to the left/top of this view will be anchored to the left/top of
|
|
80
|
+
the parent view. Views to the right/bottom of this view will be anchored
|
|
81
|
+
to the right/bottom.
|
|
82
|
+
*/
|
|
83
|
+
flexibleView: null,
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
Sets the thickness of the named view and then lays out the rest of the
|
|
87
|
+
views.
|
|
88
|
+
|
|
89
|
+
@param {SC.View} view the view to adjust. Must not be a divider.
|
|
90
|
+
@param {Number} offset the new desired offset
|
|
91
|
+
@returns the actual allowed offset
|
|
92
|
+
*/
|
|
93
|
+
setThicknessForView: function(view, thickness) {
|
|
94
|
+
if (view.get('parentNode') != this) {
|
|
95
|
+
throw "view must belong to reciever (view: %@)".fmt(view);
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
var direction = this.get('layoutDirection') ;
|
|
99
|
+
|
|
100
|
+
// constrain to thickness set on view.
|
|
101
|
+
var max = view.get('maxThickness') ;
|
|
102
|
+
var min = view.get('minThickness') ;
|
|
103
|
+
if (max != null) thickness = Math.min(max, thickness) ;
|
|
104
|
+
if (min != null) thickness = Math.max(min, thickness) ;
|
|
105
|
+
|
|
106
|
+
// constrain to thickness determined by delegate.
|
|
107
|
+
thickness = this.invokeDelegateMethod(this.delegate, 'splitViewConstrainThickness', this, view, thickness) ;
|
|
108
|
+
|
|
109
|
+
// thickness cannot be greater than the total of all the other views (
|
|
110
|
+
// except for the flexibleView) added together.
|
|
111
|
+
var total = this.get('innerFrame') ;
|
|
112
|
+
available = (direction == SC.HORIZONTAL) ? total.width : total.height ;
|
|
113
|
+
var views = this.get('childNodes') ;
|
|
114
|
+
var idx = view.length ;
|
|
115
|
+
var flexibleView = this.get('flexibleView') ;
|
|
116
|
+
while(--idx >= 0) {
|
|
117
|
+
var currentView = views[idx] ;
|
|
118
|
+
if ((currentView != view) && (currentView != flexibleView)) {
|
|
119
|
+
available -= this.thicknessForView(currentView) ;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
thickness = Math.min(thickness, available) ;
|
|
123
|
+
|
|
124
|
+
// cannot be less than 0
|
|
125
|
+
thickness = Math.max(0, thickness) ;
|
|
126
|
+
|
|
127
|
+
// now apply constrained value
|
|
128
|
+
if (thickness != this.thicknessForView(view)) {
|
|
129
|
+
|
|
130
|
+
// un-collapse if needed.
|
|
131
|
+
view.set('isCollapsed', (thickness <= 0)) ;
|
|
132
|
+
|
|
133
|
+
// set new frame
|
|
134
|
+
var f = (direction === SC.HORIZONTAL) ? { width: thickness } : { height: thickness } ;
|
|
135
|
+
view.set('frame', f) ;
|
|
136
|
+
|
|
137
|
+
// and layout
|
|
138
|
+
this.layout() ;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
},
|
|
142
|
+
|
|
143
|
+
/**
|
|
144
|
+
Returns the thickness for a given view.
|
|
145
|
+
|
|
146
|
+
@param {SC.View} view the view to get.
|
|
147
|
+
@returns the view with the width.
|
|
148
|
+
*/
|
|
149
|
+
thicknessForView: function(view) {
|
|
150
|
+
var direction = this.get('layoutDirection') ;
|
|
151
|
+
var ret = view.get('frame') ;
|
|
152
|
+
return (direction === SC.HORIZONTAL) ? ret.width : ret.height ;
|
|
153
|
+
},
|
|
154
|
+
|
|
155
|
+
/**
|
|
156
|
+
Finds the flexible view.
|
|
157
|
+
|
|
158
|
+
This will use the flexibleView property if you set it or use the center
|
|
159
|
+
most view that is not a divider.
|
|
160
|
+
*/
|
|
161
|
+
computeFlexibleView: function() {
|
|
162
|
+
var flexibleView = this.get('flexibleView') ;
|
|
163
|
+
if (!flexibleView) {
|
|
164
|
+
var views = this.get('childNodes') ;
|
|
165
|
+
flexibleView = views[Math.ceil(views.length/2)] ;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// If the flexible view is a divider, find the first non-g.
|
|
169
|
+
while(flexibleView && (flexibleView instanceof SC.SplitDividerView)) {
|
|
170
|
+
flexibleView = flexibleView.get('nextSibling') ;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
return flexibleView;
|
|
174
|
+
},
|
|
175
|
+
|
|
176
|
+
/**
|
|
177
|
+
Layout the views.
|
|
178
|
+
|
|
179
|
+
This method needs to be called anytime you change the view thicknesses
|
|
180
|
+
to make sure they are arranged properly. This will setup the views so
|
|
181
|
+
that they can resize appropriately.
|
|
182
|
+
*/
|
|
183
|
+
layout: function() {
|
|
184
|
+
|
|
185
|
+
var views = this.get('childNodes') ;
|
|
186
|
+
|
|
187
|
+
// find the flexible view, if it is not set.
|
|
188
|
+
var flexibleView = this.computeFlexibleView();
|
|
189
|
+
|
|
190
|
+
// everything before the flexible view is anchored to the left/top
|
|
191
|
+
var direction = this.get('layoutDirection') ;
|
|
192
|
+
var view = views[0];
|
|
193
|
+
var offset = 0 ;
|
|
194
|
+
while(view && (view !== flexibleView)) {
|
|
195
|
+
var isCollapsed = view.get('isCollapsed') || NO ;
|
|
196
|
+
view.setIfChanged('isVisible', !isCollapsed) ;
|
|
197
|
+
if (!isCollapsed) {
|
|
198
|
+
view.viewFrameWillChange() ;
|
|
199
|
+
if (direction == SC.HORIZONTAL) {
|
|
200
|
+
view.setIfChanged('styleLeft', offset) ;
|
|
201
|
+
view.setIfChanged('styleRight', null) ;
|
|
202
|
+
} else {
|
|
203
|
+
view.setIfChanged('styleTop', offset) ;
|
|
204
|
+
view.setIfChanged('styleBottom', null) ;
|
|
205
|
+
}
|
|
206
|
+
view.viewFrameDidChange() ;
|
|
207
|
+
|
|
208
|
+
offset += this.thicknessForView(view) ;
|
|
209
|
+
}
|
|
210
|
+
view = view.get('nextSibling') ;
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
var flexHead = offset ;
|
|
214
|
+
|
|
215
|
+
// everything after the flexible view is anchored to the right/bottom.
|
|
216
|
+
var view = views.last() ;
|
|
217
|
+
var offset = 0;
|
|
218
|
+
while(view && (view !== flexibleView)) {
|
|
219
|
+
var isCollapsed = view.get('isCollapsed') || NO ;
|
|
220
|
+
view.setIfChanged('isVisible', !isCollapsed) ;
|
|
221
|
+
if (!isCollapsed) {
|
|
222
|
+
view.viewFrameWillChange() ;
|
|
223
|
+
if (direction == SC.HORIZONTAL) {
|
|
224
|
+
view.setIfChanged('styleLeft', null) ;
|
|
225
|
+
view.setIfChanged('styleRight', offset) ;
|
|
226
|
+
} else {
|
|
227
|
+
view.setIfChanged('styleTop', null) ;
|
|
228
|
+
view.setIfChanged('styleBottom', offset) ;
|
|
229
|
+
}
|
|
230
|
+
view.viewFrameDidChange() ;
|
|
231
|
+
|
|
232
|
+
offset += this.thicknessForView(view) ;
|
|
233
|
+
}
|
|
234
|
+
view = view.get('previousSibling') ;
|
|
235
|
+
}
|
|
236
|
+
|
|
237
|
+
var flexTail = offset ;
|
|
238
|
+
|
|
239
|
+
if (flexibleView) {
|
|
240
|
+
view = flexibleView ;
|
|
241
|
+
view.viewFrameWillChange() ;
|
|
242
|
+
if (direction == SC.HORIZONTAL) {
|
|
243
|
+
view.setIfChanged('styleLeft', flexHead) ;
|
|
244
|
+
view.setIfChanged('styleRight', flexTail) ;
|
|
245
|
+
view.setIfChanged('styleWidth', null) ;
|
|
246
|
+
} else {
|
|
247
|
+
view.setIfChanged('styleTop', flexHead) ;
|
|
248
|
+
view.setIfChanged('styleBottom', flexTail) ;
|
|
249
|
+
view.setIfChanged('styleHeight', null) ;
|
|
250
|
+
}
|
|
251
|
+
view.viewFrameDidChange() ;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
},
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
(DELEGATE) Control whether a view can be collapsed.
|
|
258
|
+
|
|
259
|
+
The default implemention returns YES.
|
|
260
|
+
|
|
261
|
+
@param {SC.SplitView} splitView the split view
|
|
262
|
+
@param {SC.View} view the view we want to collapse.
|
|
263
|
+
@returns {Boolean} YES to allow collapse.
|
|
264
|
+
*/
|
|
265
|
+
splitViewCanCollapse: function(splitView, view) { return YES; },
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
(DELEGATE) Constrain a views allowed thickness.
|
|
269
|
+
|
|
270
|
+
The default implementation allows any thickness. The view will
|
|
271
|
+
automatically constrain the view to not allow views to overflow the
|
|
272
|
+
visible area.
|
|
273
|
+
|
|
274
|
+
@param {SC.SplitView} splitView the split view
|
|
275
|
+
@param {SC.View} view the view in question
|
|
276
|
+
@param {Number} proposedThickness the proposed thickness.
|
|
277
|
+
@returns the allowed thickness
|
|
278
|
+
*/
|
|
279
|
+
splitViewConstrainThickness: function(splitView, view, proposedThickness) {
|
|
280
|
+
return proposedThickness;
|
|
281
|
+
},
|
|
282
|
+
|
|
283
|
+
/** @private */
|
|
284
|
+
init: function() {
|
|
285
|
+
arguments.callee.base.apply(this, arguments) ;
|
|
286
|
+
this.addClassName(this.get('layoutDirection')) ;
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
|
|
290
|
+
}) ;
|
|
291
|
+
|
|
292
|
+
|