can
Version:
MIT-licensed, client-side, JavaScript framework that makes building rich web applications easy.
1,135 lines (795 loc) • 40.7 kB
HTML
<!--####################################################################
THIS IS A GENERATED FILE -- ANY CHANGES MADE WILL BE OVERWRITTEN
INSTEAD CHANGE:
source: [object Object]
@module can-control
######################################################################## -->
<html lang="en">
<head>
<meta charset="utf-8">
<title>CanJS - can-control</title>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<link rel="stylesheet" type="text/css" href="./static/bundles/bit-docs-site/static.css">
<link rel="shortcut icon" sizes="16x16 24x24 32x32 48x48 64x64" href="/docs/images/canjs_favicon.ico">
<link rel="apple-touch-icon" sizes="57x57" href="../docs/images/canjs_favicon_57x57.png">
<link rel="apple-touch-icon-precomposed" sizes="57x57" href="../docs/images/canjs_favicon_57x57.png">
<link rel="apple-touch-icon" sizes="72x72" href="../docs/images/canjs_favicon_72x72.png">
<link rel="apple-touch-icon" sizes="114x114" href="../docs/images/canjs_favicon_114x114.png">
<link rel="apple-touch-icon" sizes="120x120" href="../docs/images/canjs_favicon_128x128.png">
<link rel="apple-touch-icon" sizes="144x144" href="../docs/images/canjs_favicon_144x144.png">
<link rel="apple-touch-icon" sizes="152x152" href="../docs/images/canjs_favicon_152x152.png">
<meta content="yes" name="apple-mobile-web-app-capable">
<meta name="apple-mobile-web-app-status-bar-style" content="white-translucent">
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-2302003-11', 'auto');
ga('send', 'pageview');
</script>
</head>
<body>
<input type="checkbox" id="nav-trigger" class="nav-trigger"/>
<label for="nav-trigger">Menu</label>
<div id="everything">
<div id="left" class="column">
<div class="top-left">
<div class="brand">
<div class="logo">
<a href="../index.html" alt="CanJS"></a>
<div class="dropdown project-dropdown">
<a href="https://donejs.com/">DoneJS</a>
<a href="http://stealjs.com/">StealJS</a>
<a href="http://jquerypp.com/">jQuery ++</a>
<a href="https://funcunit.com/">FuncUnit</a>
<a href="http://documentjs.com/">DocumentJS</a>
</div>
</div>
<div class="version">
<div class="version-number">
3.0.0
</div>
<div class="dropdown version-dropdown">
<a href="https://v2.canjs.com">2.3.27</a>
</div>
</div>
</div>
<div class="search-bar">
<p>
</p>
</div>
</div>
<div class="bottom-left">
<div class="social-side-container">
<ul class="social-side">
<li>
<a class="header-mobile github" href="https://github.com/canjs/canjs" target="_blank"><img class="social-icon-small" src="../docs/images/github.png">Github</a>
</li>
<li>
<a class="header-mobile twitter" href="https://twitter.com/canjs" target="_blank"><img class="social-icon-small" src="../docs/images/twitter.png">Twitter</a>
</li>
</ul>
<ul class="social-side">
<li>
<a class="header-mobile" href="https://gitter.im/canjs/canjs" target="_blank">Chat</a>
</li>
<li>
<a class="header-mobile" href="http://forums.donejs.com/c/canjs" target="_blank">Forum</a>
</li>
</ul>
</div>
<ul>
<li class="
">
<a class="page"
href="guides.html"
title="Welcome to CanJS! These guides are here to help you develop and improve your relationship with CanJS. After all, picking a JavaScript framework is a commitment. We want CanJS to be the
framework you marry. This page helps you know how advance through the different stages of this
relationship:">
Guides
</a>
</li>
<li class="
">
<a class="page"
href="can-core.html"
title="The best, most hardened and generally useful libraries in CanJS.">
Core
</a>
</li>
<li class="
">
<a class="page"
href="can-ecosystem.html"
title="Useful libraries that extend or add important features to the core collection.">
Ecosystem
</a>
</li>
<li class="
parent
expanded">
<a class="page"
href="can-infrastructure.html"
title="Utility libraries that power the core and ecosystem collection.">
Infrastructure
</a>
<ul>
<li class="
">
<a class="module"
href="can-construct.html"
title="Provides a way to easily use the power of prototypal inheritance
without worrying about hooking up all the particulars yourself. Use
can-construct.extend to create an inheritable
constructor function of your own.">
can-construct
</a>
</li>
<li class="current
parent
expanded">
<a class="module"
href="can-control.html"
title="Create organized, memory-leak free, rapidly performing, stateful controls with declarative event binding. Use Control to create UI
controls like tabs, grids, and context menus,
and organize them into higher-order business rules with
can.route. It can serve as both a traditional view and a traditional controller.">
can-control
</a>
<ul>
<li>
<span>static</span>
<ul>
<li class="
">
<a class="property"
href="can-control.defaults.html"
title="Default values for the Control's options.">
defaults
</a>
</li>
<li class="
">
<a class="function"
href="can-control.extend.html"
title="">
extend
</a>
</li>
<li class="
">
<a class="property"
href="can-control.processors.html"
title="A collection of hookups for custom events on Controls.">
processors
</a>
</li>
</ul>
</li>
<li>
<span>prototype</span>
<ul>
<li class="
">
<a class="function"
href="can-control.prototype.destroy.html"
title="Remove a Control from an element and clean up the Control.">
destroy
</a>
</li>
<li class="
">
<a class="property"
href="can-control.prototype.element.html"
title="The element passed to the Control when creating a new instance.">
element
</a>
</li>
<li class="
">
<a class="function"
href="can-control.prototype.on.html"
title="Bind an event handler to a Control, or rebind all event handlers on a Control.">
on
</a>
</li>
<li class="
">
<a class="property"
href="can-control.prototype.options.html"
title="Options used to configure a control.">
options
</a>
</li>
<li class="
">
<a class="function"
href="can-control.prototype.setup.html"
title="Perform pre-initialization logic for control instances and classes.">
setup
</a>
</li>
</ul>
</li>
</ul>
</li>
<li class="
">
<a class="module"
href="can-event.html"
title="Add event functionality into your objects.
The canEvent object provides a number of methods for handling events in objects. This functionality is best used by mixing the canEvent object into an object or prototype. However, event listeners can still be used even on objects that don't include canEvent.
All methods provided by canEvent assume that they are mixed into an object -- this should be the object dispatching the events.">
can-event
</a>
</li>
<li class="
">
<a class="module"
href="can-event/async/async.html"
title="Makes the event system asynchronous. WARNING: This is experimental technology.">
can-event/async/async
</a>
</li>
<li class="
">
<a class="module"
href="can-event/batch/batch.html"
title="Adds task batching abilities to event dispatching.">
can-event/batch/batch
</a>
</li>
<li class="
">
<a class="module"
href="can-observation.html"
title="Provides a mechanism to notify when an observable has been read and a
way to observe those reads called within a given function.">
can-observation
</a>
</li>
<li class="
">
<a class="module"
href="can-simple-map.html"
title="A performant live-bound map.">
can-simple-map
</a>
</li>
<li class="
">
<a class="page"
href="can-util.html"
title="A set of utilities.">
can-util
</a>
</li>
<li class="
">
<a class="module"
href="can-view-callbacks.html"
title="Registered callbacks for behaviors">
can-view-callbacks
</a>
</li>
<li class="
">
<a class="module"
href="can-view-live.html"
title="Setup live-binding between the DOM and a compute manually.">
can-view-live
</a>
</li>
<li class="
">
<a class="module"
href="can-view-model.html"
title="Gets the ViewModel of an element.">
can-view-model
</a>
</li>
<li class="
">
<a class="module"
href="can-view-nodelist.html"
title="Adds nesting of text nodes
can.view.nodeLists are used to make sure "directly nested" live-binding
sections update content correctly.
Consider the following template:
<div>
{{#if items.length}}
Items:
{{#items}}
<label></label>
{{/items}}
{{/if}}
</div>
The {{#if}} and {{#items}} seconds are "directly nested" because
they share the same <div> parent element.
If {{#items}} changes the DOM by adding more <labels>,
{{#if}} needs to know about the <labels> to remove them
if {{#if}} is re-rendered. {{#if}} would be re-rendered, for example, if
all items were removed.">
can-view-nodelist
</a>
</li>
<li class="
">
<a class="module"
href="can-view-parser.html"
title="Parse HTML and mustache tokens.">
can-view-parser
</a>
</li>
<li class="
">
<a class="module"
href="can-view-scope.html"
title="Create a lookup node for keys.">
can-view-scope
</a>
</li>
<li class="
">
<a class="module"
href="can-view-target.html"
title="">
can-view-target
</a>
</li>
</ul>
</li>
<li class="
">
<a class="page"
href="can-legacy.html"
title="Former libraries that we still accept patches for, but are not under active development.">
Legacy
</a>
</li>
</ul>
</div>
</div>
<div id="right" class="column">
<div class="top-right">
<div class="top-right-top">
<ul class="top-right-bitovi">
<li class="dropdown">
<a href="http://bitovi.com" class="bitovi icon-bits">Bitovi</a>
<ul class="dropdown-menu">
<li><a href="http://bitovi.com">Bitovi.com</a></li>
<li><a href="http://bitovi.com/blog/">Blog</a></li>
<li><a href="http://bitovi.com/consulting/">Consulting</a></li>
<li><a href="http://bitovi.com/training/">Training</a></li>
<li><a href="http://bitovi.com/open-source/">Open Source</a></li>
</ul>
</li>
</ul>
<div class="brand">
<div class="logo">
<a href="../index.html" alt="CanJS"></a>
</div>
</div>
<ul class="top-right-links">
<li>
<a href="https://gitter.im/canjs/canjs">Chat</a>
</li>
<li>
<a href="http://forums.donejs.com/c/canjs">Forum</a>
</li>
<li>
<a class="github-button nav-social" href="https://github.com/canjs/canjs" data-count-href="/canjs/canjs/stargazers" data-count-api="/repos/canjs/canjs#stargazers_count">Star</a>
</li>
<li>
<a href="https://twitter.com/canjs" class="twitter-follow-button nav-social" data-show-count="true" data-show-screen-name="false">Follow @canjs</a><script async src="//platform.twitter.com/widgets.js" charset="utf-8"></script>
</li>
</ul>
</div>
<div class="breadcrumb">
<li><a href="../index.html">CanJS</a></li> /
<li><a href="can-infrastructure.html">Infrastructure</a></li> /
<li><a href="can-control.html">can-control</a></li>
<li class="breadcrumb-dropdown">/ <a> On this page</a>
<ul class="on-this-page"></ul>
</li>
<div class="nav-toggle" title="Back to top"></div>
</div>
</div>
<div class="bottom-right">
<article>
<section class="title">
<div class="page-type">
<h1>can-control</h1>
<div>module</div>
</div>
<section class="description">
<p>Create organized, memory-leak free, rapidly performing, stateful controls with declarative event binding. Use <code>Control</code> to create UI
controls like tabs, grids, and context menus,
and organize them into higher-order business rules with
[can.route]. It can serve as both a traditional view and a traditional controller.</p>
</section>
</section>
<section class="on-this-page-table">
</section>
<section class="title-footer">
<ul class="title-social">
<li>
<a class="npm-button" href="https://www.npmjs.com/package/can-control">
<img src="https://img.shields.io/badge/npm%20package-3.0.3-brightgreen.svg" alt="npm package badge" />
</a>
</li>
<li>
<a class="github-button nav-social" href="https://github.com/canjs/can-control"
data-count-href="/canjs/can-control/stargazers"
data-count-api="/repos/canjs/can-control#stargazers_count">Star</a>
</li>
</ul>
<ul class="title-links">
<!-- <li><a href="#">docco</a></li> -->
<li><a href="//github.com/canjs/can-control/tree/v3.0.3/docs/control.md">source</a></li>
<!-- <li><a href="#">download</a></li> -->
<!-- <li><a href="#">tests</a></li> -->
</ul>
</section>
<div class="signature">
<h2 class="signature-title">
<code>Control( [staticProperties,] instanceProperties )</code>
</h2>
<p>Create a new, extended, control constructor
function. This functionality is inherited from <a href="can-construct.html" title="Provides a way to easily use the power of prototypal inheritance
without worrying about hooking up all the particulars yourself. Use
can-construct.extend to create an inheritable
constructor function of your own.">can-construct</a> and is deprecated in favor of using
<a href="can-control.extend.html" title="">extend</a>.</p>
<div class="parameters">
<h3 class="parameters-title">Parameters</h3>
<ol>
<li><b>staticProperties</b> <code>{Object}</code>: <p>An object of properties and methods that are added the control constructor
function directly. The most common property to add is <a href="can-control.defaults.html" title="Default values for the Control's options.">defaults</a>.</p>
</li>
<li><b>instanceProperties</b> <code>{Object}</code>: <p>An object of properties and methods that belong to
instances of the <code>Control</code> constructor function. These properties are added to the
control's <code>prototype</code> object. Properties that
look like event handlers (ex: <code>"{element} click"</code> or <code>"{element} li mouseenter"</code>) are setup
as event handlers (see <a href="#section_Listeningtoevents">Listening to events</a>).</p>
</li>
</ol>
</div>
<div class="returns">
<h3 class="returns-title">Returns</h3>
<p> <code>{constructor(element, options) => can.Construct}</code>: <p>A control constructor function that has been
extended with the provided <code>staticProperties</code> and <code>instanceProperties</code>.</p>
</p>
</div>
</div>
<div class="signature">
<h2 class="signature-title">
<code>new Control( element, options )</code>
</h2>
<p>Create an instance of a control. [can.Control.prototype.setup] processes
the arguments and sets up event binding. Write your initialization
code in [can.Control.prototype.init]. Note, you never call <code>new Control()</code> directly,
instead, you call it on constructor functions extended from <code>Control</code>.</p>
<div class="parameters">
<h3 class="parameters-title">Parameters</h3>
<ol>
<li><b>element</b> <code>{HTMLElement|<a href="can-view-nodelist.html" title="Adds nesting of text nodes
can.view.nodeLists are used to make sure "directly nested" live-binding
sections update content correctly.
Consider the following template:
<div>
{{#if items.length}}
Items:
{{#items}}
<label></label>
{{/items}}
{{/if}}
</div>
The {{#if}} and {{#items}} seconds are "directly nested" because
they share the same <div> parent element.
If {{#items}} changes the DOM by adding more <labels>,
{{#if}} needs to know about the <labels> to remove them
if {{#if}} is re-rendered. {{#if}} would be re-rendered, for example, if
all items were removed.">can-view-nodelist</a>|CSSSelectorString}</code>: <p>Specifies the element the control will be created on.</p>
</li>
<li><b>options</b> <code>{Object|<a href="can-map.html" title="Create observable objects.">can-map</a>|<a href="can-define/map/map.html" title="Create observable objects.">can-define/map/map</a>}</code>: <p>Option values merged with <a href="can-control.defaults.html" title="Default values for the Control's options.">Control.defaults</a>
and set as <a href="can-control.prototype.options.html" title="Options used to configure a control.">this.options</a>. If options is an observable (<a href="can-map.html" title="Create observable objects.">CanMap</a> / <a href="can-define/map/map.html" title="Create observable objects.">DefineMap</a>), any values from <a href="can-control.defaults.html" title="Default values for the Control's options.">defaults</a> that do not exist on the observable will be set. The observable will then be set as <a href="can-control.prototype.options.html" title="Options used to configure a control.">this.options</a>.</p>
</li>
</ol>
</div>
<div class="returns">
<h3 class="returns-title">Returns</h3>
<p> <code>{<a href="can-control.html" title="Create organized, memory-leak free, rapidly performing, stateful controls with declarative event binding. Use Control to create UI
controls like tabs, grids, and context menus,
and organize them into higher-order business rules with
can.route. It can serve as both a traditional view and a traditional controller.">can-control</a>}</code>: <p>A new instance of the constructor function extending Control.</p>
</p>
</div>
</div>
<section class="body">
<h2>The Control Lifecycle</h2>
<p>The following walks through a control's lifecycle
with an example todo list widget. It's broken up into the following
lifecycle events:</p>
<ul>
<li>Extending a control</li>
<li>Creating a control instance</li>
<li>Listening to events</li>
<li>Destroying a control</li>
</ul>
<h2>Extending a control</h2>
<p>The following example builds up a basic todos widget for listing
and completing todo items. Start by creating a control constructor
function of your own by extending <a href="can-control.html" title="Create organized, memory-leak free, rapidly performing, stateful controls with declarative event binding. Use Control to create UI
controls like tabs, grids, and context menus,
and organize them into higher-order business rules with
can.route. It can serve as both a traditional view and a traditional controller.">can-control</a> and defining an instance init method.</p>
<pre><code>var Todos = Control.extend({
init: function( element, options ) { ... }
});
</code></pre>
<h2>Creating a control instance</h2>
<p>Create an instance of the Todos control on the <code>todos</code> element with:</p>
<pre><code>var todosControl = new Todos( '#todos', {} );
</code></pre>
<p>The control's associated [can.ejs EJS] template looks like:</p>
<pre><code><% todos.each(function( todo ) { %>
<li <%= (el) -> el.data( 'todo', todo ) %> >
<%= todo.attr( 'name' ) %>
<a href="javascript://" class="destroy">
</li>
<% }) %>
</code></pre>
<h3><code>init(element, options)</code></h3>
<p>[can-control.prototype.init] is called with the below arguments when new instances of <a href="can-control.html" title="Create organized, memory-leak free, rapidly performing, stateful controls with declarative event binding. Use Control to create UI
controls like tabs, grids, and context menus,
and organize them into higher-order business rules with
can.route. It can serve as both a traditional view and a traditional controller.">can-control</a> are created:</p>
<ul>
<li><strong>element</strong> - The wrapped element passed to the
control. Control accepts a
raw HTMLElement, a CSS selector, or a NodeList. This is
set as <code>this.element</code> on the control instance.</li>
<li><strong>options</strong> - The second argument passed to new Control, extended with
the can.Control's static <strong>defaults</strong>. This is set as
<code>this.options</code> on the control instance. Note that static is used
formally to indicate that <em>default values are shared across control instances</em>.</li>
</ul>
<p>Any additional arguments provided to the constructor will be passed as normal. Use <a href="can.view.html" title="undefined">can.view</a> to produce a document fragment
from your template and inject it in the passed element. Note that the <code>todos</code> parameter passed to <a href="can.view.html" title="undefined">can.view</a> below
is an instance of <a href="can-list.html" title="">can-list</a>:</p>
<pre><code>var Todos = Control.extend({
//defaults are merged into the options arg provided to the constructor
defaults : { view: 'todos.ejs' }
}, {
init: function( element , options ) {
//create a pointer to the control's scope
var self = this;
//run the Todo model's .findAll() method to produce a can.List
Todo.findAll( {}, function( todos ) {
//create a document fragment with can.view
//and inject it into the provided element's body
self.element.html( can.view(self.options.view, todos) );
});
}
});
// create a Todos Control with default options
new Todos( document.body.firstElementChild );
// overwrite the template default
new Todos( '#todos', { view: 'specialTodos.ejs' } );
</code></pre>
<h3><code>this.element</code></h3>
<p><a href="can-control.prototype.element.html" title="The element passed to the Control when creating a new instance.">element</a> is the
NodeList consisting of the element the control is created on.</p>
<pre><code>var todosControl = new Todos( document.body.firstElementChild );
todosControl.element[0] //-> document.body.firstElementChild
</code></pre>
<p>Each library wraps elements differently. If you are using jQuery, for example,
the element is wrapped with <code>jQuery( element )</code>.</p>
<h3><code>this.options</code></h3>
<p><a href="can-control.prototype.options.html" title="Options used to configure a control.">options</a> is the second argument passed to
<code>new Control()</code>, merged with the control's static <strong>defaults</strong> property.</p>
<h2>Listening to events</h2>
<p>Control automatically binds prototype methods that look
like event handlers. Listen to <strong>click</strong>'s on <code><li></code> elements within <a href="can-control.prototype.element.html" title="The element passed to the Control when creating a new instance.">this.element</a> like:</p>
<pre><code>var Todos = Control.extend({
init: function( element , options ) {...},
'{element} li click': function( li, event ) {
console.log( 'You clicked', li.text() );
// let other controls know what happened
li.trigger( 'selected' );
}
});
</code></pre>
<p>When an <code><li></code> is clicked, <code>"{element} li click"</code> is called with:</p>
<ul>
<li>The library-wrapped <strong>element</strong> that was clicked</li>
<li>The <strong>event</strong> data</li>
</ul>
<p>Control uses event delegation, so you can add <code><li></code>s without needing to rebind
event handlers.</p>
<p>To destroy a todo when its <code><a href="javascript://" class="destroy"></code> link
is clicked:</p>
<pre><code>var Todos = can.Control.extend({
init: function( element, options ) {...},
'{element} li click': function( li ) {...},
'{element} li .destroy click': function( el, ev ) {
// get the li element that has todo data
var li = el.closest( 'li' );
// get the model
var todo = li.data( 'todo' );
//destroy it
todo.destroy();
}
});
</code></pre>
<p>When the todo is destroyed, EJS's live binding will remove its LI automatically.</p>
<h3>Templated Event Handlers Part 1 <code>"{eventName}"</code></h3>
<p>Customize event handler behavior with <code>"{NAME}"</code> in
the event handler name. The following allows customization
of the event that destroys a todo:</p>
<pre><code>var Todos = Control.extend({
init: function( element , options ) { ... },
'{element} li click': function( li ) { ... },
'{element} li .destroy {destroyEvent}': function( el, ev ) {
// previous destroy code here
}
});
// create Todos with this.options.destroyEvent
new Todos( '#todos', { destroyEvent: 'mouseenter' } );
</code></pre>
<p>Values inside <code>{NAME}</code> are looked up on the control's <code>this.options</code> first,
and then the <code>window</code>. For example, we could customize it instead like:</p>
<pre><code>var Todos = Control.extend({
init: function( element , options ) { ... },
'{element} li click': function( li ) { ... },
'{element} li .destroy {Events.destroy}': function( el, ev ) {
// previous destroy code here
}
});
// Events config
Events = { destroy: 'click' };
// Events.destroy is looked up on the window.
new Todos( '#todos' );
</code></pre>
<p>The selector can also be templated.</p>
<pre><code>var Todos = Control.extend({
init: function( element , options ) { ... },
'{element} {listElement} click': function( li ) { ... },
'{element} {listElement} .destroy {destroyEvent}': function( el, ev ) {
// previous destroy code here
}
});
// create Todos with this.options.destroyEvent
new Todos( '#todos', {
destroyEvent: 'mouseenter',
listElement: 'li'
} );
</code></pre>
<h3>Templated Event Handlers Part 2 <code>"{objectName}"</code></h3>
<p>Control can also bind to objects other than <code>this.element</code> with
templated event handlers. This is <em>critical</em>
for avoiding memory leaks that are so common among MVC applications.</p>
<p>If the value inside <code>{NAME}</code> is an object, Control will bind to that
object to listen for events. For example, the following tooltip listens to
clicks on the window:</p>
<pre><code>var Tooltip = Control.extend({
'{window} click': function( el, ev ) {
// hide only if we clicked outside the tooltip
if ( !this.element.has( ev.target ) ) {
this.element.remove();
}
}
});
// create a Tooltip
new Tooltip( $( '<div>INFO</div>' ).appendTo( el ) );
</code></pre>
<p>This is convenient when listening for model changes. If EJS were not
taking care of removing <code><li></code>s after their associated models were destroyed,
we could implement it in <code>Todos</code> like:</p>
<pre><code>var Todos = Control.extend({
init: function( element, options ) {...},
'{element} li click': function( li ) {...},
'{element} li .destroy click': function( el, ev ) {
// get the li element that has todo data
var li = el.closest( 'li' );
// get the model
var todo = li.data( 'todo' );
//destroy it
todo.destroy();
},
'{Todo} destroyed': function( Todo, ev, todoDestroyed ) {
// find where the element
var index = this.todosList.indexOf( todoDestroyed );
this.element.children( ':nth-child(' + ( index + 1 ) + ')' )
.remove();
}
});
new Todos( '#todos' );
</code></pre>
<h3><code>on()</code></h3>
<p><a href="can-control.prototype.on.html" title="Bind an event handler to a Control, or rebind all event handlers on a Control.">on</a> rebinds a control's event handlers. This is useful when you want
to listen to a specific model and change it:</p>
<pre><code>var Editor = Control.extend({
todo: function( todo ) {
this.options.todo = todo;
this.on();
this.setName();
},
// a helper that sets the value of the input
// to the todo's name
setName: function() {
this.element.val( this.options.todo.name );
},
// listen for changes in the todo
// and update the input
'{todo} updated': function() {
this.setName();
},
// when the input changes
// update the todo instance
'{element} change': function() {
var todo = this.options.todo;
todo.attr( 'name', this.element.val() );
todo.save();
}
});
var todo1 = new Todo({ id: 6, name: 'trash' }),
todo2 = new Todo({ id: 6, name: 'dishes' });
// create the editor;
var editor = new Editor( '#editor' );
// show the first todo
editor.todo( todo1 );
// switch it to the second todo
editor.todo( todo2 );
</code></pre>
<h2>Destroying a control</h2>
<p><a href="can-control.prototype.destroy.html" title="Remove a Control from an element and clean up the Control.">destroy</a> unbinds a control's
event handlers and releases its element, but does not remove
the element from the page.</p>
<pre><code>var todo = new Todos( '#todos' );
todo.destroy();
</code></pre>
<p>When a control's element is removed from the page
<strong>destroy</strong> is called automatically.</p>
<pre><code>new Todos( '#todos' );
$( '#todos' ).remove();
</code></pre>
<p>All event handlers bound with Control are unbound when the control
is destroyed (or its element is removed).</p>
<p><em>Brief aside on destroy and templated event binding. Taken
together, templated event binding, and control's automatic
clean-up make it almost impossible
to write leaking applications. An application that uses
only templated event handlers on controls within the body
could free up all
data by calling <code>$(document.body).empty()</code>.</em></p>
<h2>Tabs Example</h2>
<p>Here is an example of how to build a simple tab widget using Control:</p>
<iframe style="width: 100%; height: 300px"
src="http://jsfiddle.net/donejs/kXLLt/embedded/result,html,js,css"
allowfullscreen="allowfullscreen"
frameborder="0">JSFiddle</iframe>
</section>
<script type="text/javascript">
var docObject = {"src":{"path":"node_modules/can-control/docs/control.md"},"description":"Create organized, memory-leak free, rapidly performing, stateful controls with declarative event binding. Use `Control` to create UI\ncontrols like tabs, grids, and context menus,\nand organize them into higher-order business rules with\n[can.route]. It can serve as both a traditional view and a traditional controller.\n\n","type":"module","title":"can-control","types":[{"type":"constructor"}],"name":"can-control","parent":"can-infrastructure","download":"can/route","test":["can/route/test.html","can/control/test.html"],"inherits":"can","link":"../docco/control/control.html docco","package":{"_args":[[{"raw":"can-control@3.0.3","scope":null,"escapedName":"can-control","name":"can-control","rawSpec":"3.0.3","spec":"3.0.3","type":"version"},"/Users/kevin/dev/canjs"]],"_from":"can-control@3.0.3","_id":"can-control@3.0.3","_inCache":true,"_location":"/can-control","_nodeVersion":"6.9.1","_npmOperationalInternal":{"host":"packages-12-west.internal.npmjs.com","tmp":"tmp/can-control-3.0.3.tgz_1478735732683_0.8053654539398849"},"_npmUser":{"name":"phillipskevin","email":"kphillips86@gmail.com"},"_npmVersion":"3.10.8","_phantomChildren":{},"_requested":{"raw":"can-control@3.0.3","scope":null,"escapedName":"can-control","name":"can-control","rawSpec":"3.0.3","spec":"3.0.3","type":"version"},"_requiredBy":["/","/can-component"],"_resolved":"https://registry.npmjs.org/can-control/-/can-control-3.0.3.tgz","_shasum":"9041c9ffe786cb67ede36f2e4696a853fdca976f","_shrinkwrap":null,"_spec":"can-control@3.0.3","_where":"/Users/kevin/dev/canjs","author":{"name":"Bitovi","email":"contact@bitovi.com","url":"http://bitovi.com"},"bit-docs":{"dependencies":{"bit-docs-glob-finder":"^0.0.5","bit-docs-dev":"^0.0.3","bit-docs-js":"^0.0.3","bit-docs-generate-readme":"^0.0.8"},"glob":{"pattern":"**/*.{js,md}","ignore":"node_modules/**/*"},"readme":{"apis":"./docs/apis.json"},"parent":"can-control"},"browser":{"transform":["cssify"]},"browserify":{"transform":["cssify"]},"bugs":{"url":"https://github.com/canjs/can-control/issues"},"dependencies":{"can-compute":"^3.0.0-pre.14","can-construct":"^3.0.0-pre.8","can-event":"^3.0.0-pre.1","can-observation":"^3.0.0-pre.11","can-util":"^3.0.0-pre.34"},"description":"[](https://travis-ci.org/canjs/can-control)","devDependencies":{"bit-docs":"0.0.6","can-define":"^1.0.1","can-map":"^3.0.0-pre.9","cssify":"^1.0.2","done-serve":"^0.2.4","donejs-cli":"^0.9.5","generator-donejs":"^0.9.0","jshint":"^2.9.1","steal":"^0.16.0","steal-qunit":"^0.1.1","steal-tools":"^0.16.0","testee":"^0.2.4"},"directories":{},"dist":{"shasum":"9041c9ffe786cb67ede36f2e4696a853fdca976f","tarball":"https://registry.npmjs.org/can-control/-/can-control-3.0.3.tgz"},"gitHead":"ed710c01d5c9e033e24cde85fa0bd1cbc5cf3d29","homepage":"http://canjs.com","keywords":["canjs","canjs-plugin","donejs"],"main":"can-control","maintainers":[{"name":"daffl","email":"daff@neyeon.de"},{"name":"justinbmeyer","email":"justin@bitovi.com"},{"name":"matthewp","email":"matthew@matthewphillips.info"},{"name":"phillipskevin","email":"kphillips86@gmail.com"},{"name":"sinjhin","email":"john@ardea.io"}],"name":"can-control","optionalDependencies":{},"readme":"ERROR: No README data found!","repository":{"type":"git","url":"git://github.com/canjs/can-control.git"},"scripts":{"build":"node build.js","develop":"done-serve --static --develop --port 8080","document":"bit-docs","jshint":"jshint can-control.js can-control_test.js --config","postversion":"git push --tags && git checkout master && git branch -D release && git push","preversion":"npm test && npm run build","release:major":"npm version major && npm publish","release:minor":"npm version minor && npm publish","release:patch":"npm version patch && npm publish","release:pre":"npm version prerelease && npm publish","test":"npm run jshint && npm run testee","testee":"testee test/test.html --browsers firefox","version":"git commit -am \"Update dist for release\" && git checkout -b release && git add -f dist/"},"system":{"configDependencies":["live-reload"],"npmAlgorithm":"flat"},"version":"3.0.3"},"signatures":[{"code":"Control( [staticProperties,] instanceProperties )","description":"\n\nCreate a new, extended, control constructor\nfunction. This functionality is inherited from [can-construct] and is deprecated in favor of using\n[can-control.extend].\n","params":[{"types":[{"type":"Object","options":[]}],"optional":true,"name":"staticProperties","description":"An object of properties and methods that are added the control constructor\nfunction directly. The most common property to add is [can-control.defaults].\n"},{"types":[{"type":"Object","options":[]}],"name":"instanceProperties","description":"An object of properties and methods that belong to\ninstances of the `Control` constructor function. These properties are added to the\ncontrol's `prototype` object. Properties that\nlook like event handlers (ex: `\"{element} click\"` or `\"{element} li mouseenter\"`) are setup\nas event handlers (see [Listening to events](#section_Listeningtoevents)).\n"}],"returns":{"types":[{"type":"function","constructs":{"types":[{"type":"can.Construct"}]},"returns":{"types":[{"type":"undefined"}]},"params":[{"types":[{"type":"element"}]},{"types":[{"type":"options"}]}]}],"description":"A control constructor function that has been\nextended with the provided `staticProperties` and `instanceProperties`.\n\n"}},{"code":"new Control( element, options )","description":"\n\nCreate an instance of a control. [can.Control.prototype.setup] processes\nthe arguments and sets up event binding. Write your initialization\ncode in [can.Control.prototype.init]. Note, you never call `new Control()` directly,\ninstead, you call it on constructor functions extended from `Control`.\n","params":[{"types":[{"type":"HTMLElement"},{"type":"can-view-nodelist"},{"type":"CSSSelectorString"}],"name":"element","description":"Specifies the element the control will be created on.\n"},{"types":[{"type":"Object"},{"type":"can-map"},{"type":"can-define/map/map"}],"optional":true,"name":"options","description":"Option values merged with [can-control.defaults Control.defaults]\nand set as [can-control::options this.options]. If options is an observable ([can-map CanMap] / [can-define/map/map DefineMap]), any values from [can-control.defaults defaults] that do not exist on the observable will be set. The observable will then be set as [can-control::options this.options].\n\n"}],"returns":{"types":[{"type":"can-control"}],"description":"A new instance of the constructor function extending Control.\n"}}],"_curReturn":{"types":[{"type":"can-control"}],"description":"A new instance of the constructor function extending Control.\n"},"_curParam":{"types":[{"type":"Object"},{"type":"can-map"},{"type":"can-define/map/map"}],"optional":true,"name":"options","description":"Option values merged with [can-control.defaults Control.defaults]\nand set as [can-control::options this.options]. If options is an observable ([can-map CanMap] / [can-define/map/map DefineMap]), any values from [can-control.defaults defaults] that do not exist on the observable will be set. The observable will then be set as [can-control::options this.options].\n\n"},"comment":" ","pathToRoot":".."};
</script>
</article>
<footer><p>CanJS is part of <a href="http://donejs.com" target="_blank">DoneJS</a>. Created and maintained by the core <a href="https://donejs.com/About.html#section=section_Team" target="_blank">DoneJS team</a> and <a href="http://bitovi.com" target="_blank">Bitovi</a>. <strong>Currently 3.0.0.</strong></p></footer>
</div>
</div>
</div>
<script>
steal = {
instantiated: {
"bundles/bit-docs-site/static.css!$css" : null
}
};
</script>
<script type='text/javascript' data-main="bit-docs-site/static" src="./static/node_modules/steal/steal.production.js"></script>
<script async defer src="https://buttons.github.io/buttons.js"></script>
</body>
</html>