Skip to content

Instantly share code, notes, and snippets.

@cschneid
Created September 17, 2010 17:36
Show Gist options
  • Save cschneid/584609 to your computer and use it in GitHub Desktop.
Save cschneid/584609 to your computer and use it in GitHub Desktop.
/*
* Widget that tracks the state of a togglable item. To toggle, click on the
* item. No visible action is taken directly, but events and callbacks are
* fired (via _trigger()) so that callbacks may change state
*/
$.widget("ui.toggle", {
/*
* Constructor -- attach a click handler which calls the toggle() function.
*/
_init: function(){
/* Helpful variables to get scope correct in callbacks */
var toggle = this;
var $toggle = this.element;
/*
* We need to default the state. As an enhancement to this widget, I'd
* allow the user to pass in an option defining the initial state this
* widget is in.
*/
toggle._setState(true);
/*
* The click handler is very simple. I use an anonymous function here
* so that the scope inside toggle() is correct.
*
* As a (WRONG / NOT WORKING) example, if you did this:
* $toggle.click(this.toggle);
*
* Then, when the toggle function gets run, the definition of the `this`
* variable will not be this widget, but instead will be the click event
* context. Which is rarely what you want.
*
* An alternate way of doing this correctly is to use jQuery's proxy function.
* $toggle.click($.proxy(this, "toggle"));
*
* I prefer the way that is uncommented, because I dislike defining
* function names via strings, and the anonymous function is going to get
* created either way (it's how $.proxy() works internally).
*/
$toggle.click(function(e) {
toggle.toggle(e);
});
},
/*
* Turn this on or off, run callbacks, and fire events.
*
* The _trigger() function is builtin to jQuery widgets. It does a few things.
* First it attempts to call a callback with the name provided. (change, on,
* off). If the function doesn't exist, nothing happens.
*
* Then it fires an event, combining the name of the widget with the passed
* argument. So "toggle" + "change" becomes an event named "togglechange".
* This event is triggered on the element itself, and bubbles as per normal
* javascript behaviors. So in this case, you could attach a listener to
* $(body) to listen for ANY toggle widget.
*
*/
toggle: function(e){
this._trigger("change");
if (this.state() == true)
{
this._setState(false);
this._trigger("off");
}
else
{
this._setState(true);
this._trigger("on");
}
},
/* Get the current state of this widget */
state: function() {
return this.options.state;
},
/*
* Set state. This is private due to the leading underscore, so the outside
* world can only interact with this widget via the public toggle() function.
*/
_setState: function(state) {
this.options.state = state;
}
});
/*
* A simple widget that uses the toggle functionality to change it's own color.
* This is a good example of how widgets can start building on each other to build out
*/
$.widget("ui.textcolor", {
/*
* Default options. See the .ready() function for an example of how to
* override the defaults with your own.
*/
options: {
on: "#f00",
off: "#0f0"
},
/* The constructor for this widget. */
_init: function(){
/* Helpful variables to get scope correct in callbacks */
var textcolor = this;
var $textcolor = this.element;
/*
* Init the toggle widget on the element that this widget is attached to
* (the $textcolor variable). In addition, define some callbacks so that
* we can take action when it gets toggled.
*
* Also note that we don't define a callback for the `toggle` action. The
* _trigger call in the toggle widget is smart enough to not call it if it
* doesn't exist. It does however still raise the event.
*/
$textcolor.toggle({
on: function(){
$textcolor.css({color: textcolor.options.on});
},
off: function(){
$textcolor.css({color: textcolor.options.off});
}
});
}
});
/*
* None of the code above actually does anything to the page. The .ready()
* function here ties the widgets defined above onto actual DOM elements in the
* HTML page.
*/
$(document).ready(function() {
// Init the textcolor widget on the paragraph. Note that in turn, the
// textcolor widget will init the toggle widget.
$("#color").textcolor({on: "#00f"});
// We can bind to the toggle events so other items on the page can react to
// the toggle status
$("#color").bind('togglechange', function() { /* ... */ });
$("#color").bind('toggleon', function() { /* ... */ });
$("#color").bind('toggleoff', function() { /* ... */ });
// We can find out what the current status is by asking.
// This will return true/false
$("#color").toggle("state");
});
/*
* The HTML for this example is super simple:
*
* <html>
* <head>
* <script type="text/javascript" src="jquery.js"></script>
* <script type="text/javascript" src="jquery-ui.js"></script>
* </head>
* <body>
* <p id="#color">Toggle Me!</p>
* </body>
* </html>
*
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment