From 43961a4aa660166251eb448cdeb38a02d7938658 Mon Sep 17 00:00:00 2001 From: Aaron Date: Mon, 15 Oct 2012 13:18:42 -0400 Subject: [PATCH] Converted code examples for all events articles to github markdown --- page/events/event-delegation.md | 20 ++-- page/events/event-extensions.md | 34 +++--- page/events/event-helpers.md | 11 +- page/events/events-to-elements.md | 106 +++++++++--------- page/events/inside-event-handling-function.md | 9 +- page/events/introduction-to-custom-events.md | 46 ++++---- page/events/introduction-to-events.md | 42 +++---- page/events/triggering-event-handlers.md | 35 +++--- page/events/using_delegate_and_undelegate.md | 61 +++++----- page/events/working_with_events_part_1.md | 42 +++---- page/events/working_with_events_part_2.md | 67 ++++++----- 11 files changed, 247 insertions(+), 226 deletions(-) diff --git a/page/events/event-delegation.md b/page/events/event-delegation.md index 15a96e3b..079a9d61 100644 --- a/page/events/event-delegation.md +++ b/page/events/event-delegation.md @@ -25,29 +25,31 @@ certain event types were supported. As of jQuery 1.4.2, the `$.fn.delegate` method is available, and is the preferred method. -
-Event delegation using `$.fn.delegate` +``` +//Event delegation using `$.fn.delegate` $('#myUnorderedList').delegate('li', 'click', function(e) { var $myListItem = $(this); // ... }); -
+``` - +``` +//Event delegation using `$.fn.live` $('#myUnorderedList li').live('click', function(e) { var $myListItem = $(this); // ... }); - +``` ### Unbinding Delegated Events If you need to remove delegated events, you can't simply unbind them. Instead, use `$.fn.undelegate` for events connected with `$.fn.delegate`, and `$.fn.die` for events connected with `$.fn.live`. As with bind, you can optionally pass -in the name of the bound function. +in the name of the bound function. +``` +//Unbinding delegated events $('#myUnorderedList').undelegate('li', 'click'); - $('#myUnorderedList li').die('click'); -
-
+ $('#myUnorderedList li').die('click'); +``` diff --git a/page/events/event-extensions.md b/page/events/event-extensions.md index 65991c2d..473ef546 100644 --- a/page/events/event-extensions.md +++ b/page/events/event-extensions.md @@ -51,20 +51,23 @@ Note that for all events, the browser's native event object is available in `eve For example, to set a hook for the "drop" event that copies the "dataTransfer" property, assign an object to jQuery.event.fixHooks.drop: -jQuery.event.fixHooks.drop = { props: [ "dataTransfer" ] }; - +``` +jQuery.event.fixHooks.drop = { props: [ "dataTransfer" ] }; +``` Since fixHooks are an advanced feature and rarely used externally, we have not added extra code and interfaces to deal with conflict resolution. If there is a chance that some other code may be assigning fixHooks to the same events, the code should check for an existing hook and take appropriate measures. A simple solution might look like this: -if ( jQuery.event.fixHooks.drop ) { +``` +if ( jQuery.event.fixHooks.drop ) { throw new Error("Someone else took the jQuery.event.fixHooks.drop hook!"); } jQuery.event.fixHooks.drop = { props: [ "dataTransfer" ] }; - +``` When there are known cases of different plugins wanting to attach to the drop hook, this solution might be more appropriate: -var existingHook = jQuery.event.fixHooks.drop; +``` +var existingHook = jQuery.event.fixHooks.drop; if ( !existingHook ) { jQuery.event.fixHooks.drop = { props: [ "dataTransfer" ] }; } else { @@ -74,7 +77,7 @@ if ( !existingHook ) { existingHook.props = [ "dataTransfer" ]; } } - +``` ### Special event hooks @@ -91,11 +94,11 @@ When defined, these string properties specify that a special event should be han The behavior of these properties is easiest to see with an example. Assume a special event defined as follows: -jQuery.event.special.pushy = { +```jQuery.event.special.pushy = { bindType: "click", delegateType: "click" }; - +``` When these properties are defined, the following behavior occurs in the jQuery event system: @@ -106,7 +109,8 @@ When these properties are defined, the following behavior occurs in the jQuery e So given the special event above, this code shows that a pushy isn't removed by removing clicks. That might be an effective way to defend against an ill-behaved plugin that didn't namespace its removal of click events, for example: -var $p = $("p"); +``` +var $p = $("p"); $p.on("click", function( e ) { $("body").append("I am a " + e.type + "!")); }); @@ -117,7 +121,7 @@ $p.trigger("click"); // triggers both handlers $p.off("click"); $p.trigger("click"); // still triggers "pushy" $p.off("pushy"); - +``` These two properties are often used in conjunction with a `handle` hook function; the hook might, for example, change the event name from "click" to "pushy" before calling event handlers. See below for an example. @@ -125,8 +129,9 @@ These two properties are often used in conjunction with a `handle` hook function Many of the special event hook functions below are passed a `handleObj` object that provides more information about the event, how it was attached, and its current state. This object and its contents should be treated as read-only data, and only the properties below are documented for use by special event handlers. For the discussion below, assume an event is attached with this code: -$(".dialog").on("click.myPlugin", "button", {mydata: 42}, myHandler); - +``` +$(".dialog").on("click.myPlugin", "button", {mydata: 42}, myHandler); +``` type: String : The type of event, such as `"click"`. When special event mapping is used via bindType or delegateType, this will be the mapped type. @@ -189,7 +194,8 @@ This `multiclick` special event maps itself into a standard click event, but use The hook stores the current click count in the data object, so multiclick handlers on different elements don't interfere with each other. It changes the event type to the original "multiclick" type before calling the handler and restores it to the mapped "click" type before returning: -jQuery.event.special.multiclick = { +``` +jQuery.event.special.multiclick = { delegateType: "click", bindType: "click", handle: function( event ) { @@ -212,4 +218,4 @@ The hook stores the current click count in the data object, so multiclick handle $("p").on("multiclick", { clicks: 3 }, function(e){ alert("clicked 3 times"); }); - +``` diff --git a/page/events/event-helpers.md b/page/events/event-helpers.md index ea02e7d8..69711d57 100644 --- a/page/events/event-helpers.md +++ b/page/events/event-helpers.md @@ -15,11 +15,12 @@ will run for `mouseenter`, and the second will run for `mouseleave`. Prior to jQuery 1.4, the `$.fn.hover` method required two functions. - +``` +//The hover helper function $('#menu li').hover(function() { $(this).toggleClass('hover'); }); - +``` ### `$.fn.toggle` @@ -29,8 +30,8 @@ list is called. Generally, `$.fn.toggle` is used with just two functions; however, it will accept an unlimited number of functions. Be careful, though: providing a long list of functions can be difficult to debug. - - +``` +//The toggle helper function $('p.expander').toggle( function() { $(this).prev().addClass('open'); @@ -39,4 +40,4 @@ providing a long list of functions can be difficult to debug. $(this).prev().removeClass('open'); } ); - +``` diff --git a/page/events/events-to-elements.md b/page/events/events-to-elements.md index 33e85cf2..1127b1f4 100644 --- a/page/events/events-to-elements.md +++ b/page/events/events-to-elements.md @@ -10,30 +10,31 @@ function to multiple events, when you want to provide data to the event hander, when you are working with custom events, or when you want to pass an object of multiple events and handlers. - - $('p').click(function() { - console.log('click'); - }); - - - - - $('p').bind('click', function() { - console.log('click'); - }); - - - - $('input').bind( - 'click change', // bind to multiple events - { foo : 'bar' }, // pass in data - - function(eventObject) { - console.log(eventObject.type, eventObject.data); - // logs event type, then { foo : 'bar' } - } - ); - +``` +//Event binding using a convenience method +$('p').click(function() { + console.log('click'); +}); +``` + +``` +//Event biding using the `$.fn.bind` method +$('p').bind('click', function() { + console.log('click'); +}); +``` + +``` +//Event binding using the `$.fn.bind` method with data +$('input').bind( + 'click change', // bind to multiple events + { foo : 'bar' }, // pass in data + function(eventObject) { + console.log(eventObject.type, eventObject.data); + // logs event type, then { foo : 'bar' } + } +); +``` ### Connecting Events to Run Only Once @@ -41,12 +42,13 @@ Sometimes you need a particular handler to run only once — after that, you may want no handler to run, or you may want a different handler to run. jQuery provides the `$.fn.one` method for this purpose. - - $('p').one('click', function() { - console.log('You just clicked this for the first time!'); - $(this).click(function() { console.log('You have clicked this before!'); }); - }); - +``` +//Switching handlers using the `$.fn.one` method +$('p').one('click', function() { + console.log('You just clicked this for the first time!'); + $(this).click(function() { console.log('You have clicked this before!'); }); +}); +``` The `$.fn.one` method is especially useful if you need to do some complicated setup the first time an element is clicked, but not subsequent times. @@ -58,17 +60,19 @@ the event type to unbind. If you attached a named function to the event, then you can isolate the unbinding to that named function by passing it as the second argument. - - $('p').unbind('click'); - +``` +//Unbinding all click handlers on a selection +$('p').unbind('click'); +``` - - var foo = function() { console.log('foo'); }; - var bar = function() { console.log('bar'); }; +``` +//Unbinding a particular click handler, using a reference to the function +var foo = function() { console.log('foo'); }; +var bar = function() { console.log('bar'); }; - $('p').bind('click', foo).bind('click', bar); - $('p').unbind('click', bar); // foo is still bound to the click event - +$('p').bind('click', foo).bind('click', bar); +$('p').unbind('click', bar); // foo is still bound to the click event +``` ### Namespacing Events @@ -76,11 +80,12 @@ For complex applications and for plugins you share with others, it can be useful to namespace your events so you don't unintentionally disconnect events that you didn't or couldn't know about. - - $('p').bind('click.myNamespace', function() { /* ... */ }); - $('p').unbind('click.myNamespace'); - $('p').unbind('.myNamespace'); // unbind all events in the namespace - +``` +//Namespacing events +$('p').bind('click.myNamespace', function() { /* ... */ }); +$('p').unbind('click.myNamespace'); +$('p').unbind('.myNamespace'); // unbind all events in the namespace +``` ### Binding Multiple Events @@ -89,12 +94,13 @@ having a different function for handing the event. In these cases you can pass an object into `$.fn.bind` with one or more key/value pairs, with the key being the event name and the value being the function to handle the event. - - $('p').bind({ - 'click': function() { console.log('clicked!'); }, - 'mouseover': function() { console.log('hovered!'); } - }); - +``` +//Binding Multiple Events +$('p').bind({ + 'click': function() { console.log('clicked!'); }, + 'mouseover': function() { console.log('hovered!'); } +}); +```
The option to pass an object of multiple events and handlers to `$.fn.bind` was diff --git a/page/events/inside-event-handling-function.md b/page/events/inside-event-handling-function.md index b85cca9e..d57a3f8b 100644 --- a/page/events/inside-event-handling-function.md +++ b/page/events/inside-event-handling-function.md @@ -41,11 +41,12 @@ the DOM element that the handler was bound to via the keyword this. To turn the DOM element into a jQuery object that we can use jQuery methods on, we simply do $(this), often following this idiom: - +``` var $this = $(this); - +``` - +``` +//Preventing a link from being followed $('a').click(function(e) { var $this = $(this); if ($this.attr('href').match('evil')) { @@ -53,4 +54,4 @@ simply do $(this), often following this idiom: $this.addClass('evil'); } }); - +``` diff --git a/page/events/introduction-to-custom-events.md b/page/events/introduction-to-custom-events.md index 17aa9571..d06431a9 100644 --- a/page/events/introduction-to-custom-events.md +++ b/page/events/introduction-to-custom-events.md @@ -25,7 +25,7 @@ Why should you care? An example is probably the best way to explain. Suppose you have a lightbulb in a room in a house. The lightbulb is currently turned on, and it’s controlled by two three-way switches and a clapper: - +```
@@ -34,7 +34,7 @@ on, and it’s controlled by two three-way switches and a clapper:
-
+``` Triggering the clapper or either of the switches will change the state of the lightbulb. The switches and the clapper don’t care what state the lightbulb is @@ -42,7 +42,7 @@ in; they just want to change the state. Without custom events, you might write some code like this: - +``` $('.switch, .clapper').click(function() { var $light = $(this).parent().find('.lightbulb'); if ($light.hasClass('on')) { @@ -51,11 +51,11 @@ Without custom events, you might write some code like this: $light.removeClass('off').addClass('on'); } }); - +``` With custom events, your code might look more like this: - +``` $('.lightbulb').bind('changeState', function(e) { var $light = $(this); if ($light.hasClass('on')) { @@ -68,13 +68,13 @@ With custom events, your code might look more like this: $('.switch, .clapper').click(function() { $(this).parent().find('.lightbulb').trigger('changeState'); }); - +``` This last bit of code is not that exciting, but something important has happened: we’ve moved the behavior of the lightbulb to the lightbulb, and away from the switches and the clapper. Let’s make our example a little more interesting. We’ll add another room to our house, along with a master switch, as shown here: - +```
@@ -90,7 +90,7 @@ Let’s make our example a little more interesting. We’ll add another room to
-
+``` If there are any lights on in the house, we want the master switch to turn all the lights off; otherwise, we want it to turn all lights on. To accomplish @@ -98,7 +98,7 @@ this, we’ll add two more custom events to the lightbulbs: `turnOn` and `turnOff`. We’ll make use of them in the `changeState` custom event, and use some logic to decide which one the master switch should trigger: - +``` $('.lightbulb') .bind('changeState', function(e) { var $light = $(this); @@ -126,7 +126,7 @@ some logic to decide which one the master switch should trigger: $('.lightbulb').trigger('turnOn'); } }); - +``` Note how the behavior of the master switch is attached to the master switch; the behavior of a lightbulb belongs to the lightbulbs. @@ -159,7 +159,7 @@ remember two things: Here is an example of the usage of `$.fn.bind` and `$.fn.trigger` that uses custom data in both cases: - +``` $(document).bind('myCustomEvent', { foo : 'bar' }, function(e, arg1, arg2) { console.log(e.data.foo); // 'bar' console.log(arg1); // 'bim' @@ -167,7 +167,7 @@ custom data in both cases: }); $(document).trigger('myCustomEvent', [ 'bim', 'baz' ]); - +``` ### A Sample Application @@ -185,7 +185,7 @@ When we’re done, it will look like this: ![Our finished application](http://gyazo.com/70415e9fffab1c47953f5264ecf722fe.png) - +```

Twitter Search

@@ -200,7 +200,7 @@ When we’re done, it will look like this:
- +``` This gives us a container (#twitter) for our widget, a template for our results containers (hidden via CSS), and a simple form where users can input a search @@ -239,7 +239,7 @@ It binds a click event to each action’s list item, and uses the list item’s class to determine which custom event will be triggered on the corresponding results container. - +``` $.fn.twitterResult = function(settings) { return this.each(function() { var $results = $(this), @@ -352,7 +352,7 @@ results container. $(this).removeClass('collapsed'); } }; - +``` The Twitter container itself will have just two custom events: @@ -370,7 +370,7 @@ The Twitter container itself will have just two custom events: Here's how the Twitter container bindings look: - +``` $('#twitter') .bind('getResults', function(e, term) { // make sure we don't have a box for this term already @@ -402,7 +402,7 @@ Here's how the Twitter container bindings look: }); }); }); - +``` So far, we’ve written a lot of code that does approximately nothing, but that’s OK. By specifying all the behaviors that we want our core objects to have, @@ -413,7 +413,7 @@ For the text input, we’ll capture the term that was entered in the input and pass it as we trigger the Twitter container’s `getResults` event. Clicking the “Load Trending Terms” will trigger the Twitter container’s `getTrends` event: - +``` $('form').submit(function(e) { e.preventDefault(); var term = $('#search_term').val(); @@ -422,8 +422,8 @@ pass it as we trigger the Twitter container’s `getResults` event. Clicking the $('#get_trends').click(function() { $('#twitter').trigger('getTrends'); - }); - + }); +``` By adding a few buttons with the appropriate IDs, we can make it possible to remove, collapse, expand, and refresh all results containers at once, as shown @@ -431,7 +431,7 @@ below. For the remove button, note how we’re passing a value of true to the event handler as its second argument, telling the event handler that we don’t want to verify the removal of individual containers. - +``` $.each(['refresh', 'expand', 'collapse'], function(i, ev) { $('#' + ev).click(function(e) { $('#twitter div.results').trigger(ev); }); }); @@ -441,7 +441,7 @@ want to verify the removal of individual containers. $('#twitter div.results').trigger('remove', [ true ]); } }); - +``` ### Conclusion diff --git a/page/events/introduction-to-events.md b/page/events/introduction-to-events.md index ef4ec5f8..ce3a5d0e 100644 --- a/page/events/introduction-to-events.md +++ b/page/events/introduction-to-events.md @@ -21,11 +21,9 @@ To specify to the browser what to do when an event occurs, you provide a functio For instance, to alert a message whenever a user clicks on a button, you might write something like this: - -
+``` -
-
+``` The event we want to listen to is specified by the button's `onclick` attribute, and the event handler is the `alert` function which alerts "Hello" to the user. While this works, it's an abysmal way to achieve this functionality for a couple of reasons: @@ -36,34 +34,35 @@ Utilizing inline event handlers like this can be considered *obtrusive JavaScrip To accomplish the desired task unobtrusively, let's change our HTML a little bit by removing the `onclick` attribute and replacing it with an `id`, which we'll utilize to "hook onto" the button from within a script file. - -
+``` -
-
+``` If we wanted to be informed when a user clicks on that button unobtrusively, we might do something like the following in a separate script file: - +``` +//Event binding using addEventListener var helloBtn = document.getElementById('helloBtn'); helloBtn.addEventListener('click', function(event) { alert('Hello.'); }, false); - +``` Here we're saving a reference to the button element by calling `getElementById` and assigning its return value to a variable. We then call `addEventListener` and provide an event handler function that will be called whenever that event occurs. While there's nothing wrong with this code as it will work fine in modern browsers, it won't fare well in versions of IE prior to IE9. This is because Microsoft chose to implement a different method, `attachEvent`, as opposed to the W3C standard `addEventListener`, and didn't get around to changing it until IE9 was released. For this reason, it's beneficial to utilize jQuery because it abstracts away browser inconsistencies, allowing developers to use a single API for these types of tasks, as seen below. - +``` +//Event binding using a convenience method $('#helloBtn').click(function(event) { alert('Hello.'); }); - +``` The `$('#helloBtn')` code selects the button element using the `$` (aka `jQuery`) function and returns a jQuery object. The jQuery object has a bunch of methods (functions) available to it, one of them named `click`, which resides in the jQuery object's prototype. We call the `click` method on the jQuery object and pass along an anonymous function event handler that's going to be executed when a user clicks the button, alerting "Hello." to the user. There are a number of ways that events can be listened for using jQuery: - +``` +//The many ways to bind events with jQuery // Attach an event handler directly to the button using jQuery's // shorthand `click` method. $('#helloBtn').click(function(event) { @@ -94,7 +93,7 @@ There are a number of ways that events can be listened for using jQuery: $('body').on('click', 'button', function(event) { alert('Hello.'); }); - +``` As of jQuery 1.7, all events are bound via the `on` method, whether you call it directly or whether you use an alias/shortcut method such as `bind` or `click`, which are mapped to the `on` method internally. With this in mind, it's beneficial to use the `on` method because the others are all just syntactic sugar, and utilizing the `on` method is going to result in faster and more consistent code. @@ -113,13 +112,14 @@ The event bubbling that occurs affords us the ability to add cells via AJAX for In all of the previous examples, we've been using anonymous functions and specifying an `event` argument within that function. Let's change it up a little bit. - +``` +//Binding a named function function sayHello(event) { alert('Hello.'); } $('#helloBtn').on('click', sayHello); - +``` In this slightly different example, we're defining a function called `sayHello` and then passing that function into the `on` method instead of an anonymous function. So many online examples show anonymous functions used as event handlers, but it's important to realize that you can also pass defined functions as event handlers as well. This is important if different elements or different events should perform the same functionality. This helps to keep your code DRY. @@ -127,13 +127,14 @@ But what about that `event` argument in the `sayHello` function—what is it and If the element has default functionality for a specific event (like a link opens a new page, a button in a form submits the form, etc), that default functionality can be cancelled. This is often useful for AJAX requests. When a user clicks on a button to submit a form via AJAX, we'd want to cancel the button/form's default action (to submit it to the form's `action` attribute), and we would instead do an AJAX request to accomplish the same task for a more seamless experience. To do this, we would utilize the event object and call its `preventDefault` method. We can also prevent the event from bubbling up the DOM tree using `stopPropagation` so that parent elements aren't notified of its occurrence (in the case that event delegation is being used). - +``` +//Preventing a default action from occurring and stopping the event bubbling $('form').on('submit', function(event) { event.preventDefault(); // Prevent the form's default submission. event.stopPropagation(); // Prevent event from bubbling up DOM tree, prohibiting delegation // Make an AJAX request to submit the form data }); - +``` When utilizing both `preventDefault` and `stopPropagation` simultaneously, you can instead `return false` to achieve both in a more concise manner, but it's advisable to only `return false` when both are actually necessary and not just for the sake of terseness. A final note on `stopPropagation` is that when using it in delegated events, the soonest that event bubbling can be stopped is when the event reaches the element that is delegating it. @@ -141,10 +142,11 @@ It's also important to note that the event object contains a property called `or Finally, to inspect the event itself and see all of the data it contains, you should log the event in the browser's console using `console.log`. This will allow you to see all of an event's properties (including the `originalEvent`) which can be really helpful for debugging. - +``` +//Logging an event's information $('form').on('submit', function(event) { event.preventDefault(); // Prevent the form's default submission. console.log(event); // Log the event object for inspectin' // Make an AJAX request to submit the form data }); - +``` diff --git a/page/events/triggering-event-handlers.md b/page/events/triggering-event-handlers.md index ad76b6fa..904fb4f5 100644 --- a/page/events/triggering-event-handlers.md +++ b/page/events/triggering-event-handlers.md @@ -5,33 +5,35 @@ github: johnkpaul level: intermediate --- #### Triggering Events -jQuery provides a way to trigger the event handlers bound to an element without any user interaction via the `$.fn.trigger` method. +jQuery provides a way to trigger the event handlers bound to an element without any user interaction via the `$.fn.trigger` method. #### What handlers can be trigger()'d -jQuery's event handling system is a layer on top of native browser events. +jQuery's event handling system is a layer on top of native browser events. When an event handler is added using .click(fn) or .on("click",fn), it can be triggered using jQuery's .trigger("click") -because jQuery stores a reference to that handler when it is originally added. Additionally, it will trigger the javascript inside the "onclick" attribute. The .trigger() function cannot be used to mimic native browser events, -such as clicking on a file input box or an anchor tag. This is because, there is no event handler attached using jQuery's event system that coorespond to these events. +because jQuery stores a reference to that handler when it is originally added. Additionally, it will trigger the javascript inside the "onclick" attribute. The .trigger() function cannot be used to mimic native browser events, +such as clicking on a file input box or an anchor tag. This is because, there is no event handler attached using jQuery's event system that coorespond to these events. - +``` Learn jQuery - +``` - +``` +//This will not change the current page $('a').trigger('click'); - +``` #### How can I mimic a native browser event, if not .trigger()? -In order to trigger a native browser event, you have to use [document.createEventObject](http://msdn.microsoft.com/en-us/library/ie/ms536390(v=vs.85).aspx) for < IE9 and [document.createEvent](https://developer.mozilla.org/en/DOM/document.createEvent) for all other browsers. -Using these two APIs, you can programatically create an event that behaves exactly as if someone has actually clicked on a file input box. The default action will happen, and the browse file dialog will display. +In order to trigger a native browser event, you have to use [document.createEventObject](http://msdn.microsoft.com/en-us/library/ie/ms536390(v=vs.85).aspx) for < IE9 and [document.createEvent](https://developer.mozilla.org/en/DOM/document.createEvent) for all other browsers. +Using these two APIs, you can programatically create an event that behaves exactly as if someone has actually clicked on a file input box. The default action will happen, and the browse file dialog will display. The jQuery UI Team created [jquery.simulate.js](https://github.com/eduardolundgren/jquery-simulate/blob/master/jquery.simulate.js) in order to simplify triggering a native browser event for use in their automated testing. Its usage is modeled after jQuery's trigger. - +``` +//Triggering a native browser event using the simulate plugin $('a').simulate('click'); - +``` This will not only trigger the jQuery event handlers, but also follow the link and change the current page. @@ -40,7 +42,7 @@ This will not only trigger the jQuery event handlers, but also follow the link a There are four differences between .trigger() and .triggerHandler() -1. triggerHandler only triggers the event on the first element of a jQuery object. +1. triggerHandler only triggers the event on the first element of a jQuery object. 2. triggerHandler cannot be chained. It returns the value that is returned by the last handler, not a jQuery object. 3. triggerHandler will not cause the default behavior of the event (such as a form submission). 4. Events triggered by triggerHandler, will not bubble up the DOM heirarchy. Only the handlers on the single element will fire. @@ -53,9 +55,10 @@ While this method has its uses, it should not be used simply to call a function handler. Instead, you should store the function you want to call in a variable, and pass the variable name when you do your binding. Then, you can call the function itself whenever you want, without the need for -`$.fn.trigger`. +`$.fn.trigger`. - +``` +//Triggering an event handler the right way var foo = function(e) { if (e) { console.log(e); @@ -67,7 +70,7 @@ call the function itself whenever you want, without the need for $('p').click(foo); foo(); // instead of $('p').trigger('click') - +``` A more complex architecture can built on top of trigger using the [publish-subscribe pattern](http://en.wikipedia.org/wiki/Publish%E2%80%93subscribe_pattern) using [jQuery plugins](https://gist.github.com/661855). With this technique, `$.fn.trigger` can be used to notify other sections of code that an application specific event has happenned. diff --git a/page/events/using_delegate_and_undelegate.md b/page/events/using_delegate_and_undelegate.md index ac20216c..d533f4a3 100644 --- a/page/events/using_delegate_and_undelegate.md +++ b/page/events/using_delegate_and_undelegate.md @@ -1,6 +1,6 @@ --- title: Using Delegate and Undelegate in jQuery -attribution: Jordan Boesch +attribution: Jordan Boesch status: needswork editrequired: 2 source: http://www.learningjquery.com/2010/03/using-delegate-and-undelegate-in-jquery-1-4-2 @@ -8,88 +8,89 @@ source: http://www.learningjquery.com/2010/03/using-delegate-and-undelegat As some of you have heard, there have been two new methods added in jQuery 1.4.2, [.delegate()](http://api.jquery.com/delegate/) and [.undelegate()](http://api.jquery.com/undelegate/). These methods achieve the same thing as the [.live()](http://api.jquery.com/live/) and [.die()](http://api.jquery.com/die/) methods, they just use a different syntax. For those new to *.live()*, it's a method in jQuery that allows you to attach events to elements that appear in the document as well as elements that will appear in the future. An example would be if you attached a click event via `.live()*` - +``` $('img.photo').live('click', function(){ lightboxify(this); }); - +``` Then appended some photos via ajax later on: - +``` +//Appends an image // append an image $('body').append('silly face'); - +``` The click event would still apply to that new image without having to re-bind the event. Handy, isn't it? Not too long ago, the *.live()* method was brought up for discussion for a [few](http://forum.jquery.com/topic/jquery-live-jquery-fn-live-discussion) [reasons](http://paulirish.com/2010/on-jquery-live/). One problem discussed is that *.live()* fails when you try to use it alongside traversals like: -
+``` // FAILS $('ul').find('li').next().live('click', function(){}); // FAILS $('ul').parent().nextAll().live('click', function(){}); -
+``` and also when you pass any native DOM elements like: -
+``` // FAILS $(document.body).live('click', function(){}); -
+``` Unfortunately, when you use *.live()*, it has to be at the top of the chain like so: -
+``` $('ul li').live('click', function(){}) -
+``` Because this can be frustrating and confusing for many users who are used to the traversing and chainability that jQuery offers, it sparked a discussion about the syntax for *.live()*. Why does it look like all the other methods, yet does not behave the same? Since changing the syntax would result in a whirlwind of code breakage, the jQuery team decided to introduce *.delegate()* and *.undelegate()* to complement *.live()* and *.die()*. Here's an example of how you would normally use *.live()* and *.die()* and how you can now use *.delegate()* and *.undelegate()*: Old way -
+``` // Using .live() $("table").each(function(){ $("td", this).live("hover", function(){ $(this).toggleClass("hover"); }); }); - + // Using .die() $("table").each(function(){ $("td", this).die("hover"); }); -
+``` New way -
+``` // Using .delegate() $("table").delegate("td", "hover", function(){ $(this).toggleClass("hover"); }); - + // Using .undelegate() $("table").undelegate("td", "hover"); -
+``` The benefit of *delegate()* is that it allows you to specify its context. This way, it ensures that we do not bubble all the way up the DOM tree to capture the target of the element. With the .live() method, it bubbles all the way up the DOM each time unless you set context like so: *$('td', $('table')[0]).live('hover', function(){})*. That just looks ugly. Some often like to think of *delegate()* like a *bind()* call. The syntax is a little different as you can see below. -
+``` // .bind() way $('ul li').bind('click', function(e){ // Do something with bind }); - + // .delegate() way $('ul').delegate('li', 'click', function(e){ // Do something with delegate }); -
+``` In short, the difference between *.bind()* and *.delegate()* is that *.bind()* will only add events to the elements that are on the page when you call it. .delegate() is listening for new elements and then adding events to them when they appear on the page. @@ -97,7 +98,7 @@ The gotchas of delegate While it does behave like *.bind()*, it does not allow you to pass an object map of events like *.bind()* does. Take this *.bind()* method for example: -
+``` // This works wonderfully $('ul li').bind({ click: function(e){ @@ -107,11 +108,11 @@ While it does behave like *.bind()*, it does not allow you to pass an object map // Something on mouse over } }); -
+``` An error will be thrown when you try to do: -
+``` // FAILS! $('ul').delegate('li', { click: function(e){ @@ -121,7 +122,7 @@ An error will be thrown when you try to do: // Something on mouse over } }); -
+``` I'm not sure the reasoning behind not implementing this, but I guess I'm not the only one pondering it. @@ -129,7 +130,7 @@ Granted, *.bind()* didn't have this feature until jQuery 1.4. But if you'd like I recommend using Robert Katic's patch above, but of course there are other approaches people can take. For example, you can rig up your own custom object map: -
+``` var customObjMap = { click : function(e){ // Something on click @@ -138,25 +139,25 @@ I recommend using Robert Katic's patch above, but of course there are other appr // Something on mouse over } }; - + $('ol').delegate('li', 'click mouseover', function(e){ if($.isFunction(customObjMap[e.type])){ customObjMap[e.type].call(this, e); } }); -
+``` Another "gotcha" with both *.delegate()* and *.live()* is that when you add the events *mouseenter* and *mouseleave* to an element, and then check the event type (e.type) in the callback function, it incorrectly displays as *mouseover* and *mouseout*. Using .bind(), on the other hand, it displays as *mouseenter* and *mouseleave* as expected. Here is an example: -
+``` $('ol').delegate('li', 'mouseenter', function(e){ alert(e.type); // outputs mouseover }); - + $('ol li').bind('mouseenter', function(e){ alert(e.type); // outputs mouseenter }); -
+``` Overall, the "gothcas" are no match for the benefits that *.delegate()* and *.undelegate()* provide. Truly great additions to the jQuery core. diff --git a/page/events/working_with_events_part_1.md b/page/events/working_with_events_part_1.md index 48d767ef..cc02e1f6 100644 --- a/page/events/working_with_events_part_1.md +++ b/page/events/working_with_events_part_1.md @@ -1,6 +1,6 @@ --- title: Working with Events, part 1 -attribution: Karl Swedberg +attribution: Karl Swedberg status: needswork editrequired: 2 source: http://www.learningjquery.com/2008/03/working-with-events-part-1 @@ -37,13 +37,13 @@ class="alert">Alert!` in our document, and we want to attach a click handler to it that generates an alert message. In jQuery, we might do so with the following code: - +``` $(document).ready(function() { $('button.alert').click(function() { alert('this is an alert message'); }); }); - +``` Here we are registering the click handler for the button with a class of "alert" as soon as the DOM has loaded. So, the button is there, and we have a @@ -54,20 +54,20 @@ button will not generate an alert. Let's test what we've just discussed. I've added a script with the above three lines of jQuery code so that the following button will produce an alert message -when clicked. +when clicked. ##Events Don't Work with Added Elements Now, let's create a new button (if we don't already have a second one) using jQuery code like this: - +``` $('#create-button').click(function() { if ( $('button.alert').length <2) { $('</li>
  • plain
  • - +``` Press the "I am special" button to create a new list item with a class of "special": @@ -93,14 +93,14 @@ item with a class of "special" (which itself is inside an element with id of "list1") a new list item with class="special" should be inserted after the list item in which the button was clicked: - +``` $(document).ready(function() { $('#list1 li.special button').click(function() { var $newLi = $('
  • special and new
  • '); $(this).parent().after($newLi); }); }); -
    +``` So, how can we get the events to carry over to the new elements? Two common approaches are event delegation and "re-binding" event handlers. In this entry, @@ -126,13 +126,13 @@ this argument event. We can call it `e` or `evt` or `gummy` or whatever we want. just like to use labels that are as obvious as possible because I have a hard time keeping track of things. Here is what we have so far: - +``` $(document).ready(function() { $('#list2').click(function(event) { var $newLi = $('
  • special and new
  • '); }); }); -
    +``` So far, the code is very similar to our first attempt, except for the selector we're starting with (#list2) and the addition of the event argument. Now we @@ -141,25 +141,25 @@ need to determine whether what is being clicked inside the `