app.js | |
|---|---|
window.App = Ember.Application.create(); | |
| Put jQuery UI inside its own namespace | JQ = Ember.Namespace.create(); |
| Create a new mixin for jQuery UI widgets using the Ember mixin syntax. | JQ.Widget = Em.Mixin.create({ |
| When Ember creates the view's DOM element, it will call this method. | didInsertElement: function() { |
| Make jQuery UI options available as Ember properties | var options = this._gatherOptions(); |
| Make sure that jQuery UI events trigger methods on this view. | this._gatherEvents(options); |
| Create a new instance of the jQuery UI widget based on its | var ui = jQuery.ui[this.get('uiType')](options, this.get('element')); |
| Save off the instance of the jQuery UI widget as the | this.set('ui', ui);
}, |
| When Ember tears down the view's DOM element, it will call this method. | willDestroyElement: function() {
var ui = this.get('ui');
if (ui) { |
| Tear down any observers that were created to make jQuery UI options available as Ember properties. | var observers = this._observers;
for (var prop in observers) {
if (observers.hasOwnProperty(prop)) {
this.removeObserver(prop, observers[prop]);
}
}
ui._destroy();
}
}, |
| Each jQuery UI widget has a series of options that can be configured.
For instance, to disable a button, you call
| _gatherOptions: function() {
var uiOptions = this.get('uiOptions'), options = {}; |
| The view can specify a list of jQuery UI options that should be treated as Ember properties. | uiOptions.forEach(function(key) {
options[key] = this.get(key); |
| Set up an observer on the Ember property. When it changes,
call jQuery UI's | var observer = function() {
var value = this.get(key);
this.get('ui').option(key, value);
};
this.addObserver(key, observer); |
| Insert the observer in a Hash so we can remove it later. | this._observers = this._observers || {};
this._observers[key] = observer;
}, this);
return options;
}, |
| Each jQuery UI widget has a number of custom events that they can
trigger. For instance, the progressbar widget triggers a | _gatherEvents: function(options) {
var uiEvents = this.get('uiEvents') || [], self = this;
uiEvents.forEach(function(event) {
var callback = self[event];
if (callback) { |
| You can register a handler for a jQuery UI event by passing it in along with the creation options. Update the options hash to include any event callbacks. | options[event] = function(event, ui) { callback.call(self, event, ui); };
}
});
}
}); |
| Create a new Ember view for the jQuery UI Button widget | JQ.ButtonView = Em.View.extend(JQ.Widget, {
uiType: 'button',
uiOptions: ['label', 'disabled'],
tagName: 'button'
}); |
| Create a new Ember view for the jQuery UI Menu widget. Because it wraps a collection, we extend from Ember's CollectionView rather than a normal view. This means that you should use | JQ.MenuView = Em.CollectionView.extend(JQ.Widget, {
uiType: 'menu',
uiOptions: ['disabled'],
uiEvents: ['select'],
tagName: 'ul', |
| Whenever the underlying Array for this | arrayDidChange: function(content, start, removed, added) {
this._super(content, start, removed, added);
var ui = this.get('ui');
if (ui) { |
| Schedule the refresh for after Ember has completed it's render cycle | Em.run.scheduleOnce('afterRender', ui, ui.refresh);
}
},
itemViewClass: Em.View.extend({ |
| Make it so that the default context for evaluating handlebars bindings is the content of this child view. | context: function(){
return this.get('content');
}.property('content')
})
}); |
| Create a new Ember view for the jQuery UI Progress Bar widget | JQ.ProgressBarView = Em.View.extend(JQ.Widget, {
uiType: 'progressbar',
uiOptions: ['value', 'max'],
uiEvents: ['change', 'complete']
}); |
| Create a simple controller to hold values that will be shared across views. | App.ApplicationController = Em.Controller.extend({
progress: 0,
menuDisabled: true,
people: [],
incrementProgress: function() { |
| Get the current progress value. | var val = this.get('progress');
if(val < 100) { |
| If the value is less than 100, increment it. | this.incrementProperty('progress'); |
| Schedule another incrementProgress call in 30ms. | Ember.run.later(this, this.incrementProgress, 30);
}
}
}); |
| Create a subclass of | App.ButtonView = JQ.ButtonView.extend({ |
| When the button is clicked... | click: function() { |
| Disable the button. | this.set('disabled', true); |
| Increment the progress bar by delegating to the controller. | this.get('controller').incrementProgress();
}
}); |
| Create a subclass of | App.ProgressBarView = JQ.ProgressBarView.extend({ |
| When the jQuery UI progress bar reaches 100%, it will invoke the
| complete: function() { |
| When the progress bar finishes, update the controller with the list of people. Because our template binds the JQ.MenuView to this value, it will automatically populate with the new people and refresh the menu. | this.set('controller.people', [
Em.Object.create({
name: "Tom DAAAAALE"
}),
Em.Object.create({
name: "Yehuda Katz"
}),
Em.Object.create({
name: "Selden Seen"
})
]); |
| Set the | this.set('controller.menuDisabled', false);
}
});
/**
Template:
{{view App.ButtonView label="Click to Load People"}}
<br><br>
{{view App.ProgressBarView valueBinding="progress"}}
<br><br>
{{#collection JQ.MenuView contentBinding="people" disabledBinding="menuDisabled"}}
<a href="#">{{name}}</a>
{{else}}
<a href="#">LIST NOT LOADED</a>
{{/collection}}
*/
|