Class: SC.RenderDelegate
Base class for all render delegates.
You should use SC.RenderDelegate
or a subclass of it as the base for all
of your render delegates. SC.RenderDelegate
offers many helper methods
and can be simpler to subclass between themes than SC.Object
.
Creating & Subclassing
You create render delegates just like you create SC.Objects
:
MyTheme.someRenderDelegate = SC.RenderDelegate.create({ ... });
You can subclass a render delegate and use that:
MyTheme.RenderDelegate = SC.RenderDelegate.extend({ ... });
MyTheme.someRenderDelegate = MyTheme.RenderDelegate.create({});
And you can even subclass instances or SC.RenderDelegate
:
MyTheme.someRenderDelegate = SC.RenderDelegate.create({ ... });
MyTheme.otherRenderDelegate = MyTheme.someRenderDelegate.create({ ... });
// this allows you to subclass another theme's render delegate:
MyTheme.buttonRenderDelegate = SC.BaseTheme.buttonRenderDelegate.create({ ... });
For render delegates, subclassing and instantiating are the same.
NOTE: Even though .extend
and .create
technically do the same thing,
convention dictates that you use .extend
for RenderDelegates that
will be used primarily as base classes, and create
for RenderDelegates
that you expect to be instances.
Rendering and Updating
Render delegates are most commonly used for two things: rendering and updating DOM representations of controls.
Render delegates use their render
and update
methods to do this:
render: function(dataSource, context) {
// rendering tasks here
// example:
context.begin('div').addClass('title')
.text(dataSource.get('title')
.end();
},
update: function(dataSource, jquery) {
// updating tasks here
// example:
jquery.find('.title').text(dataSource.get('title'));
}
Variables
The data source provides your render delegate with all of the information needed to render. However, the render delegate's consumer--usually a view-- may need to get information back.
For example, SC.AutoResize
resizes controls to fit their text. You can use
it to size a button to fit its title. But it can't just make the button
have the same width as its title: it needs to be a little larger to make room
for the padding to the left and right sides of the title.
This padding will vary from theme to theme.
You can specify properties on the render delegate like any other property:
MyRenderDelegate = SC.RenderDelegate.create({
autoSizePadding: 10
...
});
But there are multiple sizes of buttons; shouldn't the padding change as well? You can add hashes for the various control sizes and override properties:
SC.RenderDelegate.create({
autoSizePadding: 10,
'sc-jumbo-size': {
autoResizePadding: 20
}
For details, see the discussion on size helpers below.
You can also calculate values for the data source. In this example, we calculate
the autoSizePadding
to equal half the data source's height:
SC.RenderDelegate.create({
autoSizePaddingFor: function(dataSource) {
if (dataSource.get('frame')) {
return dataSource.get('frame').height / 2;
}
}
When SC.ButtonView
tries to get autoSizePadding
, the render delegate will look for
autoSizePaddingFor
. It will be called if it exists. Otherwise, the property will
be looked up like normal.
Note: To support multiple sizes, you must also render the class name; see size helper discussion below.
Helpers
SC.RenderDelegate
have "helper methods" to assist the rendering process.
There are a few built-in helpers, and you can add your own.
Slices
Chance provides the includeSlices
method to easily slice images for
use in the SproutCore theme system.
includeSlices(dataSource, context, slices);
You can call this to add DOM that matches Chance's @include slices()
directive. For example:
MyTheme.buttonRenderDelegate = SC.RenderDelegate.create({
className: 'button',
render: function(dataSource, context) {
this.includeSlices(dataSource, context, SC.THREE_SLICE);
}
});
DOM elements will be added as necessary for the slices. From your CSS, you can match it like this:
$theme.button {
Defined in: render_delegate.js
Field Summary
Instance Methods
- create()
- get(propertyName)
- getPropertyFor(dataSource, propertyName)
- render(dataSource, context)
- reopen(mixin)
- update(dataSource, jquery)
Field Detail
classNameAll render delegates should have a class name. Any time a render delegate is
used, this name should be added as a class name (SC.View
s do this
automatically).
Instance Method Detail
Creates a new render delegate based on this one. When you want to create a render delegate, you call this:
MyTheme.myRenderDelegate = SC.RenderDelegate.create({
className: 'my-render-delegate',
render: function(dataSource, context) {
// your code here...
}
})
Returns the specified property from this render delegate.
Implemented to match SC.Object's
API.
- Parameters:
- propertyName
Gets or generates the named property for the specified
dataSource
. If a method propertyName + 'For'
is found,
it will be used to compute the value, dataSource
being passed as an argument. Otherwise, it will simply
be looked up on the render delegate.
NOTE: this implementation is a reference implementation. It is overridden in the sizing code (helpers/sizing.js) to be size-sensitive.
- Parameters:
- dataSource
- propertyName
Writes the DOM representation of this render delegate to the
supplied SC.RenderContext
, using the supplied dataSource
for any data needed.
- Parameters:
- dataSource DataSource
- An object from which to get data. See documentation on data sources above.
- context SC.RenderContext
- A context to render DOM into.
Adds extra capabilities to this render delegate.
You can use this to add helpers to all render delegates:
SC.RenderDelegate.reopen({
myHelperMethod: function(dataSource) { ... }
});
- Parameters:
- mixin
Updates the DOM representation of this render delegate using
the supplied jQuery
instance and dataSource
.
- Parameters:
- dataSource DataSource
- An object from which to get data. See documentation on data sources above.
- jquery jQuery
- A jQuery instance containing the DOM element to update. This will be the DOM generated by `render()`.