From 3d67ad771391ed81e6f8dc0b557733e3c4a9aaa2 Mon Sep 17 00:00:00 2001 From: Eric Ladd Date: Tue, 16 Oct 2012 12:11:08 -0400 Subject: [PATCH 1/3] Edits to event basics; using jQuery with other libs --- order.yml | 4 +- page/events/event-basics.md | 235 ++++++++++++++++++ .../avoid-conflicts-other-libraries.md | 162 +++++++++++- 3 files changed, 386 insertions(+), 15 deletions(-) create mode 100644 page/events/event-basics.md diff --git a/order.yml b/order.yml index 286b3481..11d37871 100644 --- a/order.yml +++ b/order.yml @@ -32,13 +32,11 @@ - feature-browser-detection - utility-methods - events: - - events-to-elements - - inside-event-handling-function + - events-basics - event-helpers - event-extensions - event-delegation - using_delegate_and_undelegate - - working_with_events_part_1 - working_with_events_part_2 - triggering-event-handlers - introduction-to-custom-events diff --git a/page/events/event-basics.md b/page/events/event-basics.md new file mode 100644 index 00000000..cbe3a316 --- /dev/null +++ b/page/events/event-basics.md @@ -0,0 +1,235 @@ +--- +title: jQuery Event Basics +attribution: jQuery Fundamentals +level: beginner +--- + +## jQuery Event Basics + +### Setting Up Event Responses on DOM Elements + +jQuery makes it straightforward to set up event-driven responses on page elements. +These events are often triggered by the end user's interaction with the page, +such as when text is entered into a form element or the mouse pointer is moved. +In some cases, such as the page load and unload events, the browser itself will +trigger the event. + +jQuery offers convenience methods for most native browser events. These methods — +including `$.fn.click`, `$.fn.focus`, `$.fn.blur`, `$.fn.change`, etc. — are shorthand +for jQuery's `$.fn.on` method. The on method is useful for binding the same handler +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. + +``` +// Event setup using a convenience method +$('p').click(function() { + console.log('You clicked a paragraph!'); +}); +``` + +``` +// Equivalent event setup using the `$.fn.on` method +$('p').on('click', function() { + console.log('click'); +}); +``` + +### Extending Events to New Page Elements + +It is important to note that `$.fn.on` can only create event listeners +on elements that exist *at the time you set up the listeners*. Similar elements created +after the event listeners are established will not automatically pick up event behaviors +you've set up previously. For example: + +``` +$(document).ready(function(){ + // Sets up click behavior on all button elements with the alert class + // that exist in the DOM when the instruction was executed + $('button.alert').on('click', function(){ + console.log('A button with the alert class was clicked!'); + }); + // Now create a new button element with the alert class. This button + // was created after the click listeners were applied above, so it + // will not have the same click behavior as its peers + $('button').addClass('alert').appendTo(document.body); +}); +``` + +Consult the article on event delegation to see how to use `$.fn.on` so that +event behaviors will be extended to new elements without having to rebind them. + +### Inside the Event Handler Function + +Every event handling function receives an event object, which contains many +properties and methods. The event object is most commonly used to prevent the +default action of the event via the preventDefault method. However, the event +object contains a number of other useful properties and methods, including: + +#### pageX, pageY + +The mouse position at the time the event occurred, relative to the top left corner of +the page display area (not the entire browser window). + +#### type + +The type of the event (e.g. "click"). + +#### which + +The button or key that was pressed. + +#### data + +Any data that was passed in when the event was bound. For example: + +``` +// Event setup using the `$.fn.on` method with data +$('input').on( + 'change', + {foo : 'bar'}, // associate data with event binding + function(eventObject) { + console.log('An input value has changed! ', eventObject.data.foo); + } +); +``` + +#### target + +The DOM element that initiated the event. + +#### namespace + +The namespace specified when the event was triggered. + +#### timeStamp + +The difference in milliseconds between the time the event occurred in the browser and January 1, 1970. + +#### preventDefault() + +Prevent the default action of the event (e.g. following a link). + +#### stopPropagation() + +Stop the event from bubbling up to other elements. + +In addition to the event object, the event handling function also has access to +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); +``` + +A fuller example would be: + +``` +// Preventing a link from being followed +$('a').click(function(eventObject) { + var $this = $(this); + if ($this.attr('href').match(/evil/)) { + eventObject.preventDefault(); + $this.addClass('evil'); + } +}); +``` + +### Setting Up Multiple Event Responses + +Quite often elements in your application will be bound to multiple events. If +multiple events are to share the same handling function, you can provide the event types +as a space-separated list to `$.fn.on`: + +``` +// Multiple events, same handler +$('input').on( + 'click change', // bind listeners for multiple events + function() { + console.log('An input was clicked or changed!') + } +); +``` + +When each event has its own handler, you can pass an object into `$.fn.on` with one or +more key/value pairs, with the key being the event name and the value being the function +to handle the event. + +``` +// Binding multiple events with different handlers +$('p').on({ + 'click': function() { console.log('clicked!'); }, + 'mouseover': function() { console.log('hovered!'); } +}); +``` + +### Namespacing Events + +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. + +``` +// Namespacing events +$('p').on('click.myNamespace', function() { /* ... */ }); +$('p').off('click.myNamespace'); +$('p').off('.myNamespace'); // unbind all events in the namespace +``` + +### Tearing Down Event Listeners + +To remove an event listener, you use the `$.fn.off` method and pass in +the event type to off. If you attached a named function to the event, then +you can isolate the event tear down to just that named function by passing it as the +second argument. + +``` +// Tearing down all click handlers on a selection +$('p').off('click'); +``` + +``` +// Tearing down a particular click handler, using a reference to the function +var foo = function() { console.log('foo'); }; +var bar = function() { console.log('bar'); }; + +$('p').on('click', foo).on('click', bar); +$('p').off('click', bar); // foo is still bound to the click event +``` + +### Setting Up Events to Run Only Once + +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. + +``` +// Switching handlers using the `$.fn.one` method +$('p').one('click', firstClick); + +function firstClick(){ + console.log('You just clicked this for the first time!'); + // Now set up the new handler for subsequent clicks; + // omit this step if no further click responses are needed + $(this).click(function() { console.log('You have clicked this before!'); }); +} +``` + +Note that in the code snippet above, the `firstClick` function will be executed for +the first click on *each* paragraph element rather than the function being removed from +*all* paragraphs when *any* paragraph is clicked for the first time. + +`$.fn.one` can also be used to bind multiple events: + +``` +// Using $.fn.one to bind several events +$('input').one('focus mouseover keydown', firstEvent); + +function firstEvent(eventObject){ + console.log('The ' + eventObject.type + ' event has occurred for the first time on the input with id ' + this.id) +} +``` + +In this case, the `firstEvent` function will be executed once *for each event*. For the snippet above, this means +that once an element gains focus, the handler function will still execute for the first keydown event. \ No newline at end of file diff --git a/page/using-jquery-core/avoid-conflicts-other-libraries.md b/page/using-jquery-core/avoid-conflicts-other-libraries.md index 5ebdce89..add889cd 100644 --- a/page/using-jquery-core/avoid-conflicts-other-libraries.md +++ b/page/using-jquery-core/avoid-conflicts-other-libraries.md @@ -1,37 +1,175 @@ --- title : Avoiding Conflicts with Other Libraries -attribution: jQuery Fundamentals +attribution: jQuery Fundamentals level: beginner --- -If you are using another JavaScript library that uses the `$` variable, you can + +The jQuery library, and virtually all of its plugins are constrained within the jQuery namespace. +As a general rule, global objects are stored inside the jQuery namespace as well, so you shouldn't +get a clash between jQuery and any other library (like prototype.js, MooTools, or YUI). + +That said, there is one caveat: *By default, jQuery uses `$` as a shortcut for `jQuery`.* Thus, if +you are using another JavaScript library that uses the `$` variable, you can run into conflicts with jQuery. In order to avoid these conflicts, you need to put jQuery in no-conflict mode immediately after it is loaded onto the page and before you attempt to use jQuery in your page. +##Putting jQuery into No-Conflict Mode + When you put jQuery into no-conflict mode, you have the option of assigning a -variable name to replace `$`. +new variable name to replace the `$` alias. ``` - + ``` -You can continue to use the standard $ by wrapping your code in a -self-executing anonymous function; this is a standard pattern for plugin -authoring, where the author cannot know whether another library will have taken -over the `$`. +In the code above, the `$` will revert back to its meaning in original library. You'll +still be able to use the full function name `jQuery` as well as the new alias `$j` in +the rest of your application. The new alias can be named anything you'd like: `jq`, `$J`, +`awesomeQuery`, etc. + +Finally, if you don't want to define another alternative to the full `jQuery` function name +(you really like to use `$` and don't care about using the other library's `$` method), then +there's still another approach you might try: simply add the `$` as an argument passed to your +`jQuery(document).ready()` function. This is most frequently used in the case where you still want the +benefits of really concise jQuery code, but don't want to cause conflicts with other libraries. + +``` + + + + + +``` + +This is probably the ideal solution for most of your code, considering that there'll be +less code that you'll have to change in order to achieve complete compatibility. + +##Including jQuery Before Other Libraries + +The code snippets above rely on jQuery being loaded after prototype.js is loaded. If you +include jQuery before other libraries, you may use `jQuery` when you do some work with +jQuery, but the `$` will have the meaning defined in the other library. There is no need +to relinquish the `$` alias by calling `jQuery.noConflict()`. + +``` + + + + +``` + +##Summary of Ways to Reference the jQuery Function + +Here's a recap of ways you can reference the jQuery function when the presence of +another library creates a conflict over the use of the `$` variable: + +###Create a New Alias + +The `jQuery.noConflict()` method returns a reference to the jQuery function, so you can +capture it in whatever variable you'd like: + +``` + + + +``` + +###Use an Immediately Invoked Function + +You can continue to use the standard `$` by wrapping your code in an immediately invoked +function; this is also a standard pattern for jQuery plugin authoring, where the author +cannot know whether another library will have taken over the `$`. ``` +``` + +Note that if you use this technique, you will not be able to use prototype.js methods inside the +immediately invoked function that expect `$` to be prototype.js's `$`. + +###Use the Argument to the `jQuery(document).ready()` Function + +``` + + + ``` + +Or using the more concise syntax for the DOM ready function: + +``` + + + +``` \ No newline at end of file From 2516daf8b83f731cc6d0099ece5dae7e9cc9ccb9 Mon Sep 17 00:00:00 2001 From: Eric Ladd Date: Tue, 16 Oct 2012 13:24:08 -0400 Subject: [PATCH 2/3] edits from adam's feedback --- order.yml | 2 +- page/events/event-basics.md | 7 ++++--- 2 files changed, 5 insertions(+), 4 deletions(-) diff --git a/order.yml b/order.yml index 11d37871..349386d3 100644 --- a/order.yml +++ b/order.yml @@ -32,7 +32,7 @@ - feature-browser-detection - utility-methods - events: - - events-basics + - event-basics - event-helpers - event-extensions - event-delegation diff --git a/page/events/event-basics.md b/page/events/event-basics.md index cbe3a316..c1ff1278 100644 --- a/page/events/event-basics.md +++ b/page/events/event-basics.md @@ -224,12 +224,13 @@ the first click on *each* paragraph element rather than the function being remov ``` // Using $.fn.one to bind several events -$('input').one('focus mouseover keydown', firstEvent); +$('input[id]').one('focus mouseover keydown', firstEvent); function firstEvent(eventObject){ - console.log('The ' + eventObject.type + ' event has occurred for the first time on the input with id ' + this.id) + console.log('A ' + eventObject.type + ' event occurred for the first time on the input with id ' + this.id) } ``` In this case, the `firstEvent` function will be executed once *for each event*. For the snippet above, this means -that once an element gains focus, the handler function will still execute for the first keydown event. \ No newline at end of file +that once an input element gains focus, the handler function will still execute for the first keydown event on that +element. \ No newline at end of file From b21373b1c7faf3507497b43527a51ea967d303f5 Mon Sep 17 00:00:00 2001 From: Eric Ladd Date: Tue, 16 Oct 2012 17:00:05 -0400 Subject: [PATCH 3/3] New article as per Issue 78 --- order.yml | 3 +- page/effects/intro-to-effects.md | 215 +++++++++++++++++++++++++++++++ 2 files changed, 216 insertions(+), 2 deletions(-) create mode 100644 page/effects/intro-to-effects.md diff --git a/order.yml b/order.yml index 2ff47ea7..43df81ec 100644 --- a/order.yml +++ b/order.yml @@ -44,9 +44,8 @@ - introduction-to-custom-events - history-of-events - effects: - - built-in-effects + - intro-to-effects - custom-effects - - managing-effects - queue_and_dequeue_explained - uses_of_queue_and_dequeue - ajax: diff --git a/page/effects/intro-to-effects.md b/page/effects/intro-to-effects.md new file mode 100644 index 00000000..e199f40d --- /dev/null +++ b/page/effects/intro-to-effects.md @@ -0,0 +1,215 @@ +--- +title: Introduction to Effects +level: beginner +--- + +## Showing and Hiding Content + +jQuery can show or hide content instantaneously with `$.fn.show` or `$.fn.hide`: + +``` +// Instantaneously hide all paragraphs +$('p').hide(); + +// Instantaneously show all divs that have the hidden style class +$('div.hidden').show(); +``` + +When jQuery hides an element, it sets its CSS `display` property to `none`. This means the content will have +zero width and height; it does not mean that the content will simply become transparent and leave an empty area on the page. + +jQuery can also show or hide content by means of animation effects. You can tell +`$.fn.show` and `$.fn.hide` to use animation in a couple of ways. One is to pass +in a string-valued argument of 'slow', 'normal', or 'fast': + +``` +// Slowly hide all paragraphs +$('p').hide('slow'); + +// Quickly show all divs that have the hidden style class +$('div.hidden').show('fast'); +``` + +If you prefer more direct control over the duration of the animation effect, you +can pass the desired duration in milliseconds to `$.fn.show` and `$.fn.hide`: + +``` +// Hide all paragraphs over half a second +$('p').hide(500); + +// Show all divs that have the hidden style class over 1.25 seconds +$('div.hidden').show(1250); +``` + +Most developers pass in a number of milleseconds to have more precise control +over the duration. + +##Fade and Slide Animations + +You may have noticed that `$.fn.show` and `$.fn.hide` use a combination of slide and fade effects +when showing and hiding content in an animated way. If you would rather show or hide content with +one effect or the other, there are additional methods that can help. `$.fn.slideDown` and `$.fn.slideUp` +show and hide content, respectively, using only a slide effect. Slide animations are accomplished by +rapidly making changes to an element's CSS `height` property. + +``` +// Hide all paragraphs using a slide up animation over 0.8 seconds +$('p').slideUp(800); + +// Show all hidden divs using a slide down animation over 0.6 seconds +$('div.hidden').slideDown(600); +``` + +Similarly `$.fn.fadeIn` and `$.fn.fadeOut` show and hide content, respectively, by means of a fade +animation. Fade animations involve rapidly making changes to an element's CSS `opacity` property. + +``` +// Hide all paragraphs using a fade out animation over 1.5 seconds +$('p').fadeOut(1500); + +// Show all hidden divs using a fade in animation over 0.75 seconds +$('div.hidden').fadeIn(750); +``` + +##Changing Display Based on Current Visibility State + +jQuery can also let you change a content's visibility based on its current visibility state. `$.fn.toggle` +will show content that is currently hidden and hide content that is currently visible. You can pass the +same arguments to `$.fn.toggle` as you pass to any of the effects methods above. + +``` +// Instantaneously toggle the display of all paragraphs +$('p').toggle(); + +// Slowly toggle the display of all images +$('img').toggle('slow'); + +// Toggle the display of all divs over 1.8 seconds +$('div').toggle(1800); +``` + +`$.fn.toggle` will use a combination of slide and fade effects, just as `$.fn.show` and `$.fn.hide` do. You can +toggle the display of content with just a slide or a fade using `$.fn.slideToggle` and `$.fn.fadeToggle`. + +``` +// Toggle the display of all ordered lists over 1 second using slide up/down animations +$('ol').slideToggle(1000); + +// Toggle the display of all blockquotes over 0.4 seconds using fade in/out animations +$('blockquote').fadeToggle(400); +``` + +##Doing Something After an Animation Completes + +A common mistake when implementing jQuery effects is assuming that the execution of the next method in your +chain will wait until the animation runs to completion. + +``` +// Fade in all hidden paragraphs; then add a style class to them (not quite right) +$('p.hidden').fadeIn(750).addClass('lookAtMe'); +``` + +It is important to realize that `$.fn.fadeIn` above only *kicks off* the animation. Once started, the +animation is implemented by rapidly changing CSS properties in a JavaScript `setInterval()` loop. When +you call `$.fn.fadeIn`, it starts the animation loop and then returns the jQuery object, passing it along +to `$.fn.addClass` which will then add the `lookAtMe` style class while the animation loop is just +getting started. + +To defer an action until after an animation has run to completion, you need to use an animation callback +function. You can specify your animation callback as the second argument passed to any of the +animation methods discussed above. For the code snippet above, we can implement a callback as follows: + +``` +// Fade in all hidden paragraphs; then add a style class to them (correct with animation callback) +$('p.hidden').fadeIn(750, function(){ + // this = DOM element which has just finished being animated + $(this).addClass('lookAtMe'); +}); +``` + +Note that you can use the keyword `this` to refer to the DOM element being animated. Also note +that the callback will be called for each element in the jQuery object. This means that if your +selector returns no elements, your animation callback will never run! You can solve this problem by +testing whether your selection returned any elements; if not, you can just run the callback immediately. + +``` +// Run a callback even if there were no elements to animate +var $someElement = $('#nonexistent'); + +var cb = function() { + console.log('done!'); +}; + +if ($someElement.length) { + $someElement.fadeIn(300, cb); +} else { + cb(); +} +``` + +##Managing Animation Effects + +jQuery provides some additional features for controlling your animations: + +### `$.fn.stop` + +`$.fn.stop` will immediately terminate all animations running on the elements in your selection. You might give +end-users control over page animations by rigging a button they can click to stop the animations. + +``` +// Create a button to stop all animations on the page: +$('input').attr({type : 'button', value : 'Stop All Animations'}).on('click', function(){ + $('body *').filter(':animated').stop(); +}).appendTo(document.body); +``` + +### `$.fn.delay` + +`$.fn.delay` is used to introduce a delay between successive animations. For example: + +``` +// Hide all level 1 headings over half a second; then wait for 1.5 seconds +// and reveal all level 1 headings over 0.3 seconds +$('h1').hide(500).delay(1500).show(300); +``` + +### `jQuery.fx` + +The `jQuery.fx` object has a number of properties that control how effects are implemented. `jQuery.fx.speeds` maps +the 'slow', 'normal', and 'fast' duration arguments mentioned above to a specific +number of milliseconds. The default value of `jQuery.fx.speeds` is: + +``` +{ + slow: 600, + fast: 200, + // Default speed, used for 'normal' + _default: 400 +} +``` + +You can modify any of these settings and even introduce some of your own: + +``` +jQuery.fx.speeds.fast = 300; +jQuery.fx.speeds.blazing = 100; +jQuery.fx.speeds.excruciating = 60000; +``` + +`jQuery.fx.interval` controls the number of frames per second that are +displayed in an animation. The default value is 13 milliseconds between +successive frames. You can set this a lower value for faster browsers +to make the animations run smoother. However this will mean more frames +per second and thus a higher computational load for the browser, so you +should be sure to test the performance implications of doing so thoroughly. + +Finally, `jQuery.fx.off` can be set to true to disable all animations. Elements +will immediately be set to the target final state instead. This can be +especially useful when dealing with older browsers; you also may want to +provide the option to disable all animations to your users. + +``` +$('input').attr({type : 'button', value : 'Disable Animations'}).on('click', function(){ + jQuery.fx.off = true; +}).appendTo(document.body); +``` \ No newline at end of file