Skip to content

Commit 55548e3

Browse files
author
tomhuda
committed
Add docs for docco
1 parent 7c798ff commit 55548e3

File tree

2 files changed

+114
-39
lines changed

2 files changed

+114
-39
lines changed

index.html

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
<br><br>
2727
{{view App.ProgressBar valueBinding="App.controller.progress"}}
2828
<br><br>
29-
{{#collection JQ.Menu contentBinding="App.people" disabledBinding="App.controller.menuDisabled"}}
29+
{{#collection JQ.Menu contentBinding="App.controller.people" disabledBinding="App.controller.menuDisabled"}}
3030
<a href="#">{{content.name}} {{view JQ.Button labelBinding="parentView.content.name"}}</a>
3131
{{else}}
3232
<a href="#">LIST NOT LOADED</a>

js/app.js

Lines changed: 113 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,34 +1,39 @@
11
var App = SC.Application.create();
22

3+
// Put jQuery UI inside its own namespace
34
JQ = {};
45

6+
// Create a new mixin for jQuery UI widgets using the new SproutCore 2.0
7+
// mixin syntax.
58
JQ.Widget = SC.Mixin.create({
9+
// When SproutCore creates the view's DOM element, it will call this
10+
// method.
611
didCreateElement: function() {
712
this._super();
813

14+
// Make jQuery UI options available as SproutCore properties
915
var options = this._gatherOptions();
16+
17+
// Make sure that jQuery UI events trigger methods on this view.
1018
this._gatherEvents(options);
1119

20+
// Create a new instance of the jQuery UI widget based on its `uiType`
21+
// and the current element.
1222
var ui = jQuery.ui[this.get('uiType')](options, this.get('element'));
1323

24+
// Save off the instance of the jQuery UI widget as the `ui` property
25+
// on this SproutCore view.
1426
this.set('ui', ui);
1527
},
1628

17-
_gatherEvents: function(options) {
18-
var uiEvents = this.get('uiEvents') || [], self = this;
19-
20-
uiEvents.forEach(function(event) {
21-
var callback = self[event];
22-
23-
if (callback) {
24-
options[event] = function(event, ui) { callback.call(self, event, ui); };
25-
}
26-
});
27-
},
28-
29+
// When SproutCore tears down the view's DOM element, it will call
30+
// this method.
2931
willDestroyElement: function() {
3032
var ui = this.get('ui');
33+
3134
if (ui) {
35+
// Tear down any observers that were created to make jQuery UI
36+
// options available as SproutCore properties.
3237
var observers = this._observers;
3338
for (var prop in observers) {
3439
if (observers.hasOwnProperty(prop)) {
@@ -39,40 +44,82 @@ JQ.Widget = SC.Mixin.create({
3944
}
4045
},
4146

47+
// Each jQuery UI widget has a series of options that can be configured.
48+
// For instance, to disable a button, you call
49+
// `button.options('disabled', true)` in jQuery UI. To make this compatible
50+
// with SproutCore bindings, any time the SproutCore property for a
51+
// given jQuery UI option changes, we update the jQuery UI widget.
4252
_gatherOptions: function() {
4353
var uiOptions = this.get('uiOptions'), options = {};
4454

55+
// The view can specify a list of jQuery UI options that should be treated
56+
// as SproutCore properties.
4557
uiOptions.forEach(function(key) {
4658
options[key] = this.get(key);
4759

60+
// Set up an observer on the SproutCore property. When it changes,
61+
// call jQuery UI's `setOption` method to reflect the property onto
62+
// the jQuery UI widget.
4863
var observer = function() {
4964
var value = this.get(key);
5065
this.get('ui')._setOption(key, value);
5166
};
5267

5368
this.addObserver(key, observer);
69+
70+
// Insert the observer in a Hash so we can remove it later.
5471
this._observers = this._observers || {};
5572
this._observers[key] = observer;
5673
}, this);
5774

5875
return options;
76+
},
77+
78+
// Each jQuery UI widget has a number of custom events that they can
79+
// trigger. For instance, the progressbar widget triggers a `complete`
80+
// event when the progress bar finishes. Make these events behave like
81+
// normal SproutCore events. For instance, a subclass of JQ.ProgressBar
82+
// could implement the `complete` method to be notified when the jQuery
83+
// UI widget triggered the event.
84+
_gatherEvents: function(options) {
85+
var uiEvents = this.get('uiEvents') || [], self = this;
86+
87+
uiEvents.forEach(function(event) {
88+
var callback = self[event];
89+
90+
if (callback) {
91+
// You can register a handler for a jQuery UI event by passing
92+
// it in along with the creation options. Update the options hash
93+
// to include any event callbacks.
94+
options[event] = function(event, ui) { callback.call(self, event, ui); };
95+
}
96+
});
5997
}
6098
});
6199

100+
// Create a new SproutCore view for the jQuery UI Button widget
62101
JQ.Button = SC.View.extend(JQ.Widget, {
63102
uiType: 'button',
64103
uiOptions: ['label', 'disabled'],
65104

66105
tagName: 'button'
67106
});
68107

108+
// Create a new SproutCore view for the jQuery UI Menu widget (new
109+
// in jQuery UI 1.9). Because it wraps a collection, we extend from
110+
// SproutCore's CollectionView rather than a normal view.
111+
//
112+
// This means that you should use `#collection` in your template to
113+
// create this view.
69114
JQ.Menu = SC.CollectionView.extend(JQ.Widget, {
70115
uiType: 'menu',
71116
uiOptions: ['disabled'],
72117
uiEvents: ['select'],
73118

74119
tagName: 'ul',
75120

121+
// Whenever the underlying Array for this `CollectionView` changes,
122+
// refresh the jQuery UI widget.
76123
arrayDidChange: function(content, start, removed, added) {
77124
this._super(content, start, removed, added);
78125

@@ -81,37 +128,60 @@ JQ.Menu = SC.CollectionView.extend(JQ.Widget, {
81128
}
82129
});
83130

84-
App.controller = SC.Object.create({
85-
progress: 0,
86-
menuDisabled: true
87-
});
88-
131+
// Create a new SproutCore view for the jQuery UI Progrress Bar widget
89132
JQ.ProgressBar = SC.View.extend(JQ.Widget, {
90133
uiType: 'progressbar',
91134
uiOptions: ['value', 'max'],
92135
uiEvents: ['change', 'complete']
93136
});
94137

138+
// Create a simple controller to hold values that will be shared across
139+
// views.
140+
App.controller = SC.Object.create({
141+
progress: 0,
142+
menuDisabled: true
143+
});
144+
145+
// Create a subclass of `JQ.Button` to define behavior for our button.
95146
App.Button = JQ.Button.extend({
147+
// When the button is clicked...
96148
click: function() {
97-
var self = this;
149+
// Disable the button.
98150
this.set('disabled', true);
99-
setTimeout(function() { self.increment.call(self) }, 30);
151+
152+
// Increment the progress bar.
153+
this.increment();
100154
},
101155

102156
increment: function() {
103157
var self = this;
158+
159+
// Get the current progress value from the controller.
104160
var val = App.controller.get('progress');
161+
105162
if(val < 100) {
163+
// If the value is less than 100, increment it.
106164
App.controller.set('progress', val + 1);
107-
setTimeout(function() { self.increment.call(self) }, 30);
165+
166+
// Schedule another increment call from 30ms.
167+
setTimeout(function() { self.increment() }, 30);
108168
}
109169
}
110170
});
111171

172+
// Create a subclass of `JQ.ProgressBar` to define behavior for our
173+
// progress bar.
112174
App.ProgressBar = JQ.ProgressBar.extend({
175+
// When the jQuery UI progress bar reaches 100%, it will invoke the
176+
// `complete` event. Recall that JQ.Widget registers a callback for
177+
// the `complete` event in `didCreateElement`, which calls the
178+
// `complete` method.
113179
complete: function() {
114-
App.set('people', [
180+
// When the progress bar finishes, update App.controller with the
181+
// list of people. Because our template binds the JQ.Menu to this
182+
// value, it will automatically populate with the new people and
183+
// refresh the menu.
184+
App.controller.set('people', [
115185
SC.Object.create({
116186
name: "Tom DAAAAALE"
117187
}),
@@ -122,24 +192,29 @@ App.ProgressBar = JQ.ProgressBar.extend({
122192
name: "Majd Potatoes"
123193
})
124194
]);
195+
196+
// Set the `menuDisabled` property of our controller to false.
197+
// Because the JQ.Menu binds its `disabled` property to
198+
// App.controller.menuDisabled, this will enable it.
125199
App.controller.set('menuDisabled', false);
126200
}
127201
});
128202

129-
// App.people = [
130-
// SC.Object.create({
131-
// name: "Tom DAAAAALE"
132-
// }),
133-
// SC.Object.create({
134-
// name: "Yehuda Katz"
135-
// }),
136-
// SC.Object.create({
137-
// name: "Majd Potatoes"
138-
// })
139-
// ]
140-
141-
App.MyView = SC.View.extend({
142-
mouseDown: function() {
143-
window.alert("hello world!");
144-
}
145-
});
203+
/**
204+
Template:
205+
206+
{{view App.Button label="Click to Load People"}}
207+
<br><br>
208+
{{view App.ProgressBar valueBinding="App.controller.progress"}}
209+
<br><br>
210+
{{#collection JQ.Menu
211+
contentBinding="App.controller.people"
212+
disabledBinding="App.controller.menuDisabled"}}
213+
<a href="#">
214+
{{content.name}}
215+
{{view JQ.Button labelBinding="parentView.content.name"}}
216+
</a>
217+
{{else}}
218+
<a href="#">LIST NOT LOADED</a>
219+
{{/collection}}
220+
*/

0 commit comments

Comments
 (0)